linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Phillip Potter <phil@philpotter.co.uk>
To: gregkh@linuxfoundation.org
Cc: Larry.Finger@lwfinger.net, dan.carpenter@oracle.com,
	linux-kernel@vger.kernel.org, linux-staging@lists.linux.dev,
	fabioaiuto83@gmail.com
Subject: [PATCH 4/7] staging: rtl8188eu: introduce new os_dep dir for RTL8188eu driver
Date: Fri, 23 Jul 2021 01:42:11 +0100	[thread overview]
Message-ID: <20210723004214.912295-5-phil@philpotter.co.uk> (raw)
In-Reply-To: <20210723004214.912295-1-phil@philpotter.co.uk>

This patchset is split in order to keep the file sizes down. This os_dep
directory is part of the newer/better driver from GitHub modified by
Larry Finger. Import this as the basis for all future work going
forward.

Suggested-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Phillip Potter <phil@philpotter.co.uk>
---
 .../staging/rtl8188eu/os_dep/ioctl_cfg80211.c |  7113 +++++++++
 .../staging/rtl8188eu/os_dep/ioctl_cfg80211.h |   307 +
 .../staging/rtl8188eu/os_dep/ioctl_linux.c    | 12398 ++++++++++++++++
 drivers/staging/rtl8188eu/os_dep/ioctl_mp.c   |  2028 +++
 drivers/staging/rtl8188eu/os_dep/mlme_linux.c |   726 +
 drivers/staging/rtl8188eu/os_dep/os_intfs.c   |  4311 ++++++
 .../staging/rtl8188eu/os_dep/osdep_service.c  |  1731 +++
 drivers/staging/rtl8188eu/os_dep/recv_linux.c |   790 +
 .../staging/rtl8188eu/os_dep/rtw_android.c    |  1250 ++
 .../staging/rtl8188eu/os_dep/rtw_cfgvendor.c  |  1330 ++
 .../staging/rtl8188eu/os_dep/rtw_cfgvendor.h  |   229 +
 drivers/staging/rtl8188eu/os_dep/rtw_proc.c   |  3216 ++++
 drivers/staging/rtl8188eu/os_dep/rtw_proc.h   |    49 +
 drivers/staging/rtl8188eu/os_dep/usb_intf.c   |  1345 ++
 .../staging/rtl8188eu/os_dep/usb_ops_linux.c  |  1082 ++
 drivers/staging/rtl8188eu/os_dep/wifi_regd.c  |   354 +
 drivers/staging/rtl8188eu/os_dep/xmit_linux.c |   489 +
 17 files changed, 38748 insertions(+)
 create mode 100644 drivers/staging/rtl8188eu/os_dep/ioctl_cfg80211.c
 create mode 100644 drivers/staging/rtl8188eu/os_dep/ioctl_cfg80211.h
 create mode 100644 drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
 create mode 100644 drivers/staging/rtl8188eu/os_dep/ioctl_mp.c
 create mode 100644 drivers/staging/rtl8188eu/os_dep/mlme_linux.c
 create mode 100644 drivers/staging/rtl8188eu/os_dep/os_intfs.c
 create mode 100644 drivers/staging/rtl8188eu/os_dep/osdep_service.c
 create mode 100644 drivers/staging/rtl8188eu/os_dep/recv_linux.c
 create mode 100644 drivers/staging/rtl8188eu/os_dep/rtw_android.c
 create mode 100644 drivers/staging/rtl8188eu/os_dep/rtw_cfgvendor.c
 create mode 100644 drivers/staging/rtl8188eu/os_dep/rtw_cfgvendor.h
 create mode 100644 drivers/staging/rtl8188eu/os_dep/rtw_proc.c
 create mode 100644 drivers/staging/rtl8188eu/os_dep/rtw_proc.h
 create mode 100644 drivers/staging/rtl8188eu/os_dep/usb_intf.c
 create mode 100644 drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
 create mode 100644 drivers/staging/rtl8188eu/os_dep/wifi_regd.c
 create mode 100644 drivers/staging/rtl8188eu/os_dep/xmit_linux.c

diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8188eu/os_dep/ioctl_cfg80211.c
new file mode 100644
index 000000000000..1d7ff707ecad
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_cfg80211.c
@@ -0,0 +1,7113 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+#define  _IOCTL_CFG80211_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+
+#ifdef CONFIG_IOCTL_CFG80211
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
+#define STATION_INFO_SIGNAL		BIT(NL80211_STA_INFO_SIGNAL)
+#define STATION_INFO_TX_BITRATE		BIT(NL80211_STA_INFO_TX_BITRATE)
+#define STATION_INFO_RX_PACKETS		BIT(NL80211_STA_INFO_RX_PACKETS)
+#define STATION_INFO_TX_PACKETS		BIT(NL80211_STA_INFO_TX_PACKETS)
+#define STATION_INFO_TX_FAILED		BIT(NL80211_STA_INFO_TX_FAILED)
+#define STATION_INFO_ASSOC_REQ_IES	0
+#endif /* Linux kernel >= 4.0.0 */
+
+#include <rtw_wifi_regd.h>
+
+#define RTW_MAX_MGMT_TX_CNT (8)
+#define RTW_MAX_MGMT_TX_MS_GAS (500)
+
+#define RTW_SCAN_IE_LEN_MAX      2304
+#define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 5000 /* ms */
+#define RTW_MAX_NUM_PMKIDS 4
+
+#define RTW_CH_MAX_2G_CHANNEL               14      /* Max channel in 2G band */
+
+#ifdef CONFIG_WAPI_SUPPORT
+
+#ifndef WLAN_CIPHER_SUITE_SMS4
+#define WLAN_CIPHER_SUITE_SMS4          0x00147201
+#endif
+
+#ifndef WLAN_AKM_SUITE_WAPI_PSK
+#define WLAN_AKM_SUITE_WAPI_PSK         0x000FAC04
+#endif
+
+#ifndef WLAN_AKM_SUITE_WAPI_CERT
+#define WLAN_AKM_SUITE_WAPI_CERT        0x000FAC12
+#endif
+
+#ifndef NL80211_WAPI_VERSION_1
+#define NL80211_WAPI_VERSION_1          (1 << 2)
+#endif
+
+#endif /* CONFIG_WAPI_SUPPORT */
+
+#ifdef CONFIG_RTW_80211R
+#define WLAN_AKM_SUITE_FT_8021X		0x000FAC03
+#define WLAN_AKM_SUITE_FT_PSK			0x000FAC04
+#endif
+
+static const u32 rtw_cipher_suites[] = {
+	WLAN_CIPHER_SUITE_WEP40,
+	WLAN_CIPHER_SUITE_WEP104,
+	WLAN_CIPHER_SUITE_TKIP,
+	WLAN_CIPHER_SUITE_CCMP,
+#ifdef CONFIG_WAPI_SUPPORT
+	WLAN_CIPHER_SUITE_SMS4,
+#endif /* CONFIG_WAPI_SUPPORT */
+#ifdef CONFIG_IEEE80211W
+	WLAN_CIPHER_SUITE_AES_CMAC,
+#endif /* CONFIG_IEEE80211W */
+};
+
+#define RATETAB_ENT(_rate, _rateid, _flags) \
+	{								\
+		.bitrate	= (_rate),				\
+		.hw_value	= (_rateid),				\
+		.flags		= (_flags),				\
+	}
+
+#define CHAN2G(_channel, _freq, _flags) {			\
+		.band			= NL80211_BAND_2GHZ,		\
+		.center_freq		= (_freq),			\
+		.hw_value		= (_channel),			\
+		.flags			= (_flags),			\
+		.max_antenna_gain	= 0,				\
+		.max_power		= 30,				\
+	}
+
+#define CHAN5G(_channel, _flags) {				\
+		.band			= NL80211_BAND_5GHZ,		\
+		.center_freq		= 5000 + (5 * (_channel)),	\
+		.hw_value		= (_channel),			\
+		.flags			= (_flags),			\
+		.max_antenna_gain	= 0,				\
+		.max_power		= 30,				\
+	}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+/* if wowlan is not supported, kernel generate a disconnect at each suspend
+ * cf: /net/wireless/sysfs.c, so register a stub wowlan.
+ * Moreover wowlan has to be enabled via a the nl80211_set_wowlan callback.
+ * (from user space, e.g. iw phy0 wowlan enable)
+ */
+static const struct wiphy_wowlan_support wowlan_stub = {
+	.flags = WIPHY_WOWLAN_ANY,
+	.n_patterns = 0,
+	.pattern_max_len = 0,
+	.pattern_min_len = 0,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
+	.max_pkt_offset = 0,
+#endif
+};
+#endif
+
+static struct ieee80211_rate rtw_rates[] = {
+	RATETAB_ENT(10,  0x1,   0),
+	RATETAB_ENT(20,  0x2,   0),
+	RATETAB_ENT(55,  0x4,   0),
+	RATETAB_ENT(110, 0x8,   0),
+	RATETAB_ENT(60,  0x10,  0),
+	RATETAB_ENT(90,  0x20,  0),
+	RATETAB_ENT(120, 0x40,  0),
+	RATETAB_ENT(180, 0x80,  0),
+	RATETAB_ENT(240, 0x100, 0),
+	RATETAB_ENT(360, 0x200, 0),
+	RATETAB_ENT(480, 0x400, 0),
+	RATETAB_ENT(540, 0x800, 0),
+};
+
+#define rtw_a_rates		(rtw_rates + 4)
+#define RTW_A_RATES_NUM	8
+#define rtw_g_rates		(rtw_rates + 0)
+#define RTW_G_RATES_NUM	12
+
+#define RTW_2G_CHANNELS_NUM 14
+#define RTW_5G_CHANNELS_NUM 37
+
+static struct ieee80211_channel rtw_2ghz_channels[] = {
+	CHAN2G(1, 2412, 0),
+	CHAN2G(2, 2417, 0),
+	CHAN2G(3, 2422, 0),
+	CHAN2G(4, 2427, 0),
+	CHAN2G(5, 2432, 0),
+	CHAN2G(6, 2437, 0),
+	CHAN2G(7, 2442, 0),
+	CHAN2G(8, 2447, 0),
+	CHAN2G(9, 2452, 0),
+	CHAN2G(10, 2457, 0),
+	CHAN2G(11, 2462, 0),
+	CHAN2G(12, 2467, 0),
+	CHAN2G(13, 2472, 0),
+	CHAN2G(14, 2484, 0),
+};
+
+static struct ieee80211_channel rtw_5ghz_a_channels[] = {
+	CHAN5G(34, 0),		CHAN5G(36, 0),
+	CHAN5G(38, 0),		CHAN5G(40, 0),
+	CHAN5G(42, 0),		CHAN5G(44, 0),
+	CHAN5G(46, 0),		CHAN5G(48, 0),
+	CHAN5G(52, 0),		CHAN5G(56, 0),
+	CHAN5G(60, 0),		CHAN5G(64, 0),
+	CHAN5G(100, 0),		CHAN5G(104, 0),
+	CHAN5G(108, 0),		CHAN5G(112, 0),
+	CHAN5G(116, 0),		CHAN5G(120, 0),
+	CHAN5G(124, 0),		CHAN5G(128, 0),
+	CHAN5G(132, 0),		CHAN5G(136, 0),
+	CHAN5G(140, 0),		CHAN5G(149, 0),
+	CHAN5G(153, 0),		CHAN5G(157, 0),
+	CHAN5G(161, 0),		CHAN5G(165, 0),
+	CHAN5G(184, 0),		CHAN5G(188, 0),
+	CHAN5G(192, 0),		CHAN5G(196, 0),
+	CHAN5G(200, 0),		CHAN5G(204, 0),
+	CHAN5G(208, 0),		CHAN5G(212, 0),
+	CHAN5G(216, 0),
+};
+
+
+static void rtw_2g_channels_init(struct ieee80211_channel *channels)
+{
+	memcpy((void *)channels, (void *)rtw_2ghz_channels,
+		sizeof(struct ieee80211_channel) * RTW_2G_CHANNELS_NUM
+	);
+}
+
+static void rtw_5g_channels_init(struct ieee80211_channel *channels)
+{
+	memcpy((void *)channels, (void *)rtw_5ghz_a_channels,
+		sizeof(struct ieee80211_channel) * RTW_5G_CHANNELS_NUM
+	);
+}
+
+static void rtw_2g_rates_init(struct ieee80211_rate *rates)
+{
+	memcpy(rates, rtw_g_rates,
+		sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM
+	);
+}
+
+static void rtw_5g_rates_init(struct ieee80211_rate *rates)
+{
+	memcpy(rates, rtw_a_rates,
+		sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM
+	);
+}
+
+static struct ieee80211_supported_band *rtw_spt_band_alloc(
+	enum nl80211_band band
+)
+{
+	struct ieee80211_supported_band *spt_band = NULL;
+	int n_channels, n_bitrates;
+
+	if (band == NL80211_BAND_2GHZ) {
+		n_channels = RTW_2G_CHANNELS_NUM;
+		n_bitrates = RTW_G_RATES_NUM;
+	} else if (band == NL80211_BAND_5GHZ) {
+		n_channels = RTW_5G_CHANNELS_NUM;
+		n_bitrates = RTW_A_RATES_NUM;
+	} else
+		goto exit;
+
+	spt_band = (struct ieee80211_supported_band *)rtw_zmalloc(
+		sizeof(struct ieee80211_supported_band)
+		+ sizeof(struct ieee80211_channel) * n_channels
+		+ sizeof(struct ieee80211_rate) * n_bitrates
+	);
+	if (!spt_band)
+		goto exit;
+
+	spt_band->channels = (struct ieee80211_channel *)(((u8 *)spt_band) + sizeof(struct ieee80211_supported_band));
+	spt_band->bitrates = (struct ieee80211_rate *)(((u8 *)spt_band->channels) + sizeof(struct ieee80211_channel) * n_channels);
+	spt_band->band = band;
+	spt_band->n_channels = n_channels;
+	spt_band->n_bitrates = n_bitrates;
+
+	if (band == NL80211_BAND_2GHZ) {
+		rtw_2g_channels_init(spt_band->channels);
+		rtw_2g_rates_init(spt_band->bitrates);
+	} else if (band == NL80211_BAND_5GHZ) {
+		rtw_5g_channels_init(spt_band->channels);
+		rtw_5g_rates_init(spt_band->bitrates);
+	}
+
+	/* spt_band.ht_cap */
+
+exit:
+
+	return spt_band;
+}
+
+static void rtw_spt_band_free(struct ieee80211_supported_band *spt_band)
+{
+	u32 size = 0;
+
+	if (!spt_band)
+		return;
+
+#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)
+	if (spt_band->band == NL80211_BAND_2GHZ) {
+#else
+	if (spt_band->band == IEEE80211_BAND_2GHZ) {
+#endif
+		size = sizeof(struct ieee80211_supported_band)
+			+ sizeof(struct ieee80211_channel) * RTW_2G_CHANNELS_NUM
+			+ sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM;
+#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)
+	} else if (spt_band->band == NL80211_BAND_5GHZ) {
+#else
+	} else if (spt_band->band == IEEE80211_BAND_5GHZ) {
+#endif
+		size = sizeof(struct ieee80211_supported_band)
+			+ sizeof(struct ieee80211_channel) * RTW_5G_CHANNELS_NUM
+			+ sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM;
+	} else {
+
+	}
+	rtw_mfree((u8 *)spt_band, size);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+static const struct ieee80211_txrx_stypes
+	rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+	[NL80211_IFTYPE_ADHOC] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4)
+	},
+	[NL80211_IFTYPE_STATION] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+	},
+	[NL80211_IFTYPE_AP] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+		BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+		BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+		BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+		BIT(IEEE80211_STYPE_AUTH >> 4) |
+		BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+		BIT(IEEE80211_STYPE_ACTION >> 4)
+	},
+	[NL80211_IFTYPE_AP_VLAN] = {
+		/* copy AP */
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+		BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+		BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+		BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+		BIT(IEEE80211_STYPE_AUTH >> 4) |
+		BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+		BIT(IEEE80211_STYPE_ACTION >> 4)
+	},
+	[NL80211_IFTYPE_P2P_CLIENT] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+	},
+	[NL80211_IFTYPE_P2P_GO] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+		BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+		BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+		BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+		BIT(IEEE80211_STYPE_AUTH >> 4) |
+		BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+		BIT(IEEE80211_STYPE_ACTION >> 4)
+	},
+#if defined(RTW_DEDICATED_P2P_DEVICE)
+	[NL80211_IFTYPE_P2P_DEVICE] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+			BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+	},
+#endif
+};
+#endif
+
+static u64 rtw_get_systime_us(void)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0))
+	u64 ts;
+	ts = ktime_get_boottime();
+	return do_div(ts, 1000);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+	struct timespec ts;
+	get_monotonic_boottime(&ts);
+	return ((u64)ts.tv_sec * 1000000) + ts.tv_nsec / 1000;
+#else
+	struct timeval tv;
+	do_gettimeofday(&tv);
+	return ((u64)tv.tv_sec * 1000000) + tv.tv_usec;
+#endif
+}
+
+/* Try to remove non target BSS's SR to reduce PBC overlap rate */
+static int rtw_cfg80211_clear_wps_sr_of_non_target_bss(_adapter *padapter, struct wlan_network *pnetwork, struct cfg80211_ssid *req_ssid)
+{
+	struct rtw_wdev_priv *wdev_data = adapter_wdev_data(padapter);
+	int ret = 0;
+	u8 *psr = NULL, sr = 0;
+	NDIS_802_11_SSID *pssid = &pnetwork->network.Ssid;
+	u32 wpsielen = 0;
+	u8 *wpsie = NULL;
+
+	if (pssid->SsidLength == req_ssid->ssid_len
+		&& !memcmp(pssid->Ssid, req_ssid->ssid, req_ssid->ssid_len) )
+		goto exit;
+
+	wpsie = rtw_get_wps_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_
+		, pnetwork->network.IELength - _FIXED_IE_LENGTH_, NULL, &wpsielen);
+	if (wpsie && wpsielen > 0)
+		psr = rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_SELECTED_REGISTRAR, &sr, NULL);
+
+	if (psr && sr) {
+		if (0)
+			RTW_INFO("clear sr of non target bss:%s("MAC_FMT")\n"
+				, pssid->Ssid, MAC_ARG(pnetwork->network.MacAddress));
+		*psr = 0; /* clear sr */
+		ret = 1;
+	}
+
+exit:
+	return ret;
+}
+
+#define MAX_BSSINFO_LEN 1000
+struct cfg80211_bss *rtw_cfg80211_inform_bss(_adapter *padapter, struct wlan_network *pnetwork)
+{
+	struct ieee80211_channel *notify_channel;
+	struct cfg80211_bss *bss = NULL;
+	/* struct ieee80211_supported_band *band;       */
+	u16 channel;
+	u32 freq;
+	u64 notify_timestamp;
+	u16 notify_capability;
+	u16 notify_interval;
+	u8 *notify_ie;
+	size_t notify_ielen;
+	s32 notify_signal;
+	/* u8 buf[MAX_BSSINFO_LEN]; */
+
+	u8 *pbuf;
+	size_t buf_size = MAX_BSSINFO_LEN;
+	size_t len, bssinf_len = 0;
+	struct rtw_ieee80211_hdr *pwlanhdr;
+	__le16 *fctrl;
+	u8	bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	struct wireless_dev *wdev = padapter->rtw_wdev;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	pbuf = rtw_zmalloc(buf_size);
+	if (pbuf == NULL) {
+		RTW_INFO("%s pbuf allocate failed  !!\n", __func__);
+		return bss;
+	}
+
+	/* RTW_INFO("%s\n", __func__); */
+
+	bssinf_len = pnetwork->network.IELength + sizeof(struct rtw_ieee80211_hdr_3addr);
+	if (bssinf_len > buf_size) {
+		RTW_INFO("%s IE Length too long > %zu byte\n", __func__, buf_size);
+		goto exit;
+	}
+
+#ifndef CONFIG_WAPI_SUPPORT
+	{
+		u16 wapi_len = 0;
+
+		if (rtw_get_wapi_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &wapi_len) > 0) {
+			if (wapi_len > 0) {
+				RTW_INFO("%s, no support wapi!\n", __func__);
+				goto exit;
+			}
+		}
+	}
+#endif /* !CONFIG_WAPI_SUPPORT */
+
+	channel = pnetwork->network.Configuration.DSConfig;
+	freq = rtw_ch2freq(channel);
+	notify_channel = ieee80211_get_channel(wiphy, freq);
+
+	notify_timestamp = rtw_get_systime_us();
+
+	notify_interval = le16_to_cpu(*(__le16 *)rtw_get_beacon_interval_from_ie(pnetwork->network.IEs));
+	notify_capability = le16_to_cpu(*(__le16 *)rtw_get_capability_from_ie(pnetwork->network.IEs));
+
+	notify_ie = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
+	notify_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
+
+	/* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM: signal strength in mBm (100*dBm) */
+	if (check_fwstate(pmlmepriv, _FW_LINKED)  &&
+		is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {
+		notify_signal = 100 * translate_percentage_to_dbm(padapter->recvpriv.signal_strength); /* dbm */
+	} else {
+		notify_signal = 100 * translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength); /* dbm */
+	}
+
+	/* pbuf = buf; */
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pbuf;
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
+	/* pmlmeext->mgnt_seq++; */
+
+	if (pnetwork->network.Reserved[0] == 1) { /* WIFI_BEACON */
+		memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
+		set_frame_sub_type(pbuf, WIFI_BEACON);
+	} else {
+		memcpy(pwlanhdr->addr1, adapter_mac_addr(padapter), ETH_ALEN);
+		set_frame_sub_type(pbuf, WIFI_PROBERSP);
+	}
+
+	memcpy(pwlanhdr->addr2, pnetwork->network.MacAddress, ETH_ALEN);
+	memcpy(pwlanhdr->addr3, pnetwork->network.MacAddress, ETH_ALEN);
+
+
+	/* pbuf += sizeof(struct rtw_ieee80211_hdr_3addr); */
+	len = sizeof(struct rtw_ieee80211_hdr_3addr);
+	memcpy((pbuf + len), pnetwork->network.IEs, pnetwork->network.IELength);
+	*((__le64 *)(pbuf + len)) = cpu_to_le64(notify_timestamp);
+
+	len += pnetwork->network.IELength;
+
+	#if defined(CONFIG_P2P) && 0
+	if(rtw_get_p2p_ie(pnetwork->network.IEs+12, pnetwork->network.IELength-12, NULL, NULL))
+		RTW_INFO("%s, got p2p_ie\n", __func__);
+	#endif
+
+	bss = cfg80211_inform_bss_frame(wiphy, notify_channel, (struct ieee80211_mgmt *)pbuf,
+					len, notify_signal, GFP_ATOMIC);
+	if (unlikely(!bss)) {
+		RTW_INFO(FUNC_ADPT_FMT" bss NULL\n", FUNC_ADPT_ARG(padapter));
+		goto exit;
+	}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38))
+#ifndef COMPAT_KERNEL_RELEASE
+	/* patch for cfg80211, update beacon ies to information_elements */
+	if (pnetwork->network.Reserved[0] == 1) { /* WIFI_BEACON */
+
+		if (bss->len_information_elements != bss->len_beacon_ies) {
+			bss->information_elements = bss->beacon_ies;
+			bss->len_information_elements =  bss->len_beacon_ies;
+		}
+	}
+#endif /* COMPAT_KERNEL_RELEASE */
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+	cfg80211_put_bss(wiphy, bss);
+#else
+	cfg80211_put_bss(bss);
+#endif
+
+exit:
+	if (pbuf)
+		rtw_mfree(pbuf, buf_size);
+	return bss;
+
+}
+
+/*
+	Check the given bss is valid by kernel API cfg80211_get_bss()
+	@padapter : the given adapter
+
+	return true if bss is valid,  false for not found.
+*/
+int rtw_cfg80211_check_bss(_adapter *padapter)
+{
+	WLAN_BSSID_EX  *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);
+	struct cfg80211_bss *bss = NULL;
+	struct ieee80211_channel *notify_channel = NULL;
+	u32 freq;
+
+	if (!(pnetwork) || !(padapter->rtw_wdev))
+		return false;
+
+	freq = rtw_ch2freq(pnetwork->Configuration.DSConfig);
+	notify_channel = ieee80211_get_channel(padapter->rtw_wdev->wiphy, freq);
+	bss = cfg80211_get_bss(padapter->rtw_wdev->wiphy, notify_channel,
+			pnetwork->MacAddress, pnetwork->Ssid.Ssid,
+			pnetwork->Ssid.SsidLength,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+			pnetwork->InfrastructureMode == Ndis802_11Infrastructure?IEEE80211_BSS_TYPE_ESS:IEEE80211_BSS_TYPE_IBSS,
+			IEEE80211_PRIVACY(pnetwork->Privacy));
+#else
+			pnetwork->InfrastructureMode == Ndis802_11Infrastructure?WLAN_CAPABILITY_ESS:WLAN_CAPABILITY_IBSS, pnetwork->InfrastructureMode == Ndis802_11Infrastructure?WLAN_CAPABILITY_ESS:WLAN_CAPABILITY_IBSS);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+	cfg80211_put_bss(padapter->rtw_wdev->wiphy, bss);
+#else
+	cfg80211_put_bss(bss);
+#endif
+
+	return bss != NULL;
+}
+
+void rtw_cfg80211_ibss_indicate_connect(_adapter *padapter)
+{
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct wlan_network  *cur_network = &(pmlmepriv->cur_network);
+	struct wireless_dev *pwdev = padapter->rtw_wdev;
+	struct cfg80211_bss *bss = NULL;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
+	struct wiphy *wiphy = pwdev->wiphy;
+	int freq = 2412;
+	struct ieee80211_channel *notify_channel;
+#endif
+
+	RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
+	freq = rtw_ch2freq(cur_network->network.Configuration.DSConfig);
+
+	if (0)
+		RTW_INFO("chan: %d, freq: %d\n", cur_network->network.Configuration.DSConfig, freq);
+#endif
+
+	if (pwdev->iftype != NL80211_IFTYPE_ADHOC)
+		return;
+
+	if (!rtw_cfg80211_check_bss(padapter)) {
+		WLAN_BSSID_EX  *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);
+		struct wlan_network *scanned = pmlmepriv->cur_network_scanned;
+
+		if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ) {
+
+			memcpy(&cur_network->network, pnetwork, sizeof(WLAN_BSSID_EX));
+			if (cur_network) {
+				if (!rtw_cfg80211_inform_bss(padapter, cur_network))
+					RTW_INFO(FUNC_ADPT_FMT" inform fail !!\n", FUNC_ADPT_ARG(padapter));
+				else
+					RTW_INFO(FUNC_ADPT_FMT" inform success !!\n", FUNC_ADPT_ARG(padapter));
+			} else {
+				RTW_INFO("cur_network is not exist!!!\n");
+				return ;
+			}
+		} else {
+			if (scanned == NULL)
+				rtw_warn_on(1);
+
+			if (!memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) 
+				&& !memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) 
+			) {
+				if (!rtw_cfg80211_inform_bss(padapter, scanned))
+					RTW_INFO(FUNC_ADPT_FMT" inform fail !!\n", FUNC_ADPT_ARG(padapter));
+				else {
+					/* RTW_INFO(FUNC_ADPT_FMT" inform success !!\n", FUNC_ADPT_ARG(padapter)); */
+				}
+			} else {
+				RTW_INFO("scanned & pnetwork compare fail\n");
+				rtw_warn_on(1);
+			}
+		}
+
+		if (!rtw_cfg80211_check_bss(padapter))
+			RTW_INFO(FUNC_ADPT_FMT" BSS not found !!\n", FUNC_ADPT_ARG(padapter));
+	}
+	/* notify cfg80211 that device joined an IBSS */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
+	notify_channel = ieee80211_get_channel(wiphy, freq);
+	cfg80211_ibss_joined(padapter->pnetdev, cur_network->network.MacAddress, notify_channel, GFP_ATOMIC);
+#else
+	cfg80211_ibss_joined(padapter->pnetdev, cur_network->network.MacAddress, GFP_ATOMIC);
+#endif
+}
+
+void rtw_cfg80211_indicate_connect(_adapter *padapter)
+{
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct wlan_network  *cur_network = &(pmlmepriv->cur_network);
+	struct wireless_dev *pwdev = padapter->rtw_wdev;
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+#endif
+	struct cfg80211_bss *bss = NULL;
+
+	RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+	if (pwdev->iftype != NL80211_IFTYPE_STATION
+		#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+		&& pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT
+		#endif
+	)
+		return;
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) )
+		return;
+
+#ifdef CONFIG_P2P
+	if (pwdinfo->driver_interface == DRIVER_CFG80211) {
+		#if !RTW_P2P_GROUP_INTERFACE
+		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+			rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+			rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+			rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+			RTW_INFO("%s, role=%d, p2p_state=%d, pre_p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));
+		}
+		#endif
+	}
+#endif /* CONFIG_P2P */
+
+	if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) != true) {
+		WLAN_BSSID_EX  *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);
+		struct wlan_network *scanned = pmlmepriv->cur_network_scanned;
+
+		/* RTW_INFO(FUNC_ADPT_FMT" BSS not found\n", FUNC_ADPT_ARG(padapter)); */
+
+		if (scanned == NULL) {
+			rtw_warn_on(1);
+			goto check_bss;
+		}
+
+		if (!memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) 
+			&& !memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) 
+		) {
+			if (!rtw_cfg80211_inform_bss(padapter, scanned))
+				RTW_INFO(FUNC_ADPT_FMT" inform fail !!\n", FUNC_ADPT_ARG(padapter));
+			else {
+				/* RTW_INFO(FUNC_ADPT_FMT" inform success !!\n", FUNC_ADPT_ARG(padapter)); */
+			}
+		} else {
+			RTW_INFO("scanned: %s("MAC_FMT"), cur: %s("MAC_FMT")\n",
+				scanned->network.Ssid.Ssid, MAC_ARG(scanned->network.MacAddress),
+				pnetwork->Ssid.Ssid, MAC_ARG(pnetwork->MacAddress)
+			);
+			rtw_warn_on(1);
+		}
+	}
+
+check_bss:
+	if (!rtw_cfg80211_check_bss(padapter))
+		RTW_INFO(FUNC_ADPT_FMT" BSS not found !!\n", FUNC_ADPT_ARG(padapter));
+
+	if (rtw_to_roam(padapter) > 0) {
+		#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) || defined(COMPAT_KERNEL_RELEASE)
+		struct wiphy *wiphy = pwdev->wiphy;
+		struct ieee80211_channel *notify_channel;
+		u32 freq;
+		u16 channel = cur_network->network.Configuration.DSConfig;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
+		struct cfg80211_roam_info roam_info = {};
+#endif
+
+		freq = rtw_ch2freq(channel);
+		notify_channel = ieee80211_get_channel(wiphy, freq);
+		#endif
+
+		RTW_INFO(FUNC_ADPT_FMT" call cfg80211_roamed\n", FUNC_ADPT_ARG(padapter));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
+		roam_info.channel = notify_channel;
+		roam_info.bssid = cur_network->network.MacAddress;
+		roam_info.req_ie =
+			pmlmepriv->assoc_req+sizeof(struct rtw_ieee80211_hdr_3addr)+2;
+		roam_info.req_ie_len =
+			pmlmepriv->assoc_req_len-sizeof(struct rtw_ieee80211_hdr_3addr)-2;
+		roam_info.resp_ie =
+			pmlmepriv->assoc_rsp+sizeof(struct rtw_ieee80211_hdr_3addr)+6;
+		roam_info.resp_ie_len =
+			pmlmepriv->assoc_rsp_len-sizeof(struct rtw_ieee80211_hdr_3addr)-6;
+		cfg80211_roamed(padapter->pnetdev, &roam_info, GFP_ATOMIC);
+#else
+		cfg80211_roamed(padapter->pnetdev
+			#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) || defined(COMPAT_KERNEL_RELEASE)
+			, notify_channel
+			#endif
+			, cur_network->network.MacAddress
+			, pmlmepriv->assoc_req + sizeof(struct rtw_ieee80211_hdr_3addr) + 2
+			, pmlmepriv->assoc_req_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 2
+			, pmlmepriv->assoc_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 6
+			, pmlmepriv->assoc_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 6
+			, GFP_ATOMIC);
+#endif
+#ifdef CONFIG_RTW_80211R
+		if ((rtw_to_roam(padapter) > 0) && rtw_chk_ft_flags(padapter, RTW_FT_SUPPORTED))
+			rtw_set_ft_status(padapter, RTW_FT_ASSOCIATED_STA);
+#endif
+	} else {
+		#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) || defined(COMPAT_KERNEL_RELEASE)
+		RTW_INFO("pwdev->sme_state(b)=%d\n", pwdev->sme_state);
+		#endif
+		cfg80211_connect_result(padapter->pnetdev, cur_network->network.MacAddress
+			, pmlmepriv->assoc_req + sizeof(struct rtw_ieee80211_hdr_3addr) + 2
+			, pmlmepriv->assoc_req_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 2
+			, pmlmepriv->assoc_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 6
+			, pmlmepriv->assoc_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 6
+			, WLAN_STATUS_SUCCESS, GFP_ATOMIC);
+		#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) || defined(COMPAT_KERNEL_RELEASE)
+		RTW_INFO("pwdev->sme_state(a)=%d\n", pwdev->sme_state);
+		#endif
+	}
+}
+
+void rtw_cfg80211_indicate_disconnect(_adapter *padapter, u16 reason, u8 locally_generated)
+{
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct wireless_dev *pwdev = padapter->rtw_wdev;
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+#endif
+
+	RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+
+	/*always replace privated definitions with wifi reserved value 0*/
+	if ((reason == WLAN_REASON_ACTIVE_ROAM) || (reason == WLAN_REASON_JOIN_WRONG_CHANNEL) || (reason == WLAN_REASON_EXPIRATION_CHK))
+		reason = 0;
+
+	if (pwdev->iftype != NL80211_IFTYPE_STATION
+		#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+		&& pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT
+		#endif
+	)
+		return;
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) )
+		return;
+
+#ifdef CONFIG_P2P
+	if (pwdinfo->driver_interface == DRIVER_CFG80211) {
+		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+			rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+
+			#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+			if (pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
+			#endif
+				rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+
+			RTW_INFO("%s, role=%d, p2p_state=%d, pre_p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));
+		}
+	}
+#endif /* CONFIG_P2P */
+
+	#ifdef SUPPLICANT_RTK_VERSION_LOWER_THAN_JB42
+	if (!padapter->mlmepriv.not_indic_disco || padapter->ndev_unregistering) {
+	#else
+	{
+	#endif
+		#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) || defined(COMPAT_KERNEL_RELEASE)
+		RTW_INFO("pwdev->sme_state(b)=%d\n", pwdev->sme_state);
+
+		if (pwdev->sme_state == CFG80211_SME_CONNECTING)
+			cfg80211_connect_result(padapter->pnetdev, NULL, NULL, 0, NULL, 0,
+				WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_ATOMIC/*GFP_KERNEL*/);
+		else if (pwdev->sme_state == CFG80211_SME_CONNECTED) {
+			#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
+			cfg80211_disconnected(padapter->pnetdev, reason, NULL, 0, locally_generated, GFP_ATOMIC);
+			#else
+			cfg80211_disconnected(padapter->pnetdev, 0, NULL, 0, GFP_ATOMIC);
+			#endif
+		}
+		RTW_INFO("pwdev->sme_state(a)=%d\n", pwdev->sme_state);
+		#else
+
+		if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
+			#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
+			RTW_INFO(FUNC_ADPT_FMT" call cfg80211_disconnected\n", FUNC_ADPT_ARG(padapter));
+			cfg80211_disconnected(padapter->pnetdev, reason, NULL, 0, locally_generated, GFP_ATOMIC);
+			#else
+			RTW_INFO(FUNC_ADPT_FMT" call cfg80211_disconnected\n", FUNC_ADPT_ARG(padapter));
+			cfg80211_disconnected(padapter->pnetdev, 0, NULL, 0, GFP_ATOMIC);
+			#endif
+		} else {
+			RTW_INFO(FUNC_ADPT_FMT" call cfg80211_connect_result\n", FUNC_ADPT_ARG(padapter));
+			cfg80211_connect_result(padapter->pnetdev, NULL, NULL, 0, NULL, 0,
+				WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_ATOMIC);
+		}
+		#endif
+	}
+}
+
+
+#ifdef CONFIG_AP_MODE
+static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
+{
+	int ret = 0;
+	u32 wep_key_idx, wep_key_len, wep_total_len;
+	struct sta_info *psta = NULL, *pbcmc_sta = NULL;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct security_priv *psecuritypriv = &(padapter->securitypriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	RTW_INFO("%s\n", __func__);
+
+	param->u.crypt.err = 0;
+	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+	/* sizeof(struct ieee_param) = 64 bytes; */
+	/* if (param_len !=  (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) */
+	if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
+		ret =  -EINVAL;
+		goto exit;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		if (param->u.crypt.idx >= WEP_KEYS
+#ifdef CONFIG_IEEE80211W
+			&& param->u.crypt.idx > BIP_MAX_KEYID
+#endif /* CONFIG_IEEE80211W */
+		) {
+			ret = -EINVAL;
+			goto exit;
+		}
+	} else {
+		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+		if (!psta) {
+			/* ret = -EINVAL; */
+			RTW_INFO("rtw_set_encryption(), sta has already been removed or never been added\n");
+			goto exit;
+		}
+	}
+
+	if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
+		/* todo:clear default encryption keys */
+
+		RTW_INFO("clear default encryption keys, keyid=%d\n", param->u.crypt.idx);
+
+		goto exit;
+	}
+
+
+	if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
+		RTW_INFO("r871x_set_encryption, crypt.alg = WEP\n");
+
+		wep_key_idx = param->u.crypt.idx;
+		wep_key_len = param->u.crypt.key_len;
+
+		RTW_INFO("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
+
+		if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
+			ret = -EINVAL;
+			goto exit;
+		}
+
+		if (wep_key_len > 0)
+			wep_key_len = wep_key_len <= 5 ? 5 : 13;
+
+		if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
+			/* wep default key has not been set, so use this key index as default key. */
+
+			psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
+			psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
+			psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+			psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+			if (wep_key_len == 13) {
+				psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+				psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+			}
+
+			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
+		}
+
+		memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), param->u.crypt.key, wep_key_len);
+
+		psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;
+
+		rtw_ap_set_wep_key(padapter, param->u.crypt.key, wep_key_len, wep_key_idx, 1);
+
+		goto exit;
+
+	}
+
+
+	if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /* group key */
+		if (param->u.crypt.set_tx == 0) { /* group key */
+			if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+				RTW_INFO("%s, set group_key, WEP\n", __func__);
+
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+				psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+				if (param->u.crypt.key_len == 13)
+					psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+
+			} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+				RTW_INFO("%s, set group_key, TKIP\n", __func__);
+
+				psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+				/* DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len); */
+				/* set mic key */
+				memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
+				memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
+
+				psecuritypriv->busetkipkey = true;
+
+			} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+				RTW_INFO("%s, set group_key, CCMP\n", __func__);
+
+				psecuritypriv->dot118021XGrpPrivacy = _AES_;
+
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+			}
+#ifdef CONFIG_IEEE80211W
+			else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
+				int no;
+
+				RTW_INFO("BIP key_len=%d , index=%d\n", param->u.crypt.key_len, param->u.crypt.idx);
+				/* save the IGTK key, length 16 bytes */
+				memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+				/* RTW_INFO("IGTK key below:\n");
+				for(no=0;no<16;no++)
+					printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
+				RTW_INFO("\n"); */
+				padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
+				padapter->securitypriv.binstallBIPkey = true;
+				RTW_INFO(" ~~~~set sta key:IGKT\n");
+				goto exit;
+			}
+#endif /* CONFIG_IEEE80211W */
+			else {
+				RTW_INFO("%s, set group_key, none\n", __func__);
+
+				psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+			}
+
+			psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
+
+			psecuritypriv->binstallGrpkey = true;
+
+			psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* !!! */
+
+			rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
+
+			pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+			if (pbcmc_sta) {
+				pbcmc_sta->ieee8021x_blocked = false;
+				pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy			 */
+			}
+
+		}
+
+		goto exit;
+
+	}
+
+	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
+		if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+			if (param->u.crypt.set_tx == 1) { /* pairwise key */
+				memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+					RTW_INFO("%s, set pairwise key, WEP\n", __func__);
+
+					psta->dot118021XPrivacy = _WEP40_;
+					if (param->u.crypt.key_len == 13)
+						psta->dot118021XPrivacy = _WEP104_;
+				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+					RTW_INFO("%s, set pairwise key, TKIP\n", __func__);
+
+					psta->dot118021XPrivacy = _TKIP_;
+
+					/* DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len); */
+					/* set mic key */
+					memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
+					memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
+
+					psecuritypriv->busetkipkey = true;
+
+				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+
+					RTW_INFO("%s, set pairwise key, CCMP\n", __func__);
+
+					psta->dot118021XPrivacy = _AES_;
+				} else {
+					RTW_INFO("%s, set pairwise key, none\n", __func__);
+
+					psta->dot118021XPrivacy = _NO_PRIVACY_;
+				}
+
+				rtw_ap_set_pairwise_key(padapter, psta);
+
+				psta->ieee8021x_blocked = false;
+
+				psta->bpairwise_key_installed = true;
+
+			} else { /* group key??? */
+				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+					psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+					if (param->u.crypt.key_len == 13)
+						psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+					psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+					/* DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len); */
+					/* set mic key */
+					memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
+					memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
+
+					psecuritypriv->busetkipkey = true;
+
+				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+					psecuritypriv->dot118021XGrpPrivacy = _AES_;
+
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+				} else
+					psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+
+				psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
+
+				psecuritypriv->binstallGrpkey = true;
+
+				psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* !!! */
+
+				rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
+
+				pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+				if (pbcmc_sta) {
+					pbcmc_sta->ieee8021x_blocked = false;
+					pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy			 */
+				}
+
+			}
+
+		}
+
+	}
+
+exit:
+
+	return ret;
+
+}
+#endif
+
+static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
+{
+	int ret = 0;
+	u32 wep_key_idx, wep_key_len, wep_total_len;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_P2P */
+
+
+	RTW_INFO("%s\n", __func__);
+
+	param->u.crypt.err = 0;
+	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+	if (param_len < (u32)((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) {
+		ret =  -EINVAL;
+		goto exit;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		if (param->u.crypt.idx >= WEP_KEYS
+#ifdef CONFIG_IEEE80211W
+			&& param->u.crypt.idx > BIP_MAX_KEYID
+#endif /* CONFIG_IEEE80211W */
+		) {
+			ret = -EINVAL;
+			goto exit;
+		}
+	} else {
+#ifdef CONFIG_WAPI_SUPPORT
+		if (strcmp(param->u.crypt.alg, "SMS4"))
+#endif
+		{
+			ret = -EINVAL;
+			goto exit;
+		}
+	}
+
+	if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+		RTW_INFO("wpa_set_encryption, crypt.alg = WEP\n");
+
+		wep_key_idx = param->u.crypt.idx;
+		wep_key_len = param->u.crypt.key_len;
+
+		if ((wep_key_idx > WEP_KEYS) || (wep_key_len <= 0)) {
+			ret = -EINVAL;
+			goto exit;
+		}
+
+		if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
+			/* wep default key has not been set, so use this key index as default key. */
+
+			wep_key_len = wep_key_len <= 5 ? 5 : 13;
+
+			psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
+			psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+			psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+			if (wep_key_len == 13) {
+				psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+				psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+			}
+
+			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
+		}
+
+		memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), param->u.crypt.key, wep_key_len);
+
+		psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;
+
+		rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0, true);
+
+		goto exit;
+	}
+
+	if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */
+		struct sta_info *psta, *pbcmc_sta;
+		struct sta_priv *pstapriv = &padapter->stapriv;
+
+		/* RTW_INFO("%s, : dot11AuthAlgrthm == dot11AuthAlgrthm_8021X\n", __func__); */
+
+		if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) ) { /* sta mode */
+#ifdef CONFIG_RTW_80211R
+			if ((rtw_to_roam(padapter) > 0) && rtw_chk_ft_flags(padapter, RTW_FT_SUPPORTED))
+				psta = rtw_get_stainfo(pstapriv, pmlmepriv->assoc_bssid);
+			else
+#endif
+				psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
+			if (psta == NULL) {
+				/* DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
+				RTW_INFO("%s, : Obtain Sta_info fail\n", __func__);
+			} else {
+				/* Jeff: don't disable ieee8021x_blocked while clearing key */
+				if (strcmp(param->u.crypt.alg, "none") != 0)
+					psta->ieee8021x_blocked = false;
+
+
+				if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
+				    (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
+					psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
+
+				if (param->u.crypt.set_tx == 1) { /* pairwise key */
+
+					RTW_INFO("%s, : param->u.crypt.set_tx ==1\n", __func__);
+
+					memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+					if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
+						/* DEBUG_ERR(("\nset key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len)); */
+						memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
+						memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
+
+						padapter->securitypriv.busetkipkey = false;
+						/* _set_timer(&padapter->securitypriv.tkip_timer, 50);						 */
+					}
+					psta->bpairwise_key_installed = true;
+#ifdef CONFIG_RTW_80211R
+					psta->ft_pairwise_key_installed = true;
+#endif
+					/* DEBUG_ERR((" param->u.crypt.key_len=%d\n", param->u.crypt.key_len)); */
+					RTW_INFO(" ~~~~set sta key:unicastkey\n");
+
+					rtw_setstakey_cmd(padapter, psta, UNICAST_KEY, true);
+				} else { /* group key */
+					if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0) {
+						memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key,
+							(param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+						memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
+						memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
+						padapter->securitypriv.binstallGrpkey = true;
+						if (param->u.crypt.idx < 4)
+							memcpy(padapter->securitypriv.iv_seq[param->u.crypt.idx], param->u.crypt.seq, 8);
+
+						/* DEBUG_ERR((" param->u.crypt.key_len=%d\n", param->u.crypt.key_len)); */
+						RTW_INFO(" ~~~~set sta key:groupkey\n");
+
+						padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
+						rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, true);
+					}
+#ifdef CONFIG_IEEE80211W
+					else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
+						int no;
+						/* RTW_INFO("BIP key_len=%d , index=%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx); */
+						/* save the IGTK key, length 16 bytes */
+						memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey,  param->u.crypt.key,
+							(param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+						/*RTW_INFO("IGTK key below:\n");
+						for(no=0;no<16;no++)
+							printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
+						RTW_INFO("\n");*/
+						padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
+						padapter->securitypriv.binstallBIPkey = true;
+						RTW_INFO(" ~~~~set sta key:IGKT\n");
+					}
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef CONFIG_P2P
+					if (pwdinfo->driver_interface == DRIVER_CFG80211) {
+						if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
+							rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);
+					}
+#endif /* CONFIG_P2P */
+
+				}
+			}
+
+			pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+			if (pbcmc_sta == NULL) {
+				/* DEBUG_ERR( ("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
+			} else {
+				/* Jeff: don't disable ieee8021x_blocked while clearing key */
+				if (strcmp(param->u.crypt.alg, "none") != 0)
+					pbcmc_sta->ieee8021x_blocked = false;
+
+				if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
+				    (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
+					pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
+			}
+		} else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { /* adhoc mode */
+		}
+	}
+
+#ifdef CONFIG_WAPI_SUPPORT
+	if (strcmp(param->u.crypt.alg, "SMS4") == 0) {
+		PRT_WAPI_T			pWapiInfo = &padapter->wapiInfo;
+		PRT_WAPI_STA_INFO	pWapiSta;
+		u8					WapiASUEPNInitialValueSrc[16] = {0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C} ;
+		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} ;
+
+		if (param->u.crypt.set_tx == 1) {
+			list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+				if (!memcmp(pWapiSta->PeerMacAddr, param->sta_addr, 6)) {
+					memcpy(pWapiSta->lastTxUnicastPN, WapiASUEPNInitialValueSrc, 16);
+
+					pWapiSta->wapiUsk.bSet = true;
+					memcpy(pWapiSta->wapiUsk.dataKey, param->u.crypt.key, 16);
+					memcpy(pWapiSta->wapiUsk.micKey, param->u.crypt.key + 16, 16);
+					pWapiSta->wapiUsk.keyId = param->u.crypt.idx ;
+					pWapiSta->wapiUsk.bTxEnable = true;
+
+					memcpy(pWapiSta->lastRxUnicastPNBEQueue, WapiAEPNInitialValueSrc, 16);
+					memcpy(pWapiSta->lastRxUnicastPNBKQueue, WapiAEPNInitialValueSrc, 16);
+					memcpy(pWapiSta->lastRxUnicastPNVIQueue, WapiAEPNInitialValueSrc, 16);
+					memcpy(pWapiSta->lastRxUnicastPNVOQueue, WapiAEPNInitialValueSrc, 16);
+					memcpy(pWapiSta->lastRxUnicastPN, WapiAEPNInitialValueSrc, 16);
+					pWapiSta->wapiUskUpdate.bTxEnable = false;
+					pWapiSta->wapiUskUpdate.bSet = false;
+
+					if (psecuritypriv->sw_encrypt == false || psecuritypriv->sw_decrypt == false) {
+						/* set unicast key for ASUE */
+						rtw_wapi_set_key(padapter, &pWapiSta->wapiUsk, pWapiSta, false, false);
+					}
+				}
+			}
+		} else {
+			list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+				if (!memcmp(pWapiSta->PeerMacAddr, get_bssid(pmlmepriv), 6)) {
+					pWapiSta->wapiMsk.bSet = true;
+					memcpy(pWapiSta->wapiMsk.dataKey, param->u.crypt.key, 16);
+					memcpy(pWapiSta->wapiMsk.micKey, param->u.crypt.key + 16, 16);
+					pWapiSta->wapiMsk.keyId = param->u.crypt.idx ;
+					pWapiSta->wapiMsk.bTxEnable = false;
+					if (!pWapiSta->bSetkeyOk)
+						pWapiSta->bSetkeyOk = true;
+					pWapiSta->bAuthenticateInProgress = false;
+
+					memcpy(pWapiSta->lastRxMulticastPN, WapiAEMultiCastPNInitialValueSrc, 16);
+
+					if (psecuritypriv->sw_decrypt == false) {
+						/* set rx broadcast key for ASUE */
+						rtw_wapi_set_key(padapter, &pWapiSta->wapiMsk, pWapiSta, true, false);
+					}
+				}
+
+			}
+		}
+	}
+#endif
+
+
+exit:
+
+	RTW_INFO("%s, ret=%d\n", __func__, ret);
+
+
+	return ret;
+}
+
+static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+	u8 key_index, bool pairwise, const u8 *mac_addr,
+#else	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) */
+	u8 key_index, const u8 *mac_addr,
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) */
+	struct key_params *params)
+{
+	char *alg_name;
+	u32 param_len;
+	struct ieee_param *param = NULL;
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct wireless_dev *rtw_wdev = padapter->rtw_wdev;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+#ifdef CONFIG_TDLS
+	struct sta_info *ptdls_sta;
+#endif /* CONFIG_TDLS */
+
+	RTW_INFO(FUNC_NDEV_FMT" adding key for %pM\n", FUNC_NDEV_ARG(ndev), mac_addr);
+	RTW_INFO("cipher=0x%x\n", params->cipher);
+	RTW_INFO("key_len=0x%x\n", params->key_len);
+	RTW_INFO("seq_len=0x%x\n", params->seq_len);
+	RTW_INFO("key_index=%d\n", key_index);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+	RTW_INFO("pairwise=%d\n", pairwise);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) */
+
+	param_len = sizeof(struct ieee_param) + params->key_len;
+	param = (struct ieee_param *)rtw_malloc(param_len);
+	if (param == NULL)
+		return -1;
+
+	memset(param, 0, param_len);
+
+	param->cmd = IEEE_CMD_SET_ENCRYPTION;
+	memset(param->sta_addr, 0xff, ETH_ALEN);
+
+	switch (params->cipher) {
+	case IW_AUTH_CIPHER_NONE:
+		/* todo: remove key */
+		/* remove = 1;	 */
+		alg_name = "none";
+		break;
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		alg_name = "WEP";
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		alg_name = "TKIP";
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		alg_name = "CCMP";
+		break;
+#ifdef CONFIG_IEEE80211W
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+		alg_name = "BIP";
+		break;
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_WAPI_SUPPORT
+	case WLAN_CIPHER_SUITE_SMS4:
+		alg_name = "SMS4";
+		if (pairwise == NL80211_KEYTYPE_PAIRWISE) {
+			if (key_index != 0 && key_index != 1) {
+				ret = -ENOTSUPP;
+				goto addkey_end;
+			}
+			memcpy((void *)param->sta_addr, (void *)mac_addr, ETH_ALEN);
+		} else
+			RTW_INFO("mac_addr is null\n");
+		RTW_INFO("rtw_wx_set_enc_ext: SMS4 case\n");
+		break;
+#endif
+
+	default:
+		ret = -ENOTSUPP;
+		goto addkey_end;
+	}
+
+	strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
+
+
+	if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
+		param->u.crypt.set_tx = 0; /* for wpa/wpa2 group key */
+	} else {
+		param->u.crypt.set_tx = 1; /* for wpa/wpa2 pairwise key */
+	}
+
+
+	/* param->u.crypt.idx = key_index - 1; */
+	param->u.crypt.idx = key_index;
+
+	if (params->seq_len && params->seq)
+		memcpy(param->u.crypt.seq, (u8 *)params->seq, params->seq_len);
+
+	if (params->key_len && params->key) {
+		param->u.crypt.key_len = params->key_len;
+		memcpy(param->u.crypt.key, (u8 *)params->key, params->key_len);
+	}
+
+	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) ) {
+#ifdef CONFIG_TDLS
+		if (rtw_tdls_is_driver_setup(padapter) == false && mac_addr) {
+			ptdls_sta = rtw_get_stainfo(&padapter->stapriv, (void *)mac_addr);
+			if (ptdls_sta != NULL && ptdls_sta->tdls_sta_state) {
+				memcpy(ptdls_sta->tpk.tk, params->key, params->key_len);
+				rtw_tdls_set_key(padapter, ptdls_sta);
+				goto addkey_end;
+			}
+		}
+#endif /* CONFIG_TDLS */
+
+		ret =  rtw_cfg80211_set_encryption(ndev, param, param_len);
+	} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) ) {
+#ifdef CONFIG_AP_MODE
+		if (mac_addr)
+			memcpy(param->sta_addr, (void *)mac_addr, ETH_ALEN);
+
+		ret = rtw_cfg80211_ap_set_encryption(ndev, param, param_len);
+#endif
+	} else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) 
+		|| check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) 
+	) {
+		/* RTW_INFO("@@@@@@@@@@ fw_state=0x%x, iftype=%d\n", pmlmepriv->fw_state, rtw_wdev->iftype); */
+		ret =  rtw_cfg80211_set_encryption(ndev, param, param_len);
+	} else
+		RTW_INFO("error! fw_state=0x%x, iftype=%d\n", pmlmepriv->fw_state, rtw_wdev->iftype);
+
+
+addkey_end:
+	if (param)
+		rtw_mfree((u8 *)param, param_len);
+
+	return ret;
+
+}
+
+static int cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+	u8 key_index, bool pairwise, const u8 *mac_addr,
+#else	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) */
+	u8 key_index, const u8 *mac_addr,
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) */
+	void *cookie,
+	void (*callback)(void *cookie, struct key_params *))
+{
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+	return 0;
+}
+
+static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+				u8 key_index, bool pairwise, const u8 *mac_addr)
+#else	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) */
+				u8 key_index, const u8 *mac_addr)
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) */
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+	RTW_INFO(FUNC_NDEV_FMT" key_index=%d\n", FUNC_NDEV_ARG(ndev), key_index);
+
+	if (key_index == psecuritypriv->dot11PrivacyKeyIndex) {
+		/* clear the flag of wep default key set. */
+		psecuritypriv->bWepDefaultKeyIdxSet = 0;
+	}
+
+	return 0;
+}
+
+static int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
+	struct net_device *ndev, u8 key_index
+	#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
+	, bool unicast, bool multicast
+	#endif
+)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+#define SET_DEF_KEY_PARAM_FMT " key_index=%d"
+#define SET_DEF_KEY_PARAM_ARG , key_index
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
+	#define SET_DEF_KEY_PARAM_FMT_2_6_38 ", unicast=%d, multicast=%d"
+	#define SET_DEF_KEY_PARAM_ARG_2_6_38 , unicast, multicast
+#else
+	#define SET_DEF_KEY_PARAM_FMT_2_6_38 ""
+	#define SET_DEF_KEY_PARAM_ARG_2_6_38
+#endif
+
+	RTW_INFO(FUNC_NDEV_FMT
+		SET_DEF_KEY_PARAM_FMT
+		SET_DEF_KEY_PARAM_FMT_2_6_38
+		"\n", FUNC_NDEV_ARG(ndev)
+		SET_DEF_KEY_PARAM_ARG
+		SET_DEF_KEY_PARAM_ARG_2_6_38
+	);
+
+	if ((key_index < WEP_KEYS) && ((psecuritypriv->dot11PrivacyAlgrthm == _WEP40_) || (psecuritypriv->dot11PrivacyAlgrthm == _WEP104_))) { /* set wep default key */
+		psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
+
+		psecuritypriv->dot11PrivacyKeyIndex = key_index;
+
+		psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+		psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+		if (psecuritypriv->dot11DefKeylen[key_index] == 13) {
+			psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+			psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+		}
+
+		psecuritypriv->bWepDefaultKeyIdxSet = 1; /* set the flag to represent that wep default key has been set */
+	}
+
+	return 0;
+
+}
+#if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
+static int cfg80211_rtw_set_rekey_data(struct wiphy *wiphy,
+	struct net_device *ndev,
+	struct cfg80211_gtk_rekey_data *data)
+{
+	/*int i;*/
+	struct sta_info *psta;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct mlme_priv   *pmlmepriv = &padapter->mlmepriv;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct security_priv *psecuritypriv = &(padapter->securitypriv);
+
+	psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
+	if (psta == NULL) {
+		RTW_INFO("%s, : Obtain Sta_info fail\n", __func__);
+		return -1;
+	}
+
+	memcpy(psta->kek, data->kek, NL80211_KEK_LEN);
+	/*printk("\ncfg80211_rtw_set_rekey_data KEK:");
+	for(i=0;i<NL80211_KEK_LEN; i++)
+		printk(" %02x ", psta->kek[i]);*/
+	memcpy(psta->kck, data->kck, NL80211_KCK_LEN);
+	/*printk("\ncfg80211_rtw_set_rekey_data KCK:");
+	for(i=0;i<NL80211_KCK_LEN; i++)
+		printk(" %02x ", psta->kck[i]);*/
+	memcpy(psta->replay_ctr, data->replay_ctr, NL80211_REPLAY_CTR_LEN);
+	psecuritypriv->binstallKCK_KEK = true;
+	/*printk("\nREPLAY_CTR: ");
+	for(i=0;i<RTW_REPLAY_CTR_LEN; i++)
+		printk(" %02x ", psta->replay_ctr[i]);*/
+
+	return 0;
+}
+#endif /*CONFIG_GTK_OL*/
+static int cfg80211_rtw_get_station(struct wiphy *wiphy,
+	struct net_device *ndev,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))
+	u8 *mac,
+#else
+	const u8 *mac,
+#endif
+	struct station_info *sinfo)
+{
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct sta_info *psta = NULL;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	sinfo->filled = 0;
+
+	if (!mac) {
+		RTW_INFO(FUNC_NDEV_FMT" mac==%p\n", FUNC_NDEV_ARG(ndev), mac);
+		ret = -ENOENT;
+		goto exit;
+	}
+
+	psta = rtw_get_stainfo(pstapriv, (u8 *)mac);
+	if (psta == NULL) {
+		RTW_INFO("%s, sta_info is null\n", __func__);
+		ret = -ENOENT;
+		goto exit;
+	}
+
+#ifdef CONFIG_DEBUG_CFG80211
+	RTW_INFO(FUNC_NDEV_FMT" mac="MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(mac));
+#endif
+
+	/* for infra./P2PClient mode */
+	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
+		&& check_fwstate(pmlmepriv, _FW_LINKED)
+	) {
+		struct wlan_network  *cur_network = &(pmlmepriv->cur_network);
+
+		if (!memcmp((u8 *)mac, cur_network->network.MacAddress, ETH_ALEN) == false) {
+			RTW_INFO("%s, mismatch bssid="MAC_FMT"\n", __func__, MAC_ARG(cur_network->network.MacAddress));
+			ret = -ENOENT;
+			goto exit;
+		}
+
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);
+
+		sinfo->filled |= STATION_INFO_TX_BITRATE;
+		sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter);
+
+		sinfo->filled |= STATION_INFO_RX_PACKETS;
+		sinfo->rx_packets = sta_rx_data_pkts(psta);
+
+		sinfo->filled |= STATION_INFO_TX_PACKETS;
+		sinfo->tx_packets = psta->sta_stats.tx_pkts;
+
+        sinfo->filled |= STATION_INFO_TX_FAILED;
+        sinfo->tx_failed = psta->sta_stats.tx_fail_cnt;
+
+	}
+
+	/* for Ad-Hoc/AP mode */
+	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)
+		|| check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)
+		|| check_fwstate(pmlmepriv, WIFI_AP_STATE))
+		&& check_fwstate(pmlmepriv, _FW_LINKED)
+	) {
+		/* TODO: should acquire station info... */
+	}
+
+exit:
+	return ret;
+}
+
+extern int netdev_open(struct net_device *pnetdev);
+
+static int cfg80211_rtw_change_iface(struct wiphy *wiphy,
+				     struct net_device *ndev,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
+				     enum nl80211_iftype type, u32 *flags,
+#else
+				     enum nl80211_iftype type,
+#endif
+				     struct vif_params *params)
+{
+	enum nl80211_iftype old_type;
+	NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct wireless_dev *rtw_wdev = padapter->rtw_wdev;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+	u8 is_p2p = false;
+#endif
+	int ret = 0;
+	u8 change = false;
+
+	RTW_INFO(FUNC_NDEV_FMT" type=%d, hw_port:%d\n", FUNC_NDEV_ARG(ndev), type, padapter->hw_port);
+
+	if (adapter_to_dvobj(padapter)->processing_dev_remove ) {
+		ret = -EPERM;
+		goto exit;
+	}
+
+
+	RTW_INFO(FUNC_NDEV_FMT" call netdev_open\n", FUNC_NDEV_ARG(ndev));
+	if (netdev_open(ndev) != 0) {
+		RTW_INFO(FUNC_NDEV_FMT" call netdev_open fail\n", FUNC_NDEV_ARG(ndev));
+		ret = -EPERM;
+		goto exit;
+	}
+
+
+	if (_FAIL == rtw_pwr_wakeup(padapter)) {
+		RTW_INFO(FUNC_NDEV_FMT" call rtw_pwr_wakeup fail\n", FUNC_NDEV_ARG(ndev));
+		ret = -EPERM;
+		goto exit;
+	}
+
+	old_type = rtw_wdev->iftype;
+	RTW_INFO(FUNC_NDEV_FMT" old_iftype=%d, new_iftype=%d\n",
+		FUNC_NDEV_ARG(ndev), old_type, type);
+
+	if (old_type != type) {
+		change = true;
+		pmlmeext->action_public_rxseq = 0xffff;
+		pmlmeext->action_public_dialog_token = 0xff;
+	}
+
+	/* initial default type */
+	ndev->type = ARPHRD_ETHER;
+
+	/*
+	 * Disable Power Save in moniter mode,
+	 * and enable it after leaving moniter mode.
+	 */
+	if (type == NL80211_IFTYPE_MONITOR) {
+		rtw_ps_deny(padapter, PS_DENY_MONITOR_MODE);
+		LeaveAllPowerSaveMode(padapter);
+	} else if (old_type == NL80211_IFTYPE_MONITOR) {
+		/* driver in moniter mode in last time */
+		rtw_ps_deny_cancel(padapter, PS_DENY_MONITOR_MODE);
+	}
+
+	switch (type) {
+	case NL80211_IFTYPE_ADHOC:
+		networkType = Ndis802_11IBSS;
+		break;
+
+	#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
+	case NL80211_IFTYPE_P2P_CLIENT:
+		is_p2p = true;
+		__attribute__ ((__fallthrough__));/* FALL THRU */
+	#endif
+	case NL80211_IFTYPE_STATION:
+		networkType = Ndis802_11Infrastructure;
+
+		#ifdef CONFIG_P2P
+		if (change && pwdinfo->driver_interface == DRIVER_CFG80211) {
+			if (is_p2p )
+				rtw_p2p_enable(padapter, P2P_ROLE_CLIENT);
+			#if !RTW_P2P_GROUP_INTERFACE
+			else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)
+					|| rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)
+			) {
+				/* it means remove GC/GO and change mode from GC/GO to station(P2P DEVICE) */
+				rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+			}
+			#endif
+		}
+		#endif /* CONFIG_P2P */
+
+		break;
+
+	#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
+	case NL80211_IFTYPE_P2P_GO:
+		is_p2p = true;
+		__attribute__ ((__fallthrough__));/* FALL THRU */
+	#endif
+	case NL80211_IFTYPE_AP:
+		networkType = Ndis802_11APMode;
+
+		#ifdef CONFIG_P2P
+		if (change && pwdinfo->driver_interface == DRIVER_CFG80211) {
+			if (is_p2p )
+				rtw_p2p_enable(padapter, P2P_ROLE_GO);
+			#if !RTW_P2P_GROUP_INTERFACE
+			else if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+				/* it means P2P Group created, we will be GO and change mode from  P2P DEVICE to AP(GO) */
+				rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+			}
+			#endif
+		}
+		#endif /* CONFIG_P2P */
+
+		break;
+
+	case NL80211_IFTYPE_MONITOR:
+		networkType = Ndis802_11Monitor;
+		ndev->type = ARPHRD_IEEE80211_RADIOTAP; /* IEEE 802.11 + radiotap header : 803 */
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		goto exit;
+	}
+
+	rtw_wdev->iftype = type;
+
+	if (rtw_set_802_11_infrastructure_mode(padapter, networkType) == false) {
+		rtw_wdev->iftype = old_type;
+		ret = -EPERM;
+		goto exit;
+	}
+
+	rtw_setopmode_cmd(padapter, networkType, true);
+
+exit:
+
+	RTW_INFO(FUNC_NDEV_FMT" ret:%d\n", FUNC_NDEV_ARG(ndev), ret);
+	return ret;
+}
+
+void rtw_cfg80211_indicate_scan_done(_adapter *adapter, bool aborted)
+{
+	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
+	unsigned long	irqL;
+
+#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)
+	struct cfg80211_scan_info info;
+
+	memset(&info, 0, sizeof(info));
+	info.aborted = aborted;
+#endif
+
+	_enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
+	if (pwdev_priv->scan_request != NULL) {
+		#ifdef CONFIG_DEBUG_CFG80211
+		RTW_INFO("%s with scan req\n", __func__);
+		#endif
+
+		/* avoid WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); */
+		if (pwdev_priv->scan_request->wiphy != pwdev_priv->rtw_wdev->wiphy)
+			RTW_INFO("error wiphy compare\n");
+		else
+#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)
+			cfg80211_scan_done(pwdev_priv->scan_request, &info);
+#else
+			cfg80211_scan_done(pwdev_priv->scan_request, aborted);
+#endif
+
+		pwdev_priv->scan_request = NULL;
+	} else {
+		#ifdef CONFIG_DEBUG_CFG80211
+		RTW_INFO("%s without scan req\n", __func__);
+		#endif
+	}
+	_exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
+}
+
+u32 rtw_cfg80211_wait_scan_req_empty(_adapter *adapter, u32 timeout_ms)
+{
+	struct rtw_wdev_priv *wdev_priv = adapter_wdev_data(adapter);
+	u8 empty = false;
+	u32 start;
+	u32 pass_ms;
+
+	start = jiffies;
+
+	while (rtw_get_passing_time_ms(start) <= timeout_ms) {
+
+		if (RTW_CANNOT_RUN(adapter))
+			break;
+
+		if (!wdev_priv->scan_request) {
+			empty = true;
+			break;
+		}
+
+		rtw_msleep_os(10);
+	}
+
+	pass_ms = rtw_get_passing_time_ms(start);
+
+	if (empty == false && pass_ms > timeout_ms)
+		RTW_INFO(FUNC_ADPT_FMT" pass_ms:%u, timeout\n"
+			, FUNC_ADPT_ARG(adapter), pass_ms);
+
+	return pass_ms;
+}
+
+void rtw_cfg80211_unlink_bss(_adapter *padapter, struct wlan_network *pnetwork)
+{
+	struct wireless_dev *pwdev = padapter->rtw_wdev;
+	struct wiphy *wiphy = pwdev->wiphy;
+	struct cfg80211_bss *bss = NULL;
+	WLAN_BSSID_EX select_network = pnetwork->network;
+
+	bss = cfg80211_get_bss(wiphy, NULL/*notify_channel*/,
+		select_network.MacAddress, select_network.Ssid.Ssid,
+		select_network.Ssid.SsidLength,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+		select_network.InfrastructureMode == Ndis802_11Infrastructure?IEEE80211_BSS_TYPE_ESS:IEEE80211_BSS_TYPE_IBSS,
+		IEEE80211_PRIVACY(select_network.Privacy));
+#else
+		select_network.InfrastructureMode == Ndis802_11Infrastructure?WLAN_CAPABILITY_ESS:WLAN_CAPABILITY_IBSS,
+		select_network.InfrastructureMode == Ndis802_11Infrastructure?WLAN_CAPABILITY_ESS:WLAN_CAPABILITY_IBSS);
+#endif
+
+	if (bss) {
+		cfg80211_unlink_bss(wiphy, bss);
+		RTW_INFO("%s(): cfg80211_unlink %s!! () ", __func__, select_network.Ssid.Ssid);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+		cfg80211_put_bss(padapter->rtw_wdev->wiphy, bss);
+#else
+		cfg80211_put_bss(bss);
+#endif
+	}
+	return;
+}
+
+/* if target wps scan ongoing, target_ssid is filled */
+static int rtw_cfg80211_is_target_wps_scan(struct cfg80211_scan_request *scan_req, struct cfg80211_ssid *target_ssid)
+{
+	int ret = 0;
+
+	if (scan_req->n_ssids != 1
+		|| scan_req->ssids[0].ssid_len == 0
+		|| scan_req->n_channels != 1
+	)
+		goto exit;
+
+	/* under target WPS scan */
+	memcpy(target_ssid, scan_req->ssids, sizeof(struct cfg80211_ssid));
+	ret = 1;
+
+exit:
+	return ret;
+}
+
+static void _rtw_cfg80211_surveydone_event_callback(_adapter *padapter, struct cfg80211_scan_request *scan_req)
+{
+	unsigned long	irqL;
+	_list					*plist, *phead;
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	_queue				*queue	= &(pmlmepriv->scanned_queue);
+	struct	wlan_network	*pnetwork = NULL;
+	u32 cnt = 0;
+	u32 wait_for_surveydone;
+	sint wait_status;
+	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
+	struct cfg80211_ssid target_ssid;
+	u8 target_wps_scan = 0;
+
+#ifdef CONFIG_DEBUG_CFG80211
+	RTW_INFO("%s\n", __func__);
+#endif
+
+	if (scan_req)
+		target_wps_scan = rtw_cfg80211_is_target_wps_scan(scan_req, &target_ssid);
+	else {
+		_enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
+		if (pwdev_priv->scan_request != NULL)
+			target_wps_scan = rtw_cfg80211_is_target_wps_scan(pwdev_priv->scan_request, &target_ssid);
+		_exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
+	}
+
+	_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) )
+			break;
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+
+		/* report network only if the current channel set contains the channel to which this network belongs */
+		if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0
+			&& rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) 
+			&& rtw_validate_ssid(&(pnetwork->network.Ssid))
+		) {
+			if (target_wps_scan)
+				rtw_cfg80211_clear_wps_sr_of_non_target_bss(padapter, pnetwork, &target_ssid);
+			rtw_cfg80211_inform_bss(padapter, pnetwork);
+		}
+		plist = get_next(plist);
+
+	}
+
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+}
+
+inline void rtw_cfg80211_surveydone_event_callback(_adapter *padapter)
+{
+	_rtw_cfg80211_surveydone_event_callback(padapter, NULL);
+}
+
+static int rtw_cfg80211_set_probe_req_wpsp2pie(_adapter *padapter, char *buf, int len)
+{
+	int ret = 0;
+	uint wps_ielen = 0;
+	u8 *wps_ie;
+	u32	p2p_ielen = 0;
+	u8 *p2p_ie;
+	u32	wfd_ielen = 0;
+	u8 *wfd_ie;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+#ifdef CONFIG_DEBUG_CFG80211
+	RTW_INFO("%s, ielen=%d\n", __func__, len);
+#endif
+
+	if (len > 0) {
+		wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen);
+		if (wps_ie) {
+			#ifdef CONFIG_DEBUG_CFG80211
+			RTW_INFO("probe_req_wps_ielen=%d\n", wps_ielen);
+			#endif
+
+			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;
+			}
+
+			pmlmepriv->wps_probe_req_ie = rtw_malloc(wps_ielen);
+			if (pmlmepriv->wps_probe_req_ie == NULL) {
+				RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+				return -EINVAL;
+
+			}
+			memcpy(pmlmepriv->wps_probe_req_ie, wps_ie, wps_ielen);
+			pmlmepriv->wps_probe_req_ie_len = wps_ielen;
+		}
+
+		/* buf += wps_ielen; */
+		/* len -= wps_ielen; */
+
+		#ifdef CONFIG_P2P
+		p2p_ie = rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen);
+		if (p2p_ie) {
+			struct wifidirect_info *wdinfo = &padapter->wdinfo;
+			u32 attr_contentlen = 0;
+			u8 listen_ch_attr[5];
+
+			#ifdef CONFIG_DEBUG_CFG80211
+			RTW_INFO("probe_req_p2p_ielen=%d\n", p2p_ielen);
+			#endif
+
+			if (pmlmepriv->p2p_probe_req_ie) {
+				u32 free_len = pmlmepriv->p2p_probe_req_ie_len;
+				pmlmepriv->p2p_probe_req_ie_len = 0;
+				rtw_mfree(pmlmepriv->p2p_probe_req_ie, free_len);
+				pmlmepriv->p2p_probe_req_ie = NULL;
+			}
+
+			pmlmepriv->p2p_probe_req_ie = rtw_malloc(p2p_ielen);
+			if (pmlmepriv->p2p_probe_req_ie == NULL) {
+				RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+				return -EINVAL;
+
+			}
+			memcpy(pmlmepriv->p2p_probe_req_ie, p2p_ie, p2p_ielen);
+			pmlmepriv->p2p_probe_req_ie_len = p2p_ielen;
+
+			if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, (u8 *)listen_ch_attr, (uint *) &attr_contentlen)
+				&& attr_contentlen == 5) {
+				if (wdinfo->listen_channel !=  listen_ch_attr[4]) {
+					RTW_INFO(FUNC_ADPT_FMT" listen channel - country:%c%c%c, class:%u, ch:%u\n",
+						FUNC_ADPT_ARG(padapter), listen_ch_attr[0], listen_ch_attr[1], listen_ch_attr[2],
+						listen_ch_attr[3], listen_ch_attr[4]);
+					wdinfo->listen_channel = listen_ch_attr[4];
+				}
+			}
+		}
+		#endif /* CONFIG_P2P */
+
+		#ifdef CONFIG_WFD
+		wfd_ie = rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen);
+		if (wfd_ie) {
+			#ifdef CONFIG_DEBUG_CFG80211
+			RTW_INFO("probe_req_wfd_ielen=%d\n", wfd_ielen);
+			#endif
+
+			if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_PROBE_REQ_IE, wfd_ie, wfd_ielen) != _SUCCESS)
+				return -EINVAL;
+		}
+		#endif /* CONFIG_WFD */
+	}
+
+	return ret;
+
+}
+
+#ifdef CONFIG_CONCURRENT_MODE
+u8 rtw_cfg80211_scan_via_buddy(_adapter *padapter, struct cfg80211_scan_request *request)
+{
+	int i;
+	u8 ret = false;
+	_adapter *iface = NULL;
+	unsigned long	irqL;
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		struct mlme_priv *buddy_mlmepriv;
+		struct rtw_wdev_priv *buddy_wdev_priv;
+
+		iface = dvobj->padapters[i];
+		if (iface == NULL)
+			continue;
+
+		if (iface == padapter)
+			continue;
+
+		if (rtw_is_adapter_up(iface) == false)
+			continue;
+
+		buddy_mlmepriv = &iface->mlmepriv;
+		if (!check_fwstate(buddy_mlmepriv, _FW_UNDER_SURVEY))
+			continue;
+
+		buddy_wdev_priv = adapter_wdev_data(iface);
+		_enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
+		_enter_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL);
+		if (buddy_wdev_priv->scan_request) {
+			pmlmepriv->scanning_via_buddy_intf = true;
+			_enter_critical_bh(&pmlmepriv->lock, &irqL);
+			set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
+			_exit_critical_bh(&pmlmepriv->lock, &irqL);
+			pwdev_priv->scan_request = request;
+			ret = true;
+		}
+		_exit_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL);
+		_exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
+
+		if (ret )
+			goto exit;
+	}
+
+exit:
+	return ret;
+}
+
+void rtw_cfg80211_indicate_scan_done_for_buddy(_adapter *padapter, bool bscan_aborted)
+{
+	int i;
+	u8 ret = 0;
+	_adapter *iface = NULL;
+	unsigned long	irqL;
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct mlme_priv *mlmepriv;
+	struct rtw_wdev_priv *wdev_priv;
+	bool indicate_buddy_scan;
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		iface = dvobj->padapters[i];
+		if ((iface) && rtw_is_adapter_up(iface)) {
+
+			if (iface == padapter)
+				continue;
+
+			mlmepriv = &(iface->mlmepriv);
+			wdev_priv = adapter_wdev_data(iface);
+
+			indicate_buddy_scan = false;
+			_enter_critical_bh(&wdev_priv->scan_req_lock, &irqL);
+			if (wdev_priv->scan_request && mlmepriv->scanning_via_buddy_intf ) {
+				mlmepriv->scanning_via_buddy_intf = false;
+				clr_fwstate(mlmepriv, _FW_UNDER_SURVEY);
+				indicate_buddy_scan = true;
+			}
+			_exit_critical_bh(&wdev_priv->scan_req_lock, &irqL);
+
+			if (indicate_buddy_scan ) {
+				rtw_cfg80211_surveydone_event_callback(iface);
+				rtw_indicate_scan_done(iface, bscan_aborted);
+			}
+
+		}
+	}
+}
+#endif /* CONFIG_CONCURRENT_MODE */
+
+static int cfg80211_rtw_scan(struct wiphy *wiphy
+	#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
+	, struct net_device *ndev
+	#endif
+	, struct cfg80211_scan_request *request)
+{
+	int i, chan_num = 0;
+	u8 _status = false;
+	int ret = 0;
+	NDIS_802_11_SSID ssid[RTW_SSID_SCAN_AMOUNT];
+	struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
+	struct rtw_ieee80211_channel *pch;
+	unsigned long	irqL;
+	u8 *wps_ie = NULL;
+	uint wps_ielen = 0;
+	u8 *p2p_ie = NULL;
+	uint p2p_ielen = 0;
+	u8 survey_times = 3;
+	u8 survey_times_for_one_ch = 6;
+	struct cfg80211_ssid *ssids = request->ssids;
+	int social_channel = 0, j = 0;
+	bool need_indicate_scan_done = false;
+	bool ps_denied = false;
+
+	_adapter *padapter;
+	struct wireless_dev *wdev;
+	struct rtw_wdev_priv *pwdev_priv;
+	struct mlme_priv *pmlmepriv;
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo;
+#endif /* CONFIG_P2P */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	wdev = request->wdev;
+	#if defined(RTW_DEDICATED_P2P_DEVICE)
+	if (wdev == wiphy_to_pd_wdev(wiphy))
+		padapter = wiphy_to_adapter(wiphy);
+	else
+	#endif
+	if (wdev_to_ndev(wdev))
+		padapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));
+	else {
+		ret = -EINVAL;
+		goto exit;
+	}
+#else
+	if (ndev == NULL) {
+		ret = -EINVAL;
+		goto exit;
+	}
+	padapter = (_adapter *)rtw_netdev_priv(ndev);
+	wdev = ndev_to_wdev(ndev);
+#endif
+
+	pwdev_priv = adapter_wdev_data(padapter);
+	pmlmepriv = &padapter->mlmepriv;
+#ifdef CONFIG_P2P
+	pwdinfo = &(padapter->wdinfo);
+#endif /* CONFIG_P2P */
+
+	RTW_INFO(FUNC_ADPT_FMT"%s\n", FUNC_ADPT_ARG(padapter)
+		, wdev == wiphy_to_pd_wdev(wiphy) ? " PD" : "");
+
+#ifdef CONFIG_MP_INCLUDED
+	if (rtw_mi_mp_mode_check(padapter)) {
+		RTW_INFO("MP mode block Scan request\n");
+		ret = -EPERM;
+		goto exit;
+	}
+#endif
+
+	if (adapter_wdev_data(padapter)->block_scan ) {
+		RTW_INFO(FUNC_ADPT_FMT" wdev_priv.block_scan is set\n", FUNC_ADPT_ARG(padapter));
+		need_indicate_scan_done = true;
+		goto check_need_indicate_scan_done;
+	}
+
+	rtw_ps_deny(padapter, PS_DENY_SCAN);
+	ps_denied = true;
+	if (_FAIL == rtw_pwr_wakeup(padapter)) {
+		need_indicate_scan_done = true;
+		goto check_need_indicate_scan_done;
+	}
+
+#ifdef CONFIG_P2P
+	if (pwdinfo->driver_interface == DRIVER_CFG80211) {
+		if (ssids->ssid != NULL
+			&& !memcmp(ssids->ssid, "DIRECT-", 7)
+			&& rtw_get_p2p_ie((u8 *)request->ie, request->ie_len, NULL, NULL)
+		) {
+			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+				rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);
+			else {
+				rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+				#ifdef CONFIG_DEBUG_CFG80211
+				RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
+				#endif
+			}
+			rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
+
+			if (request->n_channels == 3 &&
+				request->channels[0]->hw_value == 1 &&
+				request->channels[1]->hw_value == 6 &&
+				request->channels[2]->hw_value == 11
+			)
+				social_channel = 1;
+		}
+	}
+#endif /*CONFIG_P2P*/
+
+	if (request->ie && request->ie_len > 0)
+		rtw_cfg80211_set_probe_req_wpsp2pie(padapter, (u8 *)request->ie, request->ie_len);
+
+	if (rtw_is_scan_deny(padapter)) {
+		RTW_INFO(FUNC_ADPT_FMT	": scan deny\n", FUNC_ADPT_ARG(padapter));
+		need_indicate_scan_done = true;
+		goto check_need_indicate_scan_done;
+	}
+
+	/* check fw state*/
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) ) {
+
+#ifdef CONFIG_DEBUG_CFG80211
+		RTW_INFO(FUNC_ADPT_FMT" under WIFI_AP_STATE\n", FUNC_ADPT_ARG(padapter));
+#endif
+
+		if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS | _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ) {
+			RTW_INFO("%s, fwstate=0x%x\n", __func__, pmlmepriv->fw_state);
+
+			if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS))
+				RTW_INFO("AP mode process WPS\n");
+
+			need_indicate_scan_done = true;
+			goto check_need_indicate_scan_done;
+		}
+	}
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) ) {
+		RTW_INFO("%s, fwstate=0x%x\n", __func__, pmlmepriv->fw_state);
+		need_indicate_scan_done = true;
+		goto check_need_indicate_scan_done;
+	} else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) ) {
+		RTW_INFO("%s, fwstate=0x%x\n", __func__, pmlmepriv->fw_state);
+		ret = -EBUSY;
+		goto check_need_indicate_scan_done;
+	}
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING | WIFI_UNDER_WPS)) {
+		RTW_INFO("%s exit due to buddy_intf's mlme state under linking or wps\n", __func__);
+		need_indicate_scan_done = true;
+		goto check_need_indicate_scan_done;
+
+	} else if (rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_SURVEY)) {
+		bool scan_via_buddy = rtw_cfg80211_scan_via_buddy(padapter, request);
+
+		if (scan_via_buddy == false)
+			need_indicate_scan_done = true;
+
+		goto check_need_indicate_scan_done;
+	}
+#endif /* CONFIG_CONCURRENT_MODE */
+
+	/* busy traffic check*/
+	if (rtw_mi_busy_traffic_check(padapter, true)) {
+		need_indicate_scan_done = true;
+		goto check_need_indicate_scan_done;
+	}
+
+#ifdef CONFIG_P2P
+	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
+		rtw_free_network_queue(padapter, true);
+
+		if (social_channel == 0)
+			rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
+		else
+			rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_SOCIAL_LAST);
+	}
+#endif /* CONFIG_P2P */
+
+
+	memset(ssid, 0, sizeof(NDIS_802_11_SSID) * RTW_SSID_SCAN_AMOUNT);
+	/* parsing request ssids, n_ssids */
+	for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
+		#ifdef CONFIG_DEBUG_CFG80211
+		RTW_INFO("ssid=%s, len=%d\n", ssids[i].ssid, ssids[i].ssid_len);
+		#endif
+		memcpy(ssid[i].Ssid, ssids[i].ssid, ssids[i].ssid_len);
+		ssid[i].SsidLength = ssids[i].ssid_len;
+	}
+
+	/* parsing channels, n_channels */
+	memset(ch, 0, sizeof(struct rtw_ieee80211_channel) * RTW_CHANNEL_SCAN_AMOUNT);
+	for (i = 0; i < request->n_channels && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
+		#ifdef CONFIG_DEBUG_CFG80211
+		RTW_INFO(FUNC_ADPT_FMT CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(request->channels[i]));
+		#endif
+		ch[i].hw_value = request->channels[i]->hw_value;
+		ch[i].flags = request->channels[i]->flags;
+	}
+
+	if (request->n_channels == 1) {
+		for (i = 1; i < survey_times_for_one_ch; i++)
+			memcpy(&ch[i], &ch[0], sizeof(struct rtw_ieee80211_channel));
+		pch = ch;
+		chan_num = survey_times_for_one_ch;
+	} else if (request->n_channels <= 4) {
+		for (j = request->n_channels - 1; j >= 0; j--)
+			for (i = 0; i < survey_times; i++)
+				memcpy(&ch[j * survey_times + i], &ch[j], sizeof(struct rtw_ieee80211_channel));
+		pch = ch;
+		chan_num = survey_times * request->n_channels;
+	} else {
+		pch = ch;
+		chan_num = request->n_channels;
+	}
+
+	_enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+	_status = rtw_sitesurvey_cmd(padapter, ssid, RTW_SSID_SCAN_AMOUNT, pch, chan_num);
+	if (_status == _SUCCESS)
+		pwdev_priv->scan_request = request;
+	else
+		ret = -1;
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+	_exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
+
+check_need_indicate_scan_done:
+	if (need_indicate_scan_done) {
+#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)
+		struct cfg80211_scan_info info;
+
+		memset(&info, 0, sizeof(info));
+		info.aborted = 0;
+#endif
+		_rtw_cfg80211_surveydone_event_callback(padapter, request);
+#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)
+		cfg80211_scan_done(request, &info);
+#else
+		cfg80211_scan_done(request, 0);
+#endif
+	}
+
+cancel_ps_deny:
+	if (ps_denied )
+		rtw_ps_deny_cancel(padapter, PS_DENY_SCAN);
+
+exit:
+	return ret;
+
+}
+
+static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+	RTW_INFO("%s\n", __func__);
+	return 0;
+}
+
+
+
+static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv, u32 wpa_version)
+{
+	RTW_INFO("%s, wpa_version=%d\n", __func__, wpa_version);
+
+	if (!wpa_version) {
+		psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
+		return 0;
+	}
+
+
+	if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
+		psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
+
+	#ifdef CONFIG_WAPI_SUPPORT
+	if (wpa_version & NL80211_WAPI_VERSION_1)
+		psecuritypriv->ndisauthtype = Ndis802_11AuthModeWAPI;
+	#endif
+
+	return 0;
+
+}
+
+static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
+		enum nl80211_auth_type sme_auth_type)
+{
+	RTW_INFO("%s, nl80211_auth_type=%d\n", __func__, sme_auth_type);
+
+
+	switch (sme_auth_type) {
+	case NL80211_AUTHTYPE_AUTOMATIC:
+
+		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
+
+		break;
+	case NL80211_AUTHTYPE_OPEN_SYSTEM:
+
+		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+
+		if (psecuritypriv->ndisauthtype > Ndis802_11AuthModeWPA)
+			psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+
+#ifdef CONFIG_WAPI_SUPPORT
+		if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWAPI)
+			psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;
+#endif
+
+		break;
+	case NL80211_AUTHTYPE_SHARED_KEY:
+
+		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
+
+		psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
+
+
+		break;
+	default:
+		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+		/* return -ENOTSUPP; */
+	}
+
+	return 0;
+
+}
+
+static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv, u32 cipher, bool ucast)
+{
+	u32 ndisencryptstatus = Ndis802_11EncryptionDisabled;
+
+	u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :
+		&psecuritypriv->dot118021XGrpPrivacy;
+
+	RTW_INFO("%s, ucast=%d, cipher=0x%x\n", __func__, ucast, cipher);
+
+
+	if (!cipher) {
+		*profile_cipher = _NO_PRIVACY_;
+		psecuritypriv->ndisencryptstatus = ndisencryptstatus;
+		return 0;
+	}
+
+	switch (cipher) {
+	case IW_AUTH_CIPHER_NONE:
+		*profile_cipher = _NO_PRIVACY_;
+		ndisencryptstatus = Ndis802_11EncryptionDisabled;
+#ifdef CONFIG_WAPI_SUPPORT
+		if (psecuritypriv->dot11PrivacyAlgrthm == _SMS4_)
+			*profile_cipher = _SMS4_;
+#endif
+		break;
+	case WLAN_CIPHER_SUITE_WEP40:
+		*profile_cipher = _WEP40_;
+		ndisencryptstatus = Ndis802_11Encryption1Enabled;
+		break;
+	case WLAN_CIPHER_SUITE_WEP104:
+		*profile_cipher = _WEP104_;
+		ndisencryptstatus = Ndis802_11Encryption1Enabled;
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		*profile_cipher = _TKIP_;
+		ndisencryptstatus = Ndis802_11Encryption2Enabled;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		*profile_cipher = _AES_;
+		ndisencryptstatus = Ndis802_11Encryption3Enabled;
+		break;
+#ifdef CONFIG_WAPI_SUPPORT
+	case WLAN_CIPHER_SUITE_SMS4:
+		*profile_cipher = _SMS4_;
+		ndisencryptstatus = Ndis802_11_EncrypteionWAPI;
+		break;
+#endif
+	default:
+		RTW_INFO("Unsupported cipher: 0x%x\n", cipher);
+		return -ENOTSUPP;
+	}
+
+	if (ucast) {
+		psecuritypriv->ndisencryptstatus = ndisencryptstatus;
+
+		/* if(psecuritypriv->dot11PrivacyAlgrthm >= _AES_) */
+		/*	psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK; */
+	}
+
+	return 0;
+}
+
+static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv, u32 key_mgt)
+{
+	RTW_INFO("%s, key_mgt=0x%x\n", __func__, key_mgt);
+
+	if (key_mgt == WLAN_AKM_SUITE_8021X) {
+		/* *auth_type = UMAC_AUTH_TYPE_8021X; */
+		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+		psecuritypriv->rsn_akm_suite_type = 1;
+	} else if (key_mgt == WLAN_AKM_SUITE_PSK) {
+		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+		psecuritypriv->rsn_akm_suite_type = 2;
+	}
+#ifdef CONFIG_WAPI_SUPPORT
+	else if (key_mgt == WLAN_AKM_SUITE_WAPI_PSK)
+		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;
+	else if (key_mgt == WLAN_AKM_SUITE_WAPI_CERT)
+		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;
+#endif
+#ifdef CONFIG_RTW_80211R
+	else if (key_mgt == WLAN_AKM_SUITE_FT_8021X) {
+		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+		psecuritypriv->rsn_akm_suite_type = 3;
+	} else if (key_mgt == WLAN_AKM_SUITE_FT_PSK) {
+		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+		psecuritypriv->rsn_akm_suite_type = 4;
+	}
+#endif
+	else {
+		RTW_INFO("Invalid key mgt: 0x%x\n", key_mgt);
+		/* return -EINVAL; */
+	}
+
+	return 0;
+}
+
+static int rtw_cfg80211_set_wpa_ie(_adapter *padapter, u8 *pie, size_t ielen)
+{
+	u8 *buf = NULL, *pos = NULL;
+	u32 left;
+	int group_cipher = 0, pairwise_cipher = 0;
+	int ret = 0;
+	int wpa_ielen = 0;
+	int wpa2_ielen = 0;
+	u8 *pwpa, *pwpa2;
+	u8 null_addr[] = {0, 0, 0, 0, 0, 0};
+
+	if (pie == NULL || !ielen) {
+		/* Treat this as normal case, but need to clear WIFI_UNDER_WPS */
+		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
+		goto exit;
+	}
+
+	if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	buf = rtw_zmalloc(ielen);
+	if (buf == NULL) {
+		ret =  -ENOMEM;
+		goto exit;
+	}
+
+	memcpy(buf, pie , ielen);
+
+	/* dump */
+	{
+		int i;
+		RTW_INFO("set wpa_ie(length:%zu):\n", ielen);
+		for (i = 0; i < ielen; i = i + 8)
+			RTW_INFO("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", buf[i], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]);
+	}
+
+	pos = buf;
+	if (ielen < RSN_HEADER_LEN) {
+		ret  = -1;
+		goto exit;
+	}
+
+	pwpa = rtw_get_wpa_ie(buf, &wpa_ielen, ielen);
+	if (pwpa && wpa_ielen > 0) {
+		if (rtw_parse_wpa_ie(pwpa, wpa_ielen + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
+			padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
+			memcpy(padapter->securitypriv.supplicant_ie, &pwpa[0], wpa_ielen + 2);
+
+			RTW_INFO("got wpa_ie, wpa_ielen:%u\n", wpa_ielen);
+		}
+	}
+
+	pwpa2 = rtw_get_wpa2_ie(buf, &wpa2_ielen, ielen);
+	if (pwpa2 && wpa2_ielen > 0) {
+		if (rtw_parse_wpa2_ie(pwpa2, wpa2_ielen + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
+			padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
+			memcpy(padapter->securitypriv.supplicant_ie, &pwpa2[0], wpa2_ielen + 2);
+
+			RTW_INFO("got wpa2_ie, wpa2_ielen:%u\n", wpa2_ielen);
+		}
+	}
+
+	if (group_cipher == 0)
+		group_cipher = WPA_CIPHER_NONE;
+	if (pairwise_cipher == 0)
+		pairwise_cipher = WPA_CIPHER_NONE;
+
+	switch (group_cipher) {
+	case WPA_CIPHER_NONE:
+		padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+		break;
+	case WPA_CIPHER_WEP40:
+		padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+		break;
+	case WPA_CIPHER_TKIP:
+		padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
+		break;
+	case WPA_CIPHER_CCMP:
+		padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
+		break;
+	case WPA_CIPHER_WEP104:
+		padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+		break;
+	}
+
+	switch (pairwise_cipher) {
+	case WPA_CIPHER_NONE:
+		padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+		break;
+	case WPA_CIPHER_WEP40:
+		padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+		break;
+	case WPA_CIPHER_TKIP:
+		padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
+		break;
+	case WPA_CIPHER_CCMP:
+		padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
+		break;
+	case WPA_CIPHER_WEP104:
+		padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+		break;
+	}
+
+	{/* handle wps_ie */
+		uint wps_ielen;
+		u8 *wps_ie;
+
+		wps_ie = rtw_get_wps_ie(buf, ielen, NULL, &wps_ielen);
+		if (wps_ie && wps_ielen > 0) {
+			RTW_INFO("got wps_ie, wps_ielen:%u\n", wps_ielen);
+			padapter->securitypriv.wps_ie_len = wps_ielen < MAX_WPS_IE_LEN ? wps_ielen : MAX_WPS_IE_LEN;
+			memcpy(padapter->securitypriv.wps_ie, wps_ie, padapter->securitypriv.wps_ie_len);
+			set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
+		} else
+			_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
+	}
+
+	#ifdef CONFIG_P2P
+	{/* check p2p_ie for assoc req; */
+		uint p2p_ielen = 0;
+		u8 *p2p_ie;
+		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+		p2p_ie = rtw_get_p2p_ie(buf, ielen, NULL, &p2p_ielen);
+		if (p2p_ie) {
+			#ifdef CONFIG_DEBUG_CFG80211
+			RTW_INFO("%s p2p_assoc_req_ielen=%d\n", __func__, p2p_ielen);
+			#endif
+
+			if (pmlmepriv->p2p_assoc_req_ie) {
+				u32 free_len = pmlmepriv->p2p_assoc_req_ie_len;
+				pmlmepriv->p2p_assoc_req_ie_len = 0;
+				rtw_mfree(pmlmepriv->p2p_assoc_req_ie, free_len);
+				pmlmepriv->p2p_assoc_req_ie = NULL;
+			}
+
+			pmlmepriv->p2p_assoc_req_ie = rtw_malloc(p2p_ielen);
+			if (pmlmepriv->p2p_assoc_req_ie == NULL) {
+				RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+				goto exit;
+			}
+			memcpy(pmlmepriv->p2p_assoc_req_ie, p2p_ie, p2p_ielen);
+			pmlmepriv->p2p_assoc_req_ie_len = p2p_ielen;
+		}
+	}
+	#endif /* CONFIG_P2P */
+
+	#ifdef CONFIG_WFD
+	{
+		uint wfd_ielen = 0;
+		u8 *wfd_ie;
+		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+		wfd_ie = rtw_get_wfd_ie(buf, ielen, NULL, &wfd_ielen);
+		if (wfd_ie) {
+			#ifdef CONFIG_DEBUG_CFG80211
+			RTW_INFO("%s wfd_assoc_req_ielen=%d\n", __func__, wfd_ielen);
+			#endif
+
+			if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_ASSOC_REQ_IE, wfd_ie, wfd_ielen) != _SUCCESS)
+				goto exit;
+		}
+	}
+	#endif /* CONFIG_WFD */
+
+	/* TKIP and AES disallow multicast packets until installing group key */
+	if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_
+		|| padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_
+		|| padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
+		/* WPS open need to enable multicast */
+		/* || check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) ) */
+		rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
+
+
+exit:
+	if (buf)
+		rtw_mfree(buf, ielen);
+	if (ret)
+		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
+
+	return ret;
+}
+
+static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
+				  struct cfg80211_ibss_params *params)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	NDIS_802_11_SSID ndis_ssid;
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+	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));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+	struct cfg80211_chan_def *pch_def;
+#endif
+	struct ieee80211_channel *pch;
+	int ret = 0;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+	pch_def = (struct cfg80211_chan_def *)(&params->chandef);
+	pch = (struct ieee80211_channel *) pch_def->chan;
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+	pch = (struct ieee80211_channel *)(params->channel);
+#endif
+
+	if (!params->ssid || !params->ssid_len) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (params->ssid_len > IW_ESSID_MAX_SIZE) {
+		ret = -E2BIG;
+		goto exit;
+	}
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+		ret = -EPERM;
+		goto exit;
+	}
+
+	rtw_ps_deny(padapter, PS_DENY_JOIN);
+	if (_FAIL == rtw_pwr_wakeup(padapter)) {
+		ret = -EPERM;
+		goto cancel_ps_deny;
+	}
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING)) {
+		RTW_INFO("%s, but buddy_intf is under linking\n", __func__);
+		ret = -EINVAL;
+		goto cancel_ps_deny;
+	}
+	rtw_mi_buddy_scan_abort(padapter, true); /* OR rtw_mi_scan_abort(padapter, true);*/
+#endif /*CONFIG_CONCURRENT_MODE*/
+
+
+	memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));
+	ndis_ssid.SsidLength = params->ssid_len;
+	memcpy(ndis_ssid.Ssid, (u8 *)params->ssid, params->ssid_len);
+
+	/* RTW_INFO("ssid=%s, len=%zu\n", ndis_ssid.Ssid, params->ssid_len); */
+
+	psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
+	psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+	psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+	psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
+	psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
+
+	ret = rtw_cfg80211_set_auth_type(psecuritypriv, NL80211_AUTHTYPE_OPEN_SYSTEM);
+	rtw_set_802_11_authentication_mode(padapter, psecuritypriv->ndisauthtype);
+
+	RTW_INFO("%s: center_freq = %d\n", __func__, pch->center_freq);
+	pmlmeext->cur_channel = rtw_freq2ch(pch->center_freq);
+
+	if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == false) {
+		ret = -1;
+		goto cancel_ps_deny;
+	}
+
+cancel_ps_deny:
+	rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
+exit:
+	return ret;
+}
+
+static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct wireless_dev *rtw_wdev = padapter->rtw_wdev;
+	enum nl80211_iftype old_type;
+	int ret = 0;
+
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+	#ifdef SUPPLICANT_RTK_VERSION_LOWER_THAN_JB42
+	padapter->mlmepriv.not_indic_disco = true;
+	#endif
+
+	old_type = rtw_wdev->iftype;
+
+	rtw_set_to_roam(padapter, 0);
+
+	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
+		rtw_scan_abort(padapter);
+		LeaveAllPowerSaveMode(padapter);
+
+		rtw_wdev->iftype = NL80211_IFTYPE_STATION;
+
+		if (rtw_set_802_11_infrastructure_mode(padapter, Ndis802_11Infrastructure) == false) {
+			rtw_wdev->iftype = old_type;
+			ret = -EPERM;
+			goto leave_ibss;
+		}
+		rtw_setopmode_cmd(padapter, Ndis802_11Infrastructure, true);
+	}
+
+leave_ibss:
+	#ifdef SUPPLICANT_RTK_VERSION_LOWER_THAN_JB42
+	padapter->mlmepriv.not_indic_disco = false;
+	#endif
+
+	return 0;
+}
+
+static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
+				struct cfg80211_connect_params *sme)
+{
+	int ret = 0;
+	unsigned long irqL;
+	_list *phead;
+	struct wlan_network *pnetwork = NULL;
+	NDIS_802_11_AUTHENTICATION_MODE authmode;
+	NDIS_802_11_SSID ndis_ssid;
+	u8 *dst_ssid, *src_ssid;
+	u8 *dst_bssid, *src_bssid;
+	/* u8 matched_by_bssid=false; */
+	/* u8 matched_by_ssid=false; */
+	u8 matched = false;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+	_queue *queue = &pmlmepriv->scanned_queue;
+
+#ifdef SUPPLICANT_RTK_VERSION_LOWER_THAN_JB42
+	padapter->mlmepriv.not_indic_disco = true;
+#endif
+
+	RTW_INFO("=>"FUNC_NDEV_FMT" - Start to Connection\n", FUNC_NDEV_ARG(ndev));
+	RTW_INFO("privacy=%d, key=%p, key_len=%d, key_idx=%d, auth_type=%d\n",
+		sme->privacy, sme->key, sme->key_len, sme->key_idx, sme->auth_type);
+
+
+	if (adapter_wdev_data(padapter)->block ) {
+		ret = -EBUSY;
+		RTW_INFO("%s wdev_priv.block is set\n", __func__);
+		goto exit;
+	}
+
+#ifdef CONFIG_PLATFORM_MSTAR_SCAN_BEFORE_CONNECT
+	printk("MStar Android!\n");
+	if (adapter_wdev_data(padapter)->bandroid_scan == false) {
+#ifdef CONFIG_P2P
+		struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+#endif /* CONFIG_P2P */
+		{
+			ret = -EBUSY;
+			printk("Android hasn't attached yet!\n");
+			goto exit;
+		}
+	}
+#endif
+
+	if (!sme->ssid || !sme->ssid_len) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (sme->ssid_len > IW_ESSID_MAX_SIZE) {
+		ret = -E2BIG;
+		goto exit;
+	}
+
+	rtw_ps_deny(padapter, PS_DENY_JOIN);
+	if (_FAIL == rtw_pwr_wakeup(padapter)) {
+		ret = -EPERM;
+		goto cancel_ps_deny;
+	}
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+		ret = -EPERM;
+		goto cancel_ps_deny;
+	}
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) ) {
+		ret = -EBUSY;
+		RTW_INFO("%s, fw_state=0x%x, goto exit\n", __func__, pmlmepriv->fw_state);
+		goto cancel_ps_deny;
+	}
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING)) {
+		ret = -EINVAL;
+		goto cancel_ps_deny;
+	}
+#endif
+
+	rtw_mi_scan_abort(padapter, true);
+
+	memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));
+	ndis_ssid.SsidLength = sme->ssid_len;
+	memcpy(ndis_ssid.Ssid, (u8 *)sme->ssid, sme->ssid_len);
+
+	RTW_INFO("ssid=%s, len=%zu\n", ndis_ssid.Ssid, sme->ssid_len);
+
+
+	if (sme->bssid)
+		RTW_INFO("bssid="MAC_FMT"\n", MAC_ARG(sme->bssid));
+
+
+	psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
+	psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+	psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+	psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
+	psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
+
+#ifdef CONFIG_WAPI_SUPPORT
+	padapter->wapiInfo.bWapiEnable = false;
+#endif
+
+	ret = rtw_cfg80211_set_wpa_version(psecuritypriv, sme->crypto.wpa_versions);
+	if (ret < 0)
+		goto cancel_ps_deny;
+
+#ifdef CONFIG_WAPI_SUPPORT
+	if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) {
+		padapter->wapiInfo.bWapiEnable = true;
+		padapter->wapiInfo.extra_prefix_len = WAPI_EXT_LEN;
+		padapter->wapiInfo.extra_postfix_len = SMS4_MIC_LEN;
+	}
+#endif
+
+	ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type);
+
+#ifdef CONFIG_WAPI_SUPPORT
+	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_WAPI)
+		padapter->mlmeextpriv.mlmext_info.auth_algo = psecuritypriv->dot11AuthAlgrthm;
+#endif
+
+
+	if (ret < 0)
+		goto cancel_ps_deny;
+
+	RTW_INFO("%s, ie_len=%zu\n", __func__, sme->ie_len);
+
+	ret = rtw_cfg80211_set_wpa_ie(padapter, (u8 *)sme->ie, sme->ie_len);
+	if (ret < 0)
+		goto cancel_ps_deny;
+
+	if (sme->crypto.n_ciphers_pairwise) {
+		ret = rtw_cfg80211_set_cipher(psecuritypriv, sme->crypto.ciphers_pairwise[0], true);
+		if (ret < 0)
+			goto cancel_ps_deny;
+	}
+
+	/* For WEP Shared auth */
+	if (sme->key_len > 0 && sme->key) {
+		u32 wep_key_idx, wep_key_len, wep_total_len;
+		NDIS_802_11_WEP	*pwep = NULL;
+		RTW_INFO("%s(): Shared/Auto WEP\n", __func__);
+
+		wep_key_idx = sme->key_idx;
+		wep_key_len = sme->key_len;
+
+		if (sme->key_idx > WEP_KEYS) {
+			ret = -EINVAL;
+			goto cancel_ps_deny;
+		}
+
+		if (wep_key_len > 0) {
+			wep_key_len = wep_key_len <= 5 ? 5 : 13;
+			wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
+			pwep = (NDIS_802_11_WEP *) rtw_malloc(wep_total_len);
+			if (pwep == NULL) {
+				RTW_INFO(" wpa_set_encryption: pwep allocate fail !!!\n");
+				ret = -ENOMEM;
+				goto cancel_ps_deny;
+			}
+
+			memset(pwep, 0, wep_total_len);
+
+			pwep->KeyLength = wep_key_len;
+			pwep->Length = wep_total_len;
+
+			if (wep_key_len == 13) {
+				padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
+				padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
+			}
+		} else {
+			ret = -EINVAL;
+			goto cancel_ps_deny;
+		}
+
+		pwep->KeyIndex = wep_key_idx;
+		pwep->KeyIndex |= 0x80000000;
+
+		memcpy(pwep->KeyMaterial, (void *)sme->key, pwep->KeyLength);
+
+		if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
+			ret = -EOPNOTSUPP ;
+
+		if (pwep)
+			rtw_mfree((u8 *)pwep, wep_total_len);
+
+		if (ret < 0)
+			goto cancel_ps_deny;
+	}
+
+	ret = rtw_cfg80211_set_cipher(psecuritypriv, sme->crypto.cipher_group, false);
+	if (ret < 0)
+		return ret;
+
+	if (sme->crypto.n_akm_suites) {
+		ret = rtw_cfg80211_set_key_mgt(psecuritypriv, sme->crypto.akm_suites[0]);
+		if (ret < 0)
+			goto cancel_ps_deny;
+	}
+#ifdef CONFIG_8011R
+	else {
+		/*It could be a connection without RSN IEs*/
+		psecuritypriv->rsn_akm_suite_type = 0;
+	}
+#endif
+
+#ifdef CONFIG_WAPI_SUPPORT
+	if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_WAPI_PSK)
+		padapter->wapiInfo.bWapiPSK = true;
+	else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_WAPI_CERT)
+		padapter->wapiInfo.bWapiPSK = false;
+#endif
+
+	authmode = psecuritypriv->ndisauthtype;
+	rtw_set_802_11_authentication_mode(padapter, authmode);
+
+	/* rtw_set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
+
+	if (rtw_set_802_11_connect(padapter, (u8 *)sme->bssid, &ndis_ssid) == false) {
+		ret = -1;
+		goto cancel_ps_deny;
+	}
+
+	RTW_INFO("set ssid:dot11AuthAlgrthm=%d, dot11PrivacyAlgrthm=%d, dot118021XGrpPrivacy=%d\n", psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
+		psecuritypriv->dot118021XGrpPrivacy);
+
+cancel_ps_deny:
+	rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
+
+exit:
+	RTW_INFO("<=%s, ret %d\n", __func__, ret);
+
+#ifdef SUPPLICANT_RTK_VERSION_LOWER_THAN_JB42
+	padapter->mlmepriv.not_indic_disco = false;
+#endif
+
+	return ret;
+}
+
+static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev,
+				   u16 reason_code)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+
+	RTW_INFO(FUNC_NDEV_FMT" - Start to Disconnect\n", FUNC_NDEV_ARG(ndev));
+
+#ifdef SUPPLICANT_RTK_VERSION_LOWER_THAN_JB42
+	padapter->mlmepriv.not_indic_disco = true;
+#endif
+
+	rtw_set_to_roam(padapter, 0);
+
+	/* if(check_fwstate(&padapter->mlmepriv, _FW_LINKED)) */
+	{
+		rtw_scan_abort(padapter);
+		LeaveAllPowerSaveMode(padapter);
+		rtw_disassoc_cmd(padapter, 500, false);
+		rtw_sta_mstatus_report(padapter);
+
+		RTW_INFO("%s...call rtw_indicate_disconnect\n", __func__);
+
+		rtw_free_assoc_resources(padapter, 1);
+		rtw_indicate_disconnect(padapter, 0, true);
+
+		rtw_pwr_wakeup(padapter);
+	}
+
+#ifdef SUPPLICANT_RTK_VERSION_LOWER_THAN_JB42
+	padapter->mlmepriv.not_indic_disco = false;
+#endif
+
+	RTW_INFO(FUNC_NDEV_FMT" return 0\n", FUNC_NDEV_ARG(ndev));
+	return 0;
+}
+
+static int cfg80211_rtw_set_txpower(struct wiphy *wiphy,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+	struct wireless_dev *wdev,
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) || defined(COMPAT_KERNEL_RELEASE)
+	enum nl80211_tx_power_setting type, int mbm)
+#else
+	enum tx_power_setting type, int dbm)
+#endif
+{
+	RTW_INFO("%s\n", __func__);
+	return 0;
+}
+
+static int cfg80211_rtw_get_txpower(struct wiphy *wiphy,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+	struct wireless_dev *wdev,
+#endif
+	int *dbm)
+{
+	RTW_INFO("%s\n", __func__);
+
+	*dbm = (12);
+
+	return 0;
+}
+
+inline bool rtw_cfg80211_pwr_mgmt(_adapter *adapter)
+{
+	struct rtw_wdev_priv *rtw_wdev_priv = adapter_wdev_data(adapter);
+	return rtw_wdev_priv->power_mgmt;
+}
+
+static int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy,
+				       struct net_device *ndev,
+				       bool enabled, int timeout)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct rtw_wdev_priv *rtw_wdev_priv = adapter_wdev_data(padapter);
+
+	RTW_INFO(FUNC_NDEV_FMT" enabled:%u, timeout:%d\n", FUNC_NDEV_ARG(ndev),
+		enabled, timeout);
+
+	rtw_wdev_priv->power_mgmt = enabled;
+
+#ifdef CONFIG_LPS
+	if (!enabled)
+		rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE_CFG80211_PWRMGMT, 1);
+#endif
+
+	return 0;
+}
+
+static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,
+				  struct net_device *ndev,
+				  struct cfg80211_pmksa *pmksa)
+{
+	u8	index, blInserted = false;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct mlme_priv *mlme = &padapter->mlmepriv;
+	struct security_priv	*psecuritypriv = &padapter->securitypriv;
+	u8	strZeroMacAddress[ETH_ALEN] = { 0x00 };
+
+	RTW_INFO(FUNC_NDEV_FMT" "MAC_FMT" "KEY_FMT"\n", FUNC_NDEV_ARG(ndev)
+		, MAC_ARG(pmksa->bssid), KEY_ARG(pmksa->pmkid));
+
+	if (!memcmp((u8 *)pmksa->bssid, strZeroMacAddress, ETH_ALEN) )
+		return -EINVAL;
+
+	if (check_fwstate(mlme, _FW_LINKED) == false) {
+		RTW_INFO(FUNC_NDEV_FMT" not set pmksa cause not in linked state\n", FUNC_NDEV_ARG(ndev));
+		return -EINVAL;
+	}
+
+	blInserted = false;
+
+	/* overwrite PMKID */
+	for (index = 0 ; index < NUM_PMKID_CACHE; index++) {
+		if (!memcmp(psecuritypriv->PMKIDList[index].Bssid, (u8 *)pmksa->bssid, ETH_ALEN) ) {
+			/* BSSID is matched, the same AP => rewrite with new PMKID. */
+			RTW_INFO(FUNC_NDEV_FMT" BSSID exists in the PMKList.\n", FUNC_NDEV_ARG(ndev));
+
+			memcpy(psecuritypriv->PMKIDList[index].PMKID, (u8 *)pmksa->pmkid, WLAN_PMKID_LEN);
+			psecuritypriv->PMKIDList[index].bUsed = true;
+			psecuritypriv->PMKIDIndex = index + 1;
+			blInserted = true;
+			break;
+		}
+	}
+
+	if (!blInserted) {
+		/* Find a new entry */
+		RTW_INFO(FUNC_NDEV_FMT" Use the new entry index = %d for this PMKID.\n",
+			FUNC_NDEV_ARG(ndev), psecuritypriv->PMKIDIndex);
+
+		memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, (u8 *)pmksa->bssid, ETH_ALEN);
+		memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, (u8 *)pmksa->pmkid, WLAN_PMKID_LEN);
+
+		psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true;
+		psecuritypriv->PMKIDIndex++ ;
+		if (psecuritypriv->PMKIDIndex == 16)
+			psecuritypriv->PMKIDIndex = 0;
+	}
+
+	return 0;
+}
+
+static int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,
+				  struct net_device *ndev,
+				  struct cfg80211_pmksa *pmksa)
+{
+	u8	index, bMatched = false;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct security_priv	*psecuritypriv = &padapter->securitypriv;
+
+	RTW_INFO(FUNC_NDEV_FMT" "MAC_FMT" "KEY_FMT"\n", FUNC_NDEV_ARG(ndev)
+		, MAC_ARG(pmksa->bssid), KEY_ARG(pmksa->pmkid));
+
+	for (index = 0 ; index < NUM_PMKID_CACHE; index++) {
+		if (!memcmp(psecuritypriv->PMKIDList[index].Bssid, (u8 *)pmksa->bssid, ETH_ALEN) ) {
+			/* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
+			memset(psecuritypriv->PMKIDList[index].Bssid, 0x00, ETH_ALEN);
+			memset(psecuritypriv->PMKIDList[index].PMKID, 0x00, WLAN_PMKID_LEN);
+			psecuritypriv->PMKIDList[index].bUsed = false;
+			bMatched = true;
+			RTW_INFO(FUNC_NDEV_FMT" clear id:%hhu\n", FUNC_NDEV_ARG(ndev), index);
+			break;
+		}
+	}
+
+	if (false == bMatched) {
+		RTW_INFO(FUNC_NDEV_FMT" do not have matched BSSID\n"
+			, FUNC_NDEV_ARG(ndev));
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy,
+				    struct net_device *ndev)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct security_priv	*psecuritypriv = &padapter->securitypriv;
+
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+	memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(RT_PMKID_LIST) * NUM_PMKID_CACHE);
+	psecuritypriv->PMKIDIndex = 0;
+
+	return 0;
+}
+
+#ifdef CONFIG_AP_MODE
+void rtw_cfg80211_indicate_sta_assoc(_adapter *padapter, u8 *pmgmt_frame, uint frame_len)
+{
+	s32 freq;
+	int channel;
+	struct wireless_dev *pwdev = padapter->rtw_wdev;
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+	struct net_device *ndev = padapter->pnetdev;
+
+	RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+
+#if defined(RTW_USE_CFG80211_STA_EVENT) || defined(COMPAT_KERNEL_RELEASE)
+	{
+		struct station_info sinfo;
+		u8 ie_offset;
+		if (get_frame_sub_type(pmgmt_frame) == WIFI_ASSOCREQ)
+			ie_offset = _ASOCREQ_IE_OFFSET_;
+		else /* WIFI_REASSOCREQ */
+			ie_offset = _REASOCREQ_IE_OFFSET_;
+
+		memset(&sinfo, 0, sizeof(sinfo));
+		sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
+		sinfo.assoc_req_ies = pmgmt_frame + WLAN_HDR_A3_LEN + ie_offset;
+		sinfo.assoc_req_ies_len = frame_len - WLAN_HDR_A3_LEN - ie_offset;
+		cfg80211_new_sta(ndev, get_addr2_ptr(pmgmt_frame), &sinfo, GFP_ATOMIC);
+	}
+#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
+	channel = pmlmeext->cur_channel;
+	freq = rtw_ch2freq(channel);
+
+	#ifdef COMPAT_KERNEL_RELEASE
+	rtw_cfg80211_rx_mgmt(pwdev, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);
+	#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
+	rtw_cfg80211_rx_mgmt(pwdev, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);
+	#else /* COMPAT_KERNEL_RELEASE */
+	{
+		/* to avoid WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)  when calling cfg80211_send_rx_assoc() */
+		#ifndef CONFIG_PLATFORM_MSTAR
+		pwdev->iftype = NL80211_IFTYPE_STATION;
+		#endif /* CONFIG_PLATFORM_MSTAR */
+		RTW_INFO("iftype=%d before call cfg80211_send_rx_assoc()\n", pwdev->iftype);
+		rtw_cfg80211_send_rx_assoc(padapter, NULL, pmgmt_frame, frame_len);
+		RTW_INFO("iftype=%d after call cfg80211_send_rx_assoc()\n", pwdev->iftype);
+		pwdev->iftype = NL80211_IFTYPE_AP;
+		/* cfg80211_rx_action(padapter->pnetdev, freq, pmgmt_frame, frame_len, GFP_ATOMIC); */
+	}
+	#endif /* COMPAT_KERNEL_RELEASE */
+#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
+
+}
+
+void rtw_cfg80211_indicate_sta_disassoc(_adapter *padapter, unsigned char *da, unsigned short reason)
+{
+	s32 freq;
+	int channel;
+	u8 *pmgmt_frame;
+	uint frame_len;
+	struct rtw_ieee80211_hdr *pwlanhdr;
+	unsigned short *fctrl;
+	u8 mgmt_buf[128] = {0};
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct wireless_dev *wdev = padapter->rtw_wdev;
+	struct net_device *ndev = padapter->pnetdev;
+
+	RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+
+#if defined(RTW_USE_CFG80211_STA_EVENT) || defined(COMPAT_KERNEL_RELEASE)
+	cfg80211_del_sta(ndev, da, GFP_ATOMIC);
+#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
+	channel = pmlmeext->cur_channel;
+	freq = rtw_ch2freq(channel);
+
+	pmgmt_frame = mgmt_buf;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pmgmt_frame;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	memcpy(pwlanhdr->addr1, adapter_mac_addr(padapter), ETH_ALEN);
+	memcpy(pwlanhdr->addr2, da, ETH_ALEN);
+	memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	set_frame_sub_type(pmgmt_frame, WIFI_DEAUTH);
+
+	pmgmt_frame += sizeof(struct rtw_ieee80211_hdr_3addr);
+	frame_len = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	reason = cpu_to_le16(reason);
+	pmgmt_frame = rtw_set_fixed_ie(pmgmt_frame, _RSON_CODE_ , (unsigned char *)&reason, &frame_len);
+
+	#ifdef COMPAT_KERNEL_RELEASE
+	rtw_cfg80211_rx_mgmt(wdev, freq, 0, mgmt_buf, frame_len, GFP_ATOMIC);
+	#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
+	rtw_cfg80211_rx_mgmt(wdev, freq, 0, mgmt_buf, frame_len, GFP_ATOMIC);
+	#else /* COMPAT_KERNEL_RELEASE */
+	cfg80211_send_disassoc(padapter->pnetdev, mgmt_buf, frame_len);
+	/* cfg80211_rx_action(padapter->pnetdev, freq, mgmt_buf, frame_len, GFP_ATOMIC); */
+	#endif /* COMPAT_KERNEL_RELEASE */
+#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
+}
+
+static int rtw_cfg80211_monitor_if_open(struct net_device *ndev)
+{
+	int ret = 0;
+
+	RTW_INFO("%s\n", __func__);
+
+	return ret;
+}
+
+static int rtw_cfg80211_monitor_if_close(struct net_device *ndev)
+{
+	int ret = 0;
+
+	RTW_INFO("%s\n", __func__);
+
+	return ret;
+}
+
+static int rtw_cfg80211_monitor_if_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);
+
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(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 != 14) {
+		RTW_INFO("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) {
+		/* Check if this ia a Wireless Distribution System (WDS) frame
+		 * which has 4 MAC addresses
+		 */
+		if (le16_to_cpu(dot11_hdr->frame_ctl) & 0x0080)
+			qos_len = 2;
+		if ((le16_to_cpu(dot11_hdr->frame_ctl) & 0x0300) == 0x0300)
+			dot11_hdr_len += 6;
+
+		memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
+		memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
+
+		/* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for
+		 * for two MAC addresses
+		 */
+		skb_pull(skb, dot11_hdr_len + qos_len + snap_len - sizeof(src_mac_addr) * 2);
+		pdata = (unsigned char *)skb->data;
+		memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr));
+		memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr, sizeof(src_mac_addr));
+
+		RTW_INFO("should be eapol packet\n");
+
+		/* Use the real net device to transmit the packet */
+		ret = _rtw_xmit_entry(skb, padapter->pnetdev);
+
+		return ret;
+
+	} else if ((frame_ctl & (RTW_IEEE80211_FCTL_FTYPE | RTW_IEEE80211_FCTL_STYPE))
+		== (RTW_IEEE80211_FTYPE_MGMT | RTW_IEEE80211_STYPE_ACTION)
+	) {
+		/* only for action frames */
+		struct xmit_frame		*pmgntframe;
+		struct pkt_attrib	*pattrib;
+		unsigned char	*pframe;
+		/* u8 category, action, OUI_Subtype, dialogToken=0; */
+		/* unsigned char	*frame_body; */
+		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;
+
+		if (rtw_action_frame_parse(buf, len, &category, &action) == false) {
+			RTW_INFO(FUNC_NDEV_FMT" frame_control:0x%x\n", FUNC_NDEV_ARG(ndev),
+				le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)buf)->frame_ctl));
+			goto fail;
+		}
+
+		RTW_INFO("RTW_Tx:da="MAC_FMT" via "FUNC_NDEV_FMT"\n",
+			MAC_ARG(GetAddr1Ptr(buf)), FUNC_NDEV_ARG(ndev));
+		#ifdef CONFIG_P2P
+		type = rtw_p2p_check_frames(padapter, buf, len, true);
+		if (type >= 0)
+			goto dump;
+		#endif
+		if (category == RTW_WLAN_CATEGORY_PUBLIC)
+			RTW_INFO("RTW_Tx:%s\n", action_public_str(action));
+		else
+			RTW_INFO("RTW_Tx:category(%u), action(%u)\n", category, action);
+
+dump:
+		/* starting alloc mgmt frame to dump it */
+		pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+		if (pmgntframe == NULL)
+			goto fail;
+
+		/* update attribute */
+		pattrib = &pmgntframe->attrib;
+		update_mgntframe_attrib(padapter, pattrib);
+		pattrib->retry_ctrl = false;
+
+		memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+		pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+
+		memcpy(pframe, (void *)buf, len);
+		pattrib->pktlen = len;
+
+#ifdef CONFIG_P2P
+		if (type >= 0)
+			rtw_xframe_chk_wfd_ie(pmgntframe);
+#endif /* CONFIG_P2P */
+
+		pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+		/* update seq number */
+		pmlmeext->mgnt_seq = GetSequence(pwlanhdr);
+		pattrib->seqnum = pmlmeext->mgnt_seq;
+		pmlmeext->mgnt_seq++;
+
+
+		pattrib->last_txcmdsz = pattrib->pktlen;
+
+		dump_mgntframe(padapter, pmgntframe);
+
+	} else
+		RTW_INFO("frame_ctl=0x%x\n", frame_ctl & (RTW_IEEE80211_FCTL_FTYPE | RTW_IEEE80211_FCTL_STYPE));
+
+
+fail:
+
+	rtw_skb_free(skb);
+
+	return 0;
+
+}
+
+static void rtw_cfg80211_monitor_if_set_multicast_list(struct net_device *ndev)
+{
+	RTW_INFO("%s\n", __func__);
+}
+
+static int rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)
+{
+	int ret = 0;
+
+	RTW_INFO("%s\n", __func__);
+
+	return ret;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+static const struct net_device_ops rtw_cfg80211_monitor_if_ops = {
+	.ndo_open = rtw_cfg80211_monitor_if_open,
+	.ndo_stop = rtw_cfg80211_monitor_if_close,
+	.ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
+	#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+	.ndo_set_multicast_list = rtw_cfg80211_monitor_if_set_multicast_list,
+	#endif
+	.ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,
+};
+#endif
+
+static int rtw_cfg80211_add_monitor_if(_adapter *padapter, char *name, struct net_device **ndev)
+{
+	int ret = 0;
+	struct net_device *mon_ndev = NULL;
+	struct wireless_dev *mon_wdev = NULL;
+	struct rtw_netdev_priv_indicator *pnpi;
+	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
+
+	if (!name) {
+		RTW_INFO(FUNC_ADPT_FMT" without specific name\n", FUNC_ADPT_ARG(padapter));
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (pwdev_priv->pmon_ndev) {
+		RTW_INFO(FUNC_ADPT_FMT" monitor interface exist: "NDEV_FMT"\n",
+			FUNC_ADPT_ARG(padapter), NDEV_ARG(pwdev_priv->pmon_ndev));
+		ret = -EBUSY;
+		goto out;
+	}
+
+	mon_ndev = alloc_etherdev(sizeof(struct rtw_netdev_priv_indicator));
+	if (!mon_ndev) {
+		RTW_INFO(FUNC_ADPT_FMT" allocate ndev fail\n", FUNC_ADPT_ARG(padapter));
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;
+	strncpy(mon_ndev->name, name, IFNAMSIZ);
+	mon_ndev->name[IFNAMSIZ - 1] = 0;
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(4, 11, 9))
+	mon_ndev->needs_free_netdev = false;
+	mon_ndev->priv_destructor = rtw_ndev_destructor;
+#else
+	mon_ndev->destructor = rtw_ndev_destructor;
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+	mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;
+#else
+	mon_ndev->open = rtw_cfg80211_monitor_if_open;
+	mon_ndev->stop = rtw_cfg80211_monitor_if_close;
+	mon_ndev->hard_start_xmit = rtw_cfg80211_monitor_if_xmit_entry;
+	mon_ndev->set_mac_address = rtw_cfg80211_monitor_if_set_mac_address;
+#endif
+
+	pnpi = netdev_priv(mon_ndev);
+	pnpi->priv = padapter;
+	pnpi->sizeof_priv = sizeof(_adapter);
+
+	/*  wdev */
+	mon_wdev = (struct wireless_dev *)rtw_zmalloc(sizeof(struct wireless_dev));
+	if (!mon_wdev) {
+		RTW_INFO(FUNC_ADPT_FMT" allocate mon_wdev fail\n", FUNC_ADPT_ARG(padapter));
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	mon_wdev->wiphy = padapter->rtw_wdev->wiphy;
+	mon_wdev->netdev = mon_ndev;
+	mon_wdev->iftype = NL80211_IFTYPE_MONITOR;
+	mon_ndev->ieee80211_ptr = mon_wdev;
+
+	ret = register_netdevice(mon_ndev);
+	if (ret)
+		goto out;
+
+	*ndev = pwdev_priv->pmon_ndev = mon_ndev;
+	memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1);
+
+out:
+	if (ret && mon_wdev) {
+		rtw_mfree((u8 *)mon_wdev, sizeof(struct wireless_dev));
+		mon_wdev = NULL;
+	}
+
+	if (ret && mon_ndev) {
+		free_netdev(mon_ndev);
+		*ndev = mon_ndev = NULL;
+	}
+
+	return ret;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+static struct wireless_dev *
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
+static struct net_device *
+#else
+static int
+#endif
+	cfg80211_rtw_add_virtual_intf(struct wiphy *wiphy,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
+		const char *name,
+#else
+		char *name,
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
+		unsigned char name_assign_type,
+#endif
+		enum nl80211_iftype type,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
+		u32 *flags,
+#endif
+		struct vif_params *params)
+{
+	int ret = 0;
+	struct wireless_dev *wdev = NULL;
+	struct net_device *ndev = NULL;
+	_adapter *padapter;
+	struct dvobj_priv *dvobj = wiphy_to_dvobj(wiphy);
+
+	rtw_set_rtnl_lock_holder(dvobj, current);
+
+	RTW_INFO(FUNC_WIPHY_FMT" name:%s, type:%d\n", FUNC_WIPHY_ARG(wiphy), name, type);
+
+	switch (type) {
+	case NL80211_IFTYPE_MONITOR:
+		padapter = wiphy_to_adapter(wiphy); /* TODO: get ap iface ? */
+		ret = rtw_cfg80211_add_monitor_if(padapter, (char *)name, &ndev);
+		if (ret == 0)
+			wdev = ndev->ieee80211_ptr;
+		break;
+
+#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
+	case NL80211_IFTYPE_P2P_CLIENT:
+	case NL80211_IFTYPE_P2P_GO:
+#endif
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_AP:
+		padapter = dvobj_get_unregisterd_adapter(dvobj);
+		if (!padapter) {
+			RTW_WARN("adapter pool empty!\n");
+			ret = -ENODEV;
+			break;
+		}
+		if (rtw_os_ndev_init(padapter, name) != _SUCCESS) {
+			RTW_WARN("ndev init fail!\n");
+			ret = -ENODEV;
+			break;
+		}
+		#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
+		if (type == NL80211_IFTYPE_P2P_CLIENT || type == NL80211_IFTYPE_P2P_GO)
+			rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);
+		#endif
+		ndev = padapter->pnetdev;
+		wdev = ndev->ieee80211_ptr;
+		break;
+
+#if defined(CONFIG_P2P) && defined(RTW_DEDICATED_P2P_DEVICE)
+	case NL80211_IFTYPE_P2P_DEVICE:
+		ret = rtw_pd_iface_alloc(wiphy, name, &wdev);
+		break;
+#endif
+
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_WDS:
+	case NL80211_IFTYPE_MESH_POINT:
+	default:
+		ret = -ENODEV;
+		RTW_INFO("Unsupported interface type\n");
+		break;
+	}
+
+	if (ndev)
+		RTW_INFO(FUNC_WIPHY_FMT" ndev:%p, ret:%d\n", FUNC_WIPHY_ARG(wiphy), ndev, ret);
+	else
+		RTW_INFO(FUNC_WIPHY_FMT" wdev:%p, ret:%d\n", FUNC_WIPHY_ARG(wiphy), wdev, ret);
+
+	rtw_set_rtnl_lock_holder(dvobj, NULL);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	return wdev ? wdev : ERR_PTR(ret);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
+	return ndev ? ndev : ERR_PTR(ret);
+#else
+	return ret;
+#endif
+}
+
+static int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	struct wireless_dev *wdev
+#else
+	struct net_device *ndev
+#endif
+)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	struct net_device *ndev = wdev_to_ndev(wdev);
+#endif
+	int ret = 0;
+	struct dvobj_priv *dvobj = wiphy_to_dvobj(wiphy);
+	_adapter *adapter;
+	struct rtw_wdev_priv *pwdev_priv;
+
+	rtw_set_rtnl_lock_holder(dvobj, current);
+
+	if (ndev) {
+		adapter = (_adapter *)rtw_netdev_priv(ndev);
+		pwdev_priv = adapter_wdev_data(adapter);
+
+		if (ndev == pwdev_priv->pmon_ndev) {
+			unregister_netdevice(ndev);
+			pwdev_priv->pmon_ndev = NULL;
+			pwdev_priv->ifname_mon[0] = '\0';
+			RTW_INFO(FUNC_NDEV_FMT" remove monitor ndev\n", FUNC_NDEV_ARG(ndev));
+		} else {
+			RTW_INFO(FUNC_NDEV_FMT" unregister ndev\n", FUNC_NDEV_ARG(ndev));
+			rtw_os_ndev_unregister(adapter);
+		}
+	} else
+#if defined(CONFIG_P2P) && defined(RTW_DEDICATED_P2P_DEVICE)
+	if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
+		if (wdev == wiphy_to_pd_wdev(wiphy))
+			rtw_pd_iface_free(wiphy);
+		else {
+			RTW_ERR(FUNC_WIPHY_FMT" unknown P2P Device wdev:%p\n", FUNC_WIPHY_ARG(wiphy), wdev);
+			rtw_warn_on(1);
+		}
+	} else
+#endif
+	{
+		ret = -EINVAL;
+		goto exit;
+	}
+
+exit:
+	rtw_set_rtnl_lock_holder(dvobj, NULL);
+	return ret;
+}
+
+static int rtw_add_beacon(_adapter *adapter, const u8 *head, size_t head_len, const u8 *tail, size_t tail_len)
+{
+	int ret = 0;
+	u8 *pbuf = NULL;
+	uint len, wps_ielen = 0;
+	uint p2p_ielen = 0;
+	u8 *p2p_ie;
+	u8 got_p2p_ie = false;
+	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
+	/* struct sta_priv *pstapriv = &padapter->stapriv; */
+
+
+	RTW_INFO("%s beacon_head_len=%zu, beacon_tail_len=%zu\n", __func__, head_len, tail_len);
+
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	if (head_len < 24)
+		return -EINVAL;
+
+
+	pbuf = rtw_zmalloc(head_len + tail_len);
+	if (!pbuf)
+		return -ENOMEM;
+
+
+	/* memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2); */
+
+	/* if((pstapriv->max_num_sta>NUM_STA) || (pstapriv->max_num_sta<=0)) */
+	/*	pstapriv->max_num_sta = NUM_STA; */
+
+
+	memcpy(pbuf, (void *)head + 24, head_len - 24); /* 24=beacon header len. */
+	memcpy(pbuf + head_len - 24, (void *)tail, tail_len);
+
+	len = head_len + tail_len - 24;
+
+	/* check wps ie if inclued */
+	if (rtw_get_wps_ie(pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL, &wps_ielen))
+		RTW_INFO("add bcn, wps_ielen=%d\n", wps_ielen);
+
+#ifdef CONFIG_P2P
+	if (adapter->wdinfo.driver_interface == DRIVER_CFG80211) {
+		/* check p2p if enable */
+		if (rtw_get_p2p_ie(pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL, &p2p_ielen)) {
+			struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+			struct wifidirect_info *pwdinfo = &(adapter->wdinfo);
+
+			RTW_INFO("got p2p_ie, len=%d\n", p2p_ielen);
+
+			got_p2p_ie = true;
+
+			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+				RTW_INFO("Enable P2P function for the first time\n");
+				rtw_p2p_enable(adapter, P2P_ROLE_GO);
+
+				adapter->stapriv.expire_to = 3; /* 3x2 = 6 sec in p2p mode */
+			} else {
+				RTW_INFO("enter GO Mode, p2p_ielen=%d\n", p2p_ielen);
+
+				rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+				pwdinfo->intent = 15;
+			}
+		}
+	}
+#endif /* CONFIG_P2P */
+
+	/* pbss_network->IEs will not include p2p_ie, wfd ie */
+	rtw_ies_remove_ie(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, P2P_OUI, 4);
+	rtw_ies_remove_ie(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, WFD_OUI, 4);
+
+	if (rtw_check_beacon_data(adapter, pbuf,  len) == _SUCCESS) {
+#ifdef CONFIG_P2P
+		/* check p2p if enable */
+		if (got_p2p_ie ) {
+			struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+			struct wifidirect_info *pwdinfo = &(adapter->wdinfo);
+			pwdinfo->operating_channel = pmlmeext->cur_channel;
+		}
+#endif /* CONFIG_P2P */
+		ret = 0;
+	} else
+		ret = -EINVAL;
+
+
+	rtw_mfree(pbuf, head_len + tail_len);
+
+	return ret;
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(COMPAT_KERNEL_RELEASE)
+static int cfg80211_rtw_add_beacon(struct wiphy *wiphy, struct net_device *ndev,
+		struct beacon_parameters *info)
+{
+	int ret = 0;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
+
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+	ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, info->tail_len);
+
+	return ret;
+}
+
+static int cfg80211_rtw_set_beacon(struct wiphy *wiphy, struct net_device *ndev,
+		struct beacon_parameters *info)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
+
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+	pmlmeext->bstart_bss = true;
+
+	cfg80211_rtw_add_beacon(wiphy, ndev, info);
+
+	return 0;
+}
+
+static int	cfg80211_rtw_del_beacon(struct wiphy *wiphy, struct net_device *ndev)
+{
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+	return 0;
+}
+#else
+static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,
+		struct cfg80211_ap_settings *settings)
+{
+	int ret = 0;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
+
+	RTW_INFO(FUNC_NDEV_FMT" hidden_ssid:%d, auth_type:%d\n", FUNC_NDEV_ARG(ndev),
+		settings->hidden_ssid, settings->auth_type);
+
+	ret = rtw_add_beacon(adapter, settings->beacon.head, settings->beacon.head_len,
+		settings->beacon.tail, settings->beacon.tail_len);
+
+	adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode = settings->hidden_ssid;
+
+	if (settings->ssid && settings->ssid_len) {
+		WLAN_BSSID_EX *pbss_network = &adapter->mlmepriv.cur_network.network;
+		WLAN_BSSID_EX *pbss_network_ext = &adapter->mlmeextpriv.mlmext_info.network;
+
+		if (0)
+			RTW_INFO(FUNC_ADPT_FMT" ssid:(%s,%zu), from ie:(%s,%d)\n", FUNC_ADPT_ARG(adapter),
+				settings->ssid, settings->ssid_len,
+				pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength);
+
+		memcpy(pbss_network->Ssid.Ssid, (void *)settings->ssid, settings->ssid_len);
+		pbss_network->Ssid.SsidLength = settings->ssid_len;
+		memcpy(pbss_network_ext->Ssid.Ssid, (void *)settings->ssid, settings->ssid_len);
+		pbss_network_ext->Ssid.SsidLength = settings->ssid_len;
+
+		if (0)
+			RTW_INFO(FUNC_ADPT_FMT" after ssid:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
+				pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
+				pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
+	}
+
+	return ret;
+}
+
+static int cfg80211_rtw_change_beacon(struct wiphy *wiphy, struct net_device *ndev,
+		struct cfg80211_beacon_data *info)
+{
+	int ret = 0;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
+
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+	ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, info->tail_len);
+
+	return ret;
+}
+
+static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
+{
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+	return 0;
+}
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) */
+
+#if CONFIG_RTW_MACADDR_ACL && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+static int cfg80211_rtw_set_mac_acl(struct wiphy *wiphy, struct net_device *ndev,
+		const struct cfg80211_acl_data *params)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
+	u8 acl_mode = RTW_ACL_MODE_DISABLED;
+	int ret = -1;
+	int i;
+
+	if (!params) {
+		RTW_WARN(FUNC_ADPT_FMT" params NULL\n", FUNC_ADPT_ARG(adapter));
+		goto exit;
+	}
+
+	RTW_INFO(FUNC_ADPT_FMT" acl_policy:%d, entry_num:%d\n"
+		, FUNC_ADPT_ARG(adapter), params->acl_policy, params->n_acl_entries);
+
+	if (params->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED)
+		acl_mode = RTW_ACL_MODE_ACCEPT_UNLESS_LISTED;
+	else if (params->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
+		acl_mode = RTW_ACL_MODE_DENY_UNLESS_LISTED;
+
+	if (!params->n_acl_entries) {
+		if (acl_mode != RTW_ACL_MODE_DISABLED)
+			RTW_WARN(FUNC_ADPT_FMT" acl_policy:%d with no entry\n"
+				, FUNC_ADPT_ARG(adapter), params->acl_policy);
+		acl_mode = RTW_ACL_MODE_DISABLED;
+		goto exit;
+	}
+
+	for (i = 0; i < params->n_acl_entries; i++)
+		rtw_acl_add_sta(adapter, params->mac_addrs[i].addr);
+
+	ret = 0;
+
+exit:
+	rtw_set_macaddr_acl(adapter, acl_mode);
+	return ret;
+}
+#endif /* CONFIG_RTW_MACADDR_ACL && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) */
+
+static int	cfg80211_rtw_add_station(struct wiphy *wiphy, struct net_device *ndev,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))
+	u8 *mac,
+#else
+	const u8 *mac,
+#endif
+	struct station_parameters *params)
+{
+	int ret = 0;
+#ifdef CONFIG_TDLS
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct sta_info *psta;
+#endif /* CONFIG_TDLS */
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+#ifdef CONFIG_TDLS
+	psta = rtw_get_stainfo(pstapriv, (u8 *)mac);
+	if (psta == NULL) {
+		psta = rtw_alloc_stainfo(pstapriv, (u8 *)mac);
+		if (psta == NULL) {
+			RTW_INFO("[%s] Alloc station for "MAC_FMT" fail\n", __func__, MAC_ARG(mac));
+			ret = -EOPNOTSUPP;
+			goto exit;
+		}
+	}
+#endif /* CONFIG_TDLS */
+
+exit:
+	return ret;
+}
+
+static int	cfg80211_rtw_del_station(struct wiphy *wiphy, struct net_device *ndev,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))
+	u8 *mac
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
+	const u8 *mac
+#else
+	struct station_del_parameters *params
+#endif
+)
+{
+	int ret = 0;
+	unsigned long irqL;
+	_list	*phead, *plist;
+	u8 updated = false;
+	const u8 *target_mac;
+	struct sta_info *psta = NULL;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	RTW_INFO("+"FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
+	target_mac = mac;
+#else
+	target_mac = params->mac;
+#endif
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true) {
+		RTW_INFO("%s, fw_state != FW_LINKED|WIFI_AP_STATE\n", __func__);
+		return -EINVAL;
+	}
+
+
+	if (!target_mac) {
+		RTW_INFO("flush all sta, and cam_entry\n");
+
+		flush_all_cam_entry(padapter);	/* clear CAM */
+
+		ret = rtw_sta_flush(padapter, true);
+
+		return ret;
+	}
+
+
+	RTW_INFO("free sta macaddr =" MAC_FMT "\n", MAC_ARG(target_mac));
+
+	if (target_mac[0] == 0xff && target_mac[1] == 0xff &&
+	    target_mac[2] == 0xff && target_mac[3] == 0xff &&
+	    target_mac[4] == 0xff && target_mac[5] == 0xff)
+		return -EINVAL;
+
+
+	_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);
+
+		if (!memcmp((u8 *)target_mac, psta->hwaddr, ETH_ALEN)) {
+			if (psta->dot8021xalg == 1 && psta->bpairwise_key_installed == false)
+				RTW_INFO("%s, sta's dot8021xalg = 1 and key_installed = false\n", __func__);
+			else {
+				RTW_INFO("free psta=%p, aid=%d\n", psta, psta->aid);
+
+				list_del_init(&psta->asoc_list);
+				pstapriv->asoc_list_cnt--;
+
+				/* _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); */
+				if (check_fwstate(pmlmepriv, (WIFI_AP_STATE)) )
+					updated = ap_free_sta(padapter, psta, true, WLAN_REASON_PREV_AUTH_NOT_VALID, true);
+				else
+					updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING, true);
+				/* _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); */
+
+				psta = NULL;
+
+				break;
+			}
+
+		}
+
+	}
+
+	_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+	associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);
+
+	RTW_INFO("-"FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+	return ret;
+
+}
+
+static int	cfg80211_rtw_change_station(struct wiphy *wiphy, struct net_device *ndev,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))
+	u8 *mac,
+#else
+	const u8 *mac,
+#endif
+	struct station_parameters *params)
+{
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+	return 0;
+}
+
+static struct sta_info *rtw_sta_info_get_by_idx(const int idx, struct sta_priv *pstapriv)
+
+{
+
+	_list	*phead, *plist;
+	struct sta_info *psta = NULL;
+	int i = 0;
+
+	phead = &pstapriv->asoc_list;
+	plist = get_next(phead);
+
+	/* check asoc_queue */
+	while ((rtw_end_of_queue_search(phead, plist)) == false) {
+		if (idx == i)
+			psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+		plist = get_next(plist);
+		i++;
+	}
+	return psta;
+}
+
+static int	cfg80211_rtw_dump_station(struct wiphy *wiphy, struct net_device *ndev,
+		int idx, u8 *mac, struct station_info *sinfo)
+{
+
+	int ret = 0;
+	unsigned long irqL;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct sta_info *psta = NULL;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+	_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+	psta = rtw_sta_info_get_by_idx(idx, pstapriv);
+	_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+	if (NULL == psta) {
+		RTW_INFO("Station is not found\n");
+		ret = -ENOENT;
+		goto exit;
+	}
+	memcpy(mac, psta->hwaddr, ETH_ALEN);
+	sinfo->filled = 0;
+	sinfo->filled |= STATION_INFO_SIGNAL;
+	sinfo->signal = psta->rssi;
+
+exit:
+	return ret;
+}
+
+static int	cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,
+		struct bss_parameters *params)
+{
+	u8 i;
+
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+/*
+	RTW_INFO("use_cts_prot=%d\n", params->use_cts_prot);
+	RTW_INFO("use_short_preamble=%d\n", params->use_short_preamble);
+	RTW_INFO("use_short_slot_time=%d\n", params->use_short_slot_time);
+	RTW_INFO("ap_isolate=%d\n", params->ap_isolate);
+
+	RTW_INFO("basic_rates_len=%d\n", params->basic_rates_len);
+	for(i = 0; i < params->basic_rates_len; i++)
+		RTW_INFO("basic_rates=%d\n", params->basic_rates[i]);
+*/
+	return 0;
+
+}
+
+static int	cfg80211_rtw_set_channel(struct wiphy *wiphy
+	#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	, struct net_device *ndev
+	#endif
+	, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+#else
+	_adapter *padapter = wiphy_to_adapter(wiphy);
+#endif
+	int chan_target = (u8) ieee80211_frequency_to_channel(chan->center_freq);
+	int chan_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	int chan_width = CHANNEL_WIDTH_20;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+#endif
+
+	switch (channel_type) {
+	case NL80211_CHAN_NO_HT:
+	case NL80211_CHAN_HT20:
+		chan_width = CHANNEL_WIDTH_20;
+		chan_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		break;
+	case NL80211_CHAN_HT40MINUS:
+		chan_width = CHANNEL_WIDTH_40;
+		chan_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+		break;
+	case NL80211_CHAN_HT40PLUS:
+		chan_width = CHANNEL_WIDTH_40;
+		chan_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+		break;
+	default:
+		chan_width = CHANNEL_WIDTH_20;
+		chan_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		break;
+	}
+
+	set_channel_bwmode(padapter, chan_target, chan_offset, chan_width);
+
+	return 0;
+}
+
+static int cfg80211_rtw_set_monitor_channel(struct wiphy *wiphy
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+	, struct cfg80211_chan_def *chandef
+#else
+	, struct ieee80211_channel *chan
+	, enum nl80211_channel_type channel_type
+#endif
+)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+	struct ieee80211_channel *chan = chandef->chan;
+#endif
+
+	_adapter *padapter = wiphy_to_adapter(wiphy);
+	int target_channal = chan->hw_value;
+	int target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	int target_width = CHANNEL_WIDTH_20;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+#ifdef CONFIG_DEBUG_CFG80211
+	RTW_INFO("center_freq %u Mhz ch %u width %u freq1 %u freq2 %u\n"
+		, chan->center_freq
+		, chan->hw_value
+		, chandef->width
+		, chandef->center_freq1
+		, chandef->center_freq2);
+#endif /* CONFIG_DEBUG_CFG80211 */
+
+	switch (chandef->width) {
+	case NL80211_CHAN_WIDTH_20_NOHT:
+	case NL80211_CHAN_WIDTH_20:
+		target_width = CHANNEL_WIDTH_20;
+		target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		break;
+	case NL80211_CHAN_WIDTH_40:
+		target_width = CHANNEL_WIDTH_40;
+		if (chandef->center_freq1 > chan->center_freq)
+			target_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+		else
+			target_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+		break;
+	case NL80211_CHAN_WIDTH_80:
+		target_width = CHANNEL_WIDTH_80;
+		target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		break;
+	case NL80211_CHAN_WIDTH_80P80:
+		target_width = CHANNEL_WIDTH_80_80;
+		target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		break;
+	case NL80211_CHAN_WIDTH_160:
+		target_width = CHANNEL_WIDTH_160;
+		target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		break;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+	case NL80211_CHAN_WIDTH_5:
+	case NL80211_CHAN_WIDTH_10:
+#endif
+	default:
+		target_width = CHANNEL_WIDTH_20;
+		target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		break;
+	}
+#else
+#ifdef CONFIG_DEBUG_CFG80211
+	RTW_INFO("center_freq %u Mhz ch %u channel_type %u\n"
+		, chan->center_freq
+		, chan->hw_value
+		, channel_type);
+#endif /* CONFIG_DEBUG_CFG80211 */
+
+	switch (channel_type) {
+	case NL80211_CHAN_NO_HT:
+	case NL80211_CHAN_HT20:
+		target_width = CHANNEL_WIDTH_20;
+		target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		break;
+	case NL80211_CHAN_HT40MINUS:
+		target_width = CHANNEL_WIDTH_40;
+		target_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+		break;
+	case NL80211_CHAN_HT40PLUS:
+		target_width = CHANNEL_WIDTH_40;
+		target_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+		break;
+	default:
+		target_width = CHANNEL_WIDTH_20;
+		target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		break;
+	}
+#endif
+
+	set_channel_bwmode(padapter, target_channal, target_offset, target_width);
+
+	return 0;
+}
+
+static int	cfg80211_rtw_auth(struct wiphy *wiphy, struct net_device *ndev,
+		struct cfg80211_auth_request *req)
+{
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+	return 0;
+}
+
+static int	cfg80211_rtw_assoc(struct wiphy *wiphy, struct net_device *ndev,
+		struct cfg80211_assoc_request *req)
+{
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+	return 0;
+}
+#endif /* CONFIG_AP_MODE */
+
+void rtw_cfg80211_rx_probe_request(_adapter *adapter, union recv_frame *rframe)
+{
+	struct wireless_dev *wdev = adapter->rtw_wdev;
+	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
+	u8 *frame = get_recvframe_data(rframe);
+	uint frame_len = rframe->u.hdr.len;
+	s32 freq;
+	u8 ch, sch = rtw_get_oper_ch(adapter);
+
+	ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;
+	freq = rtw_ch2freq(ch);
+
+#ifdef CONFIG_DEBUG_CFG80211
+	RTW_INFO("RTW_Rx: probe request, ch=%d(%d)\n", ch, sch);
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+	rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);
+#else
+	cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);
+#endif
+}
+
+void rtw_cfg80211_rx_action_p2p(_adapter *adapter, union recv_frame *rframe)
+{
+	struct wireless_dev *wdev = adapter->rtw_wdev;
+	u8 *frame = get_recvframe_data(rframe);
+	uint frame_len = rframe->u.hdr.len;
+	s32 freq;
+	u8 ch, sch = rtw_get_oper_ch(adapter);
+	u8 category, action;
+	int type;
+
+	ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;
+	freq = rtw_ch2freq(ch);
+
+	RTW_INFO("RTW_Rx:ch=%d(%d)\n", ch, sch);
+#ifdef CONFIG_P2P
+	type = rtw_p2p_check_frames(adapter, frame, frame_len, false);
+	if (type >= 0)
+		goto indicate;
+#endif
+	rtw_action_frame_parse(frame, frame_len, &category, &action);
+	RTW_INFO("RTW_Rx:category(%u), action(%u)\n", category, action);
+
+indicate:
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+	rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);
+#else
+	cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);
+#endif
+}
+
+void rtw_cfg80211_rx_p2p_action_public(_adapter *adapter, union recv_frame *rframe)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct wireless_dev *wdev = adapter->rtw_wdev;
+	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
+	u8 *frame = get_recvframe_data(rframe);
+	uint frame_len = rframe->u.hdr.len;
+	s32 freq;
+	u8 ch, sch = rtw_get_oper_ch(adapter);
+	u8 category, action;
+	int type;
+
+	ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;
+	freq = rtw_ch2freq(ch);
+
+	RTW_INFO("RTW_Rx:ch=%d(%d)\n", ch, sch);
+	#ifdef CONFIG_P2P
+	type = rtw_p2p_check_frames(adapter, frame, frame_len, false);
+	if (type >= 0) {
+		switch (type) {
+		case P2P_GO_NEGO_CONF:
+			if (0) {
+				RTW_INFO(FUNC_ADPT_FMT" Nego confirm. state=%u, status=%u, iaddr="MAC_FMT"\n"
+					, FUNC_ADPT_ARG(adapter), pwdev_priv->nego_info.state, pwdev_priv->nego_info.status
+					, MAC_ARG(pwdev_priv->nego_info.iface_addr));
+			}
+			if (pwdev_priv->nego_info.state == 2
+				&& pwdev_priv->nego_info.status == 0
+				&& rtw_check_invalid_mac_address(pwdev_priv->nego_info.iface_addr, false) == false
+			) {
+				_adapter *intended_iface = dvobj_get_adapter_by_addr(dvobj, pwdev_priv->nego_info.iface_addr);
+
+				if (intended_iface) {
+					RTW_INFO(FUNC_ADPT_FMT" Nego confirm. Allow only "ADPT_FMT" to scan for 2000 ms\n"
+						, FUNC_ADPT_ARG(adapter), ADPT_ARG(intended_iface));
+					/* allow only intended_iface to do scan for 2000 ms */
+					rtw_mi_set_scan_deny(adapter, 2000);
+					rtw_clear_scan_deny(intended_iface);
+				}
+			}
+			break;
+		case P2P_PROVISION_DISC_RESP:
+		case P2P_INVIT_RESP:
+			#if !RTW_P2P_GROUP_INTERFACE
+			rtw_mi_buddy_set_scan_deny(adapter, 2000);
+			#endif
+			break;
+		}
+		goto indicate;
+	}
+	#endif
+	rtw_action_frame_parse(frame, frame_len, &category, &action);
+	RTW_INFO("RTW_Rx:category(%u), action(%u)\n", category, action);
+
+indicate:
+	#if defined(RTW_DEDICATED_P2P_DEVICE)
+	if (rtw_cfg80211_redirect_pd_wdev(dvobj_to_wiphy(dvobj), get_ra(frame), &wdev))
+		if (0)
+			RTW_INFO("redirect to pd_wdev:%p\n", wdev);
+	#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+	rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);
+#else
+	cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);
+#endif
+}
+
+void rtw_cfg80211_rx_action(_adapter *adapter, union recv_frame *rframe, const char *msg)
+{
+	struct wireless_dev *wdev = adapter->rtw_wdev;
+	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
+	u8 *frame = get_recvframe_data(rframe);
+	uint frame_len = rframe->u.hdr.len;
+	s32 freq;
+	u8 ch, sch = rtw_get_oper_ch(adapter);
+	u8 category, action;
+
+	ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;
+	freq = rtw_ch2freq(ch);
+
+	rtw_action_frame_parse(frame, frame_len, &category, &action);
+
+	if (action == ACT_PUBLIC_GAS_INITIAL_REQ) {
+		rtw_mi_set_scan_deny(adapter, 200);
+		rtw_mi_scan_abort(adapter, false); /*rtw_scan_abort_no_wait*/
+	}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+	rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);
+#else
+	cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);
+#endif
+
+	RTW_INFO("RTW_Rx:ch=%d(%d)\n", ch, sch);
+	if (msg)
+		RTW_INFO("RTW_Rx:%s\n", msg);
+	else
+		RTW_INFO("RTW_Rx:category(%u), action(%u)\n", category, action);
+}
+
+#ifdef CONFIG_P2P
+void rtw_cfg80211_issue_p2p_provision_request(_adapter *padapter, const u8 *buf, size_t len)
+{
+	u16	wps_devicepassword_id = 0x0000;
+	uint	wps_devicepassword_id_len = 0;
+	u8			wpsie[255] = { 0x00 }, p2p_ie[255] = { 0x00 };
+	uint			p2p_ielen = 0;
+	uint			wpsielen = 0;
+	u32	devinfo_contentlen = 0;
+	u8	devinfo_content[64] = { 0x00 };
+	u16	capability = 0;
+	uint capability_len = 0;
+
+	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+	u8			action = P2P_PUB_ACTION_ACTION;
+	u8			dialogToken = 1;
+	__be32			p2poui = cpu_to_be32(P2POUI);
+	u8			oui_subtype = P2P_PROVISION_DISC_REQ;
+	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;
+	__le16 *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);
+	u8 *frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr));
+	size_t frame_body_len = len - sizeof(struct rtw_ieee80211_hdr_3addr);
+	__be16 be_tmp;
+
+	RTW_INFO("[%s] In\n", __func__);
+
+	/* prepare for building provision_request frame	 */
+	memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr1Ptr(buf), ETH_ALEN);
+	memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, GetAddr1Ptr(buf), ETH_ALEN);
+
+	pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
+
+	rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
+	rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8 *)&be_tmp, &wps_devicepassword_id_len);
+	wps_devicepassword_id = be16_to_cpu(be_tmp);
+
+	switch (wps_devicepassword_id) {
+	case WPS_DPID_PIN:
+		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
+		break;
+	case WPS_DPID_USER_SPEC:
+		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
+		break;
+	case WPS_DPID_MACHINE_SPEC:
+		break;
+	case WPS_DPID_REKEY:
+		break;
+	case WPS_DPID_PBC:
+		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
+		break;
+	case WPS_DPID_REGISTRAR_SPEC:
+		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
+		break;
+	default:
+		break;
+	}
+
+	if (rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, p2p_ie, &p2p_ielen)) {
+		rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, devinfo_content, &devinfo_contentlen);
+		rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&capability, &capability_len);
+	}
+
+	/* start to build provision_request frame	 */
+	memset(wpsie, 0, sizeof(wpsie));
+	memset(p2p_ie, 0, sizeof(p2p_ie));
+	p2p_ielen = 0;
+
+	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+	if (pmgntframe == NULL)
+		return;
+
+	/* update attribute */
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	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;
+
+	memcpy(pwlanhdr->addr1, pwdinfo->tx_prov_disc_info.peerDevAddr, ETH_ALEN);
+	memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	memcpy(pwlanhdr->addr3, pwdinfo->tx_prov_disc_info.peerDevAddr, ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	set_frame_sub_type(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));
+
+
+	/* build_prov_disc_request_p2p_ie	 */
+	/*	P2P OUI */
+	p2pielen = 0;
+	p2p_ie[p2pielen++] = 0x50;
+	p2p_ie[p2pielen++] = 0x6F;
+	p2p_ie[p2pielen++] = 0x9A;
+	p2p_ie[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:	 */
+	p2p_ie[p2pielen++] = P2P_ATTR_CAPABILITY;
+
+	/*	Length: */
+	/* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 ); */
+	RTW_PUT_LE16(p2p_ie + p2pielen, 0x0002);
+	p2pielen += 2;
+
+	/*	Value: */
+	/*	Device Capability Bitmap, 1 byte */
+	/*	Group Capability Bitmap, 1 byte */
+	memcpy(p2p_ie + p2pielen, &capability, 2);
+	p2pielen += 2;
+
+
+	/*	Device Info ATTR */
+	/*	Type: */
+	p2p_ie[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(p2p_ie + p2pielen, devinfo_contentlen);
+	p2pielen += 2;
+
+	/*	Value: */
+	memcpy(p2p_ie + p2pielen, devinfo_content, devinfo_contentlen);
+	p2pielen += devinfo_contentlen;
+
+
+	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2p_ie, &p2p_ielen);
+	/* p2pielen = build_prov_disc_request_p2p_ie( pwdinfo, pframe, NULL, 0, pwdinfo->tx_prov_disc_info.peerDevAddr); */
+	/* pframe += p2pielen; */
+	pattrib->pktlen += p2p_ielen;
+
+	wpsielen = 0;
+	/*	WPS OUI */
+	*(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
+	wpsielen += 4;
+
+	/*	WPS version */
+	/*	Type: */
+	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
+	wpsielen += 2;
+
+	/*	Length: */
+	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
+	wpsielen += 2;
+
+	/*	Value: */
+	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
+
+	/*	Config Method */
+	/*	Type: */
+	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
+	wpsielen += 2;
+
+	/*	Length: */
+	*(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
+	wpsielen += 2;
+
+	/*	Value: */
+	*(__be16 *)(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); */
+	if (dump_mgntframe_and_wait_ack(padapter, pmgntframe) != _SUCCESS)
+		RTW_INFO("%s, ack to\n", __func__);
+}
+
+#ifdef CONFIG_RTW_80211R
+static s32 cfg80211_rtw_update_ft_ies(struct wiphy *wiphy,
+	struct net_device *ndev,
+	struct cfg80211_update_ft_ies_params *ftie)
+{
+	_adapter *padapter = NULL;
+	struct mlme_priv *pmlmepriv = NULL;
+	ft_priv *pftpriv = NULL;
+	unsigned long irqL;
+	u8 *p;
+	u8 *pie = NULL;
+	u32 ie_len = 0;
+
+	if (ndev == NULL)
+		return  -EINVAL;
+
+	padapter = (_adapter *)rtw_netdev_priv(ndev);
+	pmlmepriv = &(padapter->mlmepriv);
+	pftpriv = &pmlmepriv->ftpriv;
+
+	p = (u8 *)ftie->ie;
+	if (ftie->ie_len <= sizeof(pftpriv->updated_ft_ies)) {
+		_enter_critical_bh(&pmlmepriv->lock, &irqL);
+		memcpy(pftpriv->updated_ft_ies, ftie->ie, ftie->ie_len);
+		pftpriv->updated_ft_ies_len = ftie->ie_len;
+		_exit_critical_bh(&pmlmepriv->lock, &irqL);
+	} else {
+		RTW_ERR("FTIEs parsing fail!\n");
+		return -EINVAL;
+	}
+
+	if ((rtw_to_roam(padapter) > 0) && rtw_chk_ft_status(padapter, RTW_FT_AUTHENTICATED_STA)) {
+		RTW_INFO("auth success, start reassoc\n");
+		_enter_critical_bh(&pmlmepriv->lock, &irqL);
+		rtw_set_ft_status(padapter, RTW_FT_ASSOCIATING_STA);
+		_exit_critical_bh(&pmlmepriv->lock, &irqL);
+		start_clnt_assoc(padapter);
+	}
+
+	return 0;
+}
+#endif
+
+inline void rtw_cfg80211_set_is_roch(_adapter *adapter, bool val)
+{
+	adapter->cfg80211_wdinfo.is_ro_ch = val;
+	rtw_mi_update_iface_status(&(adapter->mlmepriv), 0);
+}
+
+inline bool rtw_cfg80211_get_is_roch(_adapter *adapter)
+{
+	return adapter->cfg80211_wdinfo.is_ro_ch;
+}
+
+static s32 cfg80211_rtw_remain_on_channel(struct wiphy *wiphy,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	struct wireless_dev *wdev,
+#else
+	struct net_device *ndev,
+#endif
+	struct ieee80211_channel *channel,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
+	enum nl80211_channel_type channel_type,
+#endif
+	unsigned int duration, u64 *cookie)
+{
+	s32 err = 0;
+	u8 remain_ch = (u8) ieee80211_frequency_to_channel(channel->center_freq);
+	u8 union_ch = 0, union_bw = 0, union_offset = 0;
+	u8 i;
+	u8 ready_on_channel = false;
+	_adapter *padapter = NULL;
+	_adapter *iface;
+	struct dvobj_priv *dvobj;
+	struct rtw_wdev_priv *pwdev_priv;
+	struct mlme_ext_priv *pmlmeext;
+	struct wifidirect_info *pwdinfo;
+	struct cfg80211_wifidirect_info *pcfg80211_wdinfo;
+	u8 is_p2p_find = false;
+
+#ifndef CONFIG_RADIO_WORK
+#define RTW_ROCH_DURATION_ENLARGE
+#define RTW_ROCH_BACK_OP
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	#if defined(RTW_DEDICATED_P2P_DEVICE)
+	if (wdev == wiphy_to_pd_wdev(wiphy))
+		padapter = wiphy_to_adapter(wiphy);
+	else
+	#endif
+	if (wdev_to_ndev(wdev))
+		padapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));
+	else {
+		err = -EINVAL;
+		goto exit;
+	}
+#else
+	struct wireless_dev *wdev;
+
+	if (ndev == NULL) {
+		err = -EINVAL;
+		goto exit;
+	}
+	padapter = (_adapter *)rtw_netdev_priv(ndev);
+	wdev = ndev_to_wdev(ndev);
+#endif
+
+	dvobj = adapter_to_dvobj(padapter);
+	pwdev_priv = adapter_wdev_data(padapter);
+	pmlmeext = &padapter->mlmeextpriv;
+	pwdinfo = &padapter->wdinfo;
+	pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
+#ifdef CONFIG_CONCURRENT_MODE
+	is_p2p_find = (duration < (pwdinfo->ext_listen_interval)) ? true : false;
+#endif
+
+	*cookie = ATOMIC_INC_RETURN(&pcfg80211_wdinfo->ro_ch_cookie_gen);
+
+	RTW_INFO(FUNC_ADPT_FMT"%s ch:%u duration:%d, cookie:0x%llx\n"
+		, FUNC_ADPT_ARG(padapter), wdev == wiphy_to_pd_wdev(wiphy) ? " PD" : ""
+		, remain_ch, duration, *cookie);
+
+	if (rtw_ch_set_search_ch(pmlmeext->channel_set, remain_ch) < 0) {
+		RTW_WARN(FUNC_ADPT_FMT" invalid ch:%u\n", FUNC_ADPT_ARG(padapter), remain_ch);
+		err = -EFAULT;
+		goto exit;
+	}
+
+#ifdef CONFIG_MP_INCLUDED
+	if (rtw_mi_mp_mode_check(padapter)) {
+		RTW_INFO("MP mode block remain_on_channel request\n");
+		err = -EFAULT;
+		goto exit;
+	}
+#endif
+
+	if (_FAIL == rtw_pwr_wakeup(padapter)) {
+		err = -EFAULT;
+		goto exit;
+	}
+
+	rtw_scan_abort(padapter);
+#ifdef CONFIG_CONCURRENT_MODE
+	/*don't scan_abort during p2p_listen.*/
+	if (is_p2p_find)
+		rtw_mi_buddy_scan_abort(padapter, true);
+#endif /*CONFIG_CONCURRENT_MODE*/
+
+	if (rtw_cfg80211_get_is_roch(padapter) ) {
+		_cancel_timer_ex(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
+		p2p_cancel_roch_cmd(padapter, 0, NULL, RTW_CMDF_WAIT_ACK);
+	}
+
+	/* if(!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) && !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) */
+	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+		rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);
+		padapter->wdinfo.listen_channel = remain_ch;
+		RTW_INFO(FUNC_ADPT_FMT" init listen_channel %u\n"
+			, FUNC_ADPT_ARG(padapter), padapter->wdinfo.listen_channel);
+	} else if (rtw_p2p_chk_state(pwdinfo , P2P_STATE_LISTEN)
+		&& (time_after_eq((unsigned long)jiffies, (unsigned long)pwdev_priv->probe_resp_ie_update_time)
+			&& rtw_get_passing_time_ms(pwdev_priv->probe_resp_ie_update_time) < 50)
+	) {
+		if (padapter->wdinfo.listen_channel != remain_ch) {
+			padapter->wdinfo.listen_channel = remain_ch;
+			RTW_INFO(FUNC_ADPT_FMT" update listen_channel %u\n"
+				, FUNC_ADPT_ARG(padapter), padapter->wdinfo.listen_channel);
+		}
+	} else {
+		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+		#ifdef CONFIG_DEBUG_CFG80211
+		RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
+		#endif
+	}
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		iface = dvobj->padapters[i];
+		if (check_fwstate(&iface->mlmepriv, _FW_UNDER_LINKING | WIFI_UNDER_WPS) ) {
+			RTW_INFO(ADPT_FMT"- _FW_UNDER_LINKING |WIFI_UNDER_WPS (mlme state:0x%x)\n", ADPT_ARG(iface), get_fwstate(&iface->mlmepriv));
+			remain_ch = iface->mlmeextpriv.cur_channel;
+		}
+	}
+
+	rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
+
+	#ifdef RTW_ROCH_DURATION_ENLARGE
+	if (duration < 400)
+		duration = duration * 3; /* extend from exper */
+	#endif
+
+#if defined(RTW_ROCH_BACK_OP) && defined(CONFIG_CONCURRENT_MODE)
+	if (rtw_mi_check_status(padapter, MI_LINKED)) {
+		if (is_p2p_find) /* p2p_find , duration<1000 */
+			duration = duration + pwdinfo->ext_listen_interval;
+		else /* p2p_listen, duration=5000 */
+			duration = pwdinfo->ext_listen_interval + (pwdinfo->ext_listen_interval / 4);
+	}
+#endif /*defined (RTW_ROCH_BACK_OP) && defined(CONFIG_CONCURRENT_MODE) */
+
+	rtw_cfg80211_set_is_roch(padapter, true);
+	pcfg80211_wdinfo->ro_ch_wdev = wdev;
+	pcfg80211_wdinfo->remain_on_ch_cookie = *cookie;
+	pcfg80211_wdinfo->last_ro_ch_time = jiffies;
+	memcpy(&pcfg80211_wdinfo->remain_on_ch_channel, channel, sizeof(struct ieee80211_channel));
+	#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
+	pcfg80211_wdinfo->remain_on_ch_type = channel_type;
+	#endif
+	pcfg80211_wdinfo->restore_channel = rtw_get_oper_ch(padapter);
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (rtw_mi_check_status(padapter, MI_LINKED) && (0 != rtw_mi_get_union_chan(padapter))) {
+		if ((remain_ch != rtw_mi_get_union_chan(padapter)) && !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
+			if (ATOMIC_READ(&pwdev_priv->switch_ch_to) == 1 ||
+				(remain_ch != pmlmeext->cur_channel)) {
+
+				rtw_mi_buddy_issue_nulldata(padapter, NULL, 1, 3, 500);
+				ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);
+
+				#ifdef RTW_ROCH_BACK_OP
+				RTW_INFO("%s, set switch ch timer, duration=%d\n", __func__, duration - pwdinfo->ext_listen_interval);
+				_set_timer(&pwdinfo->ap_p2p_switch_timer, duration - pwdinfo->ext_listen_interval);
+				#endif
+			}
+		}
+		ready_on_channel = true;
+	} else
+#endif /* CONFIG_CONCURRENT_MODE */
+	{
+		if (remain_ch != rtw_get_oper_ch(padapter))
+			ready_on_channel = true;
+	}
+
+	if (ready_on_channel ) {
+		#ifndef RTW_SINGLE_WIPHY
+		if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
+		#endif
+		{
+			#ifdef CONFIG_CONCURRENT_MODE
+			if (rtw_get_oper_ch(padapter) != remain_ch)
+			#endif
+			{
+				/* if (!padapter->mlmepriv.LinkDetectInfo.bBusyTraffic) */
+				set_channel_bwmode(padapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+			}
+		}
+	}
+
+#ifdef CONFIG_BT_COEXIST
+	rtw_btcoex_ScanNotify(padapter, true);
+#endif
+
+	RTW_INFO("%s, set ro ch timer, duration=%d\n", __func__, duration);
+	_set_timer(&pcfg80211_wdinfo->remain_on_ch_timer, duration);
+
+	rtw_cfg80211_ready_on_channel(wdev, *cookie, channel, channel_type, duration, GFP_KERNEL);
+
+exit:
+	return err;
+}
+
+static s32 cfg80211_rtw_cancel_remain_on_channel(struct wiphy *wiphy,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	struct wireless_dev *wdev,
+#else
+	struct net_device *ndev,
+#endif
+	u64 cookie)
+{
+	s32 err = 0;
+	_adapter *padapter;
+	struct rtw_wdev_priv *pwdev_priv;
+	struct wifidirect_info *pwdinfo;
+	struct cfg80211_wifidirect_info *pcfg80211_wdinfo;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	#if defined(RTW_DEDICATED_P2P_DEVICE)
+	if (wdev == wiphy_to_pd_wdev(wiphy))
+		padapter = wiphy_to_adapter(wiphy);
+	else
+	#endif
+	if (wdev_to_ndev(wdev))
+		padapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));
+	else {
+		err = -EINVAL;
+		goto exit;
+	}
+#else
+	struct wireless_dev *wdev;
+
+	if (ndev == NULL) {
+		err = -EINVAL;
+		goto exit;
+	}
+	padapter = (_adapter *)rtw_netdev_priv(ndev);
+	wdev = ndev_to_wdev(ndev);
+#endif
+
+	pwdev_priv = adapter_wdev_data(padapter);
+	pwdinfo = &padapter->wdinfo;
+	pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
+
+	RTW_INFO(FUNC_ADPT_FMT"%s cookie:0x%llx\n"
+		, FUNC_ADPT_ARG(padapter), wdev == wiphy_to_pd_wdev(wiphy) ? " PD" : ""
+		, cookie);
+
+	if (rtw_cfg80211_get_is_roch(padapter) ) {
+		_cancel_timer_ex(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
+		p2p_cancel_roch_cmd(padapter, cookie, wdev, RTW_CMDF_WAIT_ACK);
+	}
+
+exit:
+	return err;
+}
+
+inline int rtw_cfg80211_iface_has_p2p_group_cap(_adapter *adapter)
+{
+	struct wiphy *wiphy = adapter_to_wiphy(adapter);
+	struct rtw_wdev_priv *wdev_data = adapter_wdev_data(adapter);
+
+#if RTW_P2P_GROUP_INTERFACE
+	if (is_primary_adapter(adapter))
+		return 0;
+#endif
+	return 1;
+}
+
+inline int rtw_cfg80211_is_p2p_scan(_adapter *adapter)
+{
+#if RTW_P2P_GROUP_INTERFACE
+	if (rtw_cfg80211_iface_has_p2p_group_cap(adapter))
+#endif
+	{
+		struct wifidirect_info *wdinfo = &adapter->wdinfo;
+
+		return rtw_p2p_chk_state(wdinfo, P2P_STATE_SCAN)
+			|| rtw_p2p_chk_state(wdinfo, P2P_STATE_FIND_PHASE_SEARCH);
+	}
+
+#if RTW_P2P_GROUP_INTERFACE
+	#if defined(RTW_DEDICATED_P2P_DEVICE)
+	if (wiphy_to_pd_wdev(adapter_to_wiphy(adapter))) /* pd_wdev exist */
+		return rtw_cfg80211_is_scan_by_pd_wdev(adapter);
+	#endif
+	{
+		/*
+		* For 2 RTW_P2P_GROUP_INTERFACE cases:
+		* 1. RTW_DEDICATED_P2P_DEVICE defined but upper layer don't use pd_wdev or
+		* 2. RTW_DEDICATED_P2P_DEVICE not defined
+		*/
+		struct rtw_wdev_priv *wdev_data = adapter_wdev_data(adapter);
+		unsigned long irqL;
+		int is_p2p_scan = 0;
+
+		_enter_critical_bh(&wdev_data->scan_req_lock, &irqL);
+		if (wdev_data->scan_request
+			&& wdev_data->scan_request->ssids
+			&& wdev_data->scan_request->ie
+		) {
+			if (!memcmp(wdev_data->scan_request->ssids->ssid, "DIRECT-", 7)
+				&& rtw_get_p2p_ie((u8 *)wdev_data->scan_request->ie, wdev_data->scan_request->ie_len, NULL, NULL))
+				is_p2p_scan = 1;
+		}
+		_exit_critical_bh(&wdev_data->scan_req_lock, &irqL);
+
+		return is_p2p_scan;
+	}
+#endif
+}
+
+#if defined(RTW_DEDICATED_P2P_DEVICE)
+int rtw_pd_iface_alloc(struct wiphy *wiphy, const char *name, struct wireless_dev **pd_wdev)
+{
+	struct rtw_wiphy_data *wiphy_data = rtw_wiphy_priv(wiphy);
+	struct wireless_dev *wdev = NULL;
+	struct rtw_netdev_priv_indicator *npi;
+	_adapter *primary_adpt = wiphy_to_adapter(wiphy);
+	int ret = 0;
+
+	if (wiphy_data->pd_wdev) {
+		RTW_WARN(FUNC_WIPHY_FMT" pd_wdev already exists\n", FUNC_WIPHY_ARG(wiphy));
+		ret = -EBUSY;
+		goto exit;
+	}
+
+	wdev = (struct wireless_dev *)rtw_zmalloc(sizeof(struct wireless_dev));
+	if (!wdev) {
+		RTW_WARN(FUNC_WIPHY_FMT" allocate wdev fail\n", FUNC_WIPHY_ARG(wiphy));
+		ret = -ENOMEM;
+		goto exit;
+	}
+
+	wdev->wiphy = wiphy;
+	wdev->iftype = NL80211_IFTYPE_P2P_DEVICE;
+	memcpy(wdev->address, adapter_mac_addr(primary_adpt), ETH_ALEN);
+
+	wiphy_data->pd_wdev = wdev;
+	*pd_wdev = wdev;
+
+	RTW_INFO(FUNC_WIPHY_FMT" pd_wdev:%p, addr="MAC_FMT" added\n"
+		, FUNC_WIPHY_ARG(wiphy), wdev, MAC_ARG(wdev_address(wdev)));
+
+exit:
+	if (ret && wdev) {
+		rtw_mfree((u8 *)wdev, sizeof(struct wireless_dev));
+		wdev = NULL;
+	}
+
+	return ret;
+}
+
+void rtw_pd_iface_free(struct wiphy *wiphy)
+{
+	struct dvobj_priv *dvobj = wiphy_to_dvobj(wiphy);
+	struct rtw_wiphy_data *wiphy_data = rtw_wiphy_priv(wiphy);
+	u8 rtnl_lock_needed;
+
+	if (!wiphy_data->pd_wdev)
+		goto exit;
+
+	RTW_INFO(FUNC_WIPHY_FMT" pd_wdev:%p, addr="MAC_FMT"\n"
+		, FUNC_WIPHY_ARG(wiphy), wiphy_data->pd_wdev
+		, MAC_ARG(wdev_address(wiphy_data->pd_wdev)));
+
+	rtnl_lock_needed = rtw_rtnl_lock_needed(dvobj);
+	if (rtnl_lock_needed)
+		rtnl_lock();
+	cfg80211_unregister_wdev(wiphy_data->pd_wdev);
+	if (rtnl_lock_needed)
+		rtnl_unlock();
+
+	rtw_mfree((u8 *)wiphy_data->pd_wdev, sizeof(struct wireless_dev));
+	wiphy_data->pd_wdev = NULL;
+
+exit:
+	return;
+}
+
+static int cfg80211_rtw_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+	_adapter *adapter = wiphy_to_adapter(wiphy);
+
+	RTW_INFO(FUNC_WIPHY_FMT" wdev=%p\n", FUNC_WIPHY_ARG(wiphy), wdev);
+
+	rtw_p2p_enable(adapter, P2P_ROLE_DEVICE);
+	return 0;
+}
+
+static void cfg80211_rtw_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+	_adapter *adapter = wiphy_to_adapter(wiphy);
+
+	RTW_INFO(FUNC_WIPHY_FMT" wdev=%p\n", FUNC_WIPHY_ARG(wiphy), wdev);
+
+	if (rtw_cfg80211_is_p2p_scan(adapter))
+		rtw_scan_abort(adapter);
+
+	rtw_p2p_enable(adapter, P2P_ROLE_DISABLE);
+}
+
+inline int rtw_cfg80211_redirect_pd_wdev(struct wiphy *wiphy, u8 *ra, struct wireless_dev **wdev)
+{
+	struct wireless_dev *pd_wdev = wiphy_to_pd_wdev(wiphy);
+
+	if (pd_wdev && pd_wdev != *wdev
+		&& !memcmp(wdev_address(pd_wdev), ra, ETH_ALEN) 
+	) {
+		*wdev = pd_wdev;
+		return 1;
+	}
+	return 0;
+}
+
+inline int rtw_cfg80211_is_scan_by_pd_wdev(_adapter *adapter)
+{
+	struct wiphy *wiphy = adapter_to_wiphy(adapter);
+	struct rtw_wdev_priv *wdev_data = adapter_wdev_data(adapter);
+	struct wireless_dev *wdev = NULL;
+	unsigned long irqL;
+
+	_enter_critical_bh(&wdev_data->scan_req_lock, &irqL);
+	if (wdev_data->scan_request)
+		wdev = wdev_data->scan_request->wdev;
+	_exit_critical_bh(&wdev_data->scan_req_lock, &irqL);
+
+	if (wdev && wdev == wiphy_to_pd_wdev(wiphy))
+		return 1;
+
+	return 0;
+}
+#endif /* RTW_DEDICATED_P2P_DEVICE */
+#endif /* CONFIG_P2P */
+
+inline void rtw_cfg80211_set_is_mgmt_tx(_adapter *adapter, u8 val)
+{
+	struct rtw_wdev_priv *wdev_priv = adapter_wdev_data(adapter);
+
+	wdev_priv->is_mgmt_tx = val;
+	rtw_mi_update_iface_status(&(adapter->mlmepriv), 0);
+}
+
+inline u8 rtw_cfg80211_get_is_mgmt_tx(_adapter *adapter)
+{
+	struct rtw_wdev_priv *wdev_priv = adapter_wdev_data(adapter);
+
+	return wdev_priv->is_mgmt_tx;
+}
+
+static int _cfg80211_rtw_mgmt_tx(_adapter *padapter, u8 tx_ch, u8 no_cck, const u8 *buf, size_t len, int wait_ack)
+{
+	struct xmit_frame	*pmgntframe;
+	struct pkt_attrib	*pattrib;
+	unsigned char	*pframe;
+	int ret = _FAIL;
+	bool ack = true;
+	struct rtw_ieee80211_hdr *pwlanhdr;
+	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
+	struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_P2P */
+	/* struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo; */
+
+	rtw_mi_set_scan_deny(padapter, 1000);
+	rtw_mi_scan_abort(padapter, true);
+
+	rtw_cfg80211_set_is_mgmt_tx(padapter, 1);
+
+#ifdef CONFIG_BT_COEXIST
+	rtw_btcoex_ScanNotify(padapter, true);
+#endif
+
+#ifdef CONFIG_P2P
+	if (rtw_cfg80211_get_is_roch(padapter) ) {
+		#ifdef CONFIG_CONCURRENT_MODE
+		if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
+			RTW_INFO("%s, extend ro ch time\n", __func__);
+			_set_timer(&padapter->cfg80211_wdinfo.remain_on_ch_timer, pwdinfo->ext_listen_period);
+		}
+		#endif /* CONFIG_CONCURRENT_MODE */
+	}
+#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_MCC_MODE
+	if (MCC_EN(padapter)) {
+		if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
+			/* don't set channel, issue frame directly */
+			goto issue_mgmt_frame;
+	}
+#endif /* CONFIG_MCC_MODE */
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (rtw_mi_check_status(padapter, MI_LINKED)) {
+		u8 union_ch = rtw_mi_get_union_chan(padapter);
+		u8 co_channel = 0xff;
+		co_channel = rtw_get_oper_ch(padapter);
+
+		if (tx_ch != union_ch) {
+			u16 ext_listen_period;
+
+			if (ATOMIC_READ(&pwdev_priv->switch_ch_to) == 1) {
+				rtw_mi_buddy_issue_nulldata(padapter, NULL, 1, 3, 500);
+				ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);
+				/* RTW_INFO("%s, set switch ch timer, period=%d\n", __func__, pwdinfo->ext_listen_period); */
+				/* _set_timer(&pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_period); */
+			}
+
+			if (check_fwstate(&padapter->mlmepriv, _FW_LINKED))
+				ext_listen_period = 500;/*500ms*/
+#ifdef CONFIG_P2P				
+			else
+				ext_listen_period = pwdinfo->ext_listen_period;
+
+			_set_timer(&pwdinfo->ap_p2p_switch_timer, ext_listen_period);
+#endif
+			RTW_INFO("%s, set switch ch timer, period=%d\n", __func__, ext_listen_period);
+		}
+
+		if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
+			pmlmeext->cur_channel = tx_ch;
+
+		if (tx_ch != co_channel)
+			set_channel_bwmode(padapter, tx_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+	} else
+#endif /* CONFIG_CONCURRENT_MODE */
+	/* if (tx_ch != pmlmeext->cur_channel) { */
+	if (tx_ch != rtw_get_oper_ch(padapter)) {
+		if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
+			pmlmeext->cur_channel = tx_ch;
+		set_channel_bwmode(padapter, tx_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+	}
+
+issue_mgmt_frame:
+	/* starting alloc mgmt frame to dump it */
+	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+	if (pmgntframe == NULL) {
+		/* ret = -ENOMEM; */
+		ret = _FAIL;
+		goto exit;
+	}
+
+	/* update attribute */
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	if (no_cck && IS_CCK_RATE(pattrib->rate)) {
+		/* force OFDM 6M rate*/
+		pattrib->rate = MGN_6M;
+		pattrib->raid = rtw_get_mgntframe_raid(padapter, WIRELESS_11G);
+	}
+
+	pattrib->retry_ctrl = false;
+
+	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+
+	memcpy(pframe, (void *)buf, len);
+	pattrib->pktlen = len;
+
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+	/* update seq number */
+	pmlmeext->mgnt_seq = GetSequence(pwlanhdr);
+	pattrib->seqnum = pmlmeext->mgnt_seq;
+	pmlmeext->mgnt_seq++;
+
+#ifdef CONFIG_P2P
+	rtw_xframe_chk_wfd_ie(pmgntframe);
+#endif /* CONFIG_P2P */
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	if (wait_ack) {
+		if (dump_mgntframe_and_wait_ack(padapter, pmgntframe) != _SUCCESS) {
+			ack = false;
+			ret = _FAIL;
+
+#ifdef CONFIG_DEBUG_CFG80211
+			RTW_INFO("%s, ack == _FAIL\n", __func__);
+#endif
+		} else {
+
+#ifdef CONFIG_XMIT_ACK
+			rtw_msleep_os(50);
+#endif
+#ifdef CONFIG_DEBUG_CFG80211
+			RTW_INFO("%s, ack=%d, ok!\n", __func__, ack);
+#endif
+			ret = _SUCCESS;
+		}
+	} else {
+		dump_mgntframe(padapter, pmgntframe);
+		ret = _SUCCESS;
+	}
+exit:
+	rtw_cfg80211_set_is_mgmt_tx(padapter, 0);
+
+#ifdef CONFIG_BT_COEXIST
+	rtw_btcoex_ScanNotify(padapter, false);
+#endif
+
+#ifdef CONFIG_DEBUG_CFG80211
+	RTW_INFO("%s, ret=%d\n", __func__, ret);
+#endif
+
+	return ret;
+
+}
+
+static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	struct wireless_dev *wdev,
+#else
+	struct net_device *ndev,
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) || defined(COMPAT_KERNEL_RELEASE)
+	struct ieee80211_channel *chan,
+	#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
+	bool offchan,
+	#endif
+	#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
+	enum nl80211_channel_type channel_type,
+	#endif
+	#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
+	bool channel_type_valid,
+	#endif
+	#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
+	unsigned int wait,
+	#endif
+	const u8 *buf, size_t len,
+	#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+	bool no_cck,
+	#endif
+	#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+	bool dont_wait_for_ack,
+	#endif
+#else
+	struct cfg80211_mgmt_tx_params *params,
+#endif
+	u64 *cookie)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(COMPAT_KERNEL_RELEASE)
+	struct ieee80211_channel *chan = params->chan;
+	bool offchan = params->offchan;
+	unsigned int wait = params->wait;
+	const u8 *buf = params->buf;
+	size_t len = params->len;
+	bool no_cck = params->no_cck;
+	bool dont_wait_for_ack = params->dont_wait_for_ack;
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+	bool no_cck = 0;
+#endif
+	int ret = 0;
+	int tx_ret;
+	int wait_ack = 1;
+	u32 dump_limit = RTW_MAX_MGMT_TX_CNT;
+	u32 dump_cnt = 0;
+	bool ack = true;
+	u8 tx_ch;
+	u8 category, action;
+	u8 frame_styp;
+	int type = (-1);
+	u32 start = jiffies;
+	_adapter *padapter;
+	struct dvobj_priv *dvobj;
+	struct rtw_wdev_priv *pwdev_priv;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	#if defined(RTW_DEDICATED_P2P_DEVICE)
+	if (wdev == wiphy_to_pd_wdev(wiphy))
+		padapter = wiphy_to_adapter(wiphy);
+	else
+	#endif
+	if (wdev_to_ndev(wdev))
+		padapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));
+	else {
+		ret = -EINVAL;
+		goto exit;
+	}
+#else
+	struct wireless_dev *wdev;
+
+	if (ndev == NULL) {
+		ret = -EINVAL;
+		goto exit;
+	}
+	padapter = (_adapter *)rtw_netdev_priv(ndev);
+	wdev = ndev_to_wdev(ndev);
+#endif
+
+	if (chan == NULL) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	tx_ch = (u8)ieee80211_frequency_to_channel(chan->center_freq);
+
+	dvobj = adapter_to_dvobj(padapter);
+	pwdev_priv = adapter_wdev_data(padapter);
+
+	/* cookie generation */
+	*cookie = (unsigned long) buf;
+
+#ifdef CONFIG_DEBUG_CFG80211
+	RTW_INFO(FUNC_ADPT_FMT"%s len=%zu, ch=%d"
+		#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
+		", ch_type=%d"
+		#endif
+		#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
+		", channel_type_valid=%d"
+		#endif
+		"\n", FUNC_ADPT_ARG(padapter), wdev == wiphy_to_pd_wdev(wiphy) ? " PD" : ""
+		, len, tx_ch
+		#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
+		, channel_type
+		#endif
+		#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
+		, channel_type_valid
+		#endif
+	);
+#endif /* CONFIG_DEBUG_CFG80211 */
+
+	/* indicate ack before issue frame to avoid racing with rsp frame */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+	rtw_cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack, GFP_KERNEL);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 36))
+	cfg80211_action_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL);
+#endif
+
+	frame_styp = le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)buf)->frame_ctl) & IEEE80211_FCTL_STYPE;
+	if (IEEE80211_STYPE_PROBE_RESP == frame_styp) {
+#ifdef CONFIG_DEBUG_CFG80211
+		RTW_INFO("RTW_Tx: probe_resp tx_ch=%d, no_cck=%u, da="MAC_FMT"\n", tx_ch, no_cck, MAC_ARG(GetAddr1Ptr(buf)));
+#endif /* CONFIG_DEBUG_CFG80211 */
+		wait_ack = 0;
+		goto dump;
+	}
+
+	if (rtw_action_frame_parse(buf, len, &category, &action) == false) {
+		RTW_INFO(FUNC_ADPT_FMT" frame_control:0x%x\n", FUNC_ADPT_ARG(padapter),
+			le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)buf)->frame_ctl));
+		goto exit;
+	}
+
+	RTW_INFO("RTW_Tx:tx_ch=%d, no_cck=%u, da="MAC_FMT"\n", tx_ch, no_cck, MAC_ARG(GetAddr1Ptr(buf)));
+#ifdef CONFIG_P2P
+	type = rtw_p2p_check_frames(padapter, buf, len, true);
+	if (type >= 0) {
+		no_cck = 1; /* force no CCK for P2P frames */
+		goto dump;
+	}
+#endif
+	if (category == RTW_WLAN_CATEGORY_PUBLIC)
+		RTW_INFO("RTW_Tx:%s\n", action_public_str(action));
+	else
+		RTW_INFO("RTW_Tx:category(%u), action(%u)\n", category, action);
+
+dump:
+
+	rtw_ps_deny(padapter, PS_DENY_MGNT_TX);
+	if (_FAIL == rtw_pwr_wakeup(padapter)) {
+		ret = -EFAULT;
+		goto cancel_ps_deny;
+	}
+
+	while (1) {
+		u32 sleep_ms = 0;
+		u32 retry_guarantee_ms = 0;
+
+		dump_cnt++;
+		tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, no_cck, buf, len, wait_ack);
+
+		switch (action) {
+		case ACT_PUBLIC_GAS_INITIAL_REQ:
+		case ACT_PUBLIC_GAS_INITIAL_RSP:
+			sleep_ms = 50;
+			retry_guarantee_ms = RTW_MAX_MGMT_TX_MS_GAS;
+		}
+
+		if (tx_ret == _SUCCESS
+			|| (dump_cnt >= dump_limit && rtw_get_passing_time_ms(start) >= retry_guarantee_ms))
+			break;
+
+		if (sleep_ms > 0)
+			rtw_msleep_os(sleep_ms);
+	}
+
+	if (tx_ret != _SUCCESS || dump_cnt > 1) {
+		RTW_INFO(FUNC_ADPT_FMT" %s (%d/%d) in %d ms\n", FUNC_ADPT_ARG(padapter),
+			tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt, dump_limit, rtw_get_passing_time_ms(start));
+	}
+
+	switch (type) {
+	case P2P_GO_NEGO_CONF:
+		if (0) {
+			RTW_INFO(FUNC_ADPT_FMT" Nego confirm. state=%u, status=%u, iaddr="MAC_FMT"\n"
+				, FUNC_ADPT_ARG(padapter), pwdev_priv->nego_info.state, pwdev_priv->nego_info.status
+				, MAC_ARG(pwdev_priv->nego_info.iface_addr));
+		}
+		if (pwdev_priv->nego_info.state == 2
+			&& pwdev_priv->nego_info.status == 0
+			&& rtw_check_invalid_mac_address(pwdev_priv->nego_info.iface_addr, false) == false
+		) {
+			_adapter *intended_iface = dvobj_get_adapter_by_addr(dvobj, pwdev_priv->nego_info.iface_addr);
+
+			if (intended_iface) {
+				RTW_INFO(FUNC_ADPT_FMT" Nego confirm. Allow only "ADPT_FMT" to scan for 2000 ms\n"
+					, FUNC_ADPT_ARG(padapter), ADPT_ARG(intended_iface));
+				/* allow only intended_iface to do scan for 2000 ms */
+				rtw_mi_set_scan_deny(padapter, 2000);
+				rtw_clear_scan_deny(intended_iface);
+			}
+		}
+		break;
+	case P2P_INVIT_RESP:
+		if (pwdev_priv->invit_info.flags & BIT(0)
+			&& pwdev_priv->invit_info.status == 0
+		) {
+			RTW_INFO(FUNC_ADPT_FMT" agree with invitation of persistent group\n",
+				FUNC_ADPT_ARG(padapter));
+			#if !RTW_P2P_GROUP_INTERFACE
+			rtw_mi_buddy_set_scan_deny(padapter, 5000);
+			#endif
+			rtw_pwr_wakeup_ex(padapter, 5000);
+		}
+		break;
+	}
+
+cancel_ps_deny:
+	rtw_ps_deny_cancel(padapter, PS_DENY_MGNT_TX);
+exit:
+	return ret;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)
+static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	struct wireless_dev *wdev,
+#else
+	struct net_device *ndev,
+#endif
+	u16 frame_type, bool reg)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	struct net_device *ndev = wdev_to_ndev(wdev);
+#endif
+	_adapter *adapter;
+
+	struct rtw_wdev_priv *pwdev_priv;
+
+	if (ndev == NULL)
+		goto exit;
+
+	adapter = (_adapter *)rtw_netdev_priv(ndev);
+	pwdev_priv = adapter_wdev_data(adapter);
+
+#ifdef CONFIG_DEBUG_CFG80211
+	RTW_INFO(FUNC_ADPT_FMT" frame_type:%x, reg:%d\n", FUNC_ADPT_ARG(adapter),
+		frame_type, reg);
+#endif
+
+	/* Wait QC Verify */
+	return;
+
+	switch (frame_type) {
+	case IEEE80211_STYPE_PROBE_REQ: /* 0x0040 */
+		SET_CFG80211_REPORT_MGMT(pwdev_priv, IEEE80211_STYPE_PROBE_REQ, reg);
+		break;
+	case IEEE80211_STYPE_ACTION: /* 0x00D0 */
+		SET_CFG80211_REPORT_MGMT(pwdev_priv, IEEE80211_STYPE_ACTION, reg);
+		break;
+	default:
+		break;
+	}
+
+exit:
+	return;
+}
+#endif
+
+#if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+static int cfg80211_rtw_tdls_mgmt(struct wiphy *wiphy,
+	struct net_device *ndev,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
+	const u8 *peer,
+#else
+	u8 *peer,
+#endif
+	u8 action_code,
+	u8 dialog_token,
+	u16 status_code,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
+	u32 peer_capability,
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
+	bool initiator,
+#endif
+	const u8 *buf,
+	size_t len)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
+	int ret = 0;
+	struct tdls_txmgmt txmgmt;
+
+	if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == false) {
+		RTW_INFO("Discard tdls action:%d, since hal doesn't support tdls\n", action_code);
+		goto discard;
+	}
+
+	if (rtw_tdls_is_driver_setup(padapter)) {
+		RTW_INFO("Discard tdls action:%d, let driver to set up direct link\n", action_code);
+		goto discard;
+	}
+
+	memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	memcpy(txmgmt.peer, peer, ETH_ALEN);
+	txmgmt.action_code = action_code;
+	txmgmt.dialog_token = dialog_token;
+	txmgmt.status_code = status_code;
+	txmgmt.len = len;
+	txmgmt.buf = (u8 *)rtw_malloc(txmgmt.len);
+	if (txmgmt.buf == NULL) {
+		ret = -ENOMEM;
+		goto bad;
+	}
+	memcpy(txmgmt.buf, (void *)buf, txmgmt.len);
+
+	/* Debug purpose */
+	RTW_INFO("%s %d\n", __func__, __LINE__);
+	RTW_INFO("peer:"MAC_FMT", action code:%d, dialog:%d, status code:%d\n",
+		MAC_ARG(txmgmt.peer), txmgmt.action_code,
+		txmgmt.dialog_token, txmgmt.status_code);
+	if (txmgmt.len > 0) {
+		int i = 0;
+		for (; i < len; i++)
+			printk("%02x ", *(txmgmt.buf + i));
+		RTW_INFO("len:%d\n", (u32)txmgmt.len);
+	}
+
+	switch (txmgmt.action_code) {
+	case TDLS_SETUP_REQUEST:
+		issue_tdls_setup_req(padapter, &txmgmt, true);
+		break;
+	case TDLS_SETUP_RESPONSE:
+		issue_tdls_setup_rsp(padapter, &txmgmt);
+		break;
+	case TDLS_SETUP_CONFIRM:
+		issue_tdls_setup_cfm(padapter, &txmgmt);
+		break;
+	case TDLS_TEARDOWN:
+		issue_tdls_teardown(padapter, &txmgmt, true);
+		break;
+	case TDLS_DISCOVERY_REQUEST:
+		issue_tdls_dis_req(padapter, &txmgmt);
+		break;
+	case TDLS_DISCOVERY_RESPONSE:
+		issue_tdls_dis_rsp(padapter, &txmgmt, pmlmeinfo->enc_algo ? true : false);
+		break;
+	}
+
+bad:
+	if (txmgmt.buf)
+		rtw_mfree(txmgmt.buf, txmgmt.len);
+
+discard:
+	return ret;
+}
+
+static int cfg80211_rtw_tdls_oper(struct wiphy *wiphy,
+	struct net_device *ndev,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
+	const u8 *peer,
+#else
+	u8 *peer,
+#endif
+	enum nl80211_tdls_operation oper)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+	struct tdls_txmgmt	txmgmt;
+	struct sta_info *ptdls_sta = NULL;
+
+	RTW_INFO(FUNC_NDEV_FMT", nl80211_tdls_operation:%d\n", FUNC_NDEV_ARG(ndev), oper);
+
+	if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == false) {
+		RTW_INFO("Discard tdls oper:%d, since hal doesn't support tdls\n", oper);
+		return 0;
+	}
+
+#ifdef CONFIG_LPS
+	rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1);
+#endif /* CONFIG_LPS */
+
+	memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	if (peer)
+		memcpy(txmgmt.peer, peer, ETH_ALEN);
+
+	if (rtw_tdls_is_driver_setup(padapter)) {
+		/* these two cases are done by driver itself */
+		if (oper == NL80211_TDLS_ENABLE_LINK || oper == NL80211_TDLS_DISABLE_LINK)
+			return 0;
+	}
+
+	switch (oper) {
+	case NL80211_TDLS_DISCOVERY_REQ:
+		issue_tdls_dis_req(padapter, &txmgmt);
+		break;
+	case NL80211_TDLS_SETUP:
+#ifdef CONFIG_WFD
+		if (_AES_ != padapter->securitypriv.dot11PrivacyAlgrthm) {
+			if (padapter->wdinfo.wfd_tdls_weaksec )
+				issue_tdls_setup_req(padapter, &txmgmt, true);
+			else
+				RTW_INFO("[%s] Current link is not AES, SKIP sending the tdls setup request!!\n", __func__);
+		} else
+#endif /* CONFIG_WFD */
+		{
+			issue_tdls_setup_req(padapter, &txmgmt, true);
+		}
+		break;
+	case NL80211_TDLS_TEARDOWN:
+		ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), txmgmt.peer);
+		if (ptdls_sta != NULL) {
+			txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;
+			issue_tdls_teardown(padapter, &txmgmt, true);
+		} else
+			RTW_INFO("TDLS peer not found\n");
+		break;
+	case NL80211_TDLS_ENABLE_LINK:
+		RTW_INFO(FUNC_NDEV_FMT", NL80211_TDLS_ENABLE_LINK;mac:"MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(peer));
+		ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), (u8 *)peer);
+		if (ptdls_sta != NULL) {
+			ptdlsinfo->link_established = true;
+			ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;
+			ptdls_sta->state |= _FW_LINKED;
+			rtw_tdls_cmd(padapter, txmgmt.peer, TDLS_ESTABLISHED);
+		}
+		break;
+	case NL80211_TDLS_DISABLE_LINK:
+		RTW_INFO(FUNC_NDEV_FMT", NL80211_TDLS_DISABLE_LINK;mac:"MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(peer));
+		ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), (u8 *)peer);
+		if (ptdls_sta != NULL)
+			rtw_tdls_cmd(padapter, (u8 *)peer, TDLS_TEARDOWN_STA_LOCALLY);
+		break;
+	}
+	return 0;
+}
+#endif /* CONFIG_TDLS */
+
+#if defined(CONFIG_PNO_SUPPORT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+static int cfg80211_rtw_sched_scan_start(struct wiphy *wiphy,
+		struct net_device *dev,
+		struct cfg80211_sched_scan_request *request)
+{
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	u8 ret;
+
+	if (padapter->bup == false) {
+		RTW_INFO("%s: net device is down.\n", __func__);
+		return -EIO;
+	}
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)  ||
+		check_fwstate(pmlmepriv, _FW_LINKED)   ||
+		check_fwstate(pmlmepriv, _FW_UNDER_LINKING) ) {
+		RTW_INFO("%s: device is busy.\n", __func__);
+		rtw_scan_abort(padapter);
+	}
+
+	if (request == NULL) {
+		RTW_INFO("%s: invalid cfg80211_requests parameters.\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = rtw_android_cfg80211_pno_setup(dev, request->ssids,
+			request->n_ssids, request->interval);
+
+	if (ret < 0) {
+		RTW_INFO("%s ret: %d\n", __func__, ret);
+		goto exit;
+	}
+
+	ret = rtw_android_pno_enable(dev, true);
+	if (ret < 0) {
+		RTW_INFO("%s ret: %d\n", __func__, ret);
+		goto exit;
+	}
+exit:
+	return ret;
+}
+
+static int cfg80211_rtw_sched_scan_stop(struct wiphy *wiphy,
+		struct net_device *dev)
+{
+	return rtw_android_pno_enable(dev, false);
+}
+#endif /* CONFIG_PNO_SUPPORT */
+
+static int rtw_cfg80211_set_beacon_wpsp2pie(struct net_device *ndev, char *buf, int len)
+{
+	int ret = 0;
+	uint wps_ielen = 0;
+	u8 *wps_ie;
+	u32	p2p_ielen = 0;
+	u8 wps_oui[8] = {0x0, 0x50, 0xf2, 0x04};
+	u8 *p2p_ie;
+	u32	wfd_ielen = 0;
+	u8 *wfd_ie;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+
+	RTW_INFO(FUNC_NDEV_FMT" ielen=%d\n", FUNC_NDEV_ARG(ndev), len);
+
+	if (len > 0) {
+		wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen);
+		if (wps_ie) {
+			#ifdef CONFIG_DEBUG_CFG80211
+			RTW_INFO("bcn_wps_ielen=%d\n", wps_ielen);
+			#endif
+
+			if (pmlmepriv->wps_beacon_ie) {
+				u32 free_len = pmlmepriv->wps_beacon_ie_len;
+				pmlmepriv->wps_beacon_ie_len = 0;
+				rtw_mfree(pmlmepriv->wps_beacon_ie, free_len);
+				pmlmepriv->wps_beacon_ie = NULL;
+			}
+
+			pmlmepriv->wps_beacon_ie = rtw_malloc(wps_ielen);
+			if (pmlmepriv->wps_beacon_ie == NULL) {
+				RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+				return -EINVAL;
+
+			}
+
+			memcpy(pmlmepriv->wps_beacon_ie, wps_ie, wps_ielen);
+			pmlmepriv->wps_beacon_ie_len = wps_ielen;
+
+			update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
+
+		}
+
+		/* buf += wps_ielen; */
+		/* len -= wps_ielen; */
+
+		#ifdef CONFIG_P2P
+		p2p_ie = rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen);
+		if (p2p_ie) {
+			#ifdef CONFIG_DEBUG_CFG80211
+			RTW_INFO("bcn_p2p_ielen=%d\n", p2p_ielen);
+			#endif
+
+			if (pmlmepriv->p2p_beacon_ie) {
+				u32 free_len = pmlmepriv->p2p_beacon_ie_len;
+				pmlmepriv->p2p_beacon_ie_len = 0;
+				rtw_mfree(pmlmepriv->p2p_beacon_ie, free_len);
+				pmlmepriv->p2p_beacon_ie = NULL;
+			}
+
+			pmlmepriv->p2p_beacon_ie = rtw_malloc(p2p_ielen);
+			if (pmlmepriv->p2p_beacon_ie == NULL) {
+				RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+				return -EINVAL;
+
+			}
+
+			memcpy(pmlmepriv->p2p_beacon_ie, p2p_ie, p2p_ielen);
+			pmlmepriv->p2p_beacon_ie_len = p2p_ielen;
+
+		}
+		#endif /* CONFIG_P2P */
+
+
+		#ifdef CONFIG_WFD
+		wfd_ie = rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen);
+		if (wfd_ie) {
+			#ifdef CONFIG_DEBUG_CFG80211
+			RTW_INFO("bcn_wfd_ielen=%d\n", wfd_ielen);
+			#endif
+
+			if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_BEACON_IE, wfd_ie, wfd_ielen) != _SUCCESS)
+				return -EINVAL;
+		}
+		#endif /* CONFIG_WFD */
+
+		pmlmeext->bstart_bss = true;
+
+	}
+
+	return ret;
+
+}
+
+static int rtw_cfg80211_set_probe_resp_wpsp2pie(struct net_device *net, char *buf, int len)
+{
+	int ret = 0;
+	uint wps_ielen = 0;
+	u8 *wps_ie;
+	u32	p2p_ielen = 0;
+	u8 *p2p_ie;
+	u32	wfd_ielen = 0;
+	u8 *wfd_ie;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+#ifdef CONFIG_DEBUG_CFG80211
+	RTW_INFO("%s, ielen=%d\n", __func__, len);
+#endif
+
+	if (len > 0) {
+		wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen);
+		if (wps_ie) {
+			uint	attr_contentlen = 0;
+			__be16	uconfig_method, *puconfig_method = NULL;
+
+			#ifdef CONFIG_DEBUG_CFG80211
+			RTW_INFO("probe_resp_wps_ielen=%d\n", wps_ielen);
+			#endif
+
+			if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
+				u8 sr = 0;
+				rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
+
+				if (sr != 0)
+					RTW_INFO("%s, got sr\n", __func__);
+				else {
+					RTW_INFO("GO mode process WPS under site-survey,  sr no set\n");
+					return ret;
+				}
+			}
+
+			if (pmlmepriv->wps_probe_resp_ie) {
+				u32 free_len = pmlmepriv->wps_probe_resp_ie_len;
+				pmlmepriv->wps_probe_resp_ie_len = 0;
+				rtw_mfree(pmlmepriv->wps_probe_resp_ie, free_len);
+				pmlmepriv->wps_probe_resp_ie = NULL;
+			}
+
+			pmlmepriv->wps_probe_resp_ie = rtw_malloc(wps_ielen);
+			if (pmlmepriv->wps_probe_resp_ie == NULL) {
+				RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+				return -EINVAL;
+
+			}
+
+			/* add PUSH_BUTTON config_method by driver self in wpsie of probe_resp at GO Mode */
+			puconfig_method = (__be16 *)rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_CONF_METHOD , NULL, &attr_contentlen);
+			if (puconfig_method != NULL) {
+				/* struct registry_priv *pregistrypriv = &padapter->registrypriv; */
+				struct wireless_dev *wdev = padapter->rtw_wdev;
+
+				#ifdef CONFIG_DEBUG_CFG80211
+				/* printk("config_method in wpsie of probe_resp = 0x%x\n", be16_to_cpu(*puconfig_method)); */
+				#endif
+
+				#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+				/* for WIFI-DIRECT LOGO 4.2.2, AUTO GO can't set PUSH_BUTTON flags */
+				if (wdev->iftype == NL80211_IFTYPE_P2P_GO) {
+					uconfig_method = cpu_to_be16(WPS_CM_PUSH_BUTTON);
+
+					*puconfig_method &= ~uconfig_method;
+				}
+				#endif
+			}
+
+			memcpy(pmlmepriv->wps_probe_resp_ie, wps_ie, wps_ielen);
+			pmlmepriv->wps_probe_resp_ie_len = wps_ielen;
+
+		}
+
+		/* buf += wps_ielen; */
+		/* len -= wps_ielen; */
+
+		#ifdef CONFIG_P2P
+		p2p_ie = rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen);
+		if (p2p_ie) {
+			u8 is_GO = false;
+			u32 attr_contentlen = 0;
+			u16 cap_attr = 0;
+			__le16 le_tmp;
+
+			#ifdef CONFIG_DEBUG_CFG80211
+			RTW_INFO("probe_resp_p2p_ielen=%d\n", p2p_ielen);
+			#endif
+
+			/* Check P2P Capability ATTR */
+			if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&le_tmp, (uint *)&attr_contentlen)) {
+				u8 grp_cap = 0;
+				/* RTW_INFO( "[%s] Got P2P Capability Attr!!\n", __func__ ); */
+				cap_attr = le16_to_cpu(le_tmp);
+				grp_cap = (u8)((cap_attr >> 8) & 0xff);
+
+				is_GO = (grp_cap & BIT(0)) ? true : false;
+
+				if (is_GO)
+					RTW_INFO("Got P2P Capability Attr, grp_cap=0x%x, is_GO\n", grp_cap);
+			}
+
+
+			if (is_GO == false) {
+				if (pmlmepriv->p2p_probe_resp_ie) {
+					u32 free_len = pmlmepriv->p2p_probe_resp_ie_len;
+					pmlmepriv->p2p_probe_resp_ie_len = 0;
+					rtw_mfree(pmlmepriv->p2p_probe_resp_ie, free_len);
+					pmlmepriv->p2p_probe_resp_ie = NULL;
+				}
+
+				pmlmepriv->p2p_probe_resp_ie = rtw_malloc(p2p_ielen);
+				if (pmlmepriv->p2p_probe_resp_ie == NULL) {
+					RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+					return -EINVAL;
+
+				}
+				memcpy(pmlmepriv->p2p_probe_resp_ie, p2p_ie, p2p_ielen);
+				pmlmepriv->p2p_probe_resp_ie_len = p2p_ielen;
+			} else {
+				if (pmlmepriv->p2p_go_probe_resp_ie) {
+					u32 free_len = pmlmepriv->p2p_go_probe_resp_ie_len;
+					pmlmepriv->p2p_go_probe_resp_ie_len = 0;
+					rtw_mfree(pmlmepriv->p2p_go_probe_resp_ie, free_len);
+					pmlmepriv->p2p_go_probe_resp_ie = NULL;
+				}
+
+				pmlmepriv->p2p_go_probe_resp_ie = rtw_malloc(p2p_ielen);
+				if (pmlmepriv->p2p_go_probe_resp_ie == NULL) {
+					RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+					return -EINVAL;
+
+				}
+				memcpy(pmlmepriv->p2p_go_probe_resp_ie, p2p_ie, p2p_ielen);
+				pmlmepriv->p2p_go_probe_resp_ie_len = p2p_ielen;
+			}
+
+		}
+		#endif /* CONFIG_P2P */
+
+
+		#ifdef CONFIG_WFD
+		wfd_ie = rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen);
+		if (wfd_ie) {
+			#ifdef CONFIG_DEBUG_CFG80211
+			RTW_INFO("probe_resp_wfd_ielen=%d\n", wfd_ielen);
+			#endif
+
+			if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_PROBE_RESP_IE, wfd_ie, wfd_ielen) != _SUCCESS)
+				return -EINVAL;
+		}
+		#endif /* CONFIG_WFD */
+
+	}
+
+	return ret;
+
+}
+
+static int rtw_cfg80211_set_assoc_resp_wpsp2pie(struct net_device *net, char *buf, int len)
+{
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	u8 *ie;
+	u32 ie_len;
+
+	RTW_INFO("%s, ielen=%d\n", __func__, len);
+
+	if (len <= 0)
+		goto exit;
+
+	ie = rtw_get_wps_ie(buf, len, NULL, &ie_len);
+	if (ie && ie_len) {
+		if (pmlmepriv->wps_assoc_resp_ie) {
+			u32 free_len = pmlmepriv->wps_assoc_resp_ie_len;
+
+			pmlmepriv->wps_assoc_resp_ie_len = 0;
+			rtw_mfree(pmlmepriv->wps_assoc_resp_ie, free_len);
+			pmlmepriv->wps_assoc_resp_ie = NULL;
+		}
+
+		pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
+		if (pmlmepriv->wps_assoc_resp_ie == NULL) {
+			RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+		memcpy(pmlmepriv->wps_assoc_resp_ie, ie, ie_len);
+		pmlmepriv->wps_assoc_resp_ie_len = ie_len;
+	}
+
+	ie = rtw_get_p2p_ie(buf, len, NULL, &ie_len);
+	if (ie && ie_len) {
+		if (pmlmepriv->p2p_assoc_resp_ie) {
+			u32 free_len = pmlmepriv->p2p_assoc_resp_ie_len;
+
+			pmlmepriv->p2p_assoc_resp_ie_len = 0;
+			rtw_mfree(pmlmepriv->p2p_assoc_resp_ie, free_len);
+			pmlmepriv->p2p_assoc_resp_ie = NULL;
+		}
+
+		pmlmepriv->p2p_assoc_resp_ie = rtw_malloc(ie_len);
+		if (pmlmepriv->p2p_assoc_resp_ie == NULL) {
+			RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+		memcpy(pmlmepriv->p2p_assoc_resp_ie, ie, ie_len);
+		pmlmepriv->p2p_assoc_resp_ie_len = ie_len;
+	}
+
+#ifdef CONFIG_WFD
+	ie = rtw_get_wfd_ie(buf, len, NULL, &ie_len);
+	if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_ASSOC_RESP_IE, ie, ie_len) != _SUCCESS)
+		return -EINVAL;
+#endif
+
+exit:
+	return ret;
+}
+
+int rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device *net, char *buf, int len,
+	int type)
+{
+	int ret = 0;
+	uint wps_ielen = 0;
+	u32	p2p_ielen = 0;
+
+#ifdef CONFIG_DEBUG_CFG80211
+	RTW_INFO("%s, ielen=%d\n", __func__, len);
+#endif
+
+	if ((rtw_get_wps_ie(buf, len, NULL, &wps_ielen) && (wps_ielen > 0))
+		#ifdef CONFIG_P2P
+		|| (rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen) && (p2p_ielen > 0))
+		#endif
+	) {
+		if (net != NULL) {
+			switch (type) {
+			case 0x1: /* BEACON */
+				ret = rtw_cfg80211_set_beacon_wpsp2pie(net, buf, len);
+				break;
+			case 0x2: /* PROBE_RESP */
+				ret = rtw_cfg80211_set_probe_resp_wpsp2pie(net, buf, len);
+				#ifdef CONFIG_P2P
+				if (ret == 0)
+					adapter_wdev_data((_adapter *)rtw_netdev_priv(net))->probe_resp_ie_update_time = jiffies;
+				#endif
+				break;
+			case 0x4: /* ASSOC_RESP */
+				ret = rtw_cfg80211_set_assoc_resp_wpsp2pie(net, buf, len);
+				break;
+			}
+		}
+	}
+
+	return ret;
+
+}
+
+static void rtw_cfg80211_init_ht_capab_ex(_adapter *padapter, struct ieee80211_sta_ht_cap *ht_cap, enum nl80211_band band, u8 rf_type)
+{
+	struct registry_priv *pregistrypriv = &padapter->registrypriv;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
+	u8 stbc_rx_enable = false;
+
+	rtw_ht_use_default_setting(padapter);
+
+	/* RX LDPC */
+	if (TEST_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_RX))
+		ht_cap->cap |= IEEE80211_HT_CAP_LDPC_CODING;
+
+	/* TX STBC */
+	if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX))
+		ht_cap->cap |= IEEE80211_HT_CAP_TX_STBC;
+
+	/* RX STBC */
+	if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_RX)) {
+		/*rtw_rx_stbc 0: disable, bit(0):enable 2.4g, bit(1):enable 5g*/
+		if (band == NL80211_BAND_2GHZ)
+			stbc_rx_enable = (pregistrypriv->rx_stbc & BIT(0)) ? true : false;
+		if (band == NL80211_BAND_5GHZ)
+			stbc_rx_enable = (pregistrypriv->rx_stbc & BIT(1)) ? true : false;
+
+		if (stbc_rx_enable) {
+			switch (rf_type) {
+			case RF_1T1R:
+				ht_cap->cap |= IEEE80211_HT_CAP_RX_STBC_1R;/*RX STBC One spatial stream*/
+				break;
+
+			case RF_2T2R:
+			case RF_1T2R:
+				ht_cap->cap |= IEEE80211_HT_CAP_RX_STBC_1R;/* Only one spatial-stream STBC RX is supported */
+				break;
+			case RF_3T3R:
+			case RF_3T4R:
+			case RF_4T4R:
+				ht_cap->cap |= IEEE80211_HT_CAP_RX_STBC_1R;/* Only one spatial-stream STBC RX is supported */
+				break;
+			default:
+				RTW_INFO("[warning] rf_type %d is not expected\n", rf_type);
+				break;
+			}
+		}
+	}
+}
+
+static void rtw_cfg80211_init_ht_capab(_adapter *padapter, struct ieee80211_sta_ht_cap *ht_cap, enum nl80211_band band, u8 rf_type)
+{
+	struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
+	u8 rx_nss = 0;
+
+	ht_cap->ht_supported = true;
+
+	ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+				IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 |
+				IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;
+	rtw_cfg80211_init_ht_capab_ex(padapter, ht_cap, band, rf_type);
+
+	/*
+	 *Maximum length of AMPDU that the STA can receive.
+	 *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
+	 */
+	ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+
+	/*Minimum MPDU start spacing , */
+	ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
+
+	ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+
+	rx_nss = rtw_min(rf_type_to_rf_rx_cnt(rf_type), hal_spec->rx_nss_num);
+	switch (rx_nss) {
+	case 1:
+		ht_cap->mcs.rx_mask[0] = 0xFF;
+		break;
+	case 2:
+		ht_cap->mcs.rx_mask[0] = 0xFF;
+		ht_cap->mcs.rx_mask[1] = 0xFF;
+		break;
+	case 3:
+		ht_cap->mcs.rx_mask[0] = 0xFF;
+		ht_cap->mcs.rx_mask[1] = 0xFF;
+		ht_cap->mcs.rx_mask[2] = 0xFF;
+		break;
+	case 4:
+		ht_cap->mcs.rx_mask[0] = 0xFF;
+		ht_cap->mcs.rx_mask[1] = 0xFF;
+		ht_cap->mcs.rx_mask[2] = 0xFF;
+		ht_cap->mcs.rx_mask[3] = 0xFF;
+		break;
+	default:
+		rtw_warn_on(1);
+		RTW_INFO("%s, error rf_type=%d\n", __func__, rf_type);
+	};
+
+	ht_cap->mcs.rx_highest =
+		cpu_to_le16(rtw_mcs_rate(rf_type,
+					 hal_is_bw_support(padapter,
+							   CHANNEL_WIDTH_40),
+					 hal_is_bw_support(padapter,
+							   CHANNEL_WIDTH_40) ?
+					 ht_cap->cap & IEEE80211_HT_CAP_SGI_40 :
+					 ht_cap->cap & IEEE80211_HT_CAP_SGI_20,
+					 ht_cap->mcs.rx_mask));
+}
+
+void rtw_cfg80211_init_wdev_data(_adapter *padapter)
+{
+#ifdef CONFIG_CONCURRENT_MODE
+	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
+
+	ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
+#endif
+}
+
+void rtw_cfg80211_init_wiphy(_adapter *padapter)
+{
+	u8 rf_type;
+	struct ieee80211_supported_band *bands;
+	struct wireless_dev *pwdev = padapter->rtw_wdev;
+	struct wiphy *wiphy = pwdev->wiphy;
+
+	rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
+	RTW_INFO("%s:rf_type=%d\n", __func__, rf_type);
+
+	if (IsSupported24G(padapter->registrypriv.wireless_mode)) {
+		bands = wiphy->bands[NL80211_BAND_2GHZ];
+		if (bands)
+			rtw_cfg80211_init_ht_capab(padapter, &bands->ht_cap, NL80211_BAND_2GHZ, rf_type);
+	}
+#ifdef CONFIG_IEEE80211_BAND_5GHZ
+	if (is_supported_5g(padapter->registrypriv.wireless_mode)) {
+		bands = wiphy->bands[NL80211_BAND_5GHZ];
+		if (bands)
+			rtw_cfg80211_init_ht_capab(padapter, &bands->ht_cap, NL80211_BAND_5GHZ, rf_type);
+	}
+#endif
+	/* init regulary domain */
+	rtw_regd_init(padapter);
+
+	/* copy mac_addr to wiphy */
+	memcpy(wiphy->perm_addr, adapter_mac_addr(padapter), ETH_ALEN);
+
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+static struct ieee80211_iface_limit rtw_limits[] = {
+	{
+		.max = 2,
+		.types = BIT(NL80211_IFTYPE_STATION)
+			#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
+			| BIT(NL80211_IFTYPE_P2P_CLIENT)
+			#endif
+	},
+	#ifdef CONFIG_AP_MODE
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_AP)
+			#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
+			| BIT(NL80211_IFTYPE_P2P_GO)
+			#endif
+	},
+	#endif
+	#if defined(RTW_DEDICATED_P2P_DEVICE)
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
+	}
+	#endif
+};
+
+static struct ieee80211_iface_combination rtw_combinations[] = {
+	{
+		.limits = rtw_limits,
+		.n_limits = ARRAY_SIZE(rtw_limits),
+		#if defined(RTW_DEDICATED_P2P_DEVICE)
+		.max_interfaces = 3,
+		#else
+		.max_interfaces = 2,
+		#endif
+		.num_different_channels = 1,
+	},
+};
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) */
+
+static void rtw_cfg80211_preinit_wiphy(_adapter *adapter, struct wiphy *wiphy)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct registry_priv *regsty = dvobj_to_regsty(dvobj);
+
+	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+	wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;
+	wiphy->max_scan_ie_len = RTW_SCAN_IE_LEN_MAX;
+	wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS;
+
+#if CONFIG_RTW_MACADDR_ACL && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+	wiphy->max_acl_mac_addrs = NUM_ACL;
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
+	wiphy->max_remain_on_channel_duration = RTW_MAX_REMAIN_ON_CHANNEL_DURATION;
+#endif
+
+	wiphy->interface_modes =	BIT(NL80211_IFTYPE_STATION)
+								| BIT(NL80211_IFTYPE_ADHOC)
+#ifdef CONFIG_AP_MODE
+								| BIT(NL80211_IFTYPE_AP)
+								#ifdef CONFIG_WIFI_MONITOR
+								| BIT(NL80211_IFTYPE_MONITOR)
+								#endif
+#endif
+#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
+								| BIT(NL80211_IFTYPE_P2P_CLIENT)
+								| BIT(NL80211_IFTYPE_P2P_GO)
+								#if defined(RTW_DEDICATED_P2P_DEVICE)
+								| BIT(NL80211_IFTYPE_P2P_DEVICE)
+								#endif
+#endif
+								;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+#ifdef CONFIG_AP_MODE
+	wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes;
+#endif /* CONFIG_AP_MODE */
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+	#ifdef CONFIG_WIFI_MONITOR
+	wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
+	#endif
+#endif
+
+#if defined(RTW_SINGLE_WIPHY) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+	wiphy->iface_combinations = rtw_combinations;
+	wiphy->n_iface_combinations = ARRAY_SIZE(rtw_combinations);
+#endif
+
+	wiphy->cipher_suites = rtw_cipher_suites;
+	wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);
+
+	if (IsSupported24G(adapter->registrypriv.wireless_mode))
+		wiphy->bands[NL80211_BAND_2GHZ] = rtw_spt_band_alloc(NL80211_BAND_2GHZ);
+
+#ifdef CONFIG_IEEE80211_BAND_5GHZ
+	if (is_supported_5g(adapter->registrypriv.wireless_mode))
+		wiphy->bands[NL80211_BAND_5GHZ] = rtw_spt_band_alloc(NL80211_BAND_5GHZ);
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))
+	wiphy->flags |= WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS;
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+	wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+	wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
+	/* remove WIPHY_FLAG_OFFCHAN_TX, because we not support this feature */
+	/* wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME; */
+#endif
+
+#if defined(CONFIG_PM) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
+	wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
+#else // kernel >= 4.12
+	wiphy->max_sched_scan_reqs = 1;
+#endif
+#ifdef CONFIG_PNO_SUPPORT
+	wiphy->max_sched_scan_ssids = MAX_PNO_LIST_COUNT;
+#endif
+#endif
+
+#if defined(CONFIG_PM) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
+	wiphy->wowlan = wowlan_stub;
+#else
+	wiphy->wowlan = &wowlan_stub;
+#endif
+#endif
+
+#if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+	wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
+#ifndef CONFIG_TDLS_DRIVER_SETUP
+	wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;	/* Driver handles key exchange */
+	wiphy->flags |= NL80211_ATTR_HT_CAPABILITY;
+#endif /* CONFIG_TDLS_DRIVER_SETUP */
+#endif /* CONFIG_TDLS */
+
+	if (regsty->power_mgnt != PS_MODE_ACTIVE)
+		wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
+	else
+		wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+	/* wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */
+#endif
+}
+
+#ifdef CONFIG_RFKILL_POLL
+void rtw_cfg80211_init_rfkill(struct wiphy *wiphy)
+{
+	wiphy_rfkill_set_hw_state(wiphy, 0);
+	wiphy_rfkill_start_polling(wiphy);
+}
+
+void rtw_cfg80211_deinit_rfkill(struct wiphy *wiphy)
+{
+	wiphy_rfkill_stop_polling(wiphy);
+}
+
+static void cfg80211_rtw_rfkill_poll(struct wiphy *wiphy)
+{
+	_adapter *padapter = NULL;
+	bool blocked = false;
+	u8 valid = 0;
+
+	padapter = wiphy_to_adapter(wiphy);
+
+	if (adapter_to_dvobj(padapter)->processing_dev_remove ) {
+		/*RTW_INFO("cfg80211_rtw_rfkill_poll: device is removed!\n");*/
+		return;
+	}
+
+	blocked = rtw_hal_rfkill_poll(padapter, &valid);
+	/*RTW_INFO("cfg80211_rtw_rfkill_poll: valid=%d, blocked=%d\n",
+			valid, blocked);*/
+
+	if (valid)
+		wiphy_rfkill_set_hw_state(wiphy, blocked);
+}
+#endif
+
+static struct cfg80211_ops rtw_cfg80211_ops = {
+	.change_virtual_intf = cfg80211_rtw_change_iface,
+	.add_key = cfg80211_rtw_add_key,
+	.get_key = cfg80211_rtw_get_key,
+	.del_key = cfg80211_rtw_del_key,
+	.set_default_key = cfg80211_rtw_set_default_key,
+#if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
+	.set_rekey_data = cfg80211_rtw_set_rekey_data,
+#endif /*CONFIG_GTK_OL*/
+	.get_station = cfg80211_rtw_get_station,
+	.scan = cfg80211_rtw_scan,
+	.set_wiphy_params = cfg80211_rtw_set_wiphy_params,
+	.connect = cfg80211_rtw_connect,
+	.disconnect = cfg80211_rtw_disconnect,
+	.join_ibss = cfg80211_rtw_join_ibss,
+	.leave_ibss = cfg80211_rtw_leave_ibss,
+	.set_tx_power = cfg80211_rtw_set_txpower,
+	.get_tx_power = cfg80211_rtw_get_txpower,
+	.set_power_mgmt = cfg80211_rtw_set_power_mgmt,
+	.set_pmksa = cfg80211_rtw_set_pmksa,
+	.del_pmksa = cfg80211_rtw_del_pmksa,
+	.flush_pmksa = cfg80211_rtw_flush_pmksa,
+
+#ifdef CONFIG_AP_MODE
+	.add_virtual_intf = cfg80211_rtw_add_virtual_intf,
+	.del_virtual_intf = cfg80211_rtw_del_virtual_intf,
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(COMPAT_KERNEL_RELEASE)
+	.add_beacon = cfg80211_rtw_add_beacon,
+	.set_beacon = cfg80211_rtw_set_beacon,
+	.del_beacon = cfg80211_rtw_del_beacon,
+#else
+	.start_ap = cfg80211_rtw_start_ap,
+	.change_beacon = cfg80211_rtw_change_beacon,
+	.stop_ap = cfg80211_rtw_stop_ap,
+#endif
+
+#if CONFIG_RTW_MACADDR_ACL && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+	.set_mac_acl = cfg80211_rtw_set_mac_acl,
+#endif
+
+	.add_station = cfg80211_rtw_add_station,
+	.del_station = cfg80211_rtw_del_station,
+	.change_station = cfg80211_rtw_change_station,
+	.dump_station = cfg80211_rtw_dump_station,
+	.change_bss = cfg80211_rtw_change_bss,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
+	.set_channel = cfg80211_rtw_set_channel,
+#endif
+	/* .auth = cfg80211_rtw_auth, */
+	/* .assoc = cfg80211_rtw_assoc,	 */
+#endif /* CONFIG_AP_MODE */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	.set_monitor_channel = cfg80211_rtw_set_monitor_channel,
+#endif
+
+#ifdef CONFIG_P2P
+	.remain_on_channel = cfg80211_rtw_remain_on_channel,
+	.cancel_remain_on_channel = cfg80211_rtw_cancel_remain_on_channel,
+	#if defined(RTW_DEDICATED_P2P_DEVICE)
+	.start_p2p_device = cfg80211_rtw_start_p2p_device,
+	.stop_p2p_device = cfg80211_rtw_stop_p2p_device,
+	#endif
+#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_RTW_80211R
+	.update_ft_ies = cfg80211_rtw_update_ft_ies,
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
+	.mgmt_tx = cfg80211_rtw_mgmt_tx,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)
+	.mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,
+#endif
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+	.action = cfg80211_rtw_mgmt_tx,
+#endif
+
+#if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+	.tdls_mgmt = cfg80211_rtw_tdls_mgmt,
+	.tdls_oper = cfg80211_rtw_tdls_oper,
+#endif /* CONFIG_TDLS */
+
+#if defined(CONFIG_PNO_SUPPORT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+	.sched_scan_start = cfg80211_rtw_sched_scan_start,
+	.sched_scan_stop = cfg80211_rtw_sched_scan_stop,
+#endif /* CONFIG_PNO_SUPPORT */
+#ifdef CONFIG_RFKILL_POLL
+	.rfkill_poll = cfg80211_rtw_rfkill_poll,
+#endif
+};
+
+struct wiphy *rtw_wiphy_alloc(_adapter *padapter, struct device *dev)
+{
+	struct wiphy *wiphy;
+	struct rtw_wiphy_data *wiphy_data;
+
+	/* wiphy */
+	wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wiphy_data));
+	if (!wiphy) {
+		RTW_INFO("Couldn't allocate wiphy device\n");
+		goto exit;
+	}
+	set_wiphy_dev(wiphy, dev);
+
+	/* wiphy_data */
+	wiphy_data = rtw_wiphy_priv(wiphy);
+	wiphy_data->dvobj = adapter_to_dvobj(padapter);
+#ifndef RTW_SINGLE_WIPHY
+	wiphy_data->adapter = padapter;
+#endif
+
+	rtw_cfg80211_preinit_wiphy(padapter, wiphy);
+
+	RTW_INFO(FUNC_WIPHY_FMT"\n", FUNC_WIPHY_ARG(wiphy));
+
+exit:
+	return wiphy;
+}
+
+void rtw_wiphy_free(struct wiphy *wiphy)
+{
+	if (!wiphy)
+		return;
+
+	RTW_INFO(FUNC_WIPHY_FMT"\n", FUNC_WIPHY_ARG(wiphy));
+
+	if (wiphy->bands[NL80211_BAND_2GHZ]) {
+		rtw_spt_band_free(wiphy->bands[NL80211_BAND_2GHZ]);
+		wiphy->bands[NL80211_BAND_2GHZ] = NULL;
+	}
+	if (wiphy->bands[NL80211_BAND_5GHZ]) {
+		rtw_spt_band_free(wiphy->bands[NL80211_BAND_5GHZ]);
+		wiphy->bands[NL80211_BAND_5GHZ] = NULL;
+	}
+
+	wiphy_free(wiphy);
+}
+
+int rtw_wiphy_register(struct wiphy *wiphy)
+{
+	RTW_INFO(FUNC_WIPHY_FMT"\n", FUNC_WIPHY_ARG(wiphy));
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT)
+	rtw_cfgvendor_attach(wiphy);
+#endif
+
+	return wiphy_register(wiphy);
+}
+
+void rtw_wiphy_unregister(struct wiphy *wiphy)
+{
+	RTW_INFO(FUNC_WIPHY_FMT"\n", FUNC_WIPHY_ARG(wiphy));
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT)
+	rtw_cfgvendor_detach(wiphy);
+#endif
+
+	#if defined(RTW_DEDICATED_P2P_DEVICE)
+	rtw_pd_iface_free(wiphy);
+	#endif
+
+	return wiphy_unregister(wiphy);
+}
+
+int rtw_wdev_alloc(_adapter *padapter, struct wiphy *wiphy)
+{
+	int ret = 0;
+	struct net_device *pnetdev = padapter->pnetdev;
+	struct wireless_dev *wdev;
+	struct rtw_wdev_priv *pwdev_priv;
+
+	RTW_INFO("%s(padapter=%p)\n", __func__, padapter);
+
+	/*  wdev */
+	wdev = (struct wireless_dev *)rtw_zmalloc(sizeof(struct wireless_dev));
+	if (!wdev) {
+		RTW_INFO("Couldn't allocate wireless device\n");
+		ret = -ENOMEM;
+		goto exit;
+	}
+	wdev->wiphy = wiphy;
+	wdev->netdev = pnetdev;
+
+	wdev->iftype = NL80211_IFTYPE_STATION;	/* will be init in rtw_hal_init() */
+											/* Must sync with _rtw_init_mlme_priv() */
+											/* pmlmepriv->fw_state = WIFI_STATION_STATE */
+	/* wdev->iftype = NL80211_IFTYPE_MONITOR; */ /* for rtw_setopmode_cmd() in cfg80211_rtw_change_iface() */
+	padapter->rtw_wdev = wdev;
+	pnetdev->ieee80211_ptr = wdev;
+
+	/* init pwdev_priv */
+	pwdev_priv = adapter_wdev_data(padapter);
+	pwdev_priv->rtw_wdev = wdev;
+	pwdev_priv->pmon_ndev = NULL;
+	pwdev_priv->ifname_mon[0] = '\0';
+	pwdev_priv->padapter = padapter;
+	pwdev_priv->scan_request = NULL;
+	spin_lock_init(&pwdev_priv->scan_req_lock);
+
+	pwdev_priv->p2p_enabled = false;
+	pwdev_priv->probe_resp_ie_update_time = jiffies;
+	pwdev_priv->provdisc_req_issued = false;
+	rtw_wdev_invit_info_init(&pwdev_priv->invit_info);
+	rtw_wdev_nego_info_init(&pwdev_priv->nego_info);
+
+	pwdev_priv->bandroid_scan = false;
+
+	if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
+		pwdev_priv->power_mgmt = true;
+	else
+		pwdev_priv->power_mgmt = false;
+
+	_rtw_mutex_init(&pwdev_priv->roch_mutex);
+
+#ifdef CONFIG_CONCURRENT_MODE
+	ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
+#endif
+
+exit:
+	return ret;
+}
+
+void rtw_wdev_free(struct wireless_dev *wdev)
+{
+	if (!wdev)
+		return;
+
+	RTW_INFO("%s(wdev=%p)\n", __func__, wdev);
+
+	if (wdev_to_ndev(wdev)) {
+		_adapter *adapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));
+		struct rtw_wdev_priv *wdev_priv = adapter_wdev_data(adapter);
+
+		_rtw_mutex_free(&wdev_priv->roch_mutex);
+	}
+
+	rtw_mfree((u8 *)wdev, sizeof(struct wireless_dev));
+}
+
+void rtw_wdev_unregister(struct wireless_dev *wdev)
+{
+	struct net_device *ndev;
+	_adapter *adapter;
+	struct rtw_wdev_priv *pwdev_priv;
+
+	if (!wdev)
+		return;
+
+	RTW_INFO("%s(wdev=%p)\n", __func__, wdev);
+
+	ndev = wdev_to_ndev(wdev);
+	if (!ndev)
+		return;
+
+	adapter = (_adapter *)rtw_netdev_priv(ndev);
+	pwdev_priv = adapter_wdev_data(adapter);
+
+	rtw_cfg80211_indicate_scan_done(adapter, true);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
+	if (wdev->current_bss) {
+		u8 locally_generated = 1;
+		RTW_INFO(FUNC_ADPT_FMT" clear current_bss by cfg80211_disconnected\n", FUNC_ADPT_ARG(adapter));
+		cfg80211_disconnected(adapter->pnetdev, 0, NULL, 0, locally_generated, GFP_ATOMIC);
+	}
+#elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0))) || defined(COMPAT_KERNEL_RELEASE)
+	if (wdev->current_bss) {
+		RTW_INFO(FUNC_ADPT_FMT" clear current_bss by cfg80211_disconnected\n", FUNC_ADPT_ARG(adapter));
+		cfg80211_disconnected(adapter->pnetdev, 0, NULL, 0, GFP_ATOMIC);
+	}
+#endif
+
+	if (pwdev_priv->pmon_ndev) {
+		RTW_INFO("%s, unregister monitor interface\n", __func__);
+		unregister_netdev(pwdev_priv->pmon_ndev);
+	}
+}
+
+int rtw_cfg80211_ndev_res_alloc(_adapter *adapter)
+{
+	int ret = _FAIL;
+
+#if !defined(RTW_SINGLE_WIPHY)
+	struct wiphy *wiphy;
+	struct device *dev = dvobj_to_dev(adapter_to_dvobj(adapter));
+
+	wiphy = rtw_wiphy_alloc(adapter, dev);
+	if (wiphy == NULL)
+		goto exit;
+
+	adapter->wiphy = wiphy;
+#endif
+
+	if (rtw_wdev_alloc(adapter, adapter_to_wiphy(adapter)) == 0)
+		ret = _SUCCESS;
+
+#if !defined(RTW_SINGLE_WIPHY)
+	if (ret != _SUCCESS) {
+		rtw_wiphy_free(wiphy);
+		adapter->wiphy = NULL;
+	}
+#endif
+
+exit:
+	return ret;
+}
+
+void rtw_cfg80211_ndev_res_free(_adapter *adapter)
+{
+	rtw_wdev_free(adapter->rtw_wdev);
+#if !defined(RTW_SINGLE_WIPHY)
+	rtw_wiphy_free(adapter_to_wiphy(adapter));
+	adapter->wiphy = NULL;
+#endif
+}
+
+int rtw_cfg80211_ndev_res_register(_adapter *adapter)
+{
+	int ret = _FAIL;
+
+#if !defined(RTW_SINGLE_WIPHY)
+	if (rtw_wiphy_register(adapter_to_wiphy(adapter)) < 0) {
+		RTW_INFO("%s rtw_wiphy_register fail for if%d\n", __func__, (adapter->iface_id + 1));
+		goto exit;
+	}
+
+#ifdef CONFIG_RFKILL_POLL
+	rtw_cfg80211_init_rfkill(adapter_to_wiphy(adapter));
+#endif
+#endif
+
+	ret = _SUCCESS;
+
+exit:
+	return ret;
+}
+
+void rtw_cfg80211_ndev_res_unregister(_adapter *adapter)
+{
+	rtw_wdev_unregister(adapter->rtw_wdev);
+}
+
+int rtw_cfg80211_dev_res_alloc(struct dvobj_priv *dvobj)
+{
+	int ret = _FAIL;
+
+#if defined(RTW_SINGLE_WIPHY)
+	struct wiphy *wiphy;
+	struct device *dev = dvobj_to_dev(dvobj);
+
+	wiphy = rtw_wiphy_alloc(dvobj_get_primary_adapter(dvobj), dev);
+	if (wiphy == NULL)
+		goto exit;
+
+	dvobj->wiphy = wiphy;
+#endif
+
+	ret = _SUCCESS;
+
+exit:
+	return ret;
+}
+
+void rtw_cfg80211_dev_res_free(struct dvobj_priv *dvobj)
+{
+#if defined(RTW_SINGLE_WIPHY)
+	rtw_wiphy_free(dvobj_to_wiphy(dvobj));
+	dvobj->wiphy = NULL;
+#endif
+}
+
+int rtw_cfg80211_dev_res_register(struct dvobj_priv *dvobj)
+{
+	int ret = _FAIL;
+
+#if defined(RTW_SINGLE_WIPHY)
+	if (rtw_wiphy_register(dvobj_to_wiphy(dvobj)) != 0)
+		goto exit;
+
+#ifdef CONFIG_RFKILL_POLL
+	rtw_cfg80211_init_rfkill(dvobj_to_wiphy(dvobj));
+#endif
+#endif
+
+	ret = _SUCCESS;
+
+exit:
+	return ret;
+}
+
+void rtw_cfg80211_dev_res_unregister(struct dvobj_priv *dvobj)
+{
+#if defined(RTW_SINGLE_WIPHY)
+#ifdef CONFIG_RFKILL_POLL
+	rtw_cfg80211_deinit_rfkill(dvobj_to_wiphy(dvobj));
+#endif
+	rtw_wiphy_unregister(dvobj_to_wiphy(dvobj));
+#endif
+}
+
+#endif /* CONFIG_IOCTL_CFG80211 */
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_cfg80211.h b/drivers/staging/rtl8188eu/os_dep/ioctl_cfg80211.h
new file mode 100644
index 000000000000..a4baf5d4c995
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_cfg80211.h
@@ -0,0 +1,307 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+#ifndef __IOCTL_CFG80211_H__
+#define __IOCTL_CFG80211_H__
+
+
+#if defined(RTW_USE_CFG80211_STA_EVENT)
+	#undef CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER
+#endif
+
+#ifndef RTW_P2P_GROUP_INTERFACE
+	#define RTW_P2P_GROUP_INTERFACE 0
+#endif
+
+/*
+* (RTW_P2P_GROUP_INTERFACE, RTW_DEDICATED_P2P_DEVICE)
+* (0, 0): wlan0 + p2p0(PD+PG)
+* (1, 0): wlan0(with PD) + dynamic PGs
+* (1, 1): wlan0 (with dynamic PD wdev) + dynamic PGs
+*/
+
+#if RTW_P2P_GROUP_INTERFACE
+	#ifndef CONFIG_RTW_DYNAMIC_NDEV
+		#define CONFIG_RTW_DYNAMIC_NDEV
+	#endif
+	#ifndef RTW_SINGLE_WIPHY
+		#define RTW_SINGLE_WIPHY
+	#endif
+	#ifndef CONFIG_RADIO_WORK
+		#define CONFIG_RADIO_WORK
+	#endif
+	#ifndef RTW_DEDICATED_P2P_DEVICE
+		#define RTW_DEDICATED_P2P_DEVICE
+	#endif
+#endif
+
+#if !defined(CONFIG_P2P) && RTW_P2P_GROUP_INTERFACE
+	#error "RTW_P2P_GROUP_INTERFACE can't be enabled when CONFIG_P2P is disabled\n"
+#endif
+
+#if !RTW_P2P_GROUP_INTERFACE && defined(RTW_DEDICATED_P2P_DEVICE)
+	#error "RTW_DEDICATED_P2P_DEVICE can't be enabled when RTW_P2P_GROUP_INTERFACE is disabled\n"
+#endif
+
+#if defined(RTW_DEDICATED_P2P_DEVICE) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
+	#error "RTW_DEDICATED_P2P_DEVICE can't be enabled when kernel < 3.7.0\n"
+#endif
+
+struct rtw_wdev_invit_info {
+	u8 state; /* 0: req, 1:rep */
+	u8 peer_mac[ETH_ALEN];
+	u8 group_bssid[ETH_ALEN];
+	u8 active;
+	u8 token;
+	u8 flags;
+	u8 status;
+	u8 req_op_ch;
+	u8 rsp_op_ch;
+};
+
+#define rtw_wdev_invit_info_init(invit_info) \
+	do { \
+		(invit_info)->state = 0xff; \
+		memset((invit_info)->peer_mac, 0, ETH_ALEN); \
+		memset((invit_info)->group_bssid, 0, ETH_ALEN); \
+		(invit_info)->active = 0xff; \
+		(invit_info)->token = 0; \
+		(invit_info)->flags = 0x00; \
+		(invit_info)->status = 0xff; \
+		(invit_info)->req_op_ch = 0; \
+		(invit_info)->rsp_op_ch = 0; \
+	} while (0)
+
+struct rtw_wdev_nego_info {
+	u8 state; /* 0: req, 1:rep, 2:conf */
+	u8 iface_addr[ETH_ALEN];
+	u8 peer_mac[ETH_ALEN];
+	u8 peer_iface_addr[ETH_ALEN];
+	u8 active;
+	u8 token;
+	u8 status;
+	u8 req_intent;
+	u8 req_op_ch;
+	u8 req_listen_ch;
+	u8 rsp_intent;
+	u8 rsp_op_ch;
+	u8 conf_op_ch;
+};
+
+#define rtw_wdev_nego_info_init(nego_info) \
+	do { \
+		(nego_info)->state = 0xff; \
+		memset((nego_info)->iface_addr, 0, ETH_ALEN); \
+		memset((nego_info)->peer_mac, 0, ETH_ALEN); \
+		memset((nego_info)->peer_iface_addr, 0, ETH_ALEN); \
+		(nego_info)->active = 0xff; \
+		(nego_info)->token = 0; \
+		(nego_info)->status = 0xff; \
+		(nego_info)->req_intent = 0xff; \
+		(nego_info)->req_op_ch = 0; \
+		(nego_info)->req_listen_ch = 0; \
+		(nego_info)->rsp_intent = 0xff; \
+		(nego_info)->rsp_op_ch = 0; \
+		(nego_info)->conf_op_ch = 0; \
+	} while (0)
+
+struct rtw_wdev_priv {
+	struct wireless_dev *rtw_wdev;
+
+	_adapter *padapter;
+
+	struct cfg80211_scan_request *scan_request;
+	_lock scan_req_lock;
+
+	struct net_device *pmon_ndev;/* for monitor interface */
+	char ifname_mon[IFNAMSIZ + 1]; /* interface name for monitor interface */
+
+	u8 p2p_enabled;
+	u32 probe_resp_ie_update_time;
+
+	u8 provdisc_req_issued;
+
+	struct rtw_wdev_invit_info invit_info;
+	struct rtw_wdev_nego_info nego_info;
+
+	u8 bandroid_scan;
+	bool block;
+	bool block_scan;
+	bool power_mgmt;
+
+	/* report mgmt_frame registered */
+	u16 report_mgmt;
+
+	u8 is_mgmt_tx;
+
+	_mutex roch_mutex;
+
+#ifdef CONFIG_CONCURRENT_MODE
+	ATOMIC_T switch_ch_to;
+#endif
+
+};
+
+#define wdev_to_ndev(w) ((w)->netdev)
+#define wdev_to_wiphy(w) ((w)->wiphy)
+#define ndev_to_wdev(n) ((n)->ieee80211_ptr)
+
+struct rtw_wiphy_data {
+	struct dvobj_priv *dvobj;
+
+#ifndef RTW_SINGLE_WIPHY
+	_adapter *adapter;
+#endif
+
+#if defined(RTW_DEDICATED_P2P_DEVICE)
+	struct wireless_dev *pd_wdev; /* P2P device wdev */
+#endif
+};
+
+#define rtw_wiphy_priv(wiphy) ((struct rtw_wiphy_data *)wiphy_priv(wiphy))
+#define wiphy_to_dvobj(wiphy) (((struct rtw_wiphy_data *)wiphy_priv(wiphy))->dvobj)
+#ifdef RTW_SINGLE_WIPHY
+#define wiphy_to_adapter(wiphy) (dvobj_get_primary_adapter(wiphy_to_dvobj(wiphy)))
+#else
+#define wiphy_to_adapter(wiphy) (((struct rtw_wiphy_data *)wiphy_priv(wiphy))->adapter)
+#endif
+
+#if defined(RTW_DEDICATED_P2P_DEVICE)
+#define wiphy_to_pd_wdev(wiphy) (rtw_wiphy_priv(wiphy)->pd_wdev)
+#else
+#define wiphy_to_pd_wdev(wiphy) NULL
+#endif
+
+#define WIPHY_FMT "%s"
+#define WIPHY_ARG(wiphy) wiphy_name(wiphy)
+#define FUNC_WIPHY_FMT "%s("WIPHY_FMT")"
+#define FUNC_WIPHY_ARG(wiphy) __func__, WIPHY_ARG(wiphy)
+
+#define SET_CFG80211_REPORT_MGMT(w, t, v) (w->report_mgmt |= (v ? BIT(t >> 4) : 0))
+#define GET_CFG80211_REPORT_MGMT(w, t) ((w->report_mgmt & BIT(t >> 4)) > 0)
+
+struct wiphy *rtw_wiphy_alloc(_adapter *padapter, struct device *dev);
+void rtw_wiphy_free(struct wiphy *wiphy);
+int rtw_wiphy_register(struct wiphy *wiphy);
+void rtw_wiphy_unregister(struct wiphy *wiphy);
+
+int rtw_wdev_alloc(_adapter *padapter, struct wiphy *wiphy);
+void rtw_wdev_free(struct wireless_dev *wdev);
+void rtw_wdev_unregister(struct wireless_dev *wdev);
+
+int rtw_cfg80211_ndev_res_alloc(_adapter *adapter);
+void rtw_cfg80211_ndev_res_free(_adapter *adapter);
+int rtw_cfg80211_ndev_res_register(_adapter *adapter);
+void rtw_cfg80211_ndev_res_unregister(_adapter *adapter);
+
+int rtw_cfg80211_dev_res_alloc(struct dvobj_priv *dvobj);
+void rtw_cfg80211_dev_res_free(struct dvobj_priv *dvobj);
+int rtw_cfg80211_dev_res_register(struct dvobj_priv *dvobj);
+void rtw_cfg80211_dev_res_unregister(struct dvobj_priv *dvobj);
+
+void rtw_cfg80211_init_wdev_data(_adapter *padapter);
+void rtw_cfg80211_init_wiphy(_adapter *padapter);
+
+void rtw_cfg80211_unlink_bss(_adapter *padapter, struct wlan_network *pnetwork);
+void rtw_cfg80211_surveydone_event_callback(_adapter *padapter);
+struct cfg80211_bss *rtw_cfg80211_inform_bss(_adapter *padapter, struct wlan_network *pnetwork);
+int rtw_cfg80211_check_bss(_adapter *padapter);
+void rtw_cfg80211_ibss_indicate_connect(_adapter *padapter);
+void rtw_cfg80211_indicate_connect(_adapter *padapter);
+void rtw_cfg80211_indicate_disconnect(_adapter *padapter, u16 reason, u8 locally_generated);
+void rtw_cfg80211_indicate_scan_done(_adapter *adapter, bool aborted);
+u32 rtw_cfg80211_wait_scan_req_empty(_adapter *adapter, u32 timeout_ms);
+
+#ifdef CONFIG_CONCURRENT_MODE
+u8 rtw_cfg80211_scan_via_buddy(_adapter *padapter, struct cfg80211_scan_request *request);
+void rtw_cfg80211_indicate_scan_done_for_buddy(_adapter *padapter, bool bscan_aborted);
+#endif
+
+#ifdef CONFIG_AP_MODE
+void rtw_cfg80211_indicate_sta_assoc(_adapter *padapter, u8 *pmgmt_frame, uint frame_len);
+void rtw_cfg80211_indicate_sta_disassoc(_adapter *padapter, unsigned char *da, unsigned short reason);
+#endif /* CONFIG_AP_MODE */
+
+#ifdef CONFIG_P2P
+void rtw_cfg80211_set_is_roch(_adapter *adapter, bool val);
+bool rtw_cfg80211_get_is_roch(_adapter *adapter);
+
+int rtw_cfg80211_iface_has_p2p_group_cap(_adapter *adapter);
+int rtw_cfg80211_is_p2p_scan(_adapter *adapter);
+#if defined(RTW_DEDICATED_P2P_DEVICE)
+int rtw_cfg80211_redirect_pd_wdev(struct wiphy *wiphy, u8 *ra, struct wireless_dev **wdev);
+int rtw_cfg80211_is_scan_by_pd_wdev(_adapter *adapter);
+int rtw_pd_iface_alloc(struct wiphy *wiphy, const char *name, struct wireless_dev **pd_wdev);
+void rtw_pd_iface_free(struct wiphy *wiphy);
+#endif
+#endif /* CONFIG_P2P */
+
+void rtw_cfg80211_set_is_mgmt_tx(_adapter *adapter, u8 val);
+u8 rtw_cfg80211_get_is_mgmt_tx(_adapter *adapter);
+
+void rtw_cfg80211_issue_p2p_provision_request(_adapter *padapter, const u8 *buf, size_t len);
+
+void rtw_cfg80211_rx_p2p_action_public(_adapter *padapter, union recv_frame *rframe);
+void rtw_cfg80211_rx_action_p2p(_adapter *padapter, union recv_frame *rframe);
+void rtw_cfg80211_rx_action(_adapter *adapter, union recv_frame *rframe, const char *msg);
+void rtw_cfg80211_rx_probe_request(_adapter *padapter, union recv_frame *rframe);
+
+int rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device *net, char *buf, int len, int type);
+
+bool rtw_cfg80211_pwr_mgmt(_adapter *adapter);
+
+#ifdef CONFIG_RFKILL_POLL
+void rtw_cfg80211_init_rfkill(struct wiphy *wiphy);
+void rtw_cfg80211_deinit_rfkill(struct wiphy *wiphy);
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))  && !defined(COMPAT_KERNEL_RELEASE)
+#define rtw_cfg80211_rx_mgmt(wdev, freq, sig_dbm, buf, len, gfp) cfg80211_rx_mgmt(wdev_to_ndev(wdev), freq, buf, len, gfp)
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
+#define rtw_cfg80211_rx_mgmt(wdev, freq, sig_dbm, buf, len, gfp) cfg80211_rx_mgmt(wdev_to_ndev(wdev), freq, sig_dbm, buf, len, gfp)
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0))
+#define rtw_cfg80211_rx_mgmt(wdev, freq, sig_dbm, buf, len, gfp) cfg80211_rx_mgmt(wdev, freq, sig_dbm, buf, len, gfp)
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3 , 18 , 0))
+#define rtw_cfg80211_rx_mgmt(wdev , freq , sig_dbm , buf , len , gfp) cfg80211_rx_mgmt(wdev , freq , sig_dbm , buf , len , 0 , gfp)
+#else
+#define rtw_cfg80211_rx_mgmt(wdev , freq , sig_dbm , buf , len , gfp) cfg80211_rx_mgmt(wdev , freq , sig_dbm , buf , len , 0)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))  && !defined(COMPAT_KERNEL_RELEASE)
+#define rtw_cfg80211_send_rx_assoc(adapter, bss, buf, len) cfg80211_send_rx_assoc((adapter)->pnetdev, buf, len)
+#else
+#define rtw_cfg80211_send_rx_assoc(adapter, bss, buf, len) cfg80211_send_rx_assoc((adapter)->pnetdev, bss, buf, len)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
+#define rtw_cfg80211_mgmt_tx_status(wdev, cookie, buf, len, ack, gfp) cfg80211_mgmt_tx_status(wdev_to_ndev(wdev), cookie, buf, len, ack, gfp)
+#else
+#define rtw_cfg80211_mgmt_tx_status(wdev, cookie, buf, len, ack, gfp) cfg80211_mgmt_tx_status(wdev, cookie, buf, len, ack, gfp)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
+#define rtw_cfg80211_ready_on_channel(wdev, cookie, chan, channel_type, duration, gfp)  cfg80211_ready_on_channel(wdev_to_ndev(wdev), cookie, chan, channel_type, duration, gfp)
+#define rtw_cfg80211_remain_on_channel_expired(wdev, cookie, chan, chan_type, gfp) cfg80211_remain_on_channel_expired(wdev_to_ndev(wdev), cookie, chan, chan_type, gfp)
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
+#define rtw_cfg80211_ready_on_channel(wdev, cookie, chan, channel_type, duration, gfp)  cfg80211_ready_on_channel(wdev, cookie, chan, channel_type, duration, gfp)
+#define rtw_cfg80211_remain_on_channel_expired(wdev, cookie, chan, chan_type, gfp) cfg80211_remain_on_channel_expired(wdev, cookie, chan, chan_type, gfp)
+#else
+#define rtw_cfg80211_ready_on_channel(wdev, cookie, chan, channel_type, duration, gfp)  cfg80211_ready_on_channel(wdev, cookie, chan, duration, gfp)
+#define rtw_cfg80211_remain_on_channel_expired(wdev, cookie, chan, chan_type, gfp) cfg80211_remain_on_channel_expired(wdev, cookie, chan, gfp)
+#endif
+
+#ifdef CONFIG_RTW_80211R
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
+#define rtw_cfg80211_ft_event(adapter, parm)  cfg80211_ft_event((adapter)->pnetdev, parm)
+#else
+	#error "Cannot support FT for KERNEL_VERSION < 3.10\n"
+#endif
+#endif
+
+#if (KERNEL_VERSION(4, 7, 0) >= LINUX_VERSION_CODE)
+#define NUM_NL80211_BANDS IEEE80211_NUM_BANDS
+#endif
+
+#include "rtw_cfgvendor.h"
+
+#endif /* __IOCTL_CFG80211_H__ */
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
new file mode 100644
index 000000000000..654e2baee932
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -0,0 +1,12398 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+#define _IOCTL_LINUX_C_
+
+#include <drv_types.h>
+#include <rtw_mp.h>
+#include <rtw_mp_ioctl.h>
+#include <rtw_mlme.h>
+#include "../../hal/phydm_precomp.h"
+#ifdef RTW_HALMAC
+#include "../../hal/hal_halmac.h"
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27))
+#define  iwe_stream_add_event(a, b, c, d, e)  iwe_stream_add_event(b, c, d, e)
+#define  iwe_stream_add_point(a, b, c, d, e)  iwe_stream_add_point(b, c, d, e)
+#endif
+
+extern int rtw_ht_enable;
+
+#define RTL_IOCTL_WPA_SUPPLICANT	(SIOCIWFIRSTPRIV+30)
+
+#define SCAN_ITEM_SIZE 768
+#define MAX_CUSTOM_LEN 64
+#define RATE_COUNT 4
+
+/* combo scan */
+#define WEXT_CSCAN_AMOUNT 9
+#define WEXT_CSCAN_BUF_LEN		360
+#define WEXT_CSCAN_HEADER		"CSCAN S\x01\x00\x00S\x00"
+#define WEXT_CSCAN_HEADER_SIZE		12
+#define WEXT_CSCAN_SSID_SECTION		'S'
+#define WEXT_CSCAN_CHANNEL_SECTION	'C'
+#define WEXT_CSCAN_NPROBE_SECTION	'N'
+#define WEXT_CSCAN_ACTV_DWELL_SECTION	'A'
+#define WEXT_CSCAN_PASV_DWELL_SECTION	'P'
+#define WEXT_CSCAN_HOME_DWELL_SECTION	'H'
+#define WEXT_CSCAN_TYPE_SECTION		'T'
+
+
+extern u8 key_2char2num(u8 hch, u8 lch);
+extern u8 str_2char2num(u8 hch, u8 lch);
+extern void macstr2num(u8 *dst, u8 *src);
+extern u8 convert_ip_addr(u8 hch, u8 mch, u8 lch);
+
+static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
+	6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
+
+static const char *const iw_operation_mode[] = {
+	"Auto", "Ad-Hoc", "Managed",  "Master", "Repeater", "Secondary", "Monitor"
+};
+
+static int hex2num_i(char c)
+{
+	if (c >= '0' && c <= '9')
+		return c - '0';
+	if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	if (c >= 'A' && c <= 'F')
+		return c - 'A' + 10;
+	return -1;
+}
+
+static int hex2byte_i(const char *hex)
+{
+	int a, b;
+	a = hex2num_i(*hex++);
+	if (a < 0)
+		return -1;
+	b = hex2num_i(*hex++);
+	if (b < 0)
+		return -1;
+	return (a << 4) | b;
+}
+
+/**
+ * hwaddr_aton - Convert ASCII string to MAC address
+ * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
+ * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
+ * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
+ */
+static int hwaddr_aton_i(const char *txt, u8 *addr)
+{
+	int i;
+
+	for (i = 0; i < 6; i++) {
+		int a, b;
+
+		a = hex2num_i(*txt++);
+		if (a < 0)
+			return -1;
+		b = hex2num_i(*txt++);
+		if (b < 0)
+			return -1;
+		*addr++ = (a << 4) | b;
+		if (i < 5 && *txt++ != ':')
+			return -1;
+	}
+
+	return 0;
+}
+
+static void indicate_wx_custom_event(_adapter *padapter, char *msg)
+{
+	u8 *buff, *p;
+	union iwreq_data wrqu;
+
+	if (strlen(msg) > IW_CUSTOM_MAX) {
+		RTW_INFO("%s strlen(msg):%zu > IW_CUSTOM_MAX:%u\n", __func__ , strlen(msg), IW_CUSTOM_MAX);
+		return;
+	}
+
+	buff = rtw_zmalloc(IW_CUSTOM_MAX + 1);
+	if (!buff)
+		return;
+
+	memcpy(buff, msg, strlen(msg));
+
+	memset(&wrqu, 0, sizeof(wrqu));
+	wrqu.data.length = strlen(msg);
+
+	RTW_INFO("%s %s\n", __func__, buff);
+#ifndef CONFIG_IOCTL_CFG80211
+	wireless_send_event(padapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
+#endif
+
+	rtw_mfree(buff, IW_CUSTOM_MAX + 1);
+
+}
+
+
+static void request_wps_pbc_event(_adapter *padapter)
+{
+	u8 *buff, *p;
+	union iwreq_data wrqu;
+
+
+	buff = rtw_malloc(IW_CUSTOM_MAX);
+	if (!buff)
+		return;
+
+	memset(buff, 0, IW_CUSTOM_MAX);
+
+	p = buff;
+
+	p += sprintf(p, "WPS_PBC_START.request=true");
+
+	memset(&wrqu, 0, sizeof(wrqu));
+
+	wrqu.data.length = p - buff;
+
+	wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ? wrqu.data.length : IW_CUSTOM_MAX;
+
+	RTW_INFO("%s\n", __func__);
+
+#ifndef CONFIG_IOCTL_CFG80211
+	wireless_send_event(padapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
+#endif
+
+	if (buff)
+		rtw_mfree(buff, IW_CUSTOM_MAX);
+
+}
+
+#ifdef CONFIG_SUPPORT_HW_WPS_PBC
+void rtw_request_wps_pbc_event(_adapter *padapter)
+{
+#ifdef RTK_DMP_PLATFORM
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12))
+	kobject_uevent(&padapter->pnetdev->dev.kobj, KOBJ_NET_PBC);
+#else
+	kobject_hotplug(&padapter->pnetdev->class_dev.kobj, KOBJ_NET_PBC);
+#endif
+#else
+
+	if (padapter->pid[0] == 0) {
+		/*	0 is the default value and it means the application monitors the HW PBC doesn't privde its pid to driver. */
+		return;
+	}
+
+	rtw_signal_process(padapter->pid[0], SIGUSR1);
+
+#endif
+
+	rtw_led_control(padapter, LED_CTL_START_WPS_BOTTON);
+}
+#endif/* #ifdef CONFIG_SUPPORT_HW_WPS_PBC */
+
+void indicate_wx_scan_complete_event(_adapter *padapter)
+{
+	union iwreq_data wrqu;
+	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+	memset(&wrqu, 0, sizeof(union iwreq_data));
+
+	/* RTW_INFO("+rtw_indicate_wx_scan_complete_event\n"); */
+#ifndef CONFIG_IOCTL_CFG80211
+	wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
+#endif
+}
+
+
+void rtw_indicate_wx_assoc_event(_adapter *padapter)
+{
+	union iwreq_data wrqu;
+	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));
+
+	memset(&wrqu, 0, sizeof(union iwreq_data));
+
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+
+	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
+		memcpy(wrqu.ap_addr.sa_data, pnetwork->MacAddress, ETH_ALEN);
+	else
+		memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
+
+	RTW_INFO("assoc success\n");
+#ifndef CONFIG_IOCTL_CFG80211
+	wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
+#endif
+}
+
+void rtw_indicate_wx_disassoc_event(_adapter *padapter)
+{
+	union iwreq_data wrqu;
+
+	memset(&wrqu, 0, sizeof(union iwreq_data));
+
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+	memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+
+#ifndef CONFIG_IOCTL_CFG80211
+	RTW_INFO("indicate disassoc\n");
+	wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
+#endif
+}
+
+/*
+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;
+}
+*/
+
+static int search_p2p_wfd_ie(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop)
+{
+#ifdef CONFIG_P2P
+	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
+#ifdef CONFIG_WFD
+	if (SCAN_RESULT_ALL == pwdinfo->wfd_info->scan_result_type) {
+
+	} else if ((SCAN_RESULT_P2P_ONLY == pwdinfo->wfd_info->scan_result_type) ||
+		(SCAN_RESULT_WFD_TYPE == pwdinfo->wfd_info->scan_result_type))
+#endif /* CONFIG_WFD */
+	{
+		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+			u32	blnGotP2PIE = false;
+
+			/*	User is doing the P2P device discovery */
+			/*	The prefix of SSID should be "DIRECT-" and the IE should contains the P2P IE. */
+			/*	If not, the driver should ignore this AP and go to the next AP. */
+
+			/*	Verifying the SSID */
+			if (!memcmp(pnetwork->network.Ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN)) {
+				u32	p2pielen = 0;
+
+				/*	Verifying the P2P IE */
+				if (rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen))
+					blnGotP2PIE = true;
+			}
+
+			if (blnGotP2PIE == false)
+				return false;
+
+		}
+	}
+
+#ifdef CONFIG_WFD
+	if (SCAN_RESULT_WFD_TYPE == pwdinfo->wfd_info->scan_result_type) {
+		u32	blnGotWFD = false;
+		u8 *wfd_ie;
+		uint wfd_ielen = 0;
+
+		wfd_ie = rtw_bss_ex_get_wfd_ie(&pnetwork->network, NULL, &wfd_ielen);
+		if (wfd_ie) {
+			u8 *wfd_devinfo;
+			uint wfd_devlen;
+
+			wfd_devinfo = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &wfd_devlen);
+			if (wfd_devinfo) {
+				if (pwdinfo->wfd_info->wfd_device_type == WFD_DEVINFO_PSINK) {
+					/*	the first two bits will indicate the WFD device type */
+					if ((wfd_devinfo[1] & 0x03) == WFD_DEVINFO_SOURCE) {
+						/*	If this device is Miracast PSink device, the scan reuslt should just provide the Miracast source. */
+						blnGotWFD = true;
+					}
+				} else if (pwdinfo->wfd_info->wfd_device_type == WFD_DEVINFO_SOURCE) {
+					/*	the first two bits will indicate the WFD device type */
+					if ((wfd_devinfo[1] & 0x03) == WFD_DEVINFO_PSINK) {
+						/*	If this device is Miracast source device, the scan reuslt should just provide the Miracast PSink. */
+						/*	Todo: How about the SSink?! */
+						blnGotWFD = true;
+					}
+				}
+			}
+		}
+
+		if (blnGotWFD == false)
+			return false;
+	}
+#endif /* CONFIG_WFD */
+
+#endif /* CONFIG_P2P */
+	return true;
+}
+static inline char *iwe_stream_mac_addr_proess(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop, struct iw_event *iwe)
+{
+	/*  AP MAC address */
+	iwe->cmd = SIOCGIWAP;
+	iwe->u.ap_addr.sa_family = ARPHRD_ETHER;
+
+	memcpy(iwe->u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
+	start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_ADDR_LEN);
+	return start;
+}
+static inline char *iwe_stream_essid_proess(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop, struct iw_event *iwe)
+{
+
+	/* Add the ESSID */
+	iwe->cmd = SIOCGIWESSID;
+	iwe->u.data.flags = 1;
+	iwe->u.data.length = min((u16)pnetwork->network.Ssid.SsidLength, (u16)32);
+	start = iwe_stream_add_point(info, start, stop, iwe, pnetwork->network.Ssid.Ssid);
+	return start;
+}
+
+static inline char *iwe_stream_chan_process(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop, struct iw_event *iwe)
+{
+	if (pnetwork->network.Configuration.DSConfig < 1 /*|| pnetwork->network.Configuration.DSConfig>14*/)
+		pnetwork->network.Configuration.DSConfig = 1;
+
+	/* Add frequency/channel */
+	iwe->cmd = SIOCGIWFREQ;
+	iwe->u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
+	iwe->u.freq.e = 1;
+	iwe->u.freq.i = pnetwork->network.Configuration.DSConfig;
+	start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_FREQ_LEN);
+	return start;
+}
+static inline char *iwe_stream_mode_process(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop, struct iw_event *iwe, u16 cap)
+{
+	/* Add mode */
+	if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
+		iwe->cmd = SIOCGIWMODE;
+		if (cap & WLAN_CAPABILITY_BSS)
+			iwe->u.mode = IW_MODE_MASTER;
+		else
+			iwe->u.mode = IW_MODE_ADHOC;
+
+		start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_UINT_LEN);
+	}
+	return start;
+}
+static inline char *iwe_stream_encryption_process(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop, struct iw_event *iwe, u16 cap)
+{
+
+	/* Add encryption capability */
+	iwe->cmd = SIOCGIWENCODE;
+	if (cap & WLAN_CAPABILITY_PRIVACY)
+		iwe->u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+	else
+		iwe->u.data.flags = IW_ENCODE_DISABLED;
+	iwe->u.data.length = 0;
+	start = iwe_stream_add_point(info, start, stop, iwe, pnetwork->network.Ssid.Ssid);
+	return start;
+
+}
+
+static inline char *iwe_stream_protocol_process(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop, struct iw_event *iwe)
+{
+	u16 ht_cap = false, vht_cap = false;
+	u32 ht_ielen = 0, vht_ielen = 0;
+	char *p;
+	u8 ie_offset = (pnetwork->network.Reserved[0] == 2 ? 0 : 12); /* Probe Request	 */
+
+	/* parsing HT_CAP_IE	 */
+	p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength - ie_offset);
+	if (p && ht_ielen > 0)
+		ht_cap = true;
+
+	/* Add the protocol name */
+	iwe->cmd = SIOCGIWNAME;
+	if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates))) {
+		if (ht_cap )
+			snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11bn");
+		else
+			snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11b");
+	} else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates))) {
+		if (ht_cap )
+			snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11bgn");
+		else
+			snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11bg");
+	} else {
+		if (pnetwork->network.Configuration.DSConfig > 14) {
+			if (ht_cap )
+				snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11an");
+			else
+				snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11a");
+		} else {
+			if (ht_cap )
+				snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11gn");
+			else
+				snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11g");
+		}
+	}
+	start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_CHAR_LEN);
+	return start;
+}
+
+static inline char *iwe_stream_rate_process(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop, struct iw_event *iwe)
+{
+	u32 ht_ielen = 0, vht_ielen = 0;
+	char *p;
+	u16 max_rate = 0, rate, ht_cap = false, vht_cap = false;
+	u32 i = 0;
+	u8 bw_40MHz = 0, short_GI = 0, bw_160MHz = 0, vht_highest_rate = 0;
+	u16 mcs_rate = 0, vht_data_rate = 0;
+	char custom[MAX_CUSTOM_LEN] = {0};
+	u8 ie_offset = (pnetwork->network.Reserved[0] == 2 ? 0 : 12); /* Probe Request	 */
+
+	/* parsing HT_CAP_IE	 */
+	p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength - ie_offset);
+	if (p && ht_ielen > 0) {
+		struct rtw_ieee80211_ht_cap *pht_capie;
+
+		ht_cap = true;
+		pht_capie = (struct rtw_ieee80211_ht_cap *)(p + 2);
+		memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
+		bw_40MHz = (le16_to_cpu(pht_capie->cap_info) & IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
+		short_GI = (le16_to_cpu(pht_capie->cap_info) & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
+	}
+
+	/*Add basic and extended rates */
+	p = custom;
+	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
+	while (pnetwork->network.SupportedRates[i] != 0) {
+		rate = pnetwork->network.SupportedRates[i] & 0x7F;
+		if (rate > max_rate)
+			max_rate = rate;
+		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+			      "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
+		i++;
+	}
+	if (ht_cap ) {
+		if (mcs_rate & 0x8000) /* MCS15 */
+			max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130);
+
+		else if (mcs_rate & 0x0080) /* MCS7 */
+			max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
+		else { /* default MCS7 */
+			/* RTW_INFO("wx_get_scan, mcs_rate_bitmap=0x%x\n", mcs_rate); */
+			max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
+		}
+
+		max_rate = max_rate * 2; /* Mbps/2;		 */
+	}
+
+	iwe->cmd = SIOCGIWRATE;
+	iwe->u.bitrate.fixed = iwe->u.bitrate.disabled = 0;
+	iwe->u.bitrate.value = max_rate * 500000;
+	start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_PARAM_LEN);
+	return start ;
+}
+
+static inline char *iwe_stream_wpa_wpa2_process(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop, struct iw_event *iwe)
+{
+	int buf_size = MAX_WPA_IE_LEN * 2;
+	/* u8 pbuf[buf_size]={0};	 */
+	u8 *pbuf = rtw_zmalloc(buf_size);
+
+	u8 wpa_ie[255] = {0}, rsn_ie[255] = {0};
+	u16 i, wpa_len = 0, rsn_len = 0;
+	u8 *p;
+	sint out_len = 0;
+
+
+	if (pbuf) {
+		p = pbuf;
+
+		/* parsing WPA/WPA2 IE */
+		if (pnetwork->network.Reserved[0] != 2) { /* Probe Request */
+			out_len = rtw_get_sec_ie(pnetwork->network.IEs , pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
+
+			if (wpa_len > 0) {
+
+				memset(pbuf, 0, buf_size);
+				p += sprintf(p, "wpa_ie=");
+				for (i = 0; i < wpa_len; i++)
+					p += sprintf(p, "%02x", wpa_ie[i]);
+
+				if (wpa_len > 100) {
+					printk("-----------------Len %d----------------\n", wpa_len);
+					for (i = 0; i < wpa_len; i++)
+						printk("%02x ", wpa_ie[i]);
+					printk("\n");
+					printk("-----------------Len %d----------------\n", wpa_len);
+				}
+
+				memset(iwe, 0, sizeof(*iwe));
+				iwe->cmd = IWEVCUSTOM;
+				iwe->u.data.length = strlen(pbuf);
+				start = iwe_stream_add_point(info, start, stop, iwe, pbuf);
+
+				memset(iwe, 0, sizeof(*iwe));
+				iwe->cmd = IWEVGENIE;
+				iwe->u.data.length = wpa_len;
+				start = iwe_stream_add_point(info, start, stop, iwe, wpa_ie);
+			}
+			if (rsn_len > 0) {
+
+				memset(pbuf, 0, buf_size);
+				p += sprintf(p, "rsn_ie=");
+				for (i = 0; i < rsn_len; i++)
+					p += sprintf(p, "%02x", rsn_ie[i]);
+				memset(iwe, 0, sizeof(*iwe));
+				iwe->cmd = IWEVCUSTOM;
+				iwe->u.data.length = strlen(pbuf);
+				start = iwe_stream_add_point(info, start, stop, iwe, pbuf);
+
+				memset(iwe, 0, sizeof(*iwe));
+				iwe->cmd = IWEVGENIE;
+				iwe->u.data.length = rsn_len;
+				start = iwe_stream_add_point(info, start, stop, iwe, rsn_ie);
+			}
+		}
+
+		rtw_mfree(pbuf, buf_size);
+	}
+	return start;
+}
+
+static inline char *iwe_stream_wps_process(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop, struct iw_event *iwe)
+{
+	/* parsing WPS IE */
+	uint cnt = 0, total_ielen;
+	u8 *wpsie_ptr = NULL;
+	uint wps_ielen = 0;
+	u8 ie_offset = (pnetwork->network.Reserved[0] == 2 ? 0 : 12);
+
+	u8 *ie_ptr = pnetwork->network.IEs + ie_offset;
+	total_ielen = pnetwork->network.IELength - ie_offset;
+
+	if (pnetwork->network.Reserved[0] == 2) { /* Probe Request */
+		ie_ptr = pnetwork->network.IEs;
+		total_ielen = pnetwork->network.IELength;
+	} else { /* Beacon or Probe Respones */
+		ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
+		total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
+	}
+	while (cnt < total_ielen) {
+		if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
+			wpsie_ptr = &ie_ptr[cnt];
+			iwe->cmd = IWEVGENIE;
+			iwe->u.data.length = (u16)wps_ielen;
+			start = iwe_stream_add_point(info, start, stop, iwe, wpsie_ptr);
+		}
+		cnt += ie_ptr[cnt + 1] + 2; /* goto next */
+	}
+	return start;
+}
+
+static inline char *iwe_stream_wapi_process(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop, struct iw_event *iwe)
+{
+#ifdef CONFIG_WAPI_SUPPORT
+	char *p;
+
+	if (pnetwork->network.Reserved[0] != 2) { /* Probe Request */
+		sint out_len_wapi = 0;
+		/* here use static for stack size */
+		static u8 buf_wapi[MAX_WAPI_IE_LEN * 2] = {0};
+		static u8 wapi_ie[MAX_WAPI_IE_LEN] = {0};
+		u16 wapi_len = 0;
+		u16  i;
+
+		out_len_wapi = rtw_get_wapi_ie(pnetwork->network.IEs , pnetwork->network.IELength, wapi_ie, &wapi_len);
+
+		RTW_INFO("rtw_wx_get_scan: %s ", pnetwork->network.Ssid.Ssid);
+		RTW_INFO("rtw_wx_get_scan: ssid = %d ", wapi_len);
+
+
+		if (wapi_len > 0) {
+			p = buf_wapi;
+			/* memset(buf_wapi, 0, MAX_WAPI_IE_LEN*2); */
+			p += sprintf(p, "wapi_ie=");
+			for (i = 0; i < wapi_len; i++)
+				p += sprintf(p, "%02x", wapi_ie[i]);
+
+			memset(iwe, 0, sizeof(*iwe));
+			iwe->cmd = IWEVCUSTOM;
+			iwe->u.data.length = strlen(buf_wapi);
+			start = iwe_stream_add_point(info, start, stop, iwe, buf_wapi);
+
+			memset(iwe, 0, sizeof(*iwe));
+			iwe->cmd = IWEVGENIE;
+			iwe->u.data.length = wapi_len;
+			start = iwe_stream_add_point(info, start, stop, iwe, wapi_ie);
+		}
+	}
+#endif/* #ifdef CONFIG_WAPI_SUPPORT */
+	return start;
+}
+
+static inline char   *iwe_stream_rssi_process(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop, struct iw_event *iwe)
+{
+	u8 ss, sq;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	/* Add quality statistics */
+	iwe->cmd = IWEVQUAL;
+	iwe->u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED
+#if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
+			      | IW_QUAL_NOISE_UPDATED
+#else
+			      | IW_QUAL_NOISE_INVALID
+#endif
+#ifdef CONFIG_SIGNAL_DISPLAY_DBM
+			      | IW_QUAL_DBM
+#endif
+			      ;
+
+	if (check_fwstate(pmlmepriv, _FW_LINKED)  &&
+	    is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {
+		ss = padapter->recvpriv.signal_strength;
+		sq = padapter->recvpriv.signal_qual;
+	} else {
+		ss = pnetwork->network.PhyInfo.SignalStrength;
+		sq = pnetwork->network.PhyInfo.SignalQuality;
+	}
+
+
+#ifdef CONFIG_SIGNAL_DISPLAY_DBM
+	iwe->u.qual.level = (u8) translate_percentage_to_dbm(ss); /* dbm */
+#else
+#ifdef CONFIG_SIGNAL_SCALE_MAPPING
+	iwe->u.qual.level = (u8)ss; /* % */
+#else
+	{
+		/* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */
+
+		HAL_DATA_TYPE *pHal = GET_HAL_DATA(padapter);
+
+		iwe->u.qual.level = (u8)odm_signal_scale_mapping(&pHal->odmpriv, ss);
+	}
+#endif
+#endif
+
+	iwe->u.qual.qual = (u8)sq;   /* signal quality */
+
+#ifdef CONFIG_PLATFORM_ROCKCHIPS
+	iwe->u.qual.noise = -100; /* noise level suggest by zhf@rockchips */
+#else
+#if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
+	{
+		s16 tmp_noise = 0;
+		rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &(pnetwork->network.Configuration.DSConfig), &(tmp_noise));
+		iwe->u.qual.noise = tmp_noise ;
+	}
+#else
+	iwe->u.qual.noise = 0; /* noise level */
+#endif
+#endif /* CONFIG_PLATFORM_ROCKCHIPS */
+
+	/* RTW_INFO("iqual=%d, ilevel=%d, inoise=%d, iupdated=%d\n", iwe.u.qual.qual, iwe.u.qual.level , iwe.u.qual.noise, iwe.u.qual.updated); */
+
+	start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_QUAL_LEN);
+	return start;
+}
+
+static inline char   *iwe_stream_net_rsv_process(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop, struct iw_event *iwe)
+{
+	u8 buf[32] = {0};
+	u8 *p, *pos;
+	int len;
+	p = buf;
+	pos = pnetwork->network.Reserved;
+
+	p += sprintf(p, "fm=%02X%02X", pos[1], pos[0]);
+	memset(iwe, 0, sizeof(*iwe));
+	iwe->cmd = IWEVCUSTOM;
+	iwe->u.data.length = strlen(buf);
+	start = iwe_stream_add_point(info, start, stop, iwe, buf);
+	return start;
+}
+
+static char *translate_scan(_adapter *padapter,
+		struct iw_request_info *info, struct wlan_network *pnetwork,
+		char *start, char *stop)
+{
+	struct iw_event iwe;
+	u16 cap = 0;
+	__le16 le_tmp;
+
+	memset(&iwe, 0, sizeof(iwe));
+	if (false == search_p2p_wfd_ie(padapter, info, pnetwork, start, stop))
+		return start;
+
+	start = iwe_stream_mac_addr_proess(padapter, info, pnetwork, start, stop, &iwe);
+	start = iwe_stream_essid_proess(padapter, info, pnetwork, start, stop, &iwe);
+	start = iwe_stream_protocol_process(padapter, info, pnetwork, start, stop, &iwe);
+	if (pnetwork->network.Reserved[0] != 2) { /* Probe Request */
+		memcpy((u8 *)&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
+		cap = le16_to_cpu(le_tmp);
+	}
+
+	start = iwe_stream_mode_process(padapter, info, pnetwork, start, stop, &iwe, cap);
+	start = iwe_stream_chan_process(padapter, info, pnetwork, start, stop, &iwe);
+	start = iwe_stream_encryption_process(padapter, info, pnetwork, start, stop, &iwe, cap);
+	start = iwe_stream_rate_process(padapter, info, pnetwork, start, stop, &iwe);
+	start = iwe_stream_wpa_wpa2_process(padapter, info, pnetwork, start, stop, &iwe);
+	start = iwe_stream_wps_process(padapter, info, pnetwork, start, stop, &iwe);
+	start = iwe_stream_wapi_process(padapter, info, pnetwork, start, stop, &iwe);
+	start = iwe_stream_rssi_process(padapter, info, pnetwork, start, stop, &iwe);
+	start = iwe_stream_net_rsv_process(padapter, info, pnetwork, start, stop, &iwe);
+
+	return start;
+}
+
+static int wpa_set_auth_algs(struct net_device *dev, u32 value)
+{
+	_adapter *padapter = (_adapter *) rtw_netdev_priv(dev);
+	int ret = 0;
+
+	if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
+		RTW_INFO("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and  AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n", value);
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+		padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
+		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
+	} else if (value & AUTH_ALG_SHARED_KEY) {
+		RTW_INFO("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY  [value:0x%x]\n", value);
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+
+#ifdef CONFIG_PLATFORM_MT53XX
+		padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
+		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
+#else
+		padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
+		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
+#endif
+	} else if (value & AUTH_ALG_OPEN_SYSTEM) {
+		RTW_INFO("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n");
+		/* padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; */
+		if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
+#ifdef CONFIG_PLATFORM_MT53XX
+			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
+			padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
+#else
+			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
+			padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+#endif
+		}
+
+	} else if (value & AUTH_ALG_LEAP)
+		RTW_INFO("wpa_set_auth_algs, AUTH_ALG_LEAP\n");
+	else {
+		RTW_INFO("wpa_set_auth_algs, error!\n");
+		ret = -EINVAL;
+	}
+
+	return ret;
+
+}
+
+static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
+{
+	int ret = 0;
+	u32 wep_key_idx, wep_key_len, wep_total_len;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_P2P */
+
+
+	param->u.crypt.err = 0;
+	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+	if (param_len < (u32)((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) {
+		ret =  -EINVAL;
+		goto exit;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+
+		if (param->u.crypt.idx >= WEP_KEYS
+#ifdef CONFIG_IEEE80211W
+		    && param->u.crypt.idx > BIP_MAX_KEYID
+#endif /* CONFIG_IEEE80211W */
+		   ) {
+			ret = -EINVAL;
+			goto exit;
+		}
+	} else {
+#ifdef CONFIG_WAPI_SUPPORT
+		if (strcmp(param->u.crypt.alg, "SMS4"))
+#endif
+		{
+			ret = -EINVAL;
+			goto exit;
+		}
+	}
+
+	if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+		RTW_INFO("wpa_set_encryption, crypt.alg = WEP\n");
+
+		wep_key_idx = param->u.crypt.idx;
+		wep_key_len = param->u.crypt.key_len;
+
+		if ((wep_key_idx > WEP_KEYS) || (wep_key_len <= 0)) {
+			ret = -EINVAL;
+			goto exit;
+		}
+
+		if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
+			/* wep default key has not been set, so use this key index as default key.*/
+
+			wep_key_len = wep_key_len <= 5 ? 5 : 13;
+
+			psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
+			psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+			psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+			if (wep_key_len == 13) {
+				psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+				psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+			}
+
+			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
+		}
+
+		memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), param->u.crypt.key, wep_key_len);
+
+		psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;
+
+		psecuritypriv->key_mask |= BIT(wep_key_idx);
+
+		goto exit;
+	}
+
+	if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */
+		struct sta_info *psta, *pbcmc_sta;
+		struct sta_priv *pstapriv = &padapter->stapriv;
+
+		if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) ) { /* sta mode */
+			psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
+			if (psta == NULL) {
+				/* DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
+			} else {
+				/* Jeff: don't disable ieee8021x_blocked while clearing key */
+				if (strcmp(param->u.crypt.alg, "none") != 0)
+					psta->ieee8021x_blocked = false;
+
+				if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
+				    (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
+					psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
+
+				if (param->u.crypt.set_tx == 1) { /* pairwise key */
+					memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+					if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
+						/* DEBUG_ERR(("\nset key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len)); */
+						memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
+						memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
+
+						padapter->securitypriv.busetkipkey = false;
+						/* _set_timer(&padapter->securitypriv.tkip_timer, 50);						 */
+					}
+
+					/* DEBUG_ERR((" param->u.crypt.key_len=%d\n",param->u.crypt.key_len)); */
+					RTW_INFO(" ~~~~set sta key:unicastkey\n");
+
+					rtw_setstakey_cmd(padapter, psta, UNICAST_KEY, true);
+
+					psta->bpairwise_key_installed = true;
+
+				} else { /* group key */
+					if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0) {
+						memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key,
+							(param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+						/* only TKIP group key need to install this */
+						if (param->u.crypt.key_len > 16) {
+							memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
+							memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
+						}
+						padapter->securitypriv.binstallGrpkey = true;
+						/* DEBUG_ERR((" param->u.crypt.key_len=%d\n", param->u.crypt.key_len)); */
+						if (param->u.crypt.idx < 4) 
+							memcpy(padapter->securitypriv.iv_seq[param->u.crypt.idx], param->u.crypt.seq, 8);							
+						RTW_INFO(" ~~~~set sta key:groupkey\n");
+
+						padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
+
+						rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, true);
+					}
+#ifdef CONFIG_IEEE80211W
+					else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
+						int no;
+						/* printk("BIP key_len=%d , index=%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx); */
+						/* save the IGTK key, length 16 bytes */
+						memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey,  param->u.crypt.key,
+							(param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+						/*printk("IGTK key below:\n");
+						for(no=0;no<16;no++)
+							printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
+						printk("\n");*/
+						padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
+						padapter->securitypriv.binstallBIPkey = true;
+						RTW_INFO(" ~~~~set sta key:IGKT\n");
+					}
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef CONFIG_P2P
+					if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
+						rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);
+#endif /* CONFIG_P2P */
+
+				}
+			}
+
+			pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+			if (pbcmc_sta == NULL) {
+				/* DEBUG_ERR( ("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
+			} else {
+				/* Jeff: don't disable ieee8021x_blocked while clearing key */
+				if (strcmp(param->u.crypt.alg, "none") != 0)
+					pbcmc_sta->ieee8021x_blocked = false;
+
+				if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
+				    (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
+					pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
+			}
+		} else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { /* adhoc mode */
+		}
+	}
+
+#ifdef CONFIG_WAPI_SUPPORT
+	if (strcmp(param->u.crypt.alg, "SMS4") == 0) {
+		PRT_WAPI_T			pWapiInfo = &padapter->wapiInfo;
+		PRT_WAPI_STA_INFO	pWapiSta;
+		u8					WapiASUEPNInitialValueSrc[16] = {0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C} ;
+		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} ;
+
+		if (param->u.crypt.set_tx == 1) {
+			list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+				if (!memcmp(pWapiSta->PeerMacAddr, param->sta_addr, 6)) {
+					memcpy(pWapiSta->lastTxUnicastPN, WapiASUEPNInitialValueSrc, 16);
+
+					pWapiSta->wapiUsk.bSet = true;
+					memcpy(pWapiSta->wapiUsk.dataKey, param->u.crypt.key, 16);
+					memcpy(pWapiSta->wapiUsk.micKey, param->u.crypt.key + 16, 16);
+					pWapiSta->wapiUsk.keyId = param->u.crypt.idx ;
+					pWapiSta->wapiUsk.bTxEnable = true;
+
+					memcpy(pWapiSta->lastRxUnicastPNBEQueue, WapiAEPNInitialValueSrc, 16);
+					memcpy(pWapiSta->lastRxUnicastPNBKQueue, WapiAEPNInitialValueSrc, 16);
+					memcpy(pWapiSta->lastRxUnicastPNVIQueue, WapiAEPNInitialValueSrc, 16);
+					memcpy(pWapiSta->lastRxUnicastPNVOQueue, WapiAEPNInitialValueSrc, 16);
+					memcpy(pWapiSta->lastRxUnicastPN, WapiAEPNInitialValueSrc, 16);
+					pWapiSta->wapiUskUpdate.bTxEnable = false;
+					pWapiSta->wapiUskUpdate.bSet = false;
+
+					if (psecuritypriv->sw_encrypt == false || psecuritypriv->sw_decrypt == false) {
+						/* set unicast key for ASUE */
+						rtw_wapi_set_key(padapter, &pWapiSta->wapiUsk, pWapiSta, false, false);
+					}
+				}
+			}
+		} else {
+			list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+				if (!memcmp(pWapiSta->PeerMacAddr, get_bssid(pmlmepriv), 6)) {
+					pWapiSta->wapiMsk.bSet = true;
+					memcpy(pWapiSta->wapiMsk.dataKey, param->u.crypt.key, 16);
+					memcpy(pWapiSta->wapiMsk.micKey, param->u.crypt.key + 16, 16);
+					pWapiSta->wapiMsk.keyId = param->u.crypt.idx ;
+					pWapiSta->wapiMsk.bTxEnable = false;
+					if (!pWapiSta->bSetkeyOk)
+						pWapiSta->bSetkeyOk = true;
+					pWapiSta->bAuthenticateInProgress = false;
+
+					memcpy(pWapiSta->lastRxMulticastPN, WapiAEMultiCastPNInitialValueSrc, 16);
+
+					if (psecuritypriv->sw_decrypt == false) {
+						/* set rx broadcast key for ASUE */
+						rtw_wapi_set_key(padapter, &pWapiSta->wapiMsk, pWapiSta, true, false);
+					}
+				}
+
+			}
+		}
+	}
+#endif
+
+exit:
+
+
+	return ret;
+}
+
+static int rtw_set_wpa_ie(_adapter *padapter, char *pie, unsigned short ielen)
+{
+	u8 *buf = NULL, *pos = NULL;
+	u32 left;
+	int group_cipher = 0, pairwise_cipher = 0;
+	int ret = 0;
+	u8 null_addr[] = {0, 0, 0, 0, 0, 0};
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_P2P */
+
+	if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) {
+		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
+		if (pie == NULL)
+			return ret;
+		else
+			return -EINVAL;
+	}
+
+	if (ielen) {
+		buf = rtw_zmalloc(ielen);
+		if (buf == NULL) {
+			ret =  -ENOMEM;
+			goto exit;
+		}
+
+		memcpy(buf, pie , ielen);
+
+		/* dump */
+		{
+			int i;
+			RTW_INFO("\n wpa_ie(length:%d):\n", ielen);
+			for (i = 0; i < ielen; i = i + 8)
+				RTW_INFO("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
+					 buf[i], buf[i + 1], buf[i + 2],
+					 buf[i + 3], buf[i + 4], buf[i + 5],
+					 buf[i + 6], buf[i + 7]);
+		}
+
+		pos = buf;
+		if (ielen < RSN_HEADER_LEN) {
+			ret  = -1;
+			goto exit;
+		}
+
+		if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
+			padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
+			memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
+		}
+
+		if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
+			padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
+			memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
+		}
+
+		if (group_cipher == 0)
+			group_cipher = WPA_CIPHER_NONE;
+		if (pairwise_cipher == 0)
+			pairwise_cipher = WPA_CIPHER_NONE;
+
+		switch (group_cipher) {
+		case WPA_CIPHER_NONE:
+			padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+			padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+			break;
+		case WPA_CIPHER_WEP40:
+			padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
+			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+			break;
+		case WPA_CIPHER_TKIP:
+			padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
+			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
+			break;
+		case WPA_CIPHER_CCMP:
+			padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
+			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
+			break;
+		case WPA_CIPHER_WEP104:
+			padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
+			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+			break;
+		}
+
+		switch (pairwise_cipher) {
+		case WPA_CIPHER_NONE:
+			padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+			padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+			break;
+		case WPA_CIPHER_WEP40:
+			padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
+			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+			break;
+		case WPA_CIPHER_TKIP:
+			padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
+			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
+			break;
+		case WPA_CIPHER_CCMP:
+			padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
+			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
+			break;
+		case WPA_CIPHER_WEP104:
+			padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
+			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+			break;
+		}
+
+		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
+		{/* set wps_ie	 */
+			u16 cnt = 0;
+			u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+
+			while (cnt < ielen) {
+				eid = buf[cnt];
+
+				if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt + 2], wps_oui, 4) )) {
+					RTW_INFO("SET WPS_IE\n");
+
+					padapter->securitypriv.wps_ie_len = ((buf[cnt + 1] + 2) < MAX_WPS_IE_LEN) ? (buf[cnt + 1] + 2) : MAX_WPS_IE_LEN;
+
+					memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
+
+					set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
+
+#ifdef CONFIG_P2P
+					if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
+						rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING);
+#endif /* CONFIG_P2P */
+					cnt += buf[cnt + 1] + 2;
+
+					break;
+				} else {
+					cnt += buf[cnt + 1] + 2; /* goto next	 */
+				}
+			}
+		}
+	}
+
+	/* TKIP and AES disallow multicast packets until installing group key */
+	if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_
+	    || padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_
+	    || padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
+		/* WPS open need to enable multicast
+		 * || check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) ) */
+		rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
+
+
+exit:
+
+	if (buf)
+		rtw_mfree(buf, ielen);
+
+	return ret;
+}
+
+static int rtw_wx_get_name(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u16 cap;
+	u32 ht_ielen = 0;
+	char *p;
+	u8 ht_cap = false, vht_cap = false;
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
+	NDIS_802_11_RATES_EX *prates = NULL;
+
+
+
+	if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) ) {
+		/* parsing HT_CAP_IE */
+		p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength - 12);
+		if (p && ht_ielen > 0)
+			ht_cap = true;
+
+		prates = &pcur_bss->SupportedRates;
+
+		if (rtw_is_cckratesonly_included((u8 *)prates) ) {
+			if (ht_cap )
+				snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
+			else
+				snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
+		} else if ((rtw_is_cckrates_included((u8 *)prates)) ) {
+			if (ht_cap )
+				snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
+			else
+				snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
+		} else {
+			if (pcur_bss->Configuration.DSConfig > 14) {
+				if (ht_cap )
+					snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
+				else
+					snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
+			} else {
+				if (ht_cap )
+					snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
+				else
+					snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
+			}
+		}
+	} else {
+		/* prates = &padapter->registrypriv.dev_network.SupportedRates; */
+		/* snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g"); */
+		snprintf(wrqu->name, IFNAMSIZ, "unassociated");
+	}
+
+
+	return 0;
+}
+
+static int rtw_wx_set_freq(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	struct wlan_network  *cur_network = &(pmlmepriv->cur_network);
+	int exp = 1, freq = 0, div = 0;
+
+
+
+	if (wrqu->freq.m <= 1000) {
+		if (wrqu->freq.flags == IW_FREQ_AUTO) {
+			if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, wrqu->freq.m) > 0) {
+				padapter->mlmeextpriv.cur_channel = wrqu->freq.m;
+				RTW_INFO("%s: channel is auto, set to channel %d\n", __func__, wrqu->freq.m);
+			} else {
+				padapter->mlmeextpriv.cur_channel = 1;
+				RTW_INFO("%s: channel is auto, Channel Plan don't match just set to channel 1\n", __func__);
+			}
+		} else {
+			padapter->mlmeextpriv.cur_channel = wrqu->freq.m;
+			RTW_INFO("%s: set to channel %d\n", __func__, padapter->mlmeextpriv.cur_channel);
+		}
+	} else {
+		while (wrqu->freq.e) {
+			exp *= 10;
+			wrqu->freq.e--;
+		}
+
+		freq = wrqu->freq.m;
+
+		while (!(freq % 10)) {
+			freq /= 10;
+			exp *= 10;
+		}
+
+		/* freq unit is MHz here */
+		div = 1000000 / exp;
+
+		if (div)
+			freq /= div;
+		else {
+			div = exp / 1000000;
+			freq *= div;
+		}
+
+		/* If freq is invalid, rtw_freq2ch() will return channel 1 */
+		padapter->mlmeextpriv.cur_channel = rtw_freq2ch(freq);
+		RTW_INFO("%s: set to channel %d\n", __func__, padapter->mlmeextpriv.cur_channel);
+	}
+
+	set_channel_bwmode(padapter, padapter->mlmeextpriv.cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+
+
+	return 0;
+}
+
+static int rtw_wx_get_freq(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
+
+	if (check_fwstate(pmlmepriv, _FW_LINKED)  && check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) != true) {
+
+		wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
+		wrqu->freq.e = 1;
+		wrqu->freq.i = pcur_bss->Configuration.DSConfig;
+
+	} else {
+		wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
+		wrqu->freq.e = 1;
+		wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
+	}
+
+	return 0;
+}
+
+static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
+			   union iwreq_data *wrqu, char *b)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	NDIS_802_11_NETWORK_INFRASTRUCTURE networkType ;
+	int ret = 0;
+
+
+	if (_FAIL == rtw_pwr_wakeup(padapter)) {
+		ret = -EPERM;
+		goto exit;
+	}
+
+	if (!rtw_is_hw_init_completed(padapter)) {
+		ret = -EPERM;
+		goto exit;
+	}
+
+	/* initial default type */
+	dev->type = ARPHRD_ETHER;
+
+	if (wrqu->mode == IW_MODE_MONITOR) {
+		rtw_ps_deny(padapter, PS_DENY_MONITOR_MODE);
+		LeaveAllPowerSaveMode(padapter);
+	} else {
+		rtw_ps_deny_cancel(padapter, PS_DENY_MONITOR_MODE);
+	}
+
+	switch (wrqu->mode) {
+	case IW_MODE_MONITOR:
+		networkType = Ndis802_11Monitor;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24))
+		dev->type = ARPHRD_IEEE80211_RADIOTAP; /* IEEE 802.11 + radiotap header : 803 */
+		RTW_INFO("set_mode = IW_MODE_MONITOR\n");
+#else
+		RTW_INFO("kernel version < 2.6.24 not support IW_MODE_MONITOR\n");
+#endif
+		break;
+
+	case IW_MODE_AUTO:
+		networkType = Ndis802_11AutoUnknown;
+		RTW_INFO("set_mode = IW_MODE_AUTO\n");
+		break;
+	case IW_MODE_ADHOC:
+		networkType = Ndis802_11IBSS;
+		RTW_INFO("set_mode = IW_MODE_ADHOC\n");
+		break;
+	case IW_MODE_MASTER:
+		networkType = Ndis802_11APMode;
+		RTW_INFO("set_mode = IW_MODE_MASTER\n");
+		/* rtw_setopmode_cmd(padapter, networkType,true);	 */
+		break;
+	case IW_MODE_INFRA:
+		networkType = Ndis802_11Infrastructure;
+		RTW_INFO("set_mode = IW_MODE_INFRA\n");
+		break;
+
+	default:
+		ret = -EINVAL;;
+		goto exit;
+	}
+
+	/*
+		if(Ndis802_11APMode == networkType)
+		{
+			rtw_setopmode_cmd(padapter, networkType,true);
+		}
+		else
+		{
+			rtw_setopmode_cmd(padapter, Ndis802_11AutoUnknown,true);
+		}
+	*/
+
+	if (rtw_set_802_11_infrastructure_mode(padapter, networkType) == false) {
+
+		ret = -EPERM;
+		goto exit;
+
+	}
+
+	rtw_setopmode_cmd(padapter, networkType, true);
+
+	if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) )
+		rtw_indicate_connect(padapter);
+
+exit:
+
+
+	return ret;
+
+}
+
+static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
+			   union iwreq_data *wrqu, char *b)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+
+
+
+	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) )
+		wrqu->mode = IW_MODE_INFRA;
+	else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ) ||
+		 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ))
+
+		wrqu->mode = IW_MODE_ADHOC;
+	else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) )
+		wrqu->mode = IW_MODE_MASTER;
+	else if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) )
+		wrqu->mode = IW_MODE_MONITOR;
+	else
+		wrqu->mode = IW_MODE_AUTO;
+
+
+	return 0;
+
+}
+
+
+static int rtw_wx_set_pmkid(struct net_device *dev,
+			    struct iw_request_info *a,
+			    union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u8          j, blInserted = false;
+	int         intReturn = false;
+	struct mlme_priv  *pmlmepriv = &padapter->mlmepriv;
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+	struct iw_pmksa  *pPMK = (struct iw_pmksa *) extra;
+	u8     strZeroMacAddress[ETH_ALEN] = { 0x00 };
+	u8     strIssueBssid[ETH_ALEN] = { 0x00 };
+
+	memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
+	if (pPMK->cmd == IW_PMKSA_ADD) {
+		RTW_INFO("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n");
+		if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN) )
+			return intReturn ;
+		else
+			intReturn = true;
+		blInserted = false;
+
+		/* overwrite PMKID */
+		for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
+			if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN) ) {
+				/* BSSID is matched, the same AP => rewrite with new PMKID. */
+
+				RTW_INFO("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n");
+
+				memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
+				psecuritypriv->PMKIDList[j].bUsed = true;
+				psecuritypriv->PMKIDIndex = j + 1;
+				blInserted = true;
+				break;
+			}
+		}
+
+		if (!blInserted) {
+			/* Find a new entry */
+			RTW_INFO("[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
+				 psecuritypriv->PMKIDIndex);
+
+			memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
+			memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
+
+			psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true;
+			psecuritypriv->PMKIDIndex++ ;
+			if (psecuritypriv->PMKIDIndex == 16)
+				psecuritypriv->PMKIDIndex = 0;
+		}
+	} else if (pPMK->cmd == IW_PMKSA_REMOVE) {
+		RTW_INFO("[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n");
+		intReturn = true;
+		for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
+			if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN) ) {
+				/* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
+				memset(psecuritypriv->PMKIDList[j].Bssid, 0x00, ETH_ALEN);
+				psecuritypriv->PMKIDList[j].bUsed = false;
+				break;
+			}
+		}
+	} else if (pPMK->cmd == IW_PMKSA_FLUSH) {
+		RTW_INFO("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n");
+		memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(RT_PMKID_LIST) * NUM_PMKID_CACHE);
+		psecuritypriv->PMKIDIndex = 0;
+		intReturn = true;
+	}
+	return intReturn ;
+}
+
+static int rtw_wx_get_sens(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+#ifdef CONFIG_PLATFORM_ROCKCHIPS
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	/*
+	*  20110311 Commented by Jeff
+	*  For rockchip platform's wpa_driver_wext_get_rssi
+	*/
+	if (check_fwstate(pmlmepriv, _FW_LINKED) ) {
+		/* wrqu->sens.value=-padapter->recvpriv.signal_strength; */
+		wrqu->sens.value = -padapter->recvpriv.rssi;
+		/* RTW_INFO("%s: %d\n", __func__, wrqu->sens.value); */
+		wrqu->sens.fixed = 0; /* no auto select */
+	} else
+#endif
+	{
+		wrqu->sens.value = 0;
+		wrqu->sens.fixed = 0;	/* no auto select */
+		wrqu->sens.disabled = 1;
+	}
+	return 0;
+}
+
+static int rtw_wx_get_range(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *extra)
+{
+	struct iw_range *range = (struct iw_range *)extra;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+
+	u16 val;
+	int i;
+
+
+
+	wrqu->data.length = sizeof(*range);
+	memset(range, 0, sizeof(*range));
+
+	/* Let's try to keep this struct in the same order as in
+	 * linux/include/wireless.h
+	 */
+
+	/* TODO: See what values we can set, and remove the ones we can't
+	 * set, or fill them with some default data.
+	 */
+
+	/* ~5 Mb/s real (802.11b) */
+	range->throughput = 5 * 1000 * 1000;
+
+	/* TODO: Not used in 802.11b?
+	*	range->min_nwid;	 Minimal NWID we are able to set  */
+	/* TODO: Not used in 802.11b?
+	*	range->max_nwid;	 Maximal NWID we are able to set  */
+
+	/* Old Frequency (backward compat - moved lower ) */
+	/*	range->old_num_channels;
+	 *	range->old_num_frequency;
+	 * 	range->old_freq[6];  Filler to keep "version" at the same offset  */
+
+	/* signal level threshold range */
+
+	/* Quality of link & SNR stuff */
+	/* Quality range (link, level, noise)
+	 * If the quality is absolute, it will be in the range [0 ; max_qual],
+	 * if the quality is dBm, it will be in the range [max_qual ; 0].
+	 * Don't forget that we use 8 bit arithmetics...
+	 *
+	 * If percentage range is 0~100
+	 * Signal strength dbm range logical is -100 ~ 0
+	 * but usually value is -90 ~ -20
+	 * When CONFIG_SIGNAL_SCALE_MAPPING is defined, dbm range is -95 ~ -45
+	 */
+	range->max_qual.qual = 100;
+#ifdef CONFIG_SIGNAL_DISPLAY_DBM
+	range->max_qual.level = (u8)-100;
+	range->max_qual.noise = (u8)-100;
+	range->max_qual.updated = IW_QUAL_ALL_UPDATED; /* Updated all three */
+	range->max_qual.updated |= IW_QUAL_DBM;
+#else /* !CONFIG_SIGNAL_DISPLAY_DBM */
+	/* percent values between 0 and 100. */
+	range->max_qual.level = 100;
+	range->max_qual.noise = 100;
+	range->max_qual.updated = IW_QUAL_ALL_UPDATED; /* Updated all three */
+#endif /* !CONFIG_SIGNAL_DISPLAY_DBM */
+
+	/* This should contain the average/typical values of the quality
+	 * indicator. This should be the threshold between a "good" and
+	 * a "bad" link (example : monitor going from green to orange).
+	 * Currently, user space apps like quality monitors don't have any
+	 * way to calibrate the measurement. With this, they can split
+	 * the range between 0 and max_qual in different quality level
+	 * (using a geometric subdivision centered on the average).
+	 * I expect that people doing the user space apps will feedback
+	 * us on which value we need to put in each driver... */
+	range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
+#ifdef CONFIG_SIGNAL_DISPLAY_DBM
+	/* TODO: Find real 'good' to 'bad' threshold value for RSSI */
+	range->avg_qual.level = (u8)-70;
+	range->avg_qual.noise = 0;
+	range->avg_qual.updated = IW_QUAL_ALL_UPDATED; /* Updated all three */
+	range->avg_qual.updated |= IW_QUAL_DBM;
+#else /* !CONFIG_SIGNAL_DISPLAY_DBM */
+	/* TODO: Find real 'good' to 'bad' threshol value for RSSI */
+	range->avg_qual.level = 30;
+	range->avg_qual.noise = 100;
+	range->avg_qual.updated = IW_QUAL_ALL_UPDATED; /* Updated all three */
+#endif /* !CONFIG_SIGNAL_DISPLAY_DBM */
+
+	range->num_bitrates = RATE_COUNT;
+
+	for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
+		range->bitrate[i] = rtw_rates[i];
+
+	range->min_frag = MIN_FRAG_THRESHOLD;
+	range->max_frag = MAX_FRAG_THRESHOLD;
+
+	range->pm_capa = 0;
+
+	range->we_version_compiled = WIRELESS_EXT;
+	range->we_version_source = 16;
+
+	/*	range->retry_capa;	 What retry options are supported
+	 *	range->retry_flags;	 How to decode max/min retry limit
+	 *	range->r_time_flags;	 How to decode max/min retry life
+	 *	range->min_retry;	 Minimal number of retries
+	 *	range->max_retry;	 Maximal number of retries
+	 *	range->min_r_time;	 Minimal retry lifetime
+	 *	range->max_r_time;	 Maximal retry lifetime  */
+
+	for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
+
+		/* Include only legal frequencies for some countries */
+		if (pmlmeext->channel_set[i].ChannelNum != 0) {
+			range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
+			range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
+			range->freq[val].e = 1;
+			val++;
+		}
+
+		if (val == IW_MAX_FREQUENCIES)
+			break;
+	}
+
+	range->num_channels = val;
+	range->num_frequency = val;
+
+	/* Commented by Albert 2009/10/13
+	 * The following code will proivde the security capability to network manager.
+	 * If the driver doesn't provide this capability to network manager,
+	 * the WPA/WPA2 routers can't be choosen in the network manager. */
+
+	/*
+	#define IW_SCAN_CAPA_NONE		0x00
+	#define IW_SCAN_CAPA_ESSID		0x01
+	#define IW_SCAN_CAPA_BSSID		0x02
+	#define IW_SCAN_CAPA_CHANNEL	0x04
+	#define IW_SCAN_CAPA_MODE		0x08
+	#define IW_SCAN_CAPA_RATE		0x10
+	#define IW_SCAN_CAPA_TYPE		0x20
+	#define IW_SCAN_CAPA_TIME		0x40
+	*/
+
+#if WIRELESS_EXT > 17
+	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+			  IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+#endif
+
+#ifdef IW_SCAN_CAPA_ESSID /* WIRELESS_EXT > 21 */
+	range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE | IW_SCAN_CAPA_BSSID |
+		   IW_SCAN_CAPA_CHANNEL | IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
+#endif
+
+
+
+	return 0;
+
+}
+
+/* set bssid flow
+ * s1. rtw_set_802_11_infrastructure_mode()
+ * s2. rtw_set_802_11_authentication_mode()
+ * s3. set_802_11_encryption_mode()
+ * s4. rtw_set_802_11_bssid() */
+static int rtw_wx_set_wap(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *awrq,
+			  char *extra)
+{
+	unsigned long	irqL;
+	uint ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct sockaddr *temp = (struct sockaddr *)awrq;
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	_list	*phead;
+	u8 *dst_bssid, *src_bssid;
+	_queue	*queue	= &(pmlmepriv->scanned_queue);
+	struct	wlan_network	*pnetwork = NULL;
+	NDIS_802_11_AUTHENTICATION_MODE	authmode;
+
+	/*
+	#ifdef CONFIG_CONCURRENT_MODE
+		if(padapter->adapter_type > PRIMARY_IFACE)
+		{
+			ret = -EINVAL;
+			goto exit;
+		}
+	#endif
+	*/
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ) {
+		RTW_INFO("set bssid, but buddy_intf is under scanning or linking\n");
+
+		ret = -EINVAL;
+
+		goto exit;
+	}
+#endif
+
+	rtw_ps_deny(padapter, PS_DENY_JOIN);
+	if (_FAIL == rtw_pwr_wakeup(padapter)) {
+		ret = -1;
+		goto cancel_ps_deny;
+	}
+
+	if (!padapter->bup) {
+		ret = -1;
+		goto cancel_ps_deny;
+	}
+
+
+	if (temp->sa_family != ARPHRD_ETHER) {
+		ret = -EINVAL;
+		goto cancel_ps_deny;
+	}
+
+	authmode = padapter->securitypriv.ndisauthtype;
+	_enter_critical_bh(&queue->lock, &irqL);
+	phead = get_list_head(queue);
+	pmlmepriv->pscanned = get_next(phead);
+
+	while (1) {
+
+		if ((rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) ) {
+			break;
+		}
+
+		pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
+
+		pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
+
+		dst_bssid = pnetwork->network.MacAddress;
+
+		src_bssid = temp->sa_data;
+
+		if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN)) ) {
+			if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
+				ret = -1;
+				_exit_critical_bh(&queue->lock, &irqL);
+				goto cancel_ps_deny;
+			}
+
+			break;
+		}
+
+	}
+	_exit_critical_bh(&queue->lock, &irqL);
+
+	rtw_set_802_11_authentication_mode(padapter, authmode);
+	/* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
+	if (rtw_set_802_11_bssid(padapter, temp->sa_data) == false) {
+		ret = -1;
+		goto cancel_ps_deny;
+	}
+
+cancel_ps_deny:
+	rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
+
+exit:
+	return ret;
+}
+
+static int rtw_wx_get_wap(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
+
+	wrqu->ap_addr.sa_family = ARPHRD_ETHER;
+
+	memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+
+
+
+	if (((check_fwstate(pmlmepriv, _FW_LINKED)) ) ||
+	    ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ) ||
+	    ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) ))
+
+		memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
+	else
+		memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+
+
+	return 0;
+
+}
+
+static int rtw_wx_set_mlme(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	u16 reason;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_mlme *mlme = (struct iw_mlme *) extra;
+
+
+	if (mlme == NULL)
+		return -1;
+
+	RTW_INFO("%s\n", __func__);
+
+	reason = mlme->reason_code;
+
+
+	RTW_INFO("%s, cmd=%d, reason=%d\n", __func__, mlme->cmd, reason);
+
+
+	switch (mlme->cmd) {
+	case IW_MLME_DEAUTH:
+		if (!rtw_set_802_11_disassociate(padapter))
+			ret = -1;
+		break;
+
+	case IW_MLME_DISASSOC:
+		if (!rtw_set_802_11_disassociate(padapter))
+			ret = -1;
+
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return ret;
+}
+
+static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
+			   union iwreq_data *wrqu, char *extra)
+{
+	u8 _status = false;
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	NDIS_802_11_SSID ssid[RTW_SSID_SCAN_AMOUNT];
+
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+#endif /* CONFIG_P2P */
+
+
+#ifdef DBG_IOCTL
+	RTW_INFO("DBG_IOCTL %s:%d\n", __func__, __LINE__);
+#endif
+
+#ifdef CONFIG_MP_INCLUDED
+	if (rtw_mi_mp_mode_check(padapter)) {
+		RTW_INFO("MP mode block Scan request\n");
+		ret = -EPERM;
+		goto exit;
+	}
+#endif
+	if (rtw_is_scan_deny(padapter)) {
+		indicate_wx_scan_complete_event(padapter);
+		goto exit;
+	}
+
+	rtw_ps_deny(padapter, PS_DENY_SCAN);
+	if (_FAIL == rtw_pwr_wakeup(padapter)) {
+		ret = -1;
+		goto cancel_ps_deny;
+	}
+
+	if (!rtw_is_adapter_up(padapter)) {
+		ret = -1;
+		goto cancel_ps_deny;
+	}
+
+#ifndef CONFIG_DOSCAN_IN_BUSYTRAFFIC
+	/* When Busy Traffic, driver do not site survey. So driver return success. */
+	/* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
+	/* modify by thomas 2011-02-22. */
+	if (rtw_mi_busy_traffic_check(padapter, false)) {
+		indicate_wx_scan_complete_event(padapter);
+		goto cancel_ps_deny;
+	}
+#endif
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) && check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
+		RTW_INFO("AP mode process WPS\n");
+		indicate_wx_scan_complete_event(padapter);
+		goto cancel_ps_deny;
+	}
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ) {
+		indicate_wx_scan_complete_event(padapter);
+		goto cancel_ps_deny;
+	}
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (rtw_mi_buddy_check_fwstate(padapter,
+		       _FW_UNDER_SURVEY | _FW_UNDER_LINKING | WIFI_UNDER_WPS)) {
+
+		indicate_wx_scan_complete_event(padapter);
+		goto cancel_ps_deny;
+	}
+#endif
+
+#ifdef CONFIG_P2P
+	if (pwdinfo->p2p_state != P2P_STATE_NONE) {
+		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
+		rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_FULL);
+		rtw_free_network_queue(padapter, true);
+	}
+#endif /* CONFIG_P2P */
+
+	memset(ssid, 0, sizeof(NDIS_802_11_SSID) * RTW_SSID_SCAN_AMOUNT);
+
+#if WIRELESS_EXT >= 17
+	if (wrqu->data.length == sizeof(struct iw_scan_req)) {
+		struct iw_scan_req *req = (struct iw_scan_req *)extra;
+
+		if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+			int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
+
+			memcpy(ssid[0].Ssid, req->essid, len);
+			ssid[0].SsidLength = len;
+
+			RTW_INFO("IW_SCAN_THIS_ESSID, ssid=%s, len=%d\n", req->essid, req->essid_len);
+
+			_status = rtw_set_802_11_bssid_list_scan(padapter, ssid, 1, NULL, 0);
+
+		} else if (req->scan_type == IW_SCAN_TYPE_PASSIVE)
+			RTW_INFO("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
+
+	} else
+#endif
+
+		if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE
+		    && !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE) 
+		   ) {
+			int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
+			char *pos = extra + WEXT_CSCAN_HEADER_SIZE;
+			char section;
+			char sec_len;
+			int ssid_index = 0;
+
+			/* RTW_INFO("%s COMBO_SCAN header is recognized\n", __func__); */
+
+			while (len >= 1) {
+				section = *(pos++);
+				len -= 1;
+
+				switch (section) {
+				case WEXT_CSCAN_SSID_SECTION:
+					/* RTW_INFO("WEXT_CSCAN_SSID_SECTION\n"); */
+					if (len < 1) {
+						len = 0;
+						break;
+					}
+
+					sec_len = *(pos++);
+					len -= 1;
+
+					if (sec_len > 0 && sec_len <= len) {
+						ssid[ssid_index].SsidLength = sec_len;
+						memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
+						/* RTW_INFO("%s COMBO_SCAN with specific ssid:%s, %d\n", __func__ */
+						/*	, ssid[ssid_index].Ssid, ssid[ssid_index].SsidLength); */
+						ssid_index++;
+					}
+
+					pos += sec_len;
+					len -= sec_len;
+					break;
+
+
+				case WEXT_CSCAN_CHANNEL_SECTION:
+					/* RTW_INFO("WEXT_CSCAN_CHANNEL_SECTION\n"); */
+					pos += 1;
+					len -= 1;
+					break;
+				case WEXT_CSCAN_ACTV_DWELL_SECTION:
+					/* RTW_INFO("WEXT_CSCAN_ACTV_DWELL_SECTION\n"); */
+					pos += 2;
+					len -= 2;
+					break;
+				case WEXT_CSCAN_PASV_DWELL_SECTION:
+					/* RTW_INFO("WEXT_CSCAN_PASV_DWELL_SECTION\n"); */
+					pos += 2;
+					len -= 2;
+					break;
+				case WEXT_CSCAN_HOME_DWELL_SECTION:
+					/* RTW_INFO("WEXT_CSCAN_HOME_DWELL_SECTION\n"); */
+					pos += 2;
+					len -= 2;
+					break;
+				case WEXT_CSCAN_TYPE_SECTION:
+					/* RTW_INFO("WEXT_CSCAN_TYPE_SECTION\n"); */
+					pos += 1;
+					len -= 1;
+					break;
+				default:
+					/* RTW_INFO("Unknown CSCAN section %c\n", section); */
+					len = 0; /* stop parsing */
+				}
+				/* RTW_INFO("len:%d\n", len); */
+
+			}
+
+			/* jeff: it has still some scan paramater to parse, we only do this now... */
+			_status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT, NULL, 0);
+
+		} else
+
+			_status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0, NULL, 0);
+
+	if (_status == false)
+		ret = -1;
+
+cancel_ps_deny:
+	rtw_ps_deny_cancel(padapter, PS_DENY_SCAN);
+
+exit:
+#ifdef DBG_IOCTL
+	RTW_INFO("DBG_IOCTL %s:%d return %d\n", __func__, __LINE__, ret);
+#endif
+
+	return ret;
+}
+
+static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
+			   union iwreq_data *wrqu, char *extra)
+{
+	unsigned long	irqL;
+	_list					*plist, *phead;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	_queue				*queue	= &(pmlmepriv->scanned_queue);
+	struct	wlan_network	*pnetwork = NULL;
+	char *ev = extra;
+	char *stop = ev + wrqu->data.length;
+	u32 ret = 0;
+	u32 cnt = 0;
+	u32 wait_for_surveydone;
+	sint wait_status;
+
+#ifdef CONFIG_P2P
+	struct	wifidirect_info	*pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_P2P */
+
+
+#ifdef DBG_IOCTL
+	RTW_INFO("DBG_IOCTL %s:%d\n", __func__, __LINE__);
+#endif
+
+	if (adapter_to_pwrctl(padapter)->brfoffbyhw && rtw_is_drv_stopped(padapter)) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+#ifdef CONFIG_P2P
+	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+		wait_for_surveydone = 200;
+	else {
+		/*	P2P is disabled */
+		wait_for_surveydone = 100;
+	}
+#else
+	{
+		wait_for_surveydone = 100;
+	}
+#endif /* CONFIG_P2P */
+
+	wait_status = _FW_UNDER_SURVEY
+#ifndef CONFIG_ANDROID
+		      | _FW_UNDER_LINKING
+#endif
+		      ;
+
+	while (check_fwstate(pmlmepriv, wait_status) )
+		return -EAGAIN;
+	_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) )
+			break;
+
+		if ((stop - ev) < SCAN_ITEM_SIZE) {
+			ret = -E2BIG;
+			break;
+		}
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+
+		/* report network only if the current channel set contains the channel to which this network belongs */
+		if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0
+		    && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) 
+		    && rtw_validate_ssid(&(pnetwork->network.Ssid))
+		   )
+			ev = translate_scan(padapter, a, pnetwork, ev, stop);
+
+		plist = get_next(plist);
+
+	}
+
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+	wrqu->data.length = ev - extra;
+	wrqu->data.flags = 0;
+
+exit:
+
+
+#ifdef DBG_IOCTL
+	RTW_INFO("DBG_IOCTL %s:%d return %d\n", __func__, __LINE__, ret);
+#endif
+
+	return ret ;
+
+}
+
+/* set ssid flow
+ * s1. rtw_set_802_11_infrastructure_mode()
+ * s2. set_802_11_authenticaion_mode()
+ * s3. set_802_11_encryption_mode()
+ * s4. rtw_set_802_11_ssid() */
+static int rtw_wx_set_essid(struct net_device *dev,
+			    struct iw_request_info *a,
+			    union iwreq_data *wrqu, char *extra)
+{
+	unsigned long irqL;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	_queue *queue = &pmlmepriv->scanned_queue;
+	_list *phead;
+	s8 status = true;
+	struct wlan_network *pnetwork = NULL;
+	NDIS_802_11_AUTHENTICATION_MODE authmode;
+	NDIS_802_11_SSID ndis_ssid;
+	u8 *dst_ssid, *src_ssid;
+
+	uint ret = 0, len;
+
+
+#ifdef DBG_IOCTL
+	RTW_INFO("DBG_IOCTL %s:%d\n", __func__, __LINE__);
+#endif
+#ifdef CONFIG_WEXT_DONT_JOIN_BYSSID
+	RTW_INFO("%s: CONFIG_WEXT_DONT_JOIN_BYSSID be defined!! only allow bssid joining\n", __func__);
+	return -EPERM;
+#endif
+
+#if WIRELESS_EXT <= 20
+	if ((wrqu->essid.length - 1) > IW_ESSID_MAX_SIZE) {
+#else
+	if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
+#endif
+		ret = -E2BIG;
+		goto exit;
+	}
+
+
+
+	rtw_ps_deny(padapter, PS_DENY_JOIN);
+	if (_FAIL == rtw_pwr_wakeup(padapter)) {
+		ret = -1;
+		goto cancel_ps_deny;
+	}
+
+	if (!padapter->bup) {
+		ret = -1;
+		goto cancel_ps_deny;
+	}
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+		ret = -1;
+		goto cancel_ps_deny;
+	}
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) {
+		RTW_INFO("set ssid, but buddy_intf is under scanning or linking\n");
+		ret = -EINVAL;
+		goto cancel_ps_deny;
+	}
+#endif
+	authmode = padapter->securitypriv.ndisauthtype;
+	RTW_INFO("=>%s\n", __func__);
+	if (wrqu->essid.flags && wrqu->essid.length) {
+		/* Commented by Albert 20100519 */
+		/* We got the codes in "set_info" function of iwconfig source code. */
+		/*	========================================= */
+		/*	wrq.u.essid.length = strlen(essid) + 1; */
+		/*	if(we_kernel_version > 20) */
+		/*		wrq.u.essid.length--; */
+		/*	========================================= */
+		/*	That means, if the WIRELESS_EXT less than or equal to 20, the correct ssid len should subtract 1. */
+#if WIRELESS_EXT <= 20
+		len = ((wrqu->essid.length - 1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length - 1) : IW_ESSID_MAX_SIZE;
+#else
+		len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
+#endif
+
+		if (wrqu->essid.length != 33)
+			RTW_INFO("ssid=%s, len=%d\n", extra, wrqu->essid.length);
+
+		memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));
+		ndis_ssid.SsidLength = len;
+		memcpy(ndis_ssid.Ssid, extra, len);
+		src_ssid = ndis_ssid.Ssid;
+
+		_enter_critical_bh(&queue->lock, &irqL);
+		phead = get_list_head(queue);
+		pmlmepriv->pscanned = get_next(phead);
+
+		while (1) {
+			if (rtw_end_of_queue_search(phead, pmlmepriv->pscanned) ) {
+				break;
+			}
+
+			pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
+
+			pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
+
+			dst_ssid = pnetwork->network.Ssid.Ssid;
+
+
+			if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength) ) &&
+			    (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) {
+
+				if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ) {
+					if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
+						continue;
+				}
+
+				if (rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode) == false) {
+					ret = -1;
+					_exit_critical_bh(&queue->lock, &irqL);
+					goto cancel_ps_deny;
+				}
+
+				break;
+			}
+		}
+		_exit_critical_bh(&queue->lock, &irqL);
+		rtw_set_802_11_authentication_mode(padapter, authmode);
+		/* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
+		if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == false) {
+			ret = -1;
+			goto cancel_ps_deny;
+		}
+	}
+
+cancel_ps_deny:
+	rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
+
+exit:
+	RTW_INFO("<=%s, ret %d\n", __func__, ret);
+
+#ifdef DBG_IOCTL
+	RTW_INFO("DBG_IOCTL %s:%d return %d\n", __func__, __LINE__, ret);
+#endif
+
+
+	return ret;
+}
+
+static int rtw_wx_get_essid(struct net_device *dev,
+			    struct iw_request_info *a,
+			    union iwreq_data *wrqu, char *extra)
+{
+	u32 len, ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	WLAN_BSSID_EX  *pcur_bss = &pmlmepriv->cur_network.network;
+
+
+
+	if ((check_fwstate(pmlmepriv, _FW_LINKED) ) ||
+	    (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) )) {
+		len = pcur_bss->Ssid.SsidLength;
+
+		wrqu->essid.length = len;
+
+		memcpy(extra, pcur_bss->Ssid.Ssid, len);
+
+		wrqu->essid.flags = 1;
+	} else {
+		ret = -1;
+		goto exit;
+	}
+
+exit:
+
+
+	return ret;
+
+}
+
+static int rtw_wx_set_rate(struct net_device *dev,
+			   struct iw_request_info *a,
+			   union iwreq_data *wrqu, char *extra)
+{
+	int	i, ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u8	datarates[NumRates];
+	u32	target_rate = wrqu->bitrate.value;
+	u32	fixed = wrqu->bitrate.fixed;
+	u32	ratevalue = 0;
+	u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
+
+
+
+	if (target_rate == -1) {
+		ratevalue = 11;
+		goto set_rate;
+	}
+	target_rate = target_rate / 100000;
+
+	switch (target_rate) {
+	case 10:
+		ratevalue = 0;
+		break;
+	case 20:
+		ratevalue = 1;
+		break;
+	case 55:
+		ratevalue = 2;
+		break;
+	case 60:
+		ratevalue = 3;
+		break;
+	case 90:
+		ratevalue = 4;
+		break;
+	case 110:
+		ratevalue = 5;
+		break;
+	case 120:
+		ratevalue = 6;
+		break;
+	case 180:
+		ratevalue = 7;
+		break;
+	case 240:
+		ratevalue = 8;
+		break;
+	case 360:
+		ratevalue = 9;
+		break;
+	case 480:
+		ratevalue = 10;
+		break;
+	case 540:
+		ratevalue = 11;
+		break;
+	default:
+		ratevalue = 11;
+		break;
+	}
+
+set_rate:
+
+	for (i = 0; i < NumRates; i++) {
+		if (ratevalue == mpdatarate[i]) {
+			datarates[i] = mpdatarate[i];
+			if (fixed == 0)
+				break;
+		} else
+			datarates[i] = 0xff;
+
+	}
+
+	if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS) {
+		ret = -1;
+	}
+
+
+	return ret;
+}
+
+static int rtw_wx_get_rate(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	u16 max_rate = 0;
+
+	max_rate = rtw_get_cur_max_rate((_adapter *)rtw_netdev_priv(dev));
+
+	if (max_rate == 0)
+		return -EPERM;
+
+	wrqu->bitrate.fixed = 0;	/* no auto select */
+	wrqu->bitrate.value = max_rate * 100000;
+
+	return 0;
+}
+
+static int rtw_wx_set_rts(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+
+	if (wrqu->rts.disabled)
+		padapter->registrypriv.rts_thresh = 2347;
+	else {
+		if (wrqu->rts.value < 0 ||
+		    wrqu->rts.value > 2347)
+			return -EINVAL;
+
+		padapter->registrypriv.rts_thresh = wrqu->rts.value;
+	}
+
+	RTW_INFO("%s, rts_thresh=%d\n", __func__, padapter->registrypriv.rts_thresh);
+
+
+	return 0;
+
+}
+
+static int rtw_wx_get_rts(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+
+	RTW_INFO("%s, rts_thresh=%d\n", __func__, padapter->registrypriv.rts_thresh);
+
+	wrqu->rts.value = padapter->registrypriv.rts_thresh;
+	wrqu->rts.fixed = 0;	/* no auto select */
+	/* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
+
+
+	return 0;
+}
+
+static int rtw_wx_set_frag(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+
+	if (wrqu->frag.disabled)
+		padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
+	else {
+		if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
+		    wrqu->frag.value > MAX_FRAG_THRESHOLD)
+			return -EINVAL;
+
+		padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
+	}
+
+	RTW_INFO("%s, frag_len=%d\n", __func__, padapter->xmitpriv.frag_len);
+
+
+	return 0;
+
+}
+
+static int rtw_wx_get_frag(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+
+	RTW_INFO("%s, frag_len=%d\n", __func__, padapter->xmitpriv.frag_len);
+
+	wrqu->frag.value = padapter->xmitpriv.frag_len;
+	wrqu->frag.fixed = 0;	/* no auto select */
+	/* wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); */
+
+
+	return 0;
+}
+
+static int rtw_wx_get_retry(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *extra)
+{
+	/* _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); */
+
+
+	wrqu->retry.value = 7;
+	wrqu->retry.fixed = 0;	/* no auto select */
+	wrqu->retry.disabled = 1;
+
+	return 0;
+
+}
+
+static int rtw_wx_set_enc(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *keybuf)
+{
+	u32 key, ret = 0;
+	u32 keyindex_provided;
+	NDIS_802_11_WEP	 wep;
+	NDIS_802_11_AUTHENTICATION_MODE authmode;
+
+	struct iw_point *erq = &(wrqu->encoding);
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	RTW_INFO("+rtw_wx_set_enc, flags=0x%x\n", erq->flags);
+
+	memset(&wep, 0, sizeof(NDIS_802_11_WEP));
+
+	key = erq->flags & IW_ENCODE_INDEX;
+
+
+	if (erq->flags & IW_ENCODE_DISABLED) {
+		RTW_INFO("EncryptionDisabled\n");
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+		padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+		padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
+		authmode = Ndis802_11AuthModeOpen;
+		padapter->securitypriv.ndisauthtype = authmode;
+
+		goto exit;
+	}
+
+	if (key) {
+		if (key > WEP_KEYS)
+			return -EINVAL;
+		key--;
+		keyindex_provided = 1;
+	} else {
+		keyindex_provided = 0;
+		key = padapter->securitypriv.dot11PrivacyKeyIndex;
+		RTW_INFO("rtw_wx_set_enc, key=%d\n", key);
+	}
+
+	/* set authentication mode	 */
+	if (erq->flags & IW_ENCODE_OPEN) {
+		RTW_INFO("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
+
+#ifdef CONFIG_PLATFORM_MT53XX
+		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
+#else
+		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+#endif
+
+		padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+		padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+		authmode = Ndis802_11AuthModeOpen;
+		padapter->securitypriv.ndisauthtype = authmode;
+	} else if (erq->flags & IW_ENCODE_RESTRICTED) {
+		RTW_INFO("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+
+#ifdef CONFIG_PLATFORM_MT53XX
+		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
+#else
+		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
+#endif
+
+		padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
+		padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
+		authmode = Ndis802_11AuthModeShared;
+		padapter->securitypriv.ndisauthtype = authmode;
+	} else {
+		RTW_INFO("rtw_wx_set_enc():erq->flags=0x%x\n", erq->flags);
+
+		padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
+		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
+		padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+		padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+		authmode = Ndis802_11AuthModeOpen;
+		padapter->securitypriv.ndisauthtype = authmode;
+	}
+
+	wep.KeyIndex = key;
+	if (erq->length > 0) {
+		wep.KeyLength = erq->length <= 5 ? 5 : 13;
+
+		wep.Length = wep.KeyLength + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
+	} else {
+		wep.KeyLength = 0 ;
+
+		if (keyindex_provided == 1) { /* set key_id only, no given KeyMaterial(erq->length==0). */
+			padapter->securitypriv.dot11PrivacyKeyIndex = key;
+
+			RTW_INFO("(keyindex_provided == 1), keyid=%d, key_len=%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
+
+			switch (padapter->securitypriv.dot11DefKeylen[key]) {
+			case 5:
+				padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
+				break;
+			case 13:
+				padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
+				break;
+			default:
+				padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+				break;
+			}
+
+			goto exit;
+
+		}
+
+	}
+
+	wep.KeyIndex |= 0x80000000;
+
+	memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
+
+	if (rtw_set_802_11_add_wep(padapter, &wep) == false) {
+		if (rf_on == pwrpriv->rf_pwrstate)
+			ret = -EOPNOTSUPP;
+		goto exit;
+	}
+
+exit:
+
+
+	return ret;
+
+}
+
+static int rtw_wx_get_enc(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *keybuf)
+{
+	uint key, ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *erq = &(wrqu->encoding);
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+
+
+	if (check_fwstate(pmlmepriv, _FW_LINKED) != true) {
+		if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != true) {
+			erq->length = 0;
+			erq->flags |= IW_ENCODE_DISABLED;
+			return 0;
+		}
+	}
+
+
+	key = erq->flags & IW_ENCODE_INDEX;
+
+	if (key) {
+		if (key > WEP_KEYS)
+			return -EINVAL;
+		key--;
+	} else
+		key = padapter->securitypriv.dot11PrivacyKeyIndex;
+
+	erq->flags = key + 1;
+
+	/* if(padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen) */
+	/* { */
+	/* erq->flags |= IW_ENCODE_OPEN; */
+	/* }	  */
+
+	switch (padapter->securitypriv.ndisencryptstatus) {
+	case Ndis802_11EncryptionNotSupported:
+	case Ndis802_11EncryptionDisabled:
+
+		erq->length = 0;
+		erq->flags |= IW_ENCODE_DISABLED;
+
+		break;
+
+	case Ndis802_11Encryption1Enabled:
+
+		erq->length = padapter->securitypriv.dot11DefKeylen[key];
+
+		if (erq->length) {
+			memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
+
+			erq->flags |= IW_ENCODE_ENABLED;
+
+			if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
+				erq->flags |= IW_ENCODE_OPEN;
+			else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
+				erq->flags |= IW_ENCODE_RESTRICTED;
+		} else {
+			erq->length = 0;
+			erq->flags |= IW_ENCODE_DISABLED;
+		}
+
+		break;
+
+	case Ndis802_11Encryption2Enabled:
+	case Ndis802_11Encryption3Enabled:
+
+		erq->length = 16;
+		erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
+
+		break;
+
+	default:
+		erq->length = 0;
+		erq->flags |= IW_ENCODE_DISABLED;
+
+		break;
+
+	}
+
+
+	return ret;
+
+}
+
+static int rtw_wx_get_power(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *extra)
+{
+	/* _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); */
+
+	wrqu->power.value = 0;
+	wrqu->power.fixed = 0;	/* no auto select */
+	wrqu->power.disabled = 1;
+
+	return 0;
+
+}
+
+static int rtw_wx_set_gen_ie(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	int ret;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
+
+	return ret;
+}
+
+static int rtw_wx_set_auth(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_param *param = (struct iw_param *)&(wrqu->param);
+	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);
+	u32 value = param->value;
+	int ret = 0;
+
+	switch (param->flags & IW_AUTH_INDEX) {
+
+	case IW_AUTH_WPA_VERSION:
+#ifdef CONFIG_WAPI_SUPPORT
+#ifndef CONFIG_IOCTL_CFG80211
+		padapter->wapiInfo.bWapiEnable = false;
+		if (value == IW_AUTH_WAPI_VERSION_1) {
+			padapter->wapiInfo.bWapiEnable = true;
+			psecuritypriv->dot11PrivacyAlgrthm = _SMS4_;
+			psecuritypriv->dot118021XGrpPrivacy = _SMS4_;
+			psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;
+			pmlmeinfo->auth_algo = psecuritypriv->dot11AuthAlgrthm;
+			padapter->wapiInfo.extra_prefix_len = WAPI_EXT_LEN;
+			padapter->wapiInfo.extra_postfix_len = SMS4_MIC_LEN;
+		}
+#endif
+#endif
+		break;
+	case IW_AUTH_CIPHER_PAIRWISE:
+
+		break;
+	case IW_AUTH_CIPHER_GROUP:
+
+		break;
+	case IW_AUTH_KEY_MGMT:
+#ifdef CONFIG_WAPI_SUPPORT
+#ifndef CONFIG_IOCTL_CFG80211
+		RTW_INFO("rtw_wx_set_auth: IW_AUTH_KEY_MGMT case\n");
+		if (value == IW_AUTH_KEY_MGMT_WAPI_PSK)
+			padapter->wapiInfo.bWapiPSK = true;
+		else
+			padapter->wapiInfo.bWapiPSK = false;
+		RTW_INFO("rtw_wx_set_auth: IW_AUTH_KEY_MGMT bwapipsk %d\n", padapter->wapiInfo.bWapiPSK);
+#endif
+#endif
+		/*
+		 *  ??? does not use these parameters
+		 */
+		break;
+
+	case IW_AUTH_TKIP_COUNTERMEASURES: {
+		if (param->value) {
+			/* wpa_supplicant is enabling the tkip countermeasure. */
+			padapter->securitypriv.btkip_countermeasure = true;
+		} else {
+			/* wpa_supplicant is disabling the tkip countermeasure. */
+			padapter->securitypriv.btkip_countermeasure = false;
+		}
+		break;
+	}
+	case IW_AUTH_DROP_UNENCRYPTED: {
+		/* HACK:
+		 *
+		 * wpa_supplicant calls set_wpa_enabled when the driver
+		 * is loaded and unloaded, regardless of if WPA is being
+		 * used.  No other calls are made which can be used to
+		 * determine if encryption will be used or not prior to
+		 * association being expected.  If encryption is not being
+		 * used, drop_unencrypted is set to false, else true -- we
+		 * can use this to determine if the CAP_PRIVACY_ON bit should
+		 * be set.
+		 */
+
+		if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled) {
+			break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */
+			/* then it needn't reset it; */
+		}
+
+		if (param->value) {
+			padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+			padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+			padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+			padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
+			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
+		}
+
+		break;
+	}
+
+	case IW_AUTH_80211_AUTH_ALG:
+
+#if defined(CONFIG_ANDROID) || 1
+		/*
+		 *  It's the starting point of a link layer connection using wpa_supplicant
+		*/
+		if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
+			LeaveAllPowerSaveMode(padapter);
+			rtw_disassoc_cmd(padapter, 500, false);
+			RTW_INFO("%s...call rtw_indicate_disconnect\n ", __func__);
+			rtw_indicate_disconnect(padapter, 0, false);
+			rtw_free_assoc_resources(padapter, 1);
+		}
+#endif
+
+
+		ret = wpa_set_auth_algs(dev, (u32)param->value);
+
+		break;
+
+	case IW_AUTH_WPA_ENABLED:
+
+		/* if(param->value) */
+		/* padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; */ /* 802.1x */
+		/* else */
+		/* padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; */ /* open system */
+
+		/* _disassociate(priv); */
+
+		break;
+
+	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+		/* ieee->ieee802_1x = param->value; */
+		break;
+
+	case IW_AUTH_PRIVACY_INVOKED:
+		/* ieee->privacy_invoked = param->value; */
+		break;
+
+#ifdef CONFIG_WAPI_SUPPORT
+#ifndef CONFIG_IOCTL_CFG80211
+	case IW_AUTH_WAPI_ENABLED:
+		break;
+#endif
+#endif
+
+	default:
+		return -EOPNOTSUPP;
+
+	}
+
+	return ret;
+
+}
+
+static int rtw_wx_set_enc_ext(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+	char *alg_name;
+	u32 param_len;
+	struct ieee_param *param = NULL;
+	struct iw_point *pencoding = &wrqu->encoding;
+	struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
+	int ret = 0;
+
+	param_len = sizeof(struct ieee_param) + pext->key_len;
+	param = (struct ieee_param *)rtw_malloc(param_len);
+	if (param == NULL)
+		return -1;
+
+	memset(param, 0, param_len);
+
+	param->cmd = IEEE_CMD_SET_ENCRYPTION;
+	memset(param->sta_addr, 0xff, ETH_ALEN);
+
+
+	switch (pext->alg) {
+	case IW_ENCODE_ALG_NONE:
+		/* todo: remove key */
+		/* remove = 1;	 */
+		alg_name = "none";
+		break;
+	case IW_ENCODE_ALG_WEP:
+		alg_name = "WEP";
+		break;
+	case IW_ENCODE_ALG_TKIP:
+		alg_name = "TKIP";
+		break;
+	case IW_ENCODE_ALG_CCMP:
+		alg_name = "CCMP";
+		break;
+#ifdef CONFIG_IEEE80211W
+	case IW_ENCODE_ALG_AES_CMAC:
+		alg_name = "BIP";
+		break;
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_WAPI_SUPPORT
+#ifndef CONFIG_IOCTL_CFG80211
+	case IW_ENCODE_ALG_SM4:
+		alg_name = "SMS4";
+		memcpy(param->sta_addr, pext->addr.sa_data, ETH_ALEN);
+		RTW_INFO("rtw_wx_set_enc_ext: SMS4 case\n");
+		break;
+#endif
+#endif
+	default:
+		ret = -1;
+		goto exit;
+	}
+
+	strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
+
+	if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+		param->u.crypt.set_tx = 1;
+
+	/* cliW: WEP does not have group key
+	 * just not checking GROUP key setting
+	 */
+	if ((pext->alg != IW_ENCODE_ALG_WEP) &&
+	    ((pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+#ifdef CONFIG_IEEE80211W
+	     || (pext->ext_flags & IW_ENCODE_ALG_AES_CMAC)
+#endif /* CONFIG_IEEE80211W */
+	    ))
+		param->u.crypt.set_tx = 0;
+
+	param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1 ;
+
+	if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+#ifdef CONFIG_WAPI_SUPPORT
+#ifndef CONFIG_IOCTL_CFG80211
+		if (pext->alg == IW_ENCODE_ALG_SM4)
+			memcpy(param->u.crypt.seq, pext->rx_seq, 16);
+		else
+#endif /* CONFIG_IOCTL_CFG80211 */
+#endif /* CONFIG_WAPI_SUPPORT */
+			memcpy(param->u.crypt.seq, pext->rx_seq, 8);
+	}
+
+	if (pext->key_len) {
+		param->u.crypt.key_len = pext->key_len;
+		/* memcpy(param + 1, pext + 1, pext->key_len); */
+		memcpy(param->u.crypt.key, pext + 1, pext->key_len);
+	}
+
+	if (pencoding->flags & IW_ENCODE_DISABLED) {
+		/* todo: remove key */
+		/* remove = 1; */
+	}
+
+	ret =  wpa_set_encryption(dev, param, param_len);
+
+exit:
+	if (param)
+		rtw_mfree((u8 *)param, param_len);
+
+	return ret;
+}
+
+
+static int rtw_wx_get_nick(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	/* _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); */
+	/* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
+	/* struct security_priv *psecuritypriv = &padapter->securitypriv; */
+
+	if (extra) {
+		wrqu->data.length = 14;
+		wrqu->data.flags = 1;
+		memcpy(extra, "<WIFI@REALTEK>", 14);
+	}
+
+	/* rtw_signal_process(pid, SIGUSR1); */ /* for test */
+
+	/* dump debug info here	 */
+	return 0;
+}
+
+static int rtw_wx_read32(struct net_device *dev,
+			 struct iw_request_info *info,
+			 union iwreq_data *wrqu, char *extra)
+{
+	PADAPTER padapter;
+	struct iw_point *p;
+	u16 len;
+	u32 addr;
+	u32 data32;
+	u32 bytes;
+	u8 *ptmp;
+	int ret;
+
+
+	ret = 0;
+	padapter = (PADAPTER)rtw_netdev_priv(dev);
+	p = &wrqu->data;
+	len = p->length;
+	if (0 == len)
+		return -EINVAL;
+
+	ptmp = (u8 *)rtw_malloc(len);
+	if (NULL == ptmp)
+		return -ENOMEM;
+
+	if (copy_from_user(ptmp, p->pointer, len)) {
+		ret = -EFAULT;
+		goto exit;
+	}
+
+	bytes = 0;
+	addr = 0;
+	sscanf(ptmp, "%d,%x", &bytes, &addr);
+
+	switch (bytes) {
+	case 1:
+		data32 = rtw_read8(padapter, addr);
+		sprintf(extra, "0x%02X", data32);
+		break;
+	case 2:
+		data32 = rtw_read16(padapter, addr);
+		sprintf(extra, "0x%04X", data32);
+		break;
+	case 4:
+		data32 = rtw_read32(padapter, addr);
+		sprintf(extra, "0x%08X", data32);
+		break;
+	default:
+		RTW_INFO("%s: usage> read [bytes],[address(hex)]\n", __func__);
+		ret = -EINVAL;
+		goto exit;
+	}
+	RTW_INFO("%s: addr=0x%08X data=%s\n", __func__, addr, extra);
+
+exit:
+	rtw_mfree(ptmp, len);
+
+	return 0;
+}
+
+static int rtw_wx_write32(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+	PADAPTER padapter = (PADAPTER)rtw_netdev_priv(dev);
+
+	u32 addr;
+	u32 data32;
+	u32 bytes;
+
+
+	bytes = 0;
+	addr = 0;
+	data32 = 0;
+	sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
+
+	switch (bytes) {
+	case 1:
+		rtw_write8(padapter, addr, (u8)data32);
+		RTW_INFO("%s: addr=0x%08X data=0x%02X\n", __func__, addr, (u8)data32);
+		break;
+	case 2:
+		rtw_write16(padapter, addr, (u16)data32);
+		RTW_INFO("%s: addr=0x%08X data=0x%04X\n", __func__, addr, (u16)data32);
+		break;
+	case 4:
+		rtw_write32(padapter, addr, data32);
+		RTW_INFO("%s: addr=0x%08X data=0x%08X\n", __func__, addr, data32);
+		break;
+	default:
+		RTW_INFO("%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rtw_wx_read_rf(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u32 path, addr, data32;
+
+
+	path = *(u32 *)extra;
+	addr = *((u32 *)extra + 1);
+	data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
+	/*	RTW_INFO("%s: path=%d addr=0x%02x data=0x%05x\n", __func__, path, addr, data32); */
+	/*
+	 * IMPORTANT!!
+	 * Only when wireless private ioctl is at odd order,
+	 * "extra" would be copied to user space.
+	 */
+	sprintf(extra, "0x%05x", data32);
+
+	return 0;
+}
+
+static int rtw_wx_write_rf(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u32 path, addr, data32;
+
+
+	path = *(u32 *)extra;
+	addr = *((u32 *)extra + 1);
+	data32 = *((u32 *)extra + 2);
+	/*	RTW_INFO("%s: path=%d addr=0x%02x data=0x%05x\n", __func__, path, addr, data32); */
+	rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
+
+	return 0;
+}
+
+static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
+			    union iwreq_data *wrqu, char *b)
+{
+	return -1;
+}
+
+static int dummy(struct net_device *dev, struct iw_request_info *a,
+		 union iwreq_data *wrqu, char *b)
+{
+	/* _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);	 */
+	/* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
+
+	/* RTW_INFO("cmd_code=%x, fwstate=0x%x\n", a->cmd, get_fwstate(pmlmepriv)); */
+
+	return -1;
+
+}
+
+static int rtw_wx_set_channel_plan(struct net_device *dev,
+				   struct iw_request_info *info,
+				   union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	u8 channel_plan_req = (u8)(*((int *)wrqu));
+
+	if (_SUCCESS != rtw_set_channel_plan(padapter, channel_plan_req))
+		return -EPERM;
+
+	return 0;
+}
+
+static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
+				       struct iw_request_info *a,
+				       union iwreq_data *wrqu, char *b)
+{
+#ifdef CONFIG_PLATFORM_MT53XX
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+#endif
+	return 0;
+}
+
+static int rtw_wx_get_sensitivity(struct net_device *dev,
+				  struct iw_request_info *info,
+				  union iwreq_data *wrqu, char *buf)
+{
+#ifdef CONFIG_PLATFORM_MT53XX
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	/*	Modified by Albert 20110914 */
+	/*	This is in dbm format for MTK platform. */
+	wrqu->qual.level = padapter->recvpriv.rssi;
+	RTW_INFO(" level = %u\n",  wrqu->qual.level);
+#endif
+	return 0;
+}
+
+static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu, char *extra)
+{
+#ifdef CONFIG_PLATFORM_MT53XX
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	return rtw_set_wpa_ie(padapter, wrqu->data.pointer, wrqu->data.length);
+#else
+	return 0;
+#endif
+}
+
+/*
+typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra);
+*/
+/*
+ *	For all data larger than 16 octets, we need to use a
+ *	pointer to memory allocated in user space.
+ */
+static  int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+#ifdef CONFIG_DRVEXT_MODULE
+	u8 res;
+	struct drvext_handler *phandler;
+	struct drvext_oidparam *poidparam;
+	int ret;
+	u16 len;
+	u8 *pparmbuf, bset;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *p = &wrqu->data;
+
+	if ((!p->length) || (!p->pointer)) {
+		ret = -EINVAL;
+		goto _rtw_drvext_hdl_exit;
+	}
+
+
+	bset = (u8)(p->flags & 0xFFFF);
+	len = p->length;
+	pparmbuf = (u8 *)rtw_malloc(len);
+	if (pparmbuf == NULL) {
+		ret = -ENOMEM;
+		goto _rtw_drvext_hdl_exit;
+	}
+
+	if (bset) { /* set info */
+		if (copy_from_user(pparmbuf, p->pointer, len)) {
+			rtw_mfree(pparmbuf, len);
+			ret = -EFAULT;
+			goto _rtw_drvext_hdl_exit;
+		}
+	} else { /* query info */
+
+	}
+
+
+	/*  */
+	poidparam = (struct drvext_oidparam *)pparmbuf;
+
+
+
+	/* check subcode	 */
+	if (poidparam->subcode >= MAX_DRVEXT_HANDLERS) {
+		ret = -EINVAL;
+		goto _rtw_drvext_hdl_exit;
+	}
+
+
+	if (poidparam->subcode >= MAX_DRVEXT_OID_SUBCODES) {
+		ret = -EINVAL;
+		goto _rtw_drvext_hdl_exit;
+	}
+
+
+	phandler = drvextoidhandlers + poidparam->subcode;
+
+	if (poidparam->len != phandler->parmsize) {
+		ret = -EINVAL;
+		goto _rtw_drvext_hdl_exit;
+	}
+
+
+	res = phandler->handler(&padapter->drvextpriv, bset, poidparam->data);
+
+	if (res == 0) {
+		ret = 0;
+
+		if (bset == 0x00) {/* query info */
+			/* memcpy(p->pointer, pparmbuf, len); */
+			if (copy_to_user(p->pointer, pparmbuf, len))
+				ret = -EFAULT;
+		}
+	} else
+		ret = -EFAULT;
+
+
+_rtw_drvext_hdl_exit:
+
+	return ret;
+
+#endif
+
+	return 0;
+
+}
+
+static void rtw_dbg_mode_hdl(_adapter *padapter, u32 id, u8 *pdata, u32 len)
+{
+	pRW_Reg	RegRWStruct;
+	struct rf_reg_param *prfreg;
+	u8 path;
+	u8 offset;
+	u32 value;
+
+	RTW_INFO("%s\n", __func__);
+
+	switch (id) {
+	case GEN_MP_IOCTL_SUBCODE(MP_START):
+		RTW_INFO("871x_driver is only for normal mode, can't enter mp mode\n");
+		break;
+	case GEN_MP_IOCTL_SUBCODE(READ_REG):
+		RegRWStruct = (pRW_Reg)pdata;
+		switch (RegRWStruct->width) {
+		case 1:
+			RegRWStruct->value = rtw_read8(padapter, RegRWStruct->offset);
+			break;
+		case 2:
+			RegRWStruct->value = rtw_read16(padapter, RegRWStruct->offset);
+			break;
+		case 4:
+			RegRWStruct->value = rtw_read32(padapter, RegRWStruct->offset);
+			break;
+		default:
+			break;
+		}
+
+		break;
+	case GEN_MP_IOCTL_SUBCODE(WRITE_REG):
+		RegRWStruct = (pRW_Reg)pdata;
+		switch (RegRWStruct->width) {
+		case 1:
+			rtw_write8(padapter, RegRWStruct->offset, (u8)RegRWStruct->value);
+			break;
+		case 2:
+			rtw_write16(padapter, RegRWStruct->offset, (u16)RegRWStruct->value);
+			break;
+		case 4:
+			rtw_write32(padapter, RegRWStruct->offset, (u32)RegRWStruct->value);
+			break;
+		default:
+			break;
+		}
+
+		break;
+	case GEN_MP_IOCTL_SUBCODE(READ_RF_REG):
+
+		prfreg = (struct rf_reg_param *)pdata;
+
+		path = (u8)prfreg->path;
+		offset = (u8)prfreg->offset;
+
+		value = rtw_hal_read_rfreg(padapter, path, offset, 0xffffffff);
+
+		prfreg->value = value;
+
+		break;
+	case GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG):
+
+		prfreg = (struct rf_reg_param *)pdata;
+
+		path = (u8)prfreg->path;
+		offset = (u8)prfreg->offset;
+		value = prfreg->value;
+
+		rtw_hal_write_rfreg(padapter, path, offset, 0xffffffff, value);
+		break;
+	case GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO):
+		RTW_INFO("==> trigger gpio 0\n");
+		rtw_hal_set_hwreg(padapter, HW_VAR_TRIGGER_GPIO_0, NULL);
+		break;
+#ifdef CONFIG_BT_COEXIST
+	case GEN_MP_IOCTL_SUBCODE(SET_DM_BT):
+		RTW_INFO("==> set dm_bt_coexist:%x\n", *(u8 *)pdata);
+		rtw_hal_set_hwreg(padapter, HW_VAR_BT_SET_COEXIST, pdata);
+		break;
+	case GEN_MP_IOCTL_SUBCODE(DEL_BA):
+		RTW_INFO("==> delete ba:%x\n", *(u8 *)pdata);
+		rtw_hal_set_hwreg(padapter, HW_VAR_BT_ISSUE_DELBA, pdata);
+		break;
+#endif
+#ifdef DBG_CONFIG_ERROR_DETECT
+	case GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS):
+		*pdata = rtw_hal_sreset_get_wifi_status(padapter);
+		break;
+#endif
+
+	default:
+		break;
+	}
+}
+
+#ifdef MP_IOCTL_HDL
+static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	u32 BytesRead, BytesWritten, BytesNeeded;
+	struct oid_par_priv	oid_par;
+	struct mp_ioctl_handler	*phandler;
+	struct mp_ioctl_param	*poidparam;
+	uint status = 0;
+	u16 len;
+	u8 *pparmbuf = NULL, bset;
+	PADAPTER padapter = (PADAPTER)rtw_netdev_priv(dev);
+	struct iw_point *p = &wrqu->data;
+
+	/* RTW_INFO("+rtw_mp_ioctl_hdl\n"); */
+
+	/* mutex_lock(&ioctl_mutex); */
+
+	if ((!p->length) || (!p->pointer)) {
+		ret = -EINVAL;
+		goto _rtw_mp_ioctl_hdl_exit;
+	}
+
+	pparmbuf = NULL;
+	bset = (u8)(p->flags & 0xFFFF);
+	len = p->length;
+	pparmbuf = (u8 *)rtw_malloc(len);
+	if (pparmbuf == NULL) {
+		ret = -ENOMEM;
+		goto _rtw_mp_ioctl_hdl_exit;
+	}
+
+	if (copy_from_user(pparmbuf, p->pointer, len)) {
+		ret = -EFAULT;
+		goto _rtw_mp_ioctl_hdl_exit;
+	}
+
+	poidparam = (struct mp_ioctl_param *)pparmbuf;
+
+	if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
+		ret = -EINVAL;
+		goto _rtw_mp_ioctl_hdl_exit;
+	}
+
+	/* RTW_INFO("%s: %d\n", __func__, poidparam->subcode); */
+#ifdef CONFIG_MP_INCLUDED
+	if (padapter->registrypriv.mp_mode == 1) {
+		phandler = mp_ioctl_hdl + poidparam->subcode;
+
+		if ((phandler->paramsize != 0) && (poidparam->len < phandler->paramsize)) {
+			ret = -EINVAL;
+			goto _rtw_mp_ioctl_hdl_exit;
+		}
+
+		if (phandler->handler) {
+			oid_par.adapter_context = padapter;
+			oid_par.oid = phandler->oid;
+			oid_par.information_buf = poidparam->data;
+			oid_par.information_buf_len = poidparam->len;
+			oid_par.dbg = 0;
+
+			BytesWritten = 0;
+			BytesNeeded = 0;
+
+			if (bset) {
+				oid_par.bytes_rw = &BytesRead;
+				oid_par.bytes_needed = &BytesNeeded;
+				oid_par.type_of_oid = SET_OID;
+			} else {
+				oid_par.bytes_rw = &BytesWritten;
+				oid_par.bytes_needed = &BytesNeeded;
+				oid_par.type_of_oid = QUERY_OID;
+			}
+
+			status = phandler->handler(&oid_par);
+
+			/* todo:check status, BytesNeeded, etc. */
+		} else {
+			RTW_INFO("rtw_mp_ioctl_hdl(): err!, subcode=%d, oid=%d, handler=%p\n",
+				poidparam->subcode, phandler->oid, phandler->handler);
+			ret = -EFAULT;
+			goto _rtw_mp_ioctl_hdl_exit;
+		}
+	} else
+#endif
+	{
+		rtw_dbg_mode_hdl(padapter, poidparam->subcode, poidparam->data, poidparam->len);
+	}
+
+	if (bset == 0x00) {/* query info */
+		if (copy_to_user(p->pointer, pparmbuf, len))
+			ret = -EFAULT;
+	}
+
+	if (status) {
+		ret = -EFAULT;
+		goto _rtw_mp_ioctl_hdl_exit;
+	}
+
+_rtw_mp_ioctl_hdl_exit:
+
+	if (pparmbuf)
+		rtw_mfree(pparmbuf, len);
+
+	/* mutex_unlock(&ioctl_mutex); */
+
+	return ret;
+}
+#endif
+static int rtw_get_ap_info(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	int bssid_match, ret = 0;
+	u32 cnt = 0, wpa_ielen;
+	unsigned long	irqL;
+	_list	*plist, *phead;
+	unsigned char *pbuf;
+	u8 bssid[ETH_ALEN];
+	char data[32];
+	struct wlan_network *pnetwork = NULL;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	_queue *queue = &(pmlmepriv->scanned_queue);
+	struct iw_point *pdata = &wrqu->data;
+
+	RTW_INFO("+rtw_get_aplist_info\n");
+
+	if (rtw_is_drv_stopped(padapter) || (pdata == NULL)) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY | _FW_UNDER_LINKING))) ) {
+		rtw_msleep_os(30);
+		cnt++;
+		if (cnt > 100)
+			break;
+	}
+
+
+	/* pdata->length = 0; */ /* ?	 */
+	pdata->flags = 0;
+	if (pdata->length >= 32) {
+		if (copy_from_user(data, pdata->pointer, 32)) {
+			ret = -EINVAL;
+			goto exit;
+		}
+	} else {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	_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) )
+			break;
+
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+
+		/* if(hwaddr_aton_i(pdata->pointer, bssid)) */
+		if (hwaddr_aton_i(data, bssid)) {
+			RTW_INFO("Invalid BSSID '%s'.\n", (u8 *)data);
+			_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+			return -EINVAL;
+		}
+
+
+		if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN) ) { /* BSSID match, then check if supporting wpa/wpa2 */
+			RTW_INFO("BSSID:" MAC_FMT "\n", MAC_ARG(bssid));
+
+			pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12);
+			if (pbuf && (wpa_ielen > 0)) {
+				pdata->flags = 1;
+				break;
+			}
+
+			pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12);
+			if (pbuf && (wpa_ielen > 0)) {
+				pdata->flags = 2;
+				break;
+			}
+
+		}
+
+		plist = get_next(plist);
+
+	}
+
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+	if (pdata->length >= 34) {
+		if (copy_to_user((u8 *)pdata->pointer + 32, (u8 *)&pdata->flags, 1)) {
+			ret = -EINVAL;
+			goto exit;
+		}
+	}
+
+exit:
+
+	return ret;
+
+}
+
+static int rtw_set_pid(struct net_device *dev,
+		       struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = rtw_netdev_priv(dev);
+	int *pdata = (int *)wrqu;
+	int selector;
+
+	if (rtw_is_drv_stopped(padapter) || (pdata == NULL)) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	selector = *pdata;
+	if (selector < 3 && selector >= 0) {
+		padapter->pid[selector] = *(pdata + 1);
+#ifdef CONFIG_GLOBAL_UI_PID
+		ui_pid[selector] = *(pdata + 1);
+#endif
+		RTW_INFO("%s set pid[%d]=%d\n", __func__, selector , padapter->pid[selector]);
+	} else
+		RTW_INFO("%s selector %d error\n", __func__, selector);
+
+exit:
+
+	return ret;
+
+}
+
+static int rtw_wps_start(struct net_device *dev,
+			 struct iw_request_info *info,
+			 union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *pdata = &wrqu->data;
+	u32   u32wps_start = 0;
+	unsigned int uintRet = 0;
+
+	if (RTW_CANNOT_RUN(padapter) || (NULL == pdata)) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	uintRet = copy_from_user((void *) &u32wps_start, pdata->pointer, 4);
+	if (u32wps_start == 0)
+		u32wps_start = *extra;
+
+	RTW_INFO("[%s] wps_start = %d\n", __func__, u32wps_start);
+
+	if (u32wps_start == 1)   /* WPS Start */
+		rtw_led_control(padapter, LED_CTL_START_WPS);
+	else if (u32wps_start == 2)   /* WPS Stop because of wps success */
+		rtw_led_control(padapter, LED_CTL_STOP_WPS);
+	else if (u32wps_start == 3)   /* WPS Stop because of wps fail */
+		rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL);
+
+#ifdef CONFIG_INTEL_WIDI
+	process_intel_widi_wps_status(padapter, u32wps_start);
+#endif /* CONFIG_INTEL_WIDI */
+
+exit:
+
+	return ret;
+
+}
+
+#ifdef CONFIG_P2P
+static int rtw_wext_p2p_enable(struct net_device *dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	enum P2P_ROLE init_role = P2P_ROLE_DISABLE;
+
+	if (*extra == '0')
+		init_role = P2P_ROLE_DISABLE;
+	else if (*extra == '1')
+		init_role = P2P_ROLE_DEVICE;
+	else if (*extra == '2')
+		init_role = P2P_ROLE_CLIENT;
+	else if (*extra == '3')
+		init_role = P2P_ROLE_GO;
+
+	if (_FAIL == rtw_p2p_enable(padapter, init_role)) {
+		ret = -EFAULT;
+		goto exit;
+	}
+
+	/* set channel/bandwidth */
+	if (init_role != P2P_ROLE_DISABLE) {
+		u8 channel, ch_offset;
+		u16 bwmode;
+
+		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) {
+			/*	Stay at the listen state and wait for discovery. */
+			channel = pwdinfo->listen_channel;
+			pwdinfo->operating_channel = pwdinfo->listen_channel;
+			ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+			bwmode = CHANNEL_WIDTH_20;
+		}
+#ifdef CONFIG_CONCURRENT_MODE
+		else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
+
+			_set_timer(&pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_interval);
+
+			channel = rtw_mi_get_union_chan(padapter);
+			ch_offset = rtw_mi_get_union_offset(padapter);
+			bwmode = rtw_mi_get_union_bw(padapter);
+
+			pwdinfo->operating_channel = channel;
+		}
+#endif
+		else {
+			pwdinfo->operating_channel = pmlmeext->cur_channel;
+
+			channel = pwdinfo->operating_channel;
+			ch_offset = pmlmeext->cur_ch_offset;
+			bwmode = pmlmeext->cur_bwmode;
+		}
+
+		set_channel_bwmode(padapter, channel, ch_offset, bwmode);
+	}
+
+exit:
+	return ret;
+
+}
+
+static int rtw_p2p_set_go_nego_ssid(struct net_device *dev,
+				    struct iw_request_info *info,
+				    union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+
+	RTW_INFO("[%s] ssid = %s, len = %zu\n", __func__, extra, strlen(extra));
+	memcpy(pwdinfo->nego_ssid, extra, strlen(extra));
+	pwdinfo->nego_ssidlen = strlen(extra);
+
+	return ret;
+
+}
+
+
+static int rtw_p2p_set_intent(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+	int							ret = 0;
+	_adapter						*padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wifidirect_info			*pwdinfo = &(padapter->wdinfo);
+	u8							intent = pwdinfo->intent;
+
+	extra[wrqu->data.length] = 0x00;
+
+	intent = rtw_atoi(extra);
+
+	if (intent <= 15)
+		pwdinfo->intent = intent;
+	else
+		ret = -1;
+
+	RTW_INFO("[%s] intent = %d\n", __func__, intent);
+
+	return ret;
+
+}
+
+static int rtw_p2p_set_listen_ch(struct net_device *dev,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+	u8	listen_ch = pwdinfo->listen_channel;	/*	Listen channel number */
+
+	extra[wrqu->data.length] = 0x00;
+	listen_ch = rtw_atoi(extra);
+
+	if ((listen_ch == 1) || (listen_ch == 6) || (listen_ch == 11)) {
+		pwdinfo->listen_channel = listen_ch;
+		set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+	} else
+		ret = -1;
+
+	RTW_INFO("[%s] listen_ch = %d\n", __func__, pwdinfo->listen_channel);
+
+	return ret;
+
+}
+
+static int rtw_p2p_set_op_ch(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	/*	Commented by Albert 20110524
+	 *	This function is used to set the operating channel if the driver will become the group owner */
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+	u8	op_ch = pwdinfo->operating_channel;	/*	Operating channel number */
+
+	extra[wrqu->data.length] = 0x00;
+
+	op_ch = (u8) rtw_atoi(extra);
+	if (op_ch > 0)
+		pwdinfo->operating_channel = op_ch;
+	else
+		ret = -1;
+
+	RTW_INFO("[%s] op_ch = %d\n", __func__, pwdinfo->operating_channel);
+
+	return ret;
+
+}
+
+
+static int rtw_p2p_profilefound(struct net_device *dev,
+				struct iw_request_info *info,
+				union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+
+	/*	Comment by Albert 2010/10/13 */
+	/*	Input data format: */
+	/*	Ex:  0 */
+	/*	Ex:  1XX:XX:XX:XX:XX:XXYYSSID */
+	/*	0 => Reflush the profile record list. */
+	/*	1 => Add the profile list */
+	/*	XX:XX:XX:XX:XX:XX => peer's MAC Address ( ex: 00:E0:4C:00:00:01 ) */
+	/*	YY => SSID Length */
+	/*	SSID => SSID for persistence group */
+
+	RTW_INFO("[%s] In value = %s, len = %d\n", __func__, extra, wrqu->data.length - 1);
+
+
+	/*	The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function. */
+	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+		if (extra[0] == '0') {
+			/*	Remove all the profile information of wifidirect_info structure. */
+			memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
+			pwdinfo->profileindex = 0;
+		} else {
+			if (pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM)
+				ret = -1;
+			else {
+				int jj, kk;
+
+				/*	Add this profile information into pwdinfo->profileinfo */
+				/*	Ex:  1XX:XX:XX:XX:XX:XXYYSSID */
+				for (jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3)
+					pwdinfo->profileinfo[pwdinfo->profileindex].peermac[jj] = key_2char2num(extra[kk], extra[kk + 1]);
+
+				/* pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen = ( extra[18] - '0' ) * 10 + ( extra[19] - '0' ); */
+				/* memcpy( pwdinfo->profileinfo[pwdinfo->profileindex].ssid, &extra[20], pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen ); */
+				pwdinfo->profileindex++;
+			}
+		}
+	}
+
+	return ret;
+
+}
+
+static int rtw_p2p_setDN(struct net_device *dev,
+			 struct iw_request_info *info,
+			 union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+
+
+	RTW_INFO("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
+	memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
+	memcpy(pwdinfo->device_name, extra, wrqu->data.length - 1);
+	pwdinfo->device_name_len = wrqu->data.length - 1;
+
+	return ret;
+
+}
+
+
+static int rtw_p2p_get_status(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+
+	if (padapter->bShowGetP2PState) {
+		RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+			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]);
+	}
+
+	/*	Commented by Albert 2010/10/12 */
+	/*	Because of the output size limitation, I had removed the "Role" information. */
+	/*	About the "Role" information, we will use the new private IOCTL to get the "Role" information. */
+	sprintf(extra, "\n\nStatus=%.2d\n", rtw_p2p_state(pwdinfo));
+	wrqu->data.length = strlen(extra);
+
+	return ret;
+
+}
+
+/*	Commented by Albert 20110520
+ *	This function will return the config method description
+ *	This config method description will show us which config method the remote P2P device is intented to use
+ *	by sending the provisioning discovery request frame. */
+
+static int rtw_p2p_get_req_cm(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+
+	sprintf(extra, "\n\nCM=%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
+	wrqu->data.length = strlen(extra);
+	return ret;
+
+}
+
+
+static int rtw_p2p_get_role(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+
+
+	RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+		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]);
+
+	sprintf(extra, "\n\nRole=%.2d\n", rtw_p2p_role(pwdinfo));
+	wrqu->data.length = strlen(extra);
+	return ret;
+
+}
+
+
+static int rtw_p2p_get_peer_ifaddr(struct net_device *dev,
+				   struct iw_request_info *info,
+				   union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+
+
+	RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+		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]);
+
+	sprintf(extra, "\nMAC %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
+		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]);
+	wrqu->data.length = strlen(extra);
+	return ret;
+
+}
+
+static int rtw_p2p_get_peer_devaddr(struct net_device *dev,
+				    struct iw_request_info *info,
+				    union iwreq_data *wrqu, char *extra)
+
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+
+	RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+		pwdinfo->rx_prov_disc_info.peerDevAddr[0], pwdinfo->rx_prov_disc_info.peerDevAddr[1],
+		pwdinfo->rx_prov_disc_info.peerDevAddr[2], pwdinfo->rx_prov_disc_info.peerDevAddr[3],
+		pwdinfo->rx_prov_disc_info.peerDevAddr[4], pwdinfo->rx_prov_disc_info.peerDevAddr[5]);
+	sprintf(extra, "\n%.2X%.2X%.2X%.2X%.2X%.2X",
+		pwdinfo->rx_prov_disc_info.peerDevAddr[0], pwdinfo->rx_prov_disc_info.peerDevAddr[1],
+		pwdinfo->rx_prov_disc_info.peerDevAddr[2], pwdinfo->rx_prov_disc_info.peerDevAddr[3],
+		pwdinfo->rx_prov_disc_info.peerDevAddr[4], pwdinfo->rx_prov_disc_info.peerDevAddr[5]);
+	wrqu->data.length = strlen(extra);
+	return ret;
+
+}
+
+static int rtw_p2p_get_peer_devaddr_by_invitation(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+
+	RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+		pwdinfo->p2p_peer_device_addr[0], pwdinfo->p2p_peer_device_addr[1],
+		pwdinfo->p2p_peer_device_addr[2], pwdinfo->p2p_peer_device_addr[3],
+		pwdinfo->p2p_peer_device_addr[4], pwdinfo->p2p_peer_device_addr[5]);
+	sprintf(extra, "\nMAC %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
+		pwdinfo->p2p_peer_device_addr[0], pwdinfo->p2p_peer_device_addr[1],
+		pwdinfo->p2p_peer_device_addr[2], pwdinfo->p2p_peer_device_addr[3],
+		pwdinfo->p2p_peer_device_addr[4], pwdinfo->p2p_peer_device_addr[5]);
+	wrqu->data.length = strlen(extra);
+	return ret;
+
+}
+
+static int rtw_p2p_get_groupid(struct net_device *dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+
+	sprintf(extra, "\n%.2X:%.2X:%.2X:%.2X:%.2X:%.2X %s",
+		pwdinfo->groupid_info.go_device_addr[0], pwdinfo->groupid_info.go_device_addr[1],
+		pwdinfo->groupid_info.go_device_addr[2], pwdinfo->groupid_info.go_device_addr[3],
+		pwdinfo->groupid_info.go_device_addr[4], pwdinfo->groupid_info.go_device_addr[5],
+		pwdinfo->groupid_info.ssid);
+	wrqu->data.length = strlen(extra);
+	return ret;
+
+}
+
+static int rtw_p2p_get_op_ch(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+
+
+	RTW_INFO("[%s] Op_ch = %02x\n", __func__, pwdinfo->operating_channel);
+
+	sprintf(extra, "\n\nOp_ch=%.2d\n", pwdinfo->operating_channel);
+	wrqu->data.length = strlen(extra);
+	return ret;
+
+}
+
+static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
+					struct iw_request_info *info,
+			union iwreq_data *wrqu, char *extra, char *subcmd)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 peerMAC[ETH_ALEN] = { 0x00 };
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	unsigned long irqL;
+	_list *plist, *phead;
+	_queue *queue = &(pmlmepriv->scanned_queue);
+	struct wlan_network *pnetwork = NULL;
+	u8 blnMatch = 0;
+	u16	attr_content;
+	__be16 be_tmp;
+	uint attr_contentlen = 0;
+	u8	attr_content_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
+
+	/*	Commented by Albert 20110727 */
+	/*	The input data is the MAC address which the application wants to know its WPS config method. */
+	/*	After knowing its WPS config method, the application can decide the config method for provisioning discovery. */
+	/*	Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05 */
+
+	RTW_INFO("[%s] data = %s\n", __func__, subcmd);
+
+	macstr2num(peerMAC, subcmd);
+
+	_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) )
+			break;
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
+			u8 *wpsie;
+			uint	wpsie_len = 0;
+
+			/*	The mac address is matched. */
+
+			wpsie = rtw_get_wps_ie_from_scan_queue(&pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &wpsie_len, pnetwork->network.Reserved[0]);
+			if (wpsie) {
+				rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *)&be_tmp, &attr_contentlen);
+				if (attr_contentlen) {
+					attr_content = be16_to_cpu(be_tmp);
+					sprintf(attr_content_str, "\n\nM=%.4d", attr_content);
+					blnMatch = 1;
+				}
+			}
+			break;
+		}
+		plist = get_next(plist);
+	}
+
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+	if (!blnMatch)
+		sprintf(attr_content_str, "\n\nM=0000");
+
+	wrqu->data.length = strlen(attr_content_str);
+	memcpy(extra, attr_content_str, wrqu->data.length);
+
+	return ret;
+
+}
+
+#ifdef CONFIG_WFD
+static int rtw_p2p_get_peer_wfd_port(struct net_device *dev,
+				     struct iw_request_info *info,
+				     union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+
+	RTW_INFO("[%s] p2p_state = %d\n", __func__, rtw_p2p_state(pwdinfo));
+
+	sprintf(extra, "\n\nPort=%d\n", pwdinfo->wfd_info->peer_rtsp_ctrlport);
+	RTW_INFO("[%s] remote port = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
+
+	wrqu->data.length = strlen(extra);
+	return ret;
+
+}
+
+static int rtw_p2p_get_peer_wfd_preferred_connection(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+
+	sprintf(extra, "\n\nwfd_pc=%d\n", pwdinfo->wfd_info->wfd_pc);
+	RTW_INFO("[%s] wfd_pc = %d\n", __func__, pwdinfo->wfd_info->wfd_pc);
+
+	wrqu->data.length = strlen(extra);
+	pwdinfo->wfd_info->wfd_pc = false;	/*	Reset the WFD preferred connection to P2P */
+	return ret;
+
+}
+
+static int rtw_p2p_get_peer_wfd_session_available(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+
+	sprintf(extra, "\n\nwfd_sa=%d\n", pwdinfo->wfd_info->peer_session_avail);
+	RTW_INFO("[%s] wfd_sa = %d\n", __func__, pwdinfo->wfd_info->peer_session_avail);
+
+	wrqu->data.length = strlen(extra);
+	pwdinfo->wfd_info->peer_session_avail = true;	/*	Reset the WFD session available */
+	return ret;
+
+}
+#endif /* CONFIG_WFD */
+
+static int rtw_p2p_get_go_device_address(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra, char *subcmd)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 peerMAC[ETH_ALEN] = { 0x00 };
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	unsigned long irqL;
+	_list *plist, *phead;
+	_queue *queue	= &(pmlmepriv->scanned_queue);
+	struct wlan_network *pnetwork = NULL;
+	u8 blnMatch = 0;
+	u8 *p2pie;
+	uint p2pielen = 0, attr_contentlen = 0;
+	u8 attr_content[100] = { 0x00 };
+	u8 go_devadd_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
+
+	/*	Commented by Albert 20121209 */
+	/*	The input data is the GO's interface address which the application wants to know its device address. */
+	/*	Format: iwpriv wlanx p2p_get2 go_devadd=00:E0:4C:00:00:05 */
+
+	RTW_INFO("[%s] data = %s\n", __func__, subcmd);
+
+	macstr2num(peerMAC, subcmd);
+
+	_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) )
+			break;
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
+			/*	Commented by Albert 2011/05/18 */
+			/*	Match the device address located in the P2P IE */
+			/*	This is for the case that the P2P device address is not the same as the P2P interface address. */
+
+			p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
+			if (p2pie) {
+				while (p2pie) {
+					/*	The P2P Device ID attribute is included in the Beacon frame. */
+					/*	The P2P Device Info attribute is included in the probe response frame. */
+
+					memset(attr_content, 0x00, 100);
+					if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
+						/*	Handle the P2P Device ID attribute of Beacon first */
+						blnMatch = 1;
+						break;
+
+					} else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
+						/*	Handle the P2P Device Info attribute of probe response */
+						blnMatch = 1;
+						break;
+					}
+
+					/* Get the next P2P IE */
+					p2pie = rtw_get_p2p_ie(p2pie + p2pielen, BSS_EX_TLV_IES_LEN(&pnetwork->network) - (p2pie + p2pielen - BSS_EX_TLV_IES(&pnetwork->network)), NULL, &p2pielen);
+				}
+			}
+		}
+
+		plist = get_next(plist);
+
+	}
+
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+	if (!blnMatch)
+		sprintf(go_devadd_str, "\n\ndev_add=NULL");
+	else {
+		sprintf(go_devadd_str, "\n\ndev_add=%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
+			attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
+	}
+
+	wrqu->data.length = strlen(go_devadd_str);
+	memcpy(extra, go_devadd_str, wrqu->data.length);
+
+	return ret;
+
+}
+
+static int rtw_p2p_get_device_type(struct net_device *dev,
+				   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra, char *subcmd)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 peerMAC[ETH_ALEN] = { 0x00 };
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	unsigned long irqL;
+	_list *plist, *phead;
+	_queue *queue = &(pmlmepriv->scanned_queue);
+	struct wlan_network *pnetwork = NULL;
+	u8 blnMatch = 0;
+	u8 dev_type[8] = { 0x00 };
+	uint dev_type_len = 0;
+	u8 dev_type_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };    /* +9 is for the str "dev_type=", we have to clear it at wrqu->data.pointer */
+
+	/*	Commented by Albert 20121209 */
+	/*	The input data is the MAC address which the application wants to know its device type. */
+	/*	Such user interface could know the device type. */
+	/*	Format: iwpriv wlanx p2p_get2 dev_type=00:E0:4C:00:00:05 */
+
+	RTW_INFO("[%s] data = %s\n", __func__, subcmd);
+
+	macstr2num(peerMAC, subcmd);
+
+	_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) )
+			break;
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
+			u8 *wpsie;
+			uint	wpsie_len = 0;
+
+			/*	The mac address is matched. */
+
+			wpsie = rtw_get_wps_ie_from_scan_queue(&pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &wpsie_len, pnetwork->network.Reserved[0]);
+			if (wpsie) {
+				rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_PRIMARY_DEV_TYPE, dev_type, &dev_type_len);
+				if (dev_type_len) {
+					u16 type;
+					__be16 be_tmp;
+
+					memcpy(&be_tmp, dev_type, 2);
+					type = be16_to_cpu(be_tmp);
+					sprintf(dev_type_str, "\n\nN=%.2d", type);
+					blnMatch = 1;
+				}
+			}
+			break;
+		}
+
+		plist = get_next(plist);
+
+	}
+
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+	if (!blnMatch)
+		sprintf(dev_type_str, "\n\nN=00");
+
+	wrqu->data.length = strlen(dev_type_str);
+	memcpy(extra, dev_type_str, wrqu->data.length);
+
+	return ret;
+
+}
+
+static int rtw_p2p_get_device_name(struct net_device *dev,
+				   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra, char *subcmd)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 peerMAC[ETH_ALEN] = { 0x00 };
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	unsigned long irqL;
+	_list *plist, *phead;
+	_queue *queue = &(pmlmepriv->scanned_queue);
+	struct wlan_network *pnetwork = NULL;
+	u8 blnMatch = 0;
+	u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = { 0x00 };
+	uint dev_len = 0;
+	u8 dev_name_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
+
+	/*	Commented by Albert 20121225 */
+	/*	The input data is the MAC address which the application wants to know its device name. */
+	/*	Such user interface could show peer device's device name instead of ssid. */
+	/*	Format: iwpriv wlanx p2p_get2 devN=00:E0:4C:00:00:05 */
+
+	RTW_INFO("[%s] data = %s\n", __func__, subcmd);
+
+	macstr2num(peerMAC, subcmd);
+
+	_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) )
+			break;
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
+			u8 *wpsie;
+			uint	wpsie_len = 0;
+
+			/*	The mac address is matched. */
+
+			wpsie = rtw_get_wps_ie_from_scan_queue(&pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &wpsie_len, pnetwork->network.Reserved[0]);
+			if (wpsie) {
+				rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
+				if (dev_len) {
+					sprintf(dev_name_str, "\n\nN=%s", dev_name);
+					blnMatch = 1;
+				}
+			}
+			break;
+		}
+
+		plist = get_next(plist);
+
+	}
+
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+	if (!blnMatch)
+		sprintf(dev_name_str, "\n\nN=0000");
+
+	wrqu->data.length = strlen(dev_name_str);
+	memcpy(extra, dev_name_str, wrqu->data.length);
+
+	return ret;
+
+}
+
+static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra, char *subcmd)
+{
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 peerMAC[ETH_ALEN] = { 0x00 };
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	unsigned long irqL;
+	_list *plist, *phead;
+	_queue *queue	= &(pmlmepriv->scanned_queue);
+	struct wlan_network *pnetwork = NULL;
+	u8 blnMatch = 0;
+	u8 *p2pie;
+	uint p2pielen = 0, attr_contentlen = 0;
+	u8 attr_content[2] = { 0x00 };
+	u8 inv_proc_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
+
+	/*	Commented by Ouden 20121226 */
+	/*	The application wants to know P2P initation procedure is support or not. */
+	/*	Format: iwpriv wlanx p2p_get2 InvProc=00:E0:4C:00:00:05 */
+
+	RTW_INFO("[%s] data = %s\n", __func__, subcmd);
+
+	macstr2num(peerMAC, subcmd);
+
+	_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) )
+			break;
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
+			/*	Commented by Albert 20121226 */
+			/*	Match the device address located in the P2P IE */
+			/*	This is for the case that the P2P device address is not the same as the P2P interface address. */
+
+			p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
+			if (p2pie) {
+				while (p2pie) {
+					/* memset( attr_content, 0x00, 2); */
+					if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_CAPABILITY, attr_content, &attr_contentlen)) {
+						/*	Handle the P2P capability attribute */
+						blnMatch = 1;
+						break;
+
+					}
+
+					/* Get the next P2P IE */
+					p2pie = rtw_get_p2p_ie(p2pie + p2pielen, BSS_EX_TLV_IES_LEN(&pnetwork->network) - (p2pie + p2pielen - BSS_EX_TLV_IES(&pnetwork->network)), NULL, &p2pielen);
+				}
+			}
+		}
+
+		plist = get_next(plist);
+
+	}
+
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+	if (!blnMatch)
+		sprintf(inv_proc_str, "\nIP=-1");
+	else {
+		if ((attr_content[0] & 0x20) == 0x20)
+			sprintf(inv_proc_str, "\nIP=1");
+		else
+			sprintf(inv_proc_str, "\nIP=0");
+	}
+
+	wrqu->data.length = strlen(inv_proc_str);
+	memcpy(extra, inv_proc_str, wrqu->data.length);
+
+	return ret;
+
+}
+
+static int rtw_p2p_connect(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter				*padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+	u8					peerMAC[ETH_ALEN] = { 0x00 };
+	int					jj, kk;
+	u8					peerMACStr[ETH_ALEN * 2] = { 0x00 };
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	unsigned long				irqL;
+	_list					*plist, *phead;
+	_queue				*queue	= &(pmlmepriv->scanned_queue);
+	struct	wlan_network	*pnetwork = NULL;
+	uint					uintPeerChannel = 0;
+
+	/*	Commented by Albert 20110304 */
+	/*	The input data contains two informations. */
+	/*	1. First information is the MAC address which wants to formate with */
+	/*	2. Second information is the WPS PINCode or "pbc" string for push button method */
+	/*	Format: 00:E0:4C:00:00:05 */
+	/*	Format: 00:E0:4C:00:00:05 */
+
+	RTW_INFO("[%s] data = %s\n", __func__, extra);
+
+	if (pwdinfo->p2p_state == P2P_STATE_NONE) {
+		RTW_INFO("[%s] WiFi Direct is disable!\n", __func__);
+		return ret;
+	}
+
+#ifdef CONFIG_INTEL_WIDI
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) ) {
+		RTW_INFO("[%s] WiFi is under survey!\n", __func__);
+		return ret;
+	}
+#endif /* CONFIG_INTEL_WIDI	 */
+
+	if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO)
+		return -1;
+
+	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+		peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
+
+	_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) )
+			break;
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
+			if (pnetwork->network.Configuration.DSConfig != 0)
+				uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+			else if (pwdinfo->nego_req_info.peer_ch != 0)
+				uintPeerChannel = pnetwork->network.Configuration.DSConfig = pwdinfo->nego_req_info.peer_ch;
+			else {
+				/* Unexpected case */
+				uintPeerChannel = 0;
+				RTW_INFO("%s  uintPeerChannel = 0\n", __func__);
+			}
+			break;
+		}
+
+		plist = get_next(plist);
+
+	}
+
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+	if (uintPeerChannel) {
+#ifdef CONFIG_CONCURRENT_MODE
+		if (rtw_mi_check_status(padapter, MI_LINKED))
+			_cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);
+#endif /* CONFIG_CONCURRENT_MODE */
+
+		memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
+		memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
+
+		pwdinfo->nego_req_info.peer_channel_num[0] = uintPeerChannel;
+		memcpy(pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN);
+		pwdinfo->nego_req_info.benable = true;
+
+		_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
+		if (rtw_p2p_state(pwdinfo) != P2P_STATE_GONEGO_OK) {
+			/*	Restore to the listen state if the current p2p state is not nego OK */
+			rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
+		}
+
+		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
+
+#ifdef CONFIG_CONCURRENT_MODE
+		if (rtw_mi_check_status(padapter, MI_LINKED)) {
+			u8 union_ch = rtw_mi_get_union_chan(padapter);
+			u8 union_bw = rtw_mi_get_union_bw(padapter);
+			u8 union_offset = rtw_mi_get_union_offset(padapter);
+			/*	Have to enter the power saving with the AP */
+			set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
+
+			rtw_mi_buddy_issue_nulldata(padapter, NULL, 1, 3, 500);
+		}
+#endif /* CONFIG_CONCURRENT_MODE */
+
+		RTW_INFO("[%s] Start PreTx Procedure!\n", __func__);
+		_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
+#ifdef CONFIG_CONCURRENT_MODE
+		if (rtw_mi_check_status(padapter, MI_LINKED))
+			_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_GO_NEGO_TIMEOUT);
+		else
+			_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT);
+#else
+		_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT);
+#endif /* CONFIG_CONCURRENT_MODE		 */
+
+	} else {
+		RTW_INFO("[%s] Not Found in Scanning Queue~\n", __func__);
+#ifdef CONFIG_INTEL_WIDI
+		_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
+		rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
+		rtw_free_network_queue(padapter, true);
+		/**
+		 * For WiDi, if we can't find candidate device in scanning queue,
+		 * driver will do scanning itself
+		 */
+		_enter_critical_bh(&pmlmepriv->lock, &irqL);
+		rtw_sitesurvey_cmd(padapter, NULL, 0, NULL, 0);
+		_exit_critical_bh(&pmlmepriv->lock, &irqL);
+#endif /* CONFIG_INTEL_WIDI */
+		ret = -1;
+	}
+exit:
+	return ret;
+}
+
+static int rtw_p2p_invite_req(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter					*padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point			*pdata = &wrqu->data;
+	struct wifidirect_info		*pwdinfo = &(padapter->wdinfo);
+	int						jj, kk;
+	u8						peerMACStr[ETH_ALEN * 2] = { 0x00 };
+	struct mlme_priv			*pmlmepriv = &padapter->mlmepriv;
+	_list						*plist, *phead;
+	_queue					*queue	= &(pmlmepriv->scanned_queue);
+	struct	wlan_network		*pnetwork = NULL;
+	uint						uintPeerChannel = 0;
+	u8						attr_content[50] = { 0x00 }, _status = 0;
+	u8						*p2pie;
+	uint						p2pielen = 0, attr_contentlen = 0;
+	unsigned long					irqL;
+	struct tx_invite_req_info	*pinvite_req_info = &pwdinfo->invitereq_info;
+
+	/*	Commented by Albert 20120321 */
+	/*	The input data contains two informations. */
+	/*	1. First information is the P2P device address which you want to send to.	 */
+	/*	2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */
+	/*	Command line sample: iwpriv wlan0 p2p_set invite="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
+	/*	Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */
+
+	RTW_INFO("[%s] data = %s\n", __func__, extra);
+
+	if (wrqu->data.length <=  37) {
+		RTW_INFO("[%s] Wrong format!\n", __func__);
+		return ret;
+	}
+
+	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+		RTW_INFO("[%s] WiFi Direct is disable!\n", __func__);
+		return ret;
+	} else {
+		/*	Reset the content of struct tx_invite_req_info */
+		pinvite_req_info->benable = false;
+		memset(pinvite_req_info->go_bssid, 0x00, ETH_ALEN);
+		memset(pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN);
+		pinvite_req_info->ssidlen = 0x00;
+		pinvite_req_info->operating_ch = pwdinfo->operating_channel;
+		memset(pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN);
+		pinvite_req_info->token = 3;
+	}
+
+	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+		pinvite_req_info->peer_macaddr[jj] = key_2char2num(extra[kk], extra[kk + 1]);
+
+	_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) )
+			break;
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+
+		/*	Commented by Albert 2011/05/18 */
+		/*	Match the device address located in the P2P IE */
+		/*	This is for the case that the P2P device address is not the same as the P2P interface address. */
+
+		p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
+		if (p2pie) {
+			/*	The P2P Device ID attribute is included in the Beacon frame. */
+			/*	The P2P Device Info attribute is included in the probe response frame. */
+
+			if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
+				/*	Handle the P2P Device ID attribute of Beacon first */
+				if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
+					uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+					break;
+				}
+			} else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
+				/*	Handle the P2P Device Info attribute of probe response */
+				if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
+					uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+					break;
+				}
+			}
+
+		}
+
+		plist = get_next(plist);
+
+	}
+
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+#ifdef CONFIG_WFD
+	if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST) && uintPeerChannel) {
+		struct wifi_display_info *pwfd_info = pwdinfo->wfd_info;
+		u8 *wfd_ie;
+		uint wfd_ielen = 0;
+
+		wfd_ie = rtw_bss_ex_get_wfd_ie(&pnetwork->network, NULL, &wfd_ielen);
+		if (wfd_ie) {
+			u8 *wfd_devinfo;
+			uint wfd_devlen;
+
+			RTW_INFO("[%s] Found WFD IE!\n", __func__);
+			wfd_devinfo = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &wfd_devlen);
+			if (wfd_devinfo) {
+				u16	wfd_devinfo_field = 0;
+
+				/*	Commented by Albert 20120319 */
+				/*	The first two bytes are the WFD device information field of WFD device information subelement. */
+				/*	In big endian format. */
+				wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
+				if (wfd_devinfo_field & WFD_DEVINFO_SESSION_AVAIL)
+					pwfd_info->peer_session_avail = true;
+				else
+					pwfd_info->peer_session_avail = false;
+			}
+		}
+
+		if (false == pwfd_info->peer_session_avail) {
+			RTW_INFO("[%s] WFD Session not avaiable!\n", __func__);
+			goto exit;
+		}
+	}
+#endif /* CONFIG_WFD */
+
+	if (uintPeerChannel) {
+#ifdef CONFIG_CONCURRENT_MODE
+		if (rtw_mi_check_status(padapter, MI_LINKED))
+			_cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);
+#endif /* CONFIG_CONCURRENT_MODE */
+
+		/*	Store the GO's bssid */
+		for (jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3)
+			pinvite_req_info->go_bssid[jj] = key_2char2num(extra[kk], extra[kk + 1]);
+
+		/*	Store the GO's ssid */
+		pinvite_req_info->ssidlen = wrqu->data.length - 36;
+		memcpy(pinvite_req_info->go_ssid, &extra[36], (u32) pinvite_req_info->ssidlen);
+		pinvite_req_info->benable = true;
+		pinvite_req_info->peer_ch = uintPeerChannel;
+
+		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ);
+
+#ifdef CONFIG_CONCURRENT_MODE
+		if (rtw_mi_check_status(padapter, MI_LINKED)) {
+			u8 union_ch = rtw_mi_get_union_chan(padapter);
+			u8 union_bw = rtw_mi_get_union_bw(padapter);
+			u8 union_offset = rtw_mi_get_union_offset(padapter);
+			/*	Have to enter the power saving with the AP */
+			set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
+
+			rtw_mi_buddy_issue_nulldata(padapter, NULL, 1, 3, 500);
+		} else
+			set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+#else
+		set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+#endif
+
+		_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
+
+#ifdef CONFIG_CONCURRENT_MODE
+		if (rtw_mi_check_status(padapter, MI_LINKED))
+			_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_INVITE_TIMEOUT);
+		else
+			_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT);
+#else
+		_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT);
+#endif /* CONFIG_CONCURRENT_MODE		 */
+
+
+	} else
+		RTW_INFO("[%s] NOT Found in the Scanning Queue!\n", __func__);
+exit:
+
+	return ret;
+
+}
+
+static int rtw_p2p_set_persistent(struct net_device *dev,
+				  struct iw_request_info *info,
+				  union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter					*padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point			*pdata = &wrqu->data;
+	struct wifidirect_info		*pwdinfo = &(padapter->wdinfo);
+	int						jj, kk;
+	u8						peerMACStr[ETH_ALEN * 2] = { 0x00 };
+	struct mlme_priv			*pmlmepriv = &padapter->mlmepriv;
+	_list						*plist, *phead;
+	_queue					*queue	= &(pmlmepriv->scanned_queue);
+	struct	wlan_network		*pnetwork = NULL;
+	uint						uintPeerChannel = 0;
+	u8						attr_content[50] = { 0x00 }, _status = 0;
+	u8						*p2pie;
+	uint						p2pielen = 0, attr_contentlen = 0;
+	unsigned long					irqL;
+	struct tx_invite_req_info	*pinvite_req_info = &pwdinfo->invitereq_info;
+
+	/*	Commented by Albert 20120328 */
+	/*	The input data is 0 or 1 */
+	/*	0: disable persistent group functionality */
+	/*	1: enable persistent group founctionality */
+
+	RTW_INFO("[%s] data = %s\n", __func__, extra);
+
+	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+		RTW_INFO("[%s] WiFi Direct is disable!\n", __func__);
+		return ret;
+	} else {
+		if (extra[0] == '0')	/*	Disable the persistent group function. */
+			pwdinfo->persistent_supported = false;
+		else if (extra[0] == '1')	/*	Enable the persistent group function. */
+			pwdinfo->persistent_supported = true;
+		else
+			pwdinfo->persistent_supported = false;
+	}
+	printk("[%s] persistent_supported = %d\n", __func__, pwdinfo->persistent_supported);
+
+exit:
+
+	return ret;
+
+}
+
+static int hexstr2bin(const char *hex, u8 *buf, size_t len)
+{
+	size_t i;
+	int a;
+	const char *ipos = hex;
+	u8 *opos = buf;
+
+	for (i = 0; i < len; i++) {
+		a = hex2byte_i(ipos);
+		if (a < 0)
+			return -1;
+		*opos++ = a;
+		ipos += 2;
+	}
+	return 0;
+}
+
+static int uuid_str2bin(const char *str, u8 *bin)
+{
+	const char *pos;
+	u8 *opos;
+
+	pos = str;
+	opos = bin;
+
+	if (hexstr2bin(pos, opos, 4))
+		return -1;
+	pos += 8;
+	opos += 4;
+
+	if (*pos++ != '-' || hexstr2bin(pos, opos, 2))
+		return -1;
+	pos += 4;
+	opos += 2;
+
+	if (*pos++ != '-' || hexstr2bin(pos, opos, 2))
+		return -1;
+	pos += 4;
+	opos += 2;
+
+	if (*pos++ != '-' || hexstr2bin(pos, opos, 2))
+		return -1;
+	pos += 4;
+	opos += 2;
+
+	if (*pos++ != '-' || hexstr2bin(pos, opos, 6))
+		return -1;
+
+	return 0;
+}
+
+static int rtw_p2p_set_wps_uuid(struct net_device *dev,
+				struct iw_request_info *info,
+				union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter				*padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wifidirect_info			*pwdinfo = &(padapter->wdinfo);
+
+	RTW_INFO("[%s] data = %s\n", __func__, extra);
+
+	if ((36 == strlen(extra)) && (uuid_str2bin(extra, pwdinfo->uuid) == 0))
+		pwdinfo->external_uuid = 1;
+	else {
+		pwdinfo->external_uuid = 0;
+		ret = -EINVAL;
+	}
+
+	return ret;
+
+}
+#ifdef CONFIG_WFD
+static int rtw_p2p_set_pc(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter				*padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point		*pdata = &wrqu->data;
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+	u8					peerMAC[ETH_ALEN] = { 0x00 };
+	int					jj, kk;
+	u8					peerMACStr[ETH_ALEN * 2] = { 0x00 };
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	_list					*plist, *phead;
+	_queue				*queue	= &(pmlmepriv->scanned_queue);
+	struct	wlan_network	*pnetwork = NULL;
+	u8					attr_content[50] = { 0x00 }, _status = 0;
+	u8 *p2pie;
+	uint					p2pielen = 0, attr_contentlen = 0;
+	unsigned long				irqL;
+	uint					uintPeerChannel = 0;
+
+	struct wifi_display_info	*pwfd_info = pwdinfo->wfd_info;
+
+	/*	Commented by Albert 20120512 */
+	/*	1. Input information is the MAC address which wants to know the Preferred Connection bit (PC bit) */
+	/*	Format: 00:E0:4C:00:00:05 */
+
+	RTW_INFO("[%s] data = %s\n", __func__, extra);
+
+	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+		RTW_INFO("[%s] WiFi Direct is disable!\n", __func__);
+		return ret;
+	}
+
+	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+		peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
+
+	_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) )
+			break;
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+
+		/*	Commented by Albert 2011/05/18 */
+		/*	Match the device address located in the P2P IE */
+		/*	This is for the case that the P2P device address is not the same as the P2P interface address. */
+
+		p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
+		if (p2pie) {
+			/*	The P2P Device ID attribute is included in the Beacon frame. */
+			/*	The P2P Device Info attribute is included in the probe response frame. */
+			printk("[%s] Got P2P IE\n", __func__);
+			if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
+				/*	Handle the P2P Device ID attribute of Beacon first */
+				printk("[%s] P2P_ATTR_DEVICE_ID\n", __func__);
+				if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
+					uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+					break;
+				}
+			} else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
+				/*	Handle the P2P Device Info attribute of probe response */
+				printk("[%s] P2P_ATTR_DEVICE_INFO\n", __func__);
+				if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
+					uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+					break;
+				}
+			}
+
+		}
+
+		plist = get_next(plist);
+
+	}
+
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+	printk("[%s] channel = %d\n", __func__, uintPeerChannel);
+
+	if (uintPeerChannel) {
+		u8 *wfd_ie;
+		uint wfd_ielen = 0;
+
+		wfd_ie = rtw_bss_ex_get_wfd_ie(&pnetwork->network, NULL, &wfd_ielen);
+		if (wfd_ie) {
+			u8 *wfd_devinfo;
+			uint wfd_devlen;
+
+			RTW_INFO("[%s] Found WFD IE!\n", __func__);
+			wfd_devinfo = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &wfd_devlen);
+			if (wfd_devinfo) {
+				u16	wfd_devinfo_field = 0;
+
+				/*	Commented by Albert 20120319 */
+				/*	The first two bytes are the WFD device information field of WFD device information subelement. */
+				/*	In big endian format. */
+				wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
+				if (wfd_devinfo_field & WFD_DEVINFO_PC_TDLS)
+					pwfd_info->wfd_pc = true;
+				else
+					pwfd_info->wfd_pc = false;
+			}
+		}
+	} else
+		RTW_INFO("[%s] NOT Found in the Scanning Queue!\n", __func__);
+
+exit:
+
+	return ret;
+
+}
+
+static int rtw_p2p_set_wfd_device_type(struct net_device *dev,
+				       struct iw_request_info *info,
+				       union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter					*padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point			*pdata = &wrqu->data;
+	struct wifidirect_info		*pwdinfo = &(padapter->wdinfo);
+	struct wifi_display_info		*pwfd_info = pwdinfo->wfd_info;
+
+	/*	Commented by Albert 20120328 */
+	/*	The input data is 0 or 1 */
+	/*	0: specify to Miracast source device */
+	/*	1 or others: specify to Miracast sink device (display device) */
+
+	RTW_INFO("[%s] data = %s\n", __func__, extra);
+
+	if (extra[0] == '0')	/*	Set to Miracast source device. */
+		pwfd_info->wfd_device_type = WFD_DEVINFO_SOURCE;
+	else					/*	Set to Miracast sink device. */
+		pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
+
+exit:
+
+	return ret;
+
+}
+
+static int rtw_p2p_set_wfd_enable(struct net_device *dev,
+				  struct iw_request_info *info,
+				  union iwreq_data *wrqu, char *extra)
+{
+	/*	Commented by Kurt 20121206
+	 *	This function is used to set wfd enabled */
+
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+
+	if (*extra == '0')
+		rtw_wfd_enable(padapter, 0);
+	else if (*extra == '1')
+		rtw_wfd_enable(padapter, 1);
+
+	RTW_INFO("[%s] wfd_enable = %d\n", __func__, pwdinfo->wfd_info->wfd_enable);
+
+	return ret;
+
+}
+
+static int rtw_p2p_set_driver_iface(struct net_device *dev,
+				    struct iw_request_info *info,
+				    union iwreq_data *wrqu, char *extra)
+{
+	/*	Commented by Kurt 20121206
+	 *	This function is used to set driver iface is WEXT or CFG80211 */
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+
+	if (*extra == '1') {
+		pwdinfo->driver_interface = DRIVER_WEXT;
+		RTW_INFO("[%s] driver_interface = WEXT\n", __func__);
+	} else if (*extra == '2') {
+		pwdinfo->driver_interface = DRIVER_CFG80211;
+		RTW_INFO("[%s] driver_interface = CFG80211\n", __func__);
+	}
+
+	return ret;
+
+}
+
+/*	To set the WFD session available to enable or disable */
+static int rtw_p2p_set_sa(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter					*padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point			*pdata = &wrqu->data;
+	struct wifidirect_info		*pwdinfo = &(padapter->wdinfo);
+	struct wifi_display_info		*pwfd_info = pwdinfo->wfd_info;
+
+	RTW_INFO("[%s] data = %s\n", __func__, extra);
+
+	if (0) {
+		RTW_INFO("[%s] WiFi Direct is disable!\n", __func__);
+		return ret;
+	} else {
+		if (extra[0] == '0')	/*	Disable the session available. */
+			pwdinfo->session_available = false;
+		else if (extra[0] == '1')	/*	Enable the session available. */
+			pwdinfo->session_available = true;
+		else
+			pwdinfo->session_available = false;
+	}
+	printk("[%s] session available = %d\n", __func__, pwdinfo->session_available);
+
+exit:
+
+	return ret;
+
+}
+#endif /* CONFIG_WFD */
+
+static int rtw_p2p_prov_disc(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	_adapter				*padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+	u8					peerMAC[ETH_ALEN] = { 0x00 };
+	int					jj, kk;
+	u8					peerMACStr[ETH_ALEN * 2] = { 0x00 };
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	_list					*plist, *phead;
+	_queue				*queue	= &(pmlmepriv->scanned_queue);
+	struct	wlan_network	*pnetwork = NULL;
+	uint					uintPeerChannel = 0;
+	u8					attr_content[100] = { 0x00 }, _status = 0;
+	u8 *p2pie;
+	uint					p2pielen = 0, attr_contentlen = 0;
+	unsigned long				irqL;
+
+	/*	Commented by Albert 20110301 */
+	/*	The input data contains two informations. */
+	/*	1. First information is the MAC address which wants to issue the provisioning discovery request frame. */
+	/*	2. Second information is the WPS configuration method which wants to discovery */
+	/*	Format: 00:E0:4C:00:00:05_display */
+	/*	Format: 00:E0:4C:00:00:05_keypad */
+	/*	Format: 00:E0:4C:00:00:05_pbc */
+	/*	Format: 00:E0:4C:00:00:05_label */
+
+	RTW_INFO("[%s] data = %s\n", __func__, extra);
+
+	if (pwdinfo->p2p_state == P2P_STATE_NONE) {
+		RTW_INFO("[%s] WiFi Direct is disable!\n", __func__);
+		return ret;
+	} else {
+#ifdef CONFIG_INTEL_WIDI
+		if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) ) {
+			RTW_INFO("[%s] WiFi is under survey!\n", __func__);
+			return ret;
+		}
+#endif /* CONFIG_INTEL_WIDI */
+
+		/*	Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request. */
+		memset(pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN);
+		memset(pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN);
+		memset(&pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof(NDIS_802_11_SSID));
+		pwdinfo->tx_prov_disc_info.peer_channel_num[0] = 0;
+		pwdinfo->tx_prov_disc_info.peer_channel_num[1] = 0;
+		pwdinfo->tx_prov_disc_info.benable = false;
+	}
+
+	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+		peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
+
+	if (!memcmp(&extra[18], "display", 7))
+		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
+	else if (!memcmp(&extra[18], "keypad", 7))
+		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
+	else if (!memcmp(&extra[18], "pbc", 3))
+		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
+	else if (!memcmp(&extra[18], "label", 5))
+		pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
+	else {
+		RTW_INFO("[%s] Unknown WPS config methodn", __func__);
+		return ret ;
+	}
+
+	_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) )
+			break;
+
+		if (uintPeerChannel != 0)
+			break;
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+
+		/*	Commented by Albert 2011/05/18 */
+		/*	Match the device address located in the P2P IE */
+		/*	This is for the case that the P2P device address is not the same as the P2P interface address. */
+
+		p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
+		if (p2pie) {
+			while (p2pie) {
+				/*	The P2P Device ID attribute is included in the Beacon frame. */
+				/*	The P2P Device Info attribute is included in the probe response frame. */
+
+				if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
+					/*	Handle the P2P Device ID attribute of Beacon first */
+					if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
+						uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+						break;
+					}
+				} else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
+					/*	Handle the P2P Device Info attribute of probe response */
+					if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
+						uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+						break;
+					}
+				}
+
+				/* Get the next P2P IE */
+				p2pie = rtw_get_p2p_ie(p2pie + p2pielen, BSS_EX_TLV_IES_LEN(&pnetwork->network) - (p2pie + p2pielen - BSS_EX_TLV_IES(&pnetwork->network)), NULL, &p2pielen);
+			}
+
+		}
+
+#ifdef CONFIG_INTEL_WIDI
+		/* Some Intel WiDi source may not provide P2P IE, */
+		/* so we could only compare mac addr by 802.11 Source Address */
+		if (pmlmepriv->widi_state == INTEL_WIDI_STATE_WFD_CONNECTION
+		    && uintPeerChannel == 0) {
+			if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
+				uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+				break;
+			}
+		}
+#endif /* CONFIG_INTEL_WIDI */
+
+		plist = get_next(plist);
+
+	}
+
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+	if (uintPeerChannel) {
+#ifdef CONFIG_WFD
+		if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
+			struct wifi_display_info *pwfd_info = pwdinfo->wfd_info;
+			u8 *wfd_ie;
+			uint wfd_ielen = 0;
+
+			wfd_ie = rtw_bss_ex_get_wfd_ie(&pnetwork->network, NULL, &wfd_ielen);
+			if (wfd_ie) {
+				u8 *wfd_devinfo;
+				uint wfd_devlen;
+
+				RTW_INFO("[%s] Found WFD IE!\n", __func__);
+				wfd_devinfo = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &wfd_devlen);
+				if (wfd_devinfo) {
+					u16	wfd_devinfo_field = 0;
+
+					/*	Commented by Albert 20120319 */
+					/*	The first two bytes are the WFD device information field of WFD device information subelement. */
+					/*	In big endian format. */
+					wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
+					if (wfd_devinfo_field & WFD_DEVINFO_SESSION_AVAIL)
+						pwfd_info->peer_session_avail = true;
+					else
+						pwfd_info->peer_session_avail = false;
+				}
+			}
+
+			if (false == pwfd_info->peer_session_avail) {
+				RTW_INFO("[%s] WFD Session not avaiable!\n", __func__);
+				goto exit;
+			}
+		}
+#endif /* CONFIG_WFD */
+
+		RTW_INFO("[%s] peer channel: %d!\n", __func__, uintPeerChannel);
+#ifdef CONFIG_CONCURRENT_MODE
+		if (rtw_mi_check_status(padapter, MI_LINKED))
+			_cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);
+#endif /* CONFIG_CONCURRENT_MODE */
+		memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN);
+		memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN);
+		pwdinfo->tx_prov_disc_info.peer_channel_num[0] = (u16) uintPeerChannel;
+		pwdinfo->tx_prov_disc_info.benable = true;
+		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ);
+
+		if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
+			memcpy(&pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof(NDIS_802_11_SSID));
+		else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+			memcpy(pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
+			pwdinfo->tx_prov_disc_info.ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
+		}
+
+#ifdef CONFIG_CONCURRENT_MODE
+		if (rtw_mi_check_status(padapter, MI_LINKED)) {
+			u8 union_ch = rtw_mi_get_union_chan(padapter);
+			u8 union_bw = rtw_mi_get_union_bw(padapter);
+			u8 union_offset = rtw_mi_get_union_offset(padapter);
+
+			/*	Have to enter the power saving with the AP */
+			set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
+
+			rtw_mi_buddy_issue_nulldata(padapter, NULL, 1, 3, 500);
+		} else
+			set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+#else
+		set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+#endif
+
+		_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
+
+#ifdef CONFIG_CONCURRENT_MODE
+		if (rtw_mi_check_status(padapter, MI_LINKED))
+			_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_PROVISION_TIMEOUT);
+		else
+			_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
+#else
+		_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
+#endif /* CONFIG_CONCURRENT_MODE		 */
+
+	} else {
+		RTW_INFO("[%s] NOT Found in the Scanning Queue!\n", __func__);
+#ifdef CONFIG_INTEL_WIDI
+		_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
+		rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
+		rtw_free_network_queue(padapter, true);
+		_enter_critical_bh(&pmlmepriv->lock, &irqL);
+		rtw_sitesurvey_cmd(padapter, NULL, 0, NULL, 0);
+		_exit_critical_bh(&pmlmepriv->lock, &irqL);
+#endif /* CONFIG_INTEL_WIDI */
+	}
+exit:
+
+	return ret;
+
+}
+
+/*	Added by Albert 20110328
+ *	This function is used to inform the driver the user had specified the pin code value or pbc
+ *	to application. */
+
+static int rtw_p2p_got_wpsinfo(struct net_device *dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+	_adapter				*padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+
+
+	RTW_INFO("[%s] data = %s\n", __func__, extra);
+	/*	Added by Albert 20110328 */
+	/*	if the input data is P2P_NO_WPSINFO -> reset the wpsinfo */
+	/*	if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device. */
+	/*	if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself. */
+	/*	if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC */
+
+	if (*extra == '0')
+		pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
+	else if (*extra == '1')
+		pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN;
+	else if (*extra == '2')
+		pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN;
+	else if (*extra == '3')
+		pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC;
+	else
+		pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
+
+	return ret;
+
+}
+
+#endif /* CONFIG_P2P */
+
+static int rtw_p2p_set(struct net_device *dev,
+		       struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+#ifdef CONFIG_P2P
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+
+	RTW_INFO("[%s] extra = %s\n", __func__, extra);
+
+	if (!memcmp(extra, "enable=", 7))
+		rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]);
+	else if (!memcmp(extra, "setDN=", 6)) {
+		wrqu->data.length -= 6;
+		rtw_p2p_setDN(dev, info, wrqu, &extra[6]);
+	} else if (!memcmp(extra, "profilefound=", 13)) {
+		wrqu->data.length -= 13;
+		rtw_p2p_profilefound(dev, info, wrqu, &extra[13]);
+	} else if (!memcmp(extra, "prov_disc=", 10)) {
+		wrqu->data.length -= 10;
+		rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]);
+	} else if (!memcmp(extra, "nego=", 5)) {
+		wrqu->data.length -= 5;
+		rtw_p2p_connect(dev, info, wrqu, &extra[5]);
+	} else if (!memcmp(extra, "intent=", 7)) {
+		/*	Commented by Albert 2011/03/23 */
+		/*	The wrqu->data.length will include the null character */
+		/*	So, we will decrease 7 + 1 */
+		wrqu->data.length -= 8;
+		rtw_p2p_set_intent(dev, info, wrqu, &extra[7]);
+	} else if (!memcmp(extra, "ssid=", 5)) {
+		wrqu->data.length -= 5;
+		rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]);
+	} else if (!memcmp(extra, "got_wpsinfo=", 12)) {
+		wrqu->data.length -= 12;
+		rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]);
+	} else if (!memcmp(extra, "listen_ch=", 10)) {
+		/*	Commented by Albert 2011/05/24 */
+		/*	The wrqu->data.length will include the null character */
+		/*	So, we will decrease (10 + 1)	 */
+		wrqu->data.length -= 11;
+		rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]);
+	} else if (!memcmp(extra, "op_ch=", 6)) {
+		/*	Commented by Albert 2011/05/24 */
+		/*	The wrqu->data.length will include the null character */
+		/*	So, we will decrease (6 + 1)	 */
+		wrqu->data.length -= 7;
+		rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]);
+	} else if (!memcmp(extra, "invite=", 7)) {
+		wrqu->data.length -= 8;
+		rtw_p2p_invite_req(dev, info, wrqu, &extra[7]);
+	} else if (!memcmp(extra, "persistent=", 11)) {
+		wrqu->data.length -= 11;
+		rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]);
+	} else if (!memcmp(extra, "uuid=", 5)) {
+		wrqu->data.length -= 5;
+		ret = rtw_p2p_set_wps_uuid(dev, info, wrqu, &extra[5]);
+	}
+
+#ifdef CONFIG_WFD
+	if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
+		if (!memcmp(extra, "sa=", 3)) {
+			/* sa: WFD Session Available information */
+			wrqu->data.length -= 3;
+			rtw_p2p_set_sa(dev, info, wrqu, &extra[3]);
+		} else if (!memcmp(extra, "pc=", 3)) {
+			/* pc: WFD Preferred Connection */
+			wrqu->data.length -= 3;
+			rtw_p2p_set_pc(dev, info, wrqu, &extra[3]);
+		} else if (!memcmp(extra, "wfd_type=", 9)) {
+			wrqu->data.length -= 9;
+			rtw_p2p_set_wfd_device_type(dev, info, wrqu, &extra[9]);
+		} else if (!memcmp(extra, "wfd_enable=", 11)) {
+			wrqu->data.length -= 11;
+			rtw_p2p_set_wfd_enable(dev, info, wrqu, &extra[11]);
+		} else if (!memcmp(extra, "driver_iface=", 13)) {
+			wrqu->data.length -= 13;
+			rtw_p2p_set_driver_iface(dev, info, wrqu, &extra[13]);
+		}
+	}
+#endif /* CONFIG_WFD */
+
+#endif /* CONFIG_P2P */
+
+	return ret;
+
+}
+
+static int rtw_p2p_get(struct net_device *dev,
+		       struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+#ifdef CONFIG_P2P
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct iw_point *pdata = &wrqu->data;
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+
+	if (padapter->bShowGetP2PState)
+		RTW_INFO("[%s] extra = %s\n", __func__, (char *)wrqu->data.pointer);
+
+	if (!memcmp((__force void *)wrqu->data.pointer, "status", 6))
+		rtw_p2p_get_status(dev, info, wrqu, extra);
+	else if (!memcmp((__force void *)wrqu->data.pointer, "role", 4))
+		rtw_p2p_get_role(dev, info, wrqu, extra);
+	else if (!memcmp((__force void *)wrqu->data.pointer, "peer_ifa", 8))
+		rtw_p2p_get_peer_ifaddr(dev, info, wrqu, extra);
+	else if (!memcmp((__force void *)wrqu->data.pointer, "req_cm", 6))
+		rtw_p2p_get_req_cm(dev, info, wrqu, extra);
+	else if (!memcmp((__force void *)wrqu->data.pointer, "peer_deva", 9)) {
+		/*	Get the P2P device address when receiving the provision discovery request frame. */
+		rtw_p2p_get_peer_devaddr(dev, info, wrqu, extra);
+	} else if (!memcmp((__force void *)wrqu->data.pointer, "group_id", 8))
+		rtw_p2p_get_groupid(dev, info, wrqu, extra);
+	else if (!memcmp((__force void *)wrqu->data.pointer, "inv_peer_deva", 13)) {
+		/*	Get the P2P device address when receiving the P2P Invitation request frame. */
+		rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra);
+	} else if (!memcmp((__force void *)wrqu->data.pointer, "op_ch", 5))
+		rtw_p2p_get_op_ch(dev, info, wrqu, extra);
+
+#ifdef CONFIG_WFD
+	if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
+		if (!memcmp((__force void *)wrqu->data.pointer, "peer_port", 9))
+			rtw_p2p_get_peer_wfd_port(dev, info, wrqu, extra);
+		else if (!memcmp((__force void *)wrqu->data.pointer, "wfd_sa", 6))
+			rtw_p2p_get_peer_wfd_session_available(dev, info, wrqu, extra);
+		else if (!memcmp((__force void *)wrqu->data.pointer, "wfd_pc", 6))
+			rtw_p2p_get_peer_wfd_preferred_connection(dev, info, wrqu, extra);
+	}
+#endif /* CONFIG_WFD */
+
+#endif /* CONFIG_P2P */
+
+	return ret;
+
+}
+
+static int rtw_p2p_get2(struct net_device *dev,
+			struct iw_request_info *info,
+			union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+
+#ifdef CONFIG_P2P
+
+	int length = wrqu->data.length;
+	char *buffer = (u8 *)rtw_malloc(length);
+
+	if (buffer == NULL) {
+		ret = -ENOMEM;
+		goto bad;
+	}
+
+	if (copy_from_user(buffer, wrqu->data.pointer, wrqu->data.length)) {
+		ret = -EFAULT;
+		goto bad;
+	}
+
+	RTW_INFO("[%s] buffer = %s\n", __func__, buffer);
+
+	if (!memcmp(buffer, "wpsCM=", 6))
+		ret = rtw_p2p_get_wps_configmethod(dev, info, wrqu, extra, &buffer[6]);
+	else if (!memcmp(buffer, "devN=", 5))
+		ret = rtw_p2p_get_device_name(dev, info, wrqu, extra, &buffer[5]);
+	else if (!memcmp(buffer, "dev_type=", 9))
+		ret = rtw_p2p_get_device_type(dev, info, wrqu, extra, &buffer[9]);
+	else if (!memcmp(buffer, "go_devadd=", 10))
+		ret = rtw_p2p_get_go_device_address(dev, info, wrqu, extra, &buffer[10]);
+	else if (!memcmp(buffer, "InvProc=", 8))
+		ret = rtw_p2p_get_invitation_procedure(dev, info, wrqu, extra, &buffer[8]);
+	else {
+		snprintf(extra, sizeof("Command not found."), "Command not found.");
+		wrqu->data.length = strlen(extra);
+	}
+
+bad:
+	if (buffer)
+		rtw_mfree(buffer, length);
+
+#endif /* CONFIG_P2P */
+
+	return ret;
+
+}
+
+static int rtw_cta_test_start(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	_adapter	*padapter = (_adapter *)rtw_netdev_priv(dev);
+	RTW_INFO("%s %s\n", __func__, extra);
+	if (!strcmp(extra, "1"))
+		padapter->in_cta_test = 1;
+	else
+		padapter->in_cta_test = 0;
+
+	if (padapter->in_cta_test) {
+		u32 v = rtw_read32(padapter, REG_RCR);
+		v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); /* | RCR_ADF */
+		rtw_write32(padapter, REG_RCR, v);
+		RTW_INFO("enable RCR_ADF\n");
+	} else {
+		u32 v = rtw_read32(padapter, REG_RCR);
+		v |= RCR_CBSSID_DATA | RCR_CBSSID_BCN ;/* | RCR_ADF */
+		rtw_write32(padapter, REG_RCR, v);
+		RTW_INFO("disable RCR_ADF\n");
+	}
+	return ret;
+}
+
+
+static int rtw_rereg_nd_name(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	_adapter *padapter = rtw_netdev_priv(dev);
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
+	char new_ifname[IFNAMSIZ];
+
+	if (rereg_priv->old_ifname[0] == 0) {
+		char *reg_ifname;
+#ifdef CONFIG_CONCURRENT_MODE
+		if (padapter->isprimary)
+			reg_ifname = padapter->registrypriv.ifname;
+		else
+#endif
+			reg_ifname = padapter->registrypriv.if2name;
+
+		strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
+		rereg_priv->old_ifname[IFNAMSIZ - 1] = 0;
+	}
+
+	/* RTW_INFO("%s wrqu->data.length:%d\n", __func__, wrqu->data.length); */
+	if (wrqu->data.length > IFNAMSIZ)
+		return -EFAULT;
+
+	if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ))
+		return -EFAULT;
+
+	if (0 == strcmp(rereg_priv->old_ifname, new_ifname))
+		return ret;
+
+	RTW_INFO("%s new_ifname:%s\n", __func__, new_ifname);
+	rtw_set_rtnl_lock_holder(dvobj, current);
+	ret = rtw_change_ifname(padapter, new_ifname);
+	rtw_set_rtnl_lock_holder(dvobj, NULL);
+	if (0 != ret)
+		goto exit;
+
+	if (!memcmp(rereg_priv->old_ifname, "disable%d", 9) ) {
+		padapter->ledpriv.bRegUseLed = rereg_priv->old_bRegUseLed;
+		rtw_hal_sw_led_init(padapter);
+		/* rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode); */
+	}
+
+	strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
+	rereg_priv->old_ifname[IFNAMSIZ - 1] = 0;
+
+	if (!memcmp(new_ifname, "disable%d", 9) ) {
+
+		RTW_INFO("%s disable\n", __func__);
+		/* free network queue for Android's timming issue */
+		rtw_free_network_queue(padapter, true);
+
+		/* close led */
+		rtw_led_control(padapter, LED_CTL_POWER_OFF);
+		rereg_priv->old_bRegUseLed = padapter->ledpriv.bRegUseLed;
+		padapter->ledpriv.bRegUseLed = false;
+		rtw_hal_sw_led_deinit(padapter);
+
+		/* the interface is being "disabled", we can do deeper IPS */
+		/* rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv); */
+		/* rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL); */
+	}
+exit:
+	return ret;
+
+}
+
+#ifdef CONFIG_IOL
+#include <rtw_iol.h>
+#endif
+
+#ifdef DBG_CMD_QUEUE
+u8 dump_cmd_id = 0;
+#endif
+static int rtw_dbg_port(struct net_device *dev,
+			struct iw_request_info *info,
+			union iwreq_data *wrqu, char *extra)
+{
+	unsigned long irqL;
+	int ret = 0;
+	u8 major_cmd, minor_cmd;
+	u16 arg;
+	u32 extra_arg, *pdata, val32;
+	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 mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+	struct wlan_network *cur_network = &(pmlmepriv->cur_network);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+
+	pdata = (u32 *)&wrqu->data;
+
+	val32 = *pdata;
+	arg = (u16)(val32 & 0x0000ffff);
+	major_cmd = (u8)(val32 >> 24);
+	minor_cmd = (u8)((val32 >> 16) & 0x00ff);
+
+	extra_arg = *(pdata + 1);
+
+	switch (major_cmd) {
+	case 0x70: /* read_reg */
+		switch (minor_cmd) {
+		case 1:
+			RTW_INFO("rtw_read8(0x%x)=0x%02x\n", arg, rtw_read8(padapter, arg));
+			break;
+		case 2:
+			RTW_INFO("rtw_read16(0x%x)=0x%04x\n", arg, rtw_read16(padapter, arg));
+			break;
+		case 4:
+			RTW_INFO("rtw_read32(0x%x)=0x%08x\n", arg, rtw_read32(padapter, arg));
+			break;
+		}
+		break;
+	case 0x71: /* write_reg */
+		switch (minor_cmd) {
+		case 1:
+			rtw_write8(padapter, arg, extra_arg);
+			RTW_INFO("rtw_write8(0x%x)=0x%02x\n", arg, rtw_read8(padapter, arg));
+			break;
+		case 2:
+			rtw_write16(padapter, arg, extra_arg);
+			RTW_INFO("rtw_write16(0x%x)=0x%04x\n", arg, rtw_read16(padapter, arg));
+			break;
+		case 4:
+			rtw_write32(padapter, arg, extra_arg);
+			RTW_INFO("rtw_write32(0x%x)=0x%08x\n", arg, rtw_read32(padapter, arg));
+			break;
+		}
+		break;
+	case 0x72: /* read_bb */
+		RTW_INFO("read_bbreg(0x%x)=0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
+		break;
+	case 0x73: /* write_bb */
+		rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
+		RTW_INFO("write_bbreg(0x%x)=0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
+		break;
+	case 0x74: /* read_rf */
+		RTW_INFO("read RF_reg path(0x%02x),offset(0x%x),value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
+		break;
+	case 0x75: /* write_rf */
+		rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
+		RTW_INFO("write RF_reg path(0x%02x),offset(0x%x),value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
+		break;
+
+	case 0x76:
+		switch (minor_cmd) {
+		case 0x00: /* normal mode, */
+			padapter->recvpriv.is_signal_dbg = 0;
+			break;
+		case 0x01: /* dbg mode */
+			padapter->recvpriv.is_signal_dbg = 1;
+			extra_arg = extra_arg > 100 ? 100 : extra_arg;
+			padapter->recvpriv.signal_strength_dbg = extra_arg;
+			break;
+		}
+		break;
+	case 0x78: /* IOL test */
+		switch (minor_cmd) {
+		#ifdef CONFIG_IOL
+		case 0x04: { /* LLT table initialization test */
+			u8 page_boundary = 0xf9;
+			{
+				struct xmit_frame	*xmit_frame;
+
+				xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
+				if (xmit_frame == NULL) {
+					ret = -ENOMEM;
+					break;
+				}
+
+				rtw_IOL_append_LLT_cmd(xmit_frame, page_boundary);
+
+
+				if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 500, 0))
+					ret = -EPERM;
+			}
+		}
+			break;
+		case 0x05: { /* blink LED test */
+			u16 reg = 0x4c;
+			u32 blink_num = 50;
+			u32 blink_delay_ms = 200;
+			int i;
+
+			{
+				struct xmit_frame	*xmit_frame;
+
+				xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
+				if (xmit_frame == NULL) {
+					ret = -ENOMEM;
+					break;
+				}
+
+				for (i = 0; i < blink_num; i++) {
+					#ifdef CONFIG_IOL_NEW_GENERATION
+					rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00, 0xff);
+					rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
+					rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08, 0xff);
+					rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
+					#else
+					rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00);
+					rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
+					rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08);
+					rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
+					#endif
+				}
+				if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms * blink_num * 2) + 200, 0))
+					ret = -EPERM;
+			}
+		}
+			break;
+
+		case 0x06: { /* continuous wirte byte test */
+			u16 reg = arg;
+			u16 start_value = 0;
+			u32 write_num = extra_arg;
+			int i;
+			u8 final;
+
+			{
+				struct xmit_frame	*xmit_frame;
+
+				xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
+				if (xmit_frame == NULL) {
+					ret = -ENOMEM;
+					break;
+				}
+
+				for (i = 0; i < write_num; i++) {
+					#ifdef CONFIG_IOL_NEW_GENERATION
+					rtw_IOL_append_WB_cmd(xmit_frame, reg, i + start_value, 0xFF);
+					#else
+					rtw_IOL_append_WB_cmd(xmit_frame, reg, i + start_value);
+					#endif
+				}
+				if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
+					ret = -EPERM;
+			}
+
+			final = rtw_read8(padapter, reg);
+			if (start_value + write_num - 1 == final)
+				RTW_INFO("continuous IOL_CMD_WB_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
+			else
+				RTW_INFO("continuous IOL_CMD_WB_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
+		}
+			break;
+
+		case 0x07: { /* continuous wirte word test */
+			u16 reg = arg;
+			u16 start_value = 200;
+			u32 write_num = extra_arg;
+
+			int i;
+			u16 final;
+
+			{
+				struct xmit_frame	*xmit_frame;
+
+				xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
+				if (xmit_frame == NULL) {
+					ret = -ENOMEM;
+					break;
+				}
+
+				for (i = 0; i < write_num; i++) {
+					#ifdef CONFIG_IOL_NEW_GENERATION
+					rtw_IOL_append_WW_cmd(xmit_frame, reg, i + start_value, 0xFFFF);
+					#else
+					rtw_IOL_append_WW_cmd(xmit_frame, reg, i + start_value);
+					#endif
+				}
+				if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
+					ret = -EPERM;
+			}
+
+			final = rtw_read16(padapter, reg);
+			if (start_value + write_num - 1 == final)
+				RTW_INFO("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
+			else
+				RTW_INFO("continuous IOL_CMD_WW_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
+		}
+			break;
+
+		case 0x08: { /* continuous wirte dword test */
+			u16 reg = arg;
+			u32 start_value = 0x110000c7;
+			u32 write_num = extra_arg;
+
+			int i;
+			u32 final;
+
+			{
+				struct xmit_frame	*xmit_frame;
+
+				xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
+				if (xmit_frame == NULL) {
+					ret = -ENOMEM;
+					break;
+				}
+
+				for (i = 0; i < write_num; i++) {
+					#ifdef CONFIG_IOL_NEW_GENERATION
+					rtw_IOL_append_WD_cmd(xmit_frame, reg, i + start_value, 0xFFFFFFFF);
+					#else
+					rtw_IOL_append_WD_cmd(xmit_frame, reg, i + start_value);
+					#endif
+				}
+				if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
+					ret = -EPERM;
+
+			}
+
+			final = rtw_read32(padapter, reg);
+			if (start_value + write_num - 1 == final)
+				RTW_INFO("continuous IOL_CMD_WD_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
+			else
+				RTW_INFO("continuous IOL_CMD_WD_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
+		}
+			break;
+		#endif /* CONFIG_IOL */
+		}
+		break;
+	case 0x79: {
+		/*
+		* dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
+		* dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
+		*/
+		u8 value =  extra_arg & 0x0f;
+		u8 sign = minor_cmd;
+		u16 write_value = 0;
+
+		RTW_INFO("%s set RESP_TXAGC to %s %u\n", __func__, sign ? "minus" : "plus", value);
+
+		if (sign)
+			value = value | 0x10;
+
+		write_value = value | (value << 5);
+		rtw_write16(padapter, 0x6d9, write_value);
+	}
+		break;
+	case 0x7a:
+		receive_disconnect(padapter, pmlmeinfo->network.MacAddress
+				   , WLAN_REASON_EXPIRATION_CHK, false);
+		break;
+	case 0x7F:
+		switch (minor_cmd) {
+		case 0x0:
+			RTW_INFO("fwstate=0x%x\n", get_fwstate(pmlmepriv));
+			break;
+		case 0x01:
+			RTW_INFO("auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n",
+				psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
+				psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
+			break;
+		case 0x02:
+			RTW_INFO("pmlmeinfo->state=0x%x\n", pmlmeinfo->state);
+			RTW_INFO("DrvBcnEarly=%d\n", pmlmeext->DrvBcnEarly);
+			RTW_INFO("DrvBcnTimeOut=%d\n", pmlmeext->DrvBcnTimeOut);
+			break;
+		case 0x03:
+			RTW_INFO("qos_option=%d\n", pmlmepriv->qospriv.qos_option);
+			RTW_INFO("ht_option=%d\n", pmlmepriv->htpriv.ht_option);
+			break;
+		case 0x04:
+			RTW_INFO("cur_ch=%d\n", pmlmeext->cur_channel);
+			RTW_INFO("cur_bw=%d\n", pmlmeext->cur_bwmode);
+			RTW_INFO("cur_ch_off=%d\n", pmlmeext->cur_ch_offset);
+
+			RTW_INFO("oper_ch=%d\n", rtw_get_oper_ch(padapter));
+			RTW_INFO("oper_bw=%d\n", rtw_get_oper_bw(padapter));
+			RTW_INFO("oper_ch_offet=%d\n", rtw_get_oper_choffset(padapter));
+
+			break;
+		case 0x05:
+			psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
+			if (psta) {
+				RTW_INFO("SSID=%s\n", cur_network->network.Ssid.Ssid);
+				RTW_INFO("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
+				RTW_INFO("cur_channel=%d, cur_bwmode=%d, cur_ch_offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
+				RTW_INFO("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
+				RTW_INFO("state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
+				RTW_INFO("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
+				RTW_INFO("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);
+				RTW_INFO("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
+				RTW_INFO("agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
+
+				sta_rx_reorder_ctl_dump(RTW_DBGDUMP, psta);
+			} else
+				RTW_INFO("can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress));
+			break;
+		case 0x06: {
+		}
+			break;
+		case 0x07:
+			RTW_INFO("bSurpriseRemoved=%s, bDriverStopped=%s\n"
+				, rtw_is_surprise_removed(padapter) ? "True" : "False"
+				, rtw_is_drv_stopped(padapter) ? "True" : "False");
+			break;
+		case 0x08: {
+			struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+			struct recv_priv  *precvpriv = &padapter->recvpriv;
+
+			RTW_INFO("free_xmitbuf_cnt=%d, free_xmitframe_cnt=%d"
+				", free_xmit_extbuf_cnt=%d, free_xframe_ext_cnt=%d"
+				 ", free_recvframe_cnt=%d\n",
+				pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt,
+				pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xframe_ext_cnt,
+				 precvpriv->free_recvframe_cnt);
+			RTW_INFO("rx_urb_pending_cn=%d\n", ATOMIC_READ(&(precvpriv->rx_pending_cnt)));
+		}
+			break;
+		case 0x09: {
+			int i;
+			_list	*plist, *phead;
+
+#ifdef CONFIG_AP_MODE
+			RTW_INFO("sta_dz_bitmap=0x%x, tim_bitmap=0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
+#endif
+			_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) {
+						RTW_INFO("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
+						RTW_INFO("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
+						RTW_INFO("state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
+						RTW_INFO("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
+						RTW_INFO("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);
+						RTW_INFO("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
+						RTW_INFO("agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
+
+#ifdef CONFIG_AP_MODE
+						RTW_INFO("capability=0x%x\n", psta->capability);
+						RTW_INFO("flags=0x%x\n", psta->flags);
+						RTW_INFO("wpa_psk=0x%x\n", psta->wpa_psk);
+						RTW_INFO("wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher);
+						RTW_INFO("wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher);
+						RTW_INFO("qos_info=0x%x\n", psta->qos_info);
+#endif
+						RTW_INFO("dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy);
+
+						sta_rx_reorder_ctl_dump(RTW_DBGDUMP, psta);
+					}
+
+				}
+			}
+
+			_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+
+		}
+			break;
+
+		case 0x0b: { /* Enable=1, Disable=0 driver control vrtl_carrier_sense. */
+			/* 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. */
+
+			if (arg == 0) {
+				RTW_INFO("disable driver ctrl vcs\n");
+				padapter->driver_vcs_en = 0;
+			} else if (arg == 1) {
+				RTW_INFO("enable driver ctrl vcs = %d\n", extra_arg);
+				padapter->driver_vcs_en = 1;
+
+				if (extra_arg > 2)
+					padapter->driver_vcs_type = 1;
+				else
+					padapter->driver_vcs_type = extra_arg;
+			}
+		}
+			break;
+		case 0x0c: { /* dump rx/tx packet */
+			if (arg == 0) {
+				RTW_INFO("dump rx packet (%d)\n", extra_arg);
+				/* pHalData->bDumpRxPkt =extra_arg;						 */
+				rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
+			} else if (arg == 1) {
+				RTW_INFO("dump tx packet (%d)\n", extra_arg);
+				rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
+			}
+		}
+			break;
+		case 0x0e: {
+			if (arg == 0) {
+				RTW_INFO("disable driver ctrl rx_ampdu_factor\n");
+				padapter->driver_rx_ampdu_factor = 0xFF;
+			} else if (arg == 1) {
+
+				RTW_INFO("enable driver ctrl rx_ampdu_factor = %d\n", extra_arg);
+
+				if (extra_arg > 0x03)
+					padapter->driver_rx_ampdu_factor = 0xFF;
+				else
+					padapter->driver_rx_ampdu_factor = extra_arg;
+			}
+		}
+			break;
+		#ifdef DBG_CONFIG_ERROR_DETECT
+		case 0x0f: {
+			if (extra_arg == 0) {
+				RTW_INFO("###### silent reset test.......#####\n");
+				rtw_hal_sreset_reset(padapter);
+			} else {
+				HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+				struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+				psrtpriv->dbg_trigger_point = extra_arg;
+			}
+
+		}
+			break;
+		case 0x15: {
+			struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+			RTW_INFO("==>silent resete cnts:%d\n", pwrpriv->ips_enter_cnts);
+		}
+			break;
+
+		#endif
+
+		case 0x10: /* driver version display */
+			dump_drv_version(RTW_DBGDUMP);
+			break;
+		case 0x11: { /* dump linked status */
+			int pre_mode;
+			pre_mode = padapter->bLinkInfoDump;
+			/* linked_info_dump(padapter,extra_arg); */
+			if (extra_arg == 1 || (extra_arg == 0 && pre_mode == 1)) /* not consider pwr_saving 0: */
+				padapter->bLinkInfoDump = extra_arg;
+
+			else if ((extra_arg == 2) || (extra_arg == 0 && pre_mode == 2)) { /* consider power_saving */
+				/* RTW_INFO("linked_info_dump =%s\n", (padapter->bLinkInfoDump)?"enable":"disable") */
+				linked_info_dump(padapter, extra_arg);
+			}
+
+
+
+		}
+			break;
+		case 0x12: { /* set rx_stbc */
+			struct registry_priv	*pregpriv = &padapter->registrypriv;
+			/* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */
+			/* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
+			if (pregpriv && (extra_arg == 0 || extra_arg == 1 || extra_arg == 2 || extra_arg == 3)) {
+				pregpriv->rx_stbc = extra_arg;
+				RTW_INFO("set rx_stbc=%d\n", pregpriv->rx_stbc);
+			} else
+				RTW_INFO("get rx_stbc=%d\n", pregpriv->rx_stbc);
+
+		}
+			break;
+		case 0x13: { /* set ampdu_enable */
+			struct registry_priv	*pregpriv = &padapter->registrypriv;
+			/* 0: disable, 0x1:enable */
+			if (pregpriv && extra_arg < 2) {
+				pregpriv->ampdu_enable = extra_arg;
+				RTW_INFO("set ampdu_enable=%d\n", pregpriv->ampdu_enable);
+			} else
+				RTW_INFO("get ampdu_enable=%d\n", pregpriv->ampdu_enable);
+
+		}
+			break;
+		case 0x14: { /* get wifi_spec */
+			struct registry_priv	*pregpriv = &padapter->registrypriv;
+			RTW_INFO("get wifi_spec=%d\n", pregpriv->wifi_spec);
+
+		}
+			break;
+
+#ifdef DBG_FIXED_CHAN
+		case 0x17: {
+			struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+			printk("===>  Fixed channel to %d\n", extra_arg);
+			pmlmeext->fixed_chan = extra_arg;
+
+		}
+			break;
+#endif
+		case 0x19: {
+			struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+			/* extra_arg : */
+			/* BIT0: Enable VHT LDPC Rx, BIT1: Enable VHT LDPC Tx, */
+			/* BIT4: Enable HT LDPC Rx, BIT5: Enable HT LDPC Tx */
+			if (arg == 0) {
+				RTW_INFO("driver disable LDPC\n");
+				pregistrypriv->ldpc_cap = 0x00;
+			} else if (arg == 1) {
+				RTW_INFO("driver set LDPC cap = 0x%x\n", extra_arg);
+				pregistrypriv->ldpc_cap = (u8)(extra_arg & 0x33);
+			}
+		}
+			break;
+		case 0x1a: {
+			struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+			/* extra_arg : */
+			/* BIT0: Enable VHT STBC Rx, BIT1: Enable VHT STBC Tx, */
+			/* BIT4: Enable HT STBC Rx, BIT5: Enable HT STBC Tx */
+			if (arg == 0) {
+				RTW_INFO("driver disable STBC\n");
+				pregistrypriv->stbc_cap = 0x00;
+			} else if (arg == 1) {
+				RTW_INFO("driver set STBC cap = 0x%x\n", extra_arg);
+				pregistrypriv->stbc_cap = (u8)(extra_arg & 0x33);
+			}
+		}
+			break;
+		case 0x1b: {
+			struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+
+			if (arg == 0) {
+				RTW_INFO("disable driver ctrl max_rx_rate, reset to default_rate_set\n");
+				init_mlme_default_rate_set(padapter);
+				pregistrypriv->ht_enable = (u8)rtw_ht_enable;
+			} else if (arg == 1) {
+
+				int i;
+				u8 max_rx_rate;
+
+				RTW_INFO("enable driver ctrl max_rx_rate = 0x%x\n", extra_arg);
+
+				max_rx_rate = (u8)extra_arg;
+
+				if (max_rx_rate < 0xc) { /* max_rx_rate < MSC0->B or G -> disable HT */
+					pregistrypriv->ht_enable = 0;
+					for (i = 0; i < NumRates; i++) {
+						if (pmlmeext->datarate[i] > max_rx_rate)
+							pmlmeext->datarate[i] = 0xff;
+					}
+
+				} else if (max_rx_rate < 0x1c) { /* mcs0~mcs15 */
+					u32 mcs_bitmap = 0x0;
+
+					for (i = 0; i < ((max_rx_rate + 1) - 0xc); i++)
+						mcs_bitmap |= BIT(i);
+
+					set_mcs_rate_by_mask(pmlmeext->default_supported_mcs_set, mcs_bitmap);
+				}
+			}
+		}
+			break;
+		case 0x1c: { /* enable/disable driver control AMPDU Density for peer sta's rx */
+			if (arg == 0) {
+				RTW_INFO("disable driver ctrl ampdu density\n");
+				padapter->driver_ampdu_spacing = 0xFF;
+			} else if (arg == 1) {
+
+				RTW_INFO("enable driver ctrl ampdu density = %d\n", extra_arg);
+
+				if (extra_arg > 0x07)
+					padapter->driver_ampdu_spacing = 0xFF;
+				else
+					padapter->driver_ampdu_spacing = extra_arg;
+			}
+		}
+			break;
+#ifdef CONFIG_BACKGROUND_NOISE_MONITOR
+		case 0x1e: {
+			HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+			struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv;
+			u8 chan = rtw_get_oper_ch(padapter);
+			RTW_INFO("===========================================\n");
+			odm_inband_noise_monitor(pDM_Odm, true, 0x1e, 100);
+			RTW_INFO("channel(%d),noise_a = %d, noise_b = %d , noise_all:%d\n",
+				chan, pDM_Odm->noise_level.noise[ODM_RF_PATH_A],
+				pDM_Odm->noise_level.noise[ODM_RF_PATH_B],
+				 pDM_Odm->noise_level.noise_all);
+			RTW_INFO("===========================================\n");
+
+		}
+			break;
+#endif
+
+
+		case 0x20:
+			{
+				if (arg == 0xAA) {
+					u8 page_offset, page_num;
+					u32 page_size = 0;
+					u8 *buffer = NULL;
+					u32 buf_size = 0;
+
+					page_offset = (u8)(extra_arg >> 16);
+					page_num = (u8)(extra_arg & 0xFF);
+					rtw_dump_rsvd_page(RTW_DBGDUMP, padapter, page_offset, page_num);
+				}
+#ifdef CONFIG_SUPPORT_FIFO_DUMP
+				else {
+					u8 fifo_sel;
+					u32 addr, size;
+					u8 *buffer = NULL;
+
+					fifo_sel = (u8)(arg & 0x0F);
+					addr = (extra_arg >> 16) & 0xFFFF;
+					size = extra_arg & 0xFFFF;
+
+					RTW_INFO("fifo_sel:%d, start_addr:0x%04x, size:%d\n", fifo_sel, addr, size);
+					if (size) {
+						size = RND4(size);
+						buffer = rtw_zvmalloc(size);
+						if (NULL == buffer)
+							size = 0;
+					}
+					rtw_halmac_dump_fifo(adapter_to_dvobj(padapter), fifo_sel, addr, size, buffer);
+					if (buffer)
+						rtw_vmfree(buffer, size);
+				}
+#endif
+			}
+			break;
+
+		case 0x23: {
+			RTW_INFO("turn %s the bNotifyChannelChange Variable\n", (extra_arg == 1) ? "on" : "off");
+			padapter->bNotifyChannelChange = extra_arg;
+			break;
+		}
+		case 0x24: {
+#ifdef CONFIG_P2P
+			RTW_INFO("turn %s the bShowGetP2PState Variable\n", (extra_arg == 1) ? "on" : "off");
+			padapter->bShowGetP2PState = extra_arg;
+#endif /* CONFIG_P2P */
+			break;
+		}
+#ifdef CONFIG_GPIO_API
+		case 0x25: { /* Get GPIO register */
+			/*
+			* dbg 0x7f250000 [gpio_num], Get gpio value, gpio_num:0~7
+			*/
+
+			u8 value;
+			RTW_INFO("Read GPIO Value  extra_arg = %d\n", extra_arg);
+			value = rtw_hal_get_gpio(padapter, extra_arg);
+			RTW_INFO("Read GPIO Value = %d\n", value);
+			break;
+		}
+		case 0x26: { /* Set GPIO direction */
+
+			/* dbg 0x7f26000x [y], Set gpio direction,
+			* x: gpio_num,4~7  y: indicate direction, 0~1
+			*/
+
+			int value;
+			RTW_INFO("Set GPIO Direction! arg = %d ,extra_arg=%d\n", arg , extra_arg);
+			value = rtw_hal_config_gpio(padapter, arg, extra_arg);
+			RTW_INFO("Set GPIO Direction %s\n", (value == -1) ? "Fail!!!" : "Success");
+			break;
+		}
+		case 0x27: { /* Set GPIO output direction value */
+			/*
+			* dbg 0x7f27000x [y], Set gpio output direction value,
+			* x: gpio_num,4~7  y: indicate direction, 0~1
+			*/
+
+			int value;
+			RTW_INFO("Set GPIO Value! arg = %d ,extra_arg=%d\n", arg , extra_arg);
+			value = rtw_hal_set_gpio_output_value(padapter, arg, extra_arg);
+			RTW_INFO("Set GPIO Value %s\n", (value == -1) ? "Fail!!!" : "Success");
+			break;
+		}
+#endif
+#ifdef DBG_CMD_QUEUE
+		case 0x28: {
+			dump_cmd_id = extra_arg;
+			RTW_INFO("dump_cmd_id:%d\n", dump_cmd_id);
+		}
+			break;
+#endif /* DBG_CMD_QUEUE */
+		case 0xaa: {
+			if ((extra_arg & 0x7F) > 0x3F)
+				extra_arg = 0xFF;
+			RTW_INFO("chang data rate to :0x%02x\n", extra_arg);
+			padapter->fix_rate = extra_arg;
+		}
+			break;
+		case 0xdd: { /* registers dump , 0 for mac reg,1 for bb reg, 2 for rf reg */
+			if (extra_arg == 0)
+				mac_reg_dump(RTW_DBGDUMP, padapter);
+			else if (extra_arg == 1)
+				bb_reg_dump(RTW_DBGDUMP, padapter);
+			else if (extra_arg == 2)
+				rf_reg_dump(RTW_DBGDUMP, padapter);
+			else if (extra_arg == 11)
+				bb_reg_dump_ex(RTW_DBGDUMP, padapter);
+		}
+			break;
+
+		case 0xee: {
+			RTW_INFO(" === please control /proc  to trun on/off PHYDM func ===\n");
+		}
+			break;
+
+		case 0xfd:
+			rtw_write8(padapter, 0xc50, arg);
+			RTW_INFO("wr(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
+			rtw_write8(padapter, 0xc58, arg);
+			RTW_INFO("wr(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
+			break;
+		case 0xfe:
+			RTW_INFO("rd(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
+			RTW_INFO("rd(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
+			break;
+		case 0xff: {
+			RTW_INFO("dbg(0x210)=0x%x\n", rtw_read32(padapter, 0x210));
+			RTW_INFO("dbg(0x608)=0x%x\n", rtw_read32(padapter, 0x608));
+			RTW_INFO("dbg(0x280)=0x%x\n", rtw_read32(padapter, 0x280));
+			RTW_INFO("dbg(0x284)=0x%x\n", rtw_read32(padapter, 0x284));
+			RTW_INFO("dbg(0x288)=0x%x\n", rtw_read32(padapter, 0x288));
+
+			RTW_INFO("dbg(0x664)=0x%x\n", rtw_read32(padapter, 0x664));
+
+
+			RTW_INFO("\n");
+
+			RTW_INFO("dbg(0x430)=0x%x\n", rtw_read32(padapter, 0x430));
+			RTW_INFO("dbg(0x438)=0x%x\n", rtw_read32(padapter, 0x438));
+
+			RTW_INFO("dbg(0x440)=0x%x\n", rtw_read32(padapter, 0x440));
+
+			RTW_INFO("dbg(0x458)=0x%x\n", rtw_read32(padapter, 0x458));
+
+			RTW_INFO("dbg(0x484)=0x%x\n", rtw_read32(padapter, 0x484));
+			RTW_INFO("dbg(0x488)=0x%x\n", rtw_read32(padapter, 0x488));
+
+			RTW_INFO("dbg(0x444)=0x%x\n", rtw_read32(padapter, 0x444));
+			RTW_INFO("dbg(0x448)=0x%x\n", rtw_read32(padapter, 0x448));
+			RTW_INFO("dbg(0x44c)=0x%x\n", rtw_read32(padapter, 0x44c));
+			RTW_INFO("dbg(0x450)=0x%x\n", rtw_read32(padapter, 0x450));
+		}
+			break;
+		}
+		break;
+	default:
+		RTW_INFO("error dbg cmd!\n");
+		break;
+	}
+
+
+	return ret;
+
+}
+
+static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
+{
+	uint ret = 0;
+	u32 flags;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	switch (name) {
+	case IEEE_PARAM_WPA_ENABLED:
+
+		padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
+
+		/* ret = ieee80211_wpa_enable(ieee, value); */
+
+		switch ((value) & 0xff) {
+		case 1: /* WPA */
+			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
+			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
+			break;
+		case 2: /* WPA2 */
+			padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
+			padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
+			break;
+		}
+
+
+		break;
+
+	case IEEE_PARAM_TKIP_COUNTERMEASURES:
+		/* ieee->tkip_countermeasures=value; */
+		break;
+
+	case IEEE_PARAM_DROP_UNENCRYPTED: {
+		/* HACK:
+		 *
+		 * wpa_supplicant calls set_wpa_enabled when the driver
+		 * is loaded and unloaded, regardless of if WPA is being
+		 * used.  No other calls are made which can be used to
+		 * determine if encryption will be used or not prior to
+		 * association being expected.  If encryption is not being
+		 * used, drop_unencrypted is set to false, else true -- we
+		 * can use this to determine if the CAP_PRIVACY_ON bit should
+		 * be set.
+		 */
+		break;
+	}
+	case IEEE_PARAM_PRIVACY_INVOKED:
+		break;
+	case IEEE_PARAM_AUTH_ALGS:
+		ret = wpa_set_auth_algs(dev, value);
+		break;
+	case IEEE_PARAM_IEEE_802_1X:
+		break;
+	case IEEE_PARAM_WPAX_SELECT:
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+	return ret;
+}
+
+static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
+{
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	switch (command) {
+	case IEEE_MLME_STA_DEAUTH:
+
+		if (!rtw_set_802_11_disassociate(padapter))
+			ret = -1;
+
+		break;
+
+	case IEEE_MLME_STA_DISASSOC:
+
+		if (!rtw_set_802_11_disassociate(padapter))
+			ret = -1;
+
+		break;
+
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+
+}
+
+static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
+{
+	struct ieee_param *param;
+	uint ret = 0;
+
+	/* down(&ieee->wx_sem);	 */
+
+	if (!p->pointer || p->length != sizeof(struct ieee_param))
+		return -EINVAL;
+
+	param = (struct ieee_param *)rtw_malloc(p->length);
+	if (param == NULL)
+		return -ENOMEM;
+
+	if (copy_from_user(param, p->pointer, p->length)) {
+		rtw_mfree((u8 *)param, p->length);
+		return -EFAULT;
+	}
+
+	switch (param->cmd) {
+
+	case IEEE_CMD_SET_WPA_PARAM:
+		ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
+		break;
+
+	case IEEE_CMD_SET_WPA_IE:
+		/* ret = wpa_set_wpa_ie(dev, param, p->length); */
+		ret =  rtw_set_wpa_ie((_adapter *)rtw_netdev_priv(dev), (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
+		break;
+
+	case IEEE_CMD_SET_ENCRYPTION:
+		ret = wpa_set_encryption(dev, param, p->length);
+		break;
+
+	case IEEE_CMD_MLME:
+		ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
+		break;
+
+	default:
+		RTW_INFO("Unknown WPA supplicant request: %d\n", param->cmd);
+		ret = -EOPNOTSUPP;
+		break;
+
+	}
+
+	if (ret == 0 && copy_to_user(p->pointer, param, p->length))
+		ret = -EFAULT;
+
+	rtw_mfree((u8 *)param, p->length);
+	return ret;
+}
+
+#ifdef CONFIG_AP_MODE
+static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
+{
+	int ret = 0;
+	u32 wep_key_idx, wep_key_len, wep_total_len;
+	NDIS_802_11_WEP	*pwep = NULL;
+	struct sta_info *psta = NULL, *pbcmc_sta = NULL;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct security_priv *psecuritypriv = &(padapter->securitypriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	RTW_INFO("%s\n", __func__);
+
+	param->u.crypt.err = 0;
+	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+	/* sizeof(struct ieee_param) = 64 bytes; */
+	/* if (param_len !=  (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) */
+	if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
+		ret =  -EINVAL;
+		goto exit;
+	}
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		if (param->u.crypt.idx >= WEP_KEYS
+#ifdef CONFIG_IEEE80211W
+		    && param->u.crypt.idx > BIP_MAX_KEYID
+#endif /* CONFIG_IEEE80211W */
+		   ) {
+			ret = -EINVAL;
+			goto exit;
+		}
+	} else {
+		psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+		if (!psta) {
+			/* ret = -EINVAL; */
+			RTW_INFO("rtw_set_encryption(), sta has already been removed or never been added\n");
+			goto exit;
+		}
+	}
+
+	if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
+		/* todo:clear default encryption keys */
+
+		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+		psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
+		psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+		psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+
+		RTW_INFO("clear default encryption keys, keyid=%d\n", param->u.crypt.idx);
+
+		goto exit;
+	}
+
+
+	if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
+		RTW_INFO("r871x_set_encryption, crypt.alg = WEP\n");
+
+		wep_key_idx = param->u.crypt.idx;
+		wep_key_len = param->u.crypt.key_len;
+
+		RTW_INFO("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
+
+		if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
+			ret = -EINVAL;
+			goto exit;
+		}
+
+
+		if (wep_key_len > 0) {
+			wep_key_len = wep_key_len <= 5 ? 5 : 13;
+			wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
+			pwep = (NDIS_802_11_WEP *)rtw_malloc(wep_total_len);
+			if (pwep == NULL) {
+				RTW_INFO(" r871x_set_encryption: pwep allocate fail !!!\n");
+				goto exit;
+			}
+
+			memset(pwep, 0, wep_total_len);
+
+			pwep->KeyLength = wep_key_len;
+			pwep->Length = wep_total_len;
+
+		}
+
+		pwep->KeyIndex = wep_key_idx;
+
+		memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
+
+		if (param->u.crypt.set_tx) {
+			RTW_INFO("wep, set_tx=1\n");
+
+			psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
+			psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
+			psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+			psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+			if (pwep->KeyLength == 13) {
+				psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+				psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+			}
+
+
+			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
+
+			memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
+
+			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+
+			rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 1);
+		} else {
+			RTW_INFO("wep, set_tx=0\n");
+
+			/* don't update "psecuritypriv->dot11PrivacyAlgrthm" and  */
+			/* "psecuritypriv->dot11PrivacyKeyIndex=keyid", but can rtw_set_key to cam */
+
+			memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
+
+			psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+
+			rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 0);
+		}
+
+		goto exit;
+
+	}
+
+
+	if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) /*  */ { /* group key */
+		if (param->u.crypt.set_tx == 1) {
+			if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+				RTW_INFO("%s, set group_key, WEP\n", __func__);
+
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+				psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+				if (param->u.crypt.key_len == 13)
+					psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+
+			} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+				RTW_INFO("%s, set group_key, TKIP\n", __func__);
+
+				psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+				/* DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len); */
+				/* set mic key */
+				memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
+				memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
+
+				psecuritypriv->busetkipkey = true;
+
+			} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+				RTW_INFO("%s, set group_key, CCMP\n", __func__);
+
+				psecuritypriv->dot118021XGrpPrivacy = _AES_;
+
+				memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+			}
+#ifdef CONFIG_IEEE80211W
+			else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
+				int no;
+
+				RTW_INFO("BIP key_len=%d , index=%d\n", param->u.crypt.key_len, param->u.crypt.idx);
+				/* save the IGTK key, length 16 bytes */
+				memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+				/* RTW_INFO("IGTK key below:\n");
+				for(no=0;no<16;no++)
+					printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
+				RTW_INFO("\n"); */
+				padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
+				padapter->securitypriv.binstallBIPkey = true;
+				RTW_INFO(" ~~~~set sta key:IGKT\n");
+				goto exit;
+			}
+#endif /* CONFIG_IEEE80211W */
+			else {
+				RTW_INFO("%s, set group_key, none\n", __func__);
+
+				psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+			}
+
+			psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
+
+			psecuritypriv->binstallGrpkey = true;
+
+			psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* !!! */
+
+			rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
+
+			pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+			if (pbcmc_sta) {
+				pbcmc_sta->ieee8021x_blocked = false;
+				pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy			 */
+			}
+
+		}
+
+		goto exit;
+
+	}
+
+	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
+		if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+			if (param->u.crypt.set_tx == 1) {
+				memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+					RTW_INFO("%s, set pairwise key, WEP\n", __func__);
+
+					psta->dot118021XPrivacy = _WEP40_;
+					if (param->u.crypt.key_len == 13)
+						psta->dot118021XPrivacy = _WEP104_;
+				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+					RTW_INFO("%s, set pairwise key, TKIP\n", __func__);
+
+					psta->dot118021XPrivacy = _TKIP_;
+
+					/* DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len); */
+					/* set mic key */
+					memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
+					memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
+
+					psecuritypriv->busetkipkey = true;
+
+				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+
+					RTW_INFO("%s, set pairwise key, CCMP\n", __func__);
+
+					psta->dot118021XPrivacy = _AES_;
+				} else {
+					RTW_INFO("%s, set pairwise key, none\n", __func__);
+
+					psta->dot118021XPrivacy = _NO_PRIVACY_;
+				}
+
+				rtw_ap_set_pairwise_key(padapter, psta);
+
+				psta->ieee8021x_blocked = false;
+
+				psta->bpairwise_key_installed = true;
+
+			} else { /* group key??? */
+				if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+					psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+					if (param->u.crypt.key_len == 13)
+						psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+				} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+					psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+					/* DEBUG_ERR("set key length :param->u.crypt.key_len=%d\n", param->u.crypt.key_len); */
+					/* set mic key */
+					memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
+					memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
+
+					psecuritypriv->busetkipkey = true;
+
+				} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+					psecuritypriv->dot118021XGrpPrivacy = _AES_;
+
+					memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+				} else
+					psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+
+				psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
+
+				psecuritypriv->binstallGrpkey = true;
+
+				psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* !!! */
+
+				rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
+
+				pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+				if (pbcmc_sta) {
+					pbcmc_sta->ieee8021x_blocked = false;
+					pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy			 */
+				}
+
+			}
+
+		}
+
+	}
+
+exit:
+
+	if (pwep)
+		rtw_mfree((u8 *)pwep, wep_total_len);
+
+	return ret;
+
+}
+
+static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
+{
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	unsigned char *pbuf = param->u.bcn_ie.buf;
+
+
+	RTW_INFO("%s, len=%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
+
+	if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
+		pstapriv->max_num_sta = NUM_STA;
+
+
+	if (rtw_check_beacon_data(padapter, pbuf, (len - 12 - 2)) == _SUCCESS) /* 12 = param header, 2:no packed */
+		ret = 0;
+	else
+		ret = -EINVAL;
+
+
+	return ret;
+
+}
+
+static int rtw_hostapd_sta_flush(struct net_device *dev)
+{
+	/* unsigned long irqL; */
+	/* _list	*phead, *plist; */
+	int ret = 0;
+	/* struct sta_info *psta = NULL; */
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	/* struct sta_priv *pstapriv = &padapter->stapriv; */
+
+	RTW_INFO("%s\n", __func__);
+
+	flush_all_cam_entry(padapter);	/* clear CAM */
+
+	ret = rtw_sta_flush(padapter, true);
+
+	return ret;
+
+}
+
+static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
+{
+	unsigned long irqL;
+	int ret = 0;
+	struct sta_info *psta = NULL;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	RTW_INFO("rtw_add_sta(aid=%d)=" MAC_FMT "\n", param->u.add_sta.aid, MAC_ARG(param->sta_addr));
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true)
+		return -EINVAL;
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
+		return -EINVAL;
+
+	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+	if (psta) {
+		int flags = param->u.add_sta.flags;
+
+		/* RTW_INFO("rtw_add_sta(), init sta's variables, psta=%p\n", psta); */
+
+		psta->aid = param->u.add_sta.aid;/* aid=1~2007 */
+
+		memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
+
+
+		/* check 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;
+
+		/* chec 802.11n ht cap. */
+		if (WLAN_STA_HT & flags) {
+			psta->htpriv.ht_option = true;
+			psta->qos_option = 1;
+			memcpy((void *)&psta->htpriv.ht_cap, (void *)&param->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
+		} else
+			psta->htpriv.ht_option = false;
+
+		if (pmlmepriv->htpriv.ht_option == false)
+			psta->htpriv.ht_option = false;
+
+		update_sta_info_apmode(padapter, psta);
+
+
+	} else
+		ret = -ENOMEM;
+
+	return ret;
+
+}
+
+static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
+{
+	unsigned long irqL;
+	int ret = 0;
+	struct sta_info *psta = NULL;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	RTW_INFO("rtw_del_sta=" MAC_FMT "\n", MAC_ARG(param->sta_addr));
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true)
+		return -EINVAL;
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
+		return -EINVAL;
+
+	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+	if (psta) {
+		u8 updated = false;
+
+		/* RTW_INFO("free psta=%p, aid=%d\n", psta, psta->aid); */
+
+		_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+		if (list_empty(&psta->asoc_list) == false) {
+			list_del_init(&psta->asoc_list);
+			pstapriv->asoc_list_cnt--;
+			updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING, true);
+
+		}
+		_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+		associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);
+
+		psta = NULL;
+
+	} else {
+		RTW_INFO("rtw_del_sta(), sta has already been removed or never been added\n");
+
+		/* ret = -1; */
+	}
+
+
+	return ret;
+
+}
+
+static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
+{
+	int ret = 0;
+	struct sta_info *psta = NULL;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
+	struct sta_data *psta_data = (struct sta_data *)param_ex->data;
+
+	RTW_INFO("rtw_ioctl_get_sta_info, sta_addr: " MAC_FMT "\n", MAC_ARG(param_ex->sta_addr));
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true)
+		return -EINVAL;
+
+	if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
+	    param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
+	    param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff)
+		return -EINVAL;
+
+	psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
+	if (psta) {
+		psta_data->aid = (u16)psta->aid;
+		psta_data->capability = psta->capability;
+		psta_data->flags = psta->flags;
+
+		/*
+				nonerp_set : BIT(0)
+				no_short_slot_time_set : BIT(1)
+				no_short_preamble_set : BIT(2)
+				no_ht_gf_set : BIT(3)
+				no_ht_set : BIT(4)
+				ht_20mhz_set : BIT(5)
+		*/
+
+		psta_data->sta_set = ((psta->nonerp_set) |
+				      (psta->no_short_slot_time_set << 1) |
+				      (psta->no_short_preamble_set << 2) |
+				      (psta->no_ht_gf_set << 3) |
+				      (psta->no_ht_set << 4) |
+				      (psta->ht_20mhz_set << 5));
+
+		psta_data->tx_supp_rates_len =  psta->bssratelen;
+		memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
+		memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
+		psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
+		psta_data->rx_bytes = psta->sta_stats.rx_bytes;
+		psta_data->rx_drops = psta->sta_stats.rx_drops;
+
+		psta_data->tx_pkts = psta->sta_stats.tx_pkts;
+		psta_data->tx_bytes = psta->sta_stats.tx_bytes;
+		psta_data->tx_drops = psta->sta_stats.tx_drops;
+	} else
+		ret = -1;
+
+	return ret;
+
+}
+
+static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
+{
+	int ret = 0;
+	struct sta_info *psta = NULL;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	RTW_INFO("rtw_get_sta_wpaie, sta_addr: " MAC_FMT "\n", MAC_ARG(param->sta_addr));
+
+	if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true)
+		return -EINVAL;
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
+		return -EINVAL;
+
+	psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+	if (psta) {
+		if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) {
+			int wpa_ie_len;
+			int copy_len;
+
+			wpa_ie_len = psta->wpa_ie[1];
+
+			copy_len = ((wpa_ie_len + 2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)) : (wpa_ie_len + 2);
+
+			param->u.wpa_ie.len = copy_len;
+
+			memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
+		} else {
+			/* ret = -1; */
+			RTW_INFO("sta's wpa_ie is NONE\n");
+		}
+	} else
+		ret = -1;
+
+	return ret;
+
+}
+
+static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
+{
+	int ret = 0;
+	unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	int ie_len;
+
+	RTW_INFO("%s, len=%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
+
+
+	if (pmlmepriv->wps_beacon_ie) {
+		rtw_mfree(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len);
+		pmlmepriv->wps_beacon_ie = NULL;
+	}
+
+	if (ie_len > 0) {
+		pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
+		pmlmepriv->wps_beacon_ie_len = ie_len;
+		if (pmlmepriv->wps_beacon_ie == NULL) {
+			RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+
+		memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
+
+		update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
+
+		pmlmeext->bstart_bss = true;
+
+	}
+
+
+	return ret;
+
+}
+
+static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
+{
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	int ie_len;
+
+	RTW_INFO("%s, len=%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
+
+
+	if (pmlmepriv->wps_probe_resp_ie) {
+		rtw_mfree(pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len);
+		pmlmepriv->wps_probe_resp_ie = NULL;
+	}
+
+	if (ie_len > 0) {
+		pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
+		pmlmepriv->wps_probe_resp_ie_len = ie_len;
+		if (pmlmepriv->wps_probe_resp_ie == NULL) {
+			RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+		memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
+	}
+
+
+	return ret;
+
+}
+
+static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
+{
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	int ie_len;
+
+	RTW_INFO("%s, len=%d\n", __func__, len);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
+
+
+	if (pmlmepriv->wps_assoc_resp_ie) {
+		rtw_mfree(pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
+		pmlmepriv->wps_assoc_resp_ie = NULL;
+	}
+
+	if (ie_len > 0) {
+		pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
+		pmlmepriv->wps_assoc_resp_ie_len = ie_len;
+		if (pmlmepriv->wps_assoc_resp_ie == NULL) {
+			RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+
+		memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
+	}
+
+
+	return ret;
+
+}
+
+static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
+{
+	int ret = 0;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *mlmepriv = &(adapter->mlmepriv);
+	struct mlme_ext_priv	*mlmeext = &(adapter->mlmeextpriv);
+	struct mlme_ext_info	*mlmeinfo = &(mlmeext->mlmext_info);
+	int ie_len;
+	u8 *ssid_ie;
+	char ssid[NDIS_802_11_LENGTH_SSID + 1];
+	sint ssid_len = 0;
+	u8 ignore_broadcast_ssid;
+
+	if (check_fwstate(mlmepriv, WIFI_AP_STATE) != true)
+		return -EPERM;
+
+	if (param->u.bcn_ie.reserved[0] != 0xea)
+		return -EINVAL;
+
+	mlmeinfo->hidden_ssid_mode = ignore_broadcast_ssid = param->u.bcn_ie.reserved[1];
+
+	ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
+	ssid_ie = rtw_get_ie(param->u.bcn_ie.buf,  WLAN_EID_SSID, &ssid_len, ie_len);
+
+	if (ssid_ie && ssid_len > 0 && ssid_len <= NDIS_802_11_LENGTH_SSID) {
+		WLAN_BSSID_EX *pbss_network = &mlmepriv->cur_network.network;
+		WLAN_BSSID_EX *pbss_network_ext = &mlmeinfo->network;
+
+		memcpy(ssid, ssid_ie + 2, ssid_len);
+		ssid[ssid_len] = 0x0;
+
+		if (0)
+			RTW_INFO(FUNC_ADPT_FMT" ssid:(%s,%d), from ie:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
+				ssid, ssid_len,
+				pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
+				pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
+
+		memcpy(pbss_network->Ssid.Ssid, (void *)ssid, ssid_len);
+		pbss_network->Ssid.SsidLength = ssid_len;
+		memcpy(pbss_network_ext->Ssid.Ssid, (void *)ssid, ssid_len);
+		pbss_network_ext->Ssid.SsidLength = ssid_len;
+
+		if (0)
+			RTW_INFO(FUNC_ADPT_FMT" after ssid:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
+				pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
+				pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
+	}
+
+	RTW_INFO(FUNC_ADPT_FMT" ignore_broadcast_ssid:%d, %s,%d\n", FUNC_ADPT_ARG(adapter),
+		ignore_broadcast_ssid, ssid, ssid_len);
+
+	return ret;
+}
+
+#if CONFIG_RTW_MACADDR_ACL
+static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
+{
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
+		return -EINVAL;
+
+	ret = rtw_acl_remove_sta(padapter, param->sta_addr);
+
+	return ret;
+
+}
+
+static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
+{
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
+		return -EINVAL;
+
+	ret = rtw_acl_add_sta(padapter, param->sta_addr);
+
+	return ret;
+
+}
+
+static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
+{
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
+		return -EINVAL;
+
+	rtw_set_macaddr_acl(padapter, param->u.mlme.command);
+
+	return ret;
+}
+#endif /* CONFIG_RTW_MACADDR_ACL */
+
+static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
+{
+	struct ieee_param *param;
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	/* RTW_INFO("%s\n", __func__); */
+
+	/*
+	* this function is expect to call in master mode, which allows no power saving
+	* so, we just check hw_init_completed
+	*/
+
+	if (!rtw_is_hw_init_completed(padapter))
+		return -EPERM;
+
+	if (!p->pointer || p->length != sizeof(struct ieee_param))
+		return -EINVAL;
+
+	param = (struct ieee_param *)rtw_malloc(p->length);
+	if (param == NULL)
+		return -ENOMEM;
+
+	if (copy_from_user(param, p->pointer, p->length)) {
+		rtw_mfree((u8 *)param, p->length);
+		return -EFAULT;
+	}
+
+	switch (param->cmd) {
+	case RTL871X_HOSTAPD_FLUSH:
+
+		ret = rtw_hostapd_sta_flush(dev);
+
+		break;
+
+	case RTL871X_HOSTAPD_ADD_STA:
+
+		ret = rtw_add_sta(dev, param);
+
+		break;
+
+	case RTL871X_HOSTAPD_REMOVE_STA:
+
+		ret = rtw_del_sta(dev, param);
+
+		break;
+
+	case RTL871X_HOSTAPD_SET_BEACON:
+
+		ret = rtw_set_beacon(dev, param, p->length);
+
+		break;
+
+	case RTL871X_SET_ENCRYPTION:
+
+		ret = rtw_set_encryption(dev, param, p->length);
+
+		break;
+
+	case RTL871X_HOSTAPD_GET_WPAIE_STA:
+
+		ret = rtw_get_sta_wpaie(dev, param);
+
+		break;
+
+	case RTL871X_HOSTAPD_SET_WPS_BEACON:
+
+		ret = rtw_set_wps_beacon(dev, param, p->length);
+
+		break;
+
+	case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
+
+		ret = rtw_set_wps_probe_resp(dev, param, p->length);
+
+		break;
+
+	case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
+
+		ret = rtw_set_wps_assoc_resp(dev, param, p->length);
+
+		break;
+
+	case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
+
+		ret = rtw_set_hidden_ssid(dev, param, p->length);
+
+		break;
+
+	case RTL871X_HOSTAPD_GET_INFO_STA:
+
+		ret = rtw_ioctl_get_sta_data(dev, param, p->length);
+
+		break;
+
+#if CONFIG_RTW_MACADDR_ACL
+	case RTL871X_HOSTAPD_SET_MACADDR_ACL:
+		ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
+		break;
+	case RTL871X_HOSTAPD_ACL_ADD_STA:
+		ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
+		break;
+	case RTL871X_HOSTAPD_ACL_REMOVE_STA:
+		ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
+		break;
+#endif /* CONFIG_RTW_MACADDR_ACL */
+
+	default:
+		RTW_INFO("Unknown hostapd request: %d\n", param->cmd);
+		ret = -EOPNOTSUPP;
+		break;
+
+	}
+
+	if (ret == 0 && copy_to_user(p->pointer, param, p->length))
+		ret = -EFAULT;
+
+
+	rtw_mfree((u8 *)param, p->length);
+
+	return ret;
+}
+#endif
+
+static int rtw_wx_set_priv(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *awrq,
+			   char *extra)
+{
+
+#ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
+	char *ext_dbg;
+#endif
+
+	int ret = 0;
+	int len = 0;
+	char *ext;
+	int i;
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_point *dwrq = (struct iw_point *)awrq;
+
+	if (dwrq->length == 0)
+		return -EFAULT;
+
+	len = dwrq->length;
+	ext = vmalloc(len);
+	if (!ext)
+		return -ENOMEM;
+
+	if (copy_from_user(ext, dwrq->pointer, len)) {
+		rtw_vmfree(ext, len);
+		return -EFAULT;
+	}
+
+
+
+#ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
+	ext_dbg = vmalloc(len);
+	if (!ext_dbg) {
+		rtw_vmfree(ext, len);
+		return -ENOMEM;
+	}
+
+	memcpy(ext_dbg, ext, len);
+#endif
+
+	/* added for wps2.0 @20110524 */
+	if (dwrq->flags == 0x8766 && len > 8) {
+		u32 cp_sz;
+		struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+		u8 *probereq_wpsie = ext;
+		int probereq_wpsie_len = len;
+		u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+
+		if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
+		    (!memcmp(&probereq_wpsie[2], wps_oui, 4) )) {
+			cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
+
+			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;
+			}
+
+			pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
+			if (pmlmepriv->wps_probe_req_ie == NULL) {
+				printk("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+				ret =  -EINVAL;
+				goto FREE_EXT;
+
+			}
+
+			memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
+			pmlmepriv->wps_probe_req_ie_len = cp_sz;
+
+		}
+
+		goto FREE_EXT;
+
+	}
+
+	if (len >= WEXT_CSCAN_HEADER_SIZE
+		&& !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE) 
+	) {
+		ret = rtw_wx_set_scan(dev, info, awrq, ext);
+		goto FREE_EXT;
+	}
+
+#ifdef CONFIG_ANDROID
+	/* RTW_INFO("rtw_wx_set_priv: %s req=%s\n", dev->name, ext); */
+
+	i = rtw_android_cmdstr_to_num(ext);
+
+	switch (i) {
+	case ANDROID_WIFI_CMD_START:
+		indicate_wx_custom_event(padapter, "START");
+		break;
+	case ANDROID_WIFI_CMD_STOP:
+		indicate_wx_custom_event(padapter, "STOP");
+		break;
+	case ANDROID_WIFI_CMD_RSSI: {
+		struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+		struct	wlan_network	*pcur_network = &pmlmepriv->cur_network;
+
+		if (check_fwstate(pmlmepriv, _FW_LINKED) )
+			sprintf(ext, "%s rssi %d", pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
+		else
+			sprintf(ext, "OK");
+	}
+		break;
+	case ANDROID_WIFI_CMD_LINKSPEED: {
+		u16 mbps = rtw_get_cur_max_rate(padapter) / 10;
+		sprintf(ext, "LINKSPEED %d", mbps);
+	}
+		break;
+	case ANDROID_WIFI_CMD_MACADDR:
+		sprintf(ext, "MACADDR = " MAC_FMT, MAC_ARG(dev->dev_addr));
+		break;
+	case ANDROID_WIFI_CMD_SCAN_ACTIVE: {
+		/* rtw_set_scan_mode(padapter, SCAN_ACTIVE); */
+		sprintf(ext, "OK");
+	}
+		break;
+	case ANDROID_WIFI_CMD_SCAN_PASSIVE: {
+		/* rtw_set_scan_mode(padapter, SCAN_PASSIVE); */
+		sprintf(ext, "OK");
+	}
+		break;
+
+	case ANDROID_WIFI_CMD_COUNTRY: {
+		char country_code[10];
+		sscanf(ext, "%*s %s", country_code);
+		rtw_set_country(padapter, country_code);
+		sprintf(ext, "OK");
+	}
+		break;
+	default:
+		#ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
+		RTW_INFO("%s: %s unknowned req=%s\n", __func__,
+			dev->name, ext_dbg);
+		#endif
+
+		sprintf(ext, "OK");
+
+	}
+
+	if (copy_to_user(dwrq->pointer, ext, min(dwrq->length, (u16)(strlen(ext) + 1))))
+		ret = -EFAULT;
+
+#ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
+	RTW_INFO("%s: %s req=%s rep=%s dwrq->length=%d, strlen(ext)+1=%d\n", __func__,
+		dev->name, ext_dbg , ext, dwrq->length, (u16)(strlen(ext) + 1));
+#endif
+#endif /* end of CONFIG_ANDROID */
+
+
+FREE_EXT:
+
+	rtw_vmfree(ext, len);
+	#ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
+	rtw_vmfree(ext_dbg, len);
+	#endif
+
+	/* RTW_INFO("rtw_wx_set_priv: (SIOCSIWPRIV) %s ret=%d\n",  */
+	/*		dev->name, ret); */
+
+	return ret;
+
+}
+#ifdef CONFIG_WOWLAN
+static int rtw_wowlan_ctrl(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wowlan_ioctl_param poidparam;
+	struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct sta_info	*psta = NULL;
+	int ret = 0;
+	u32 start_time = jiffies;
+	poidparam.subcode = 0;
+
+	RTW_INFO("+rtw_wowlan_ctrl: %s\n", extra);
+
+	if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
+	    check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+#ifdef CONFIG_PNO_SUPPORT
+		pwrctrlpriv->wowlan_pno_enable = true;
+#else
+		RTW_INFO("[%s] WARNING: Please Connect With AP First!!\n", __func__);
+		goto _rtw_wowlan_ctrl_exit_free;
+#endif /* CONFIG_PNO_SUPPORT */
+	}
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
+		rtw_scan_abort(padapter);
+
+	if (!memcmp(extra, "enable", 6))
+
+
+		rtw_suspend_common(padapter);
+
+	else if (!memcmp(extra, "disable", 7)) {
+		RTW_ENABLE_FUNC(padapter, DF_RX_BIT);
+		RTW_ENABLE_FUNC(padapter, DF_TX_BIT);
+		rtw_resume_common(padapter);
+
+#ifdef CONFIG_PNO_SUPPORT
+		pwrctrlpriv->wowlan_pno_enable = false;
+#endif /* CONFIG_PNO_SUPPORT */
+
+	} else {
+		RTW_INFO("[%s] Invalid Parameter.\n", __func__);
+		goto _rtw_wowlan_ctrl_exit_free;
+	}
+	/* mutex_lock(&ioctl_mutex); */
+_rtw_wowlan_ctrl_exit_free:
+	RTW_INFO("-rtw_wowlan_ctrl( subcode = %d)\n", poidparam.subcode);
+	RTW_INFO("%s in %d ms\n", __func__,
+		  rtw_get_passing_time_ms(start_time));
+_rtw_wowlan_ctrl_exit:
+	return ret;
+}
+
+/*
+ * IP filter This pattern if for a frame containing a ip packet:
+ * AA:AA:AA:AA:AA:AA:BB:BB:BB:BB:BB:BB:CC:CC:DD:-:-:-:-:-:-:-:-:EE:-:-:FF:FF:FF:FF:GG:GG:GG:GG:HH:HH:II:II
+ *
+ * A: Ethernet destination address
+ * B: Ethernet source address
+ * C: Ethernet protocol type
+ * D: IP header VER+Hlen, use: 0x45 (4 is for ver 4, 5 is for len 20)
+ * E: IP protocol
+ * F: IP source address ( 192.168.0.4: C0:A8:00:2C )
+ * G: IP destination address ( 192.168.0.4: C0:A8:00:2C )
+ * H: Source port (1024: 04:00)
+ * I: Destination port (1024: 04:00)
+ */
+
+static int rtw_wowlan_set_pattern(struct net_device *dev,
+				  struct iw_request_info *info,
+				  union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct wowlan_ioctl_param poidparam;
+	int ret = 0, len = 0, i = 0;
+	u32 start_time = jiffies;
+	u8 input[wrqu->data.length];
+	u8 index = 0;
+
+	poidparam.subcode = 0;
+
+	if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
+	    check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+		ret = -EFAULT;
+		RTW_INFO("Please Connect With AP First!!\n");
+		goto _rtw_wowlan_set_pattern_exit;
+	}
+
+	if (wrqu->data.length <= 0) {
+		ret = -EFAULT;
+		RTW_INFO("ERROR: parameter length <= 0\n");
+		goto _rtw_wowlan_set_pattern_exit;
+	} else {
+		/* set pattern */
+		if (copy_from_user(input,
+				   wrqu->data.pointer, wrqu->data.length))
+			return -EFAULT;
+		/* leave PS first */
+		rtw_ps_deny(padapter, PS_DENY_IOCTL);
+		LeaveAllPowerSaveModeDirect(padapter);
+		if (strncmp(input, "pattern=", 8) == 0) {
+			if (pwrpriv->wowlan_pattern_idx >= MAX_WKFM_CAM_NUM) {
+				RTW_INFO("WARNING: priv-pattern is full(idx: %d)\n",
+					 pwrpriv->wowlan_pattern_idx);
+				RTW_INFO("WARNING: please clean priv-pattern first\n");
+				ret = -EINVAL;
+				goto _rtw_wowlan_set_pattern_exit;
+			} else {
+				index = pwrpriv->wowlan_pattern_idx;
+				ret = rtw_wowlan_parser_pattern_cmd(input,
+					    pwrpriv->patterns[index].content,
+					    &pwrpriv->patterns[index].len,
+					    pwrpriv->patterns[index].mask);
+
+				if (ret )
+					pwrpriv->wowlan_pattern_idx++;
+			}
+		} else if (strncmp(input, "clean", 5) == 0) {
+			poidparam.subcode = WOWLAN_PATTERN_CLEAN;
+			rtw_hal_set_hwreg(padapter,
+					  HW_VAR_WOWLAN, (u8 *)&poidparam);
+		} else if (strncmp(input, "show", 4) == 0) {
+			rtw_wow_pattern_cam_dump(padapter);
+			rtw_wow_pattern_sw_dump(padapter);
+		} else {
+			RTW_INFO("ERROR: incorrect parameter!\n");
+			ret = -EINVAL;
+		}
+		rtw_ps_deny_cancel(padapter, PS_DENY_IOCTL);
+	}
+_rtw_wowlan_set_pattern_exit:
+	return ret;
+}
+#endif /* CONFIG_WOWLAN */
+
+#ifdef CONFIG_AP_WOWLAN
+static int rtw_ap_wowlan_ctrl(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wowlan_ioctl_param poidparam;
+	struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct sta_info	*psta = NULL;
+	int ret = 0;
+	u32 start_time = jiffies;
+	poidparam.subcode = 0;
+
+	RTW_INFO("+rtw_ap_wowlan_ctrl: %s\n", extra);
+
+	if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+		RTW_INFO("[%s] It is not AP mode!!\n", __func__);
+		goto _rtw_ap_wowlan_ctrl_exit_free;
+	}
+
+	if (!memcmp(extra, "enable", 6)) {
+
+		pwrctrlpriv->wowlan_ap_mode = true;
+
+		rtw_suspend_common(padapter);
+	} else if (!memcmp(extra, "disable", 7)) {
+		RTW_ENABLE_FUNC(padapter, DF_RX_BIT);
+		RTW_ENABLE_FUNC(padapter, DF_TX_BIT);
+		rtw_resume_common(padapter);
+	} else {
+		RTW_INFO("[%s] Invalid Parameter.\n", __func__);
+		goto _rtw_ap_wowlan_ctrl_exit_free;
+	}
+	/* mutex_lock(&ioctl_mutex); */
+_rtw_ap_wowlan_ctrl_exit_free:
+	RTW_INFO("-rtw_ap_wowlan_ctrl( subcode = %d)\n", poidparam.subcode);
+	RTW_INFO("%s in %d ms\n", __func__,
+		  rtw_get_passing_time_ms(start_time));
+_rtw_ap_wowlan_ctrl_exit:
+	return ret;
+}
+#endif /* CONFIG_AP_WOWLAN */
+
+static int rtw_pm_set(struct net_device *dev,
+		      struct iw_request_info *info,
+		      union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	unsigned	mode = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	RTW_INFO("[%s] extra = %s\n", __func__, extra);
+
+	if (!memcmp(extra, "lps=", 4)) {
+		sscanf(extra + 4, "%u", &mode);
+		ret = rtw_pm_set_lps(padapter, mode);
+	} else if (!memcmp(extra, "ips=", 4)) {
+		sscanf(extra + 4, "%u", &mode);
+		ret = rtw_pm_set_ips(padapter, mode);
+	} else
+		ret = -EINVAL;
+
+	return ret;
+}
+#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
+
+int rtw_vendor_ie_get_data(struct net_device *dev, int vendor_ie_num, char *extra)
+{
+	int j;
+	char *pstring;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	u32 vendor_ie_mask = 0;
+	__u16 length = 0;
+
+	vendor_ie_mask = pmlmepriv->vendor_ie_mask[vendor_ie_num];
+	pstring = extra;
+	pstring += sprintf(pstring , "\nVendor IE num %d , Mask:%x " , vendor_ie_num , vendor_ie_mask);
+
+	if (vendor_ie_mask & WIFI_BEACON_VENDOR_IE_BIT)
+		pstring += sprintf(pstring , "[Beacon]");
+	if (vendor_ie_mask & WIFI_PROBEREQ_VENDOR_IE_BIT)
+		pstring += sprintf(pstring , "[Probe Req]");
+	if (vendor_ie_mask & WIFI_PROBERESP_VENDOR_IE_BIT)
+		pstring += sprintf(pstring , "[Probe Resp]");
+	if (vendor_ie_mask & WIFI_ASSOCREQ_VENDOR_IE_BIT)
+		pstring += sprintf(pstring , "[Assoc Req]");
+	if (vendor_ie_mask & WIFI_ASSOCRESP_VENDOR_IE_BIT)
+		pstring += sprintf(pstring , "[Assoc Resp]");
+
+	pstring += sprintf(pstring , "\nVendor IE:\n");
+	for (j = 0 ; j < pmlmepriv->vendor_ielen[vendor_ie_num]  ; j++)
+		pstring += sprintf(pstring , "%02x" , pmlmepriv->vendor_ie[vendor_ie_num][j]);
+
+	length = pstring - extra;
+	return length;
+
+}
+
+int rtw_vendor_ie_get(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0, vendor_ie_num = 0, cmdlen;
+	struct iw_point *p;
+	u8 *ptmp;
+
+	p = &wrqu->data;
+	cmdlen = p->length;
+	if (0 == cmdlen)
+		return -EINVAL;
+
+	ptmp = (u8 *)rtw_malloc(cmdlen);
+	if (NULL == ptmp)
+		return -ENOMEM;
+
+	if (copy_from_user(ptmp, p->pointer, cmdlen)) {
+		ret = -EFAULT;
+		goto exit;
+	}
+	ret = sscanf(ptmp , "%d", &vendor_ie_num);
+	if (vendor_ie_num > WLAN_MAX_VENDOR_IE_NUM - 1) {
+		ret = -EFAULT;
+		goto exit;
+	}
+
+	wrqu->data.length = rtw_vendor_ie_get_data(dev, vendor_ie_num, extra);
+
+exit:
+	rtw_mfree(ptmp, cmdlen);
+
+	return 0;
+}
+
+int rtw_vendor_ie_set(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0, i , len = 0 , totoal_ie_len = 0 , total_ie_len_byte = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	u32 vendor_ie_mask = 0;
+	u32 vendor_ie_num = 0;
+	u32 id, elen;
+
+	ret = sscanf(extra, "%d,%x,%*s", &vendor_ie_num , &vendor_ie_mask);
+	if (strrchr(extra , ','))
+		extra = strrchr(extra , ',') + 1;
+	else
+		return -EINVAL;
+	totoal_ie_len = strlen(extra);
+	RTW_INFO("[%s] vendor_ie_num = %d , vendor_ie_mask = %x , vendor_ie = %s , len = %d\n", __func__ , vendor_ie_num , vendor_ie_mask , extra  , totoal_ie_len);
+
+	if (vendor_ie_num  > WLAN_MAX_VENDOR_IE_NUM - 1) {
+		RTW_INFO("[%s] only support %d vendor ie\n", __func__ , WLAN_MAX_VENDOR_IE_NUM);
+		return -EFAULT;
+	}
+
+	if (totoal_ie_len > WLAN_MAX_VENDOR_IE_LEN) {
+		RTW_INFO("[%s] Fail , not support ie length extend %d\n", __func__ , WLAN_MAX_VENDOR_IE_LEN);
+		return -EFAULT;
+	}
+
+	if (vendor_ie_mask == 0) {
+		RTW_INFO("[%s] Clear vendor_ie_num %d group\n", __func__ , vendor_ie_num);
+		goto _clear_path;
+	}
+
+	if (totoal_ie_len % 2 != 0) {
+		RTW_INFO("[%s]  Fail , IE length = %zu is odd\n" , __func__ , strlen(extra));
+		return -EFAULT;
+	}
+
+	if (totoal_ie_len > 0) {
+		for (i = 0  ; i < strlen(extra) ; i += 2) {
+			pmlmepriv->vendor_ie[vendor_ie_num][len] = key_2char2num(extra[i] , extra[i + 1]);
+			if (len == 0) {
+				id = pmlmepriv->vendor_ie[vendor_ie_num][len];
+				if (id != WLAN_EID_VENDOR_SPECIFIC) {
+					RTW_INFO("[%s] Fail , VENDOR SPECIFIC IE ID \"%x\" was not correct\n", __func__ , id);
+					goto _clear_path;
+				}
+			} else if (len == 1) {
+				total_ie_len_byte = (totoal_ie_len / 2) - 2;
+				elen = pmlmepriv->vendor_ie[vendor_ie_num][len];
+				if (elen != total_ie_len_byte) {
+					RTW_INFO("[%s] Fail , Input IE length = \"%d\"(hex:%x) bytes , not match input total IE context length \"%d\" bytes\n", __func__ , elen , elen ,
+						 total_ie_len_byte);
+					goto _clear_path;
+				}
+			}
+			len++;
+		}
+		pmlmepriv->vendor_ielen[vendor_ie_num] = len;
+	} else
+		pmlmepriv->vendor_ielen[vendor_ie_num] = 0;
+
+
+
+	if (vendor_ie_mask & WIFI_BEACON_VENDOR_IE_BIT)
+		RTW_INFO("[%s] Beacon append vendor ie\n", __func__);
+	if (vendor_ie_mask & WIFI_PROBEREQ_VENDOR_IE_BIT)
+		RTW_INFO("[%s] Probe Req append vendor ie\n", __func__);
+	if (vendor_ie_mask & WIFI_PROBERESP_VENDOR_IE_BIT)
+		RTW_INFO("[%s] Probe Resp  append vendor ie\n", __func__);
+	if (vendor_ie_mask & WIFI_ASSOCREQ_VENDOR_IE_BIT)
+		RTW_INFO("[%s] Assoc Req append vendor ie\n", __func__);
+	if (vendor_ie_mask & WIFI_ASSOCRESP_VENDOR_IE_BIT)
+		RTW_INFO("[%s] Assoc Resp append vendor ie\n", __func__);
+
+	pmlmepriv->vendor_ie_mask[vendor_ie_num] = vendor_ie_mask;
+
+	return ret;
+
+_clear_path:
+	memset(pmlmepriv->vendor_ie[vendor_ie_num] , 0 , sizeof(u32) * WLAN_MAX_VENDOR_IE_LEN);
+	pmlmepriv->vendor_ielen[vendor_ie_num] = 0;
+	pmlmepriv->vendor_ie_mask[vendor_ie_num] = 0;
+	return -EFAULT;
+}
+#endif
+
+static int rtw_mp_efuse_get(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wdata, char *extra)
+{
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+
+	PEFUSE_HAL pEfuseHal;
+	struct iw_point *wrqu;
+
+	u8	*PROMContent = pHalData->efuse_eeprom_data;
+	u8 ips_mode = IPS_NUM; /* init invalid value */
+	u8 lps_mode = PS_MODE_NUM; /* init invalid value */
+	struct pwrctrl_priv *pwrctrlpriv ;
+	u8 *data = NULL;
+	u8 *rawdata = NULL;
+	char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL};
+	u16 i = 0, j = 0, mapLen = 0, addr = 0, cnts = 0;
+	u16 max_available_len = 0, raw_cursize = 0, raw_maxsize = 0;
+	u16 mask_len;
+	u8 mask_buf[64] = "";
+	int err;
+#ifdef CONFIG_IOL
+	u8 org_fw_iol = padapter->registrypriv.fw_iol;/* 0:Disable, 1:enable, 2:by usb speed */
+#endif
+
+	wrqu = (struct iw_point *)wdata;
+	pwrctrlpriv = adapter_to_pwrctl(padapter);
+	pEfuseHal = &pHalData->EfuseHal;
+
+	err = 0;
+	data = rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
+	if (data == NULL) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	rawdata = rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
+	if (rawdata == NULL) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	if (copy_from_user(extra, wrqu->pointer, wrqu->length)) {
+		err = -EFAULT;
+		goto exit;
+	}
+#ifdef CONFIG_LPS
+	lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
+	rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
+#endif
+
+#ifdef CONFIG_IPS
+	ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
+	rtw_pm_set_ips(padapter, IPS_NONE);
+#endif
+
+	pch = extra;
+	RTW_INFO("%s: in=%s\n", __func__, extra);
+
+	i = 0;
+	/* mac 16 "00e04c871200" rmap,00,2 */
+	while ((token = strsep(&pch, ",")) != NULL) {
+		if (i > 2)
+			break;
+		tmp[i] = token;
+		i++;
+	}
+#ifdef CONFIG_IOL
+	padapter->registrypriv.fw_iol = 0;/* 0:Disable, 1:enable, 2:by usb speed */
+#endif
+
+	if (strcmp(tmp[0], "status") == 0) {
+		sprintf(extra, "Load File efuse=%s,Load File MAC=%s"
+			, pHalData->efuse_file_status == EFUSE_FILE_FAILED ? "FAIL" : "OK"
+			, pHalData->macaddr_file_status == MACADDR_FILE_FAILED ? "FAIL" : "OK"
+		       );
+		goto exit;
+	} else if (strcmp(tmp[0], "drvmap") == 0) {
+		static u8 drvmaporder = 0;
+		u8 *efuse;
+		u32 shift, cnt;
+		u32 blksz = 0x200; /* The size of one time show, default 512 */
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
+
+		efuse = pHalData->efuse_eeprom_data;
+
+		shift = blksz * drvmaporder;
+		efuse += shift;
+		cnt = mapLen - shift;
+
+		if (cnt > blksz) {
+			cnt = blksz;
+			drvmaporder++;
+		} else
+			drvmaporder = 0;
+
+		sprintf(extra, "\n");
+		for (i = 0; i < cnt; i += 16) {
+			sprintf(extra + strlen(extra), "0x%02x\t", shift + i);
+			for (j = 0; j < 8; j++)
+				sprintf(extra + strlen(extra), "%02X ", efuse[i + j]);
+			sprintf(extra + strlen(extra), "\t");
+			for (; j < 16; j++)
+				sprintf(extra + strlen(extra), "%02X ", efuse[i + j]);
+			sprintf(extra + strlen(extra), "\n");
+		}
+		if ((shift + cnt) < mapLen)
+			sprintf(extra + strlen(extra), "\t...more (left:%d/%d)\n", mapLen-(shift + cnt), mapLen);
+
+	} else if (strcmp(tmp[0], "realmap") == 0) {
+		static u8 order = 0;
+		u8 *efuse;
+		u32 shift, cnt;
+		u32 blksz = 0x200; /* The size of one time show, default 512 */
+
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&mapLen, false);
+		efuse = pEfuseHal->fakeEfuseInitMap;
+		if (rtw_efuse_mask_map_read(padapter, 0, mapLen, efuse) == _FAIL) {
+			RTW_INFO("%s: read realmap Fail!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		shift = blksz * order;
+		efuse += shift;
+		cnt = mapLen - shift;
+		if (cnt > blksz) {
+			cnt = blksz;
+			order++;
+		} else
+			order = 0;
+
+		sprintf(extra, "\n");
+		for (i = 0; i < cnt; i += 16) {
+			sprintf(extra + strlen(extra), "0x%02x\t", shift + i);
+			for (j = 0; j < 8; j++)
+				sprintf(extra + strlen(extra), "%02X ", efuse[i + j]);
+			sprintf(extra + strlen(extra), "\t");
+			for (; j < 16; j++)
+				sprintf(extra + strlen(extra), "%02X ", efuse[i + j]);
+			sprintf(extra + strlen(extra), "\n");
+		}
+		if ((shift + cnt) < mapLen)
+			sprintf(extra + strlen(extra), "\t...more (left:%d/%d)\n", mapLen-(shift + cnt), mapLen);
+	} else if (strcmp(tmp[0], "rmap") == 0) {
+		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
+			RTW_INFO("%s: rmap Fail!! Parameters error!\n", __func__);
+			err = -EINVAL;
+			goto exit;
+		}
+
+		/* rmap addr cnts */
+		addr = simple_strtoul(tmp[1], &ptmp, 16);
+		RTW_INFO("%s: addr=%x\n", __func__, addr);
+
+		cnts = simple_strtoul(tmp[2], &ptmp, 10);
+		if (cnts == 0) {
+			RTW_INFO("%s: rmap Fail!! cnts error!\n", __func__);
+			err = -EINVAL;
+			goto exit;
+		}
+		RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&max_available_len, false);
+		if ((addr + cnts) > max_available_len) {
+			RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+			err = -EINVAL;
+			goto exit;
+		}
+
+		if (rtw_efuse_mask_map_read(padapter, addr, cnts, data) == _FAIL) {
+			RTW_INFO("%s: rtw_efuse_mask_map_read error!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		/*		RTW_INFO("%s: data={", __func__); */
+		*extra = 0;
+		for (i = 0; i < cnts; i++) {
+			/*			RTW_INFO("0x%02x ", data[i]); */
+			sprintf(extra + strlen(extra), "0x%02X ", data[i]);
+		}
+		/*		RTW_INFO("}\n"); */
+	} else if (strcmp(tmp[0], "realraw") == 0) {
+		static u8 raw_order = 0;
+		u32 shift, cnt;
+		u32 blksz = 0x200; /* The size of one time show, default 512 */
+
+		addr = 0;
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN , (void *)&mapLen, false);
+		RTW_INFO("Real content len = %d\n",mapLen );
+
+		if (rtw_efuse_access(padapter, false, addr, mapLen, rawdata) == _FAIL) {
+			RTW_INFO("%s: rtw_efuse_access Fail!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		memset(extra, '\0', strlen(extra));
+
+		shift = blksz * raw_order;
+		rawdata += shift;
+		cnt = mapLen - shift;
+		if (cnt > blksz) {
+			cnt = blksz;
+			raw_order++;
+		} else
+			raw_order = 0;
+
+		sprintf(extra, "\n");
+		for (i = 0; i < cnt; i += 16) {
+			sprintf(extra + strlen(extra), "0x%02x\t", shift + i);
+			for (j = 0; j < 8; j++)
+				sprintf(extra + strlen(extra), "%02X ", rawdata[i + j]);
+			sprintf(extra + strlen(extra), "\t");
+			for (; j < 16; j++)
+				sprintf(extra + strlen(extra), "%02X ", rawdata[i + j]);
+			sprintf(extra + strlen(extra), "\n");
+		}
+		if ((shift + cnt) < mapLen)
+			sprintf(extra + strlen(extra), "\t...more (left:%d/%d)\n", mapLen-(shift + cnt), mapLen);
+
+	} else if (strcmp(tmp[0], "btrealraw") == 0) {
+		static u8 bt_raw_order = 0;
+		u32 shift, cnt;
+		u32 blksz = 0x200; /* The size of one time show, default 512 */
+
+		addr = 0;
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&mapLen, false);
+		RTW_INFO("Real content len = %d\n", mapLen);
+#ifdef RTW_HALMAC
+		if (rtw_efuse_bt_access(padapter, false, 0, mapLen, rawdata) == _FAIL) {
+			RTW_INFO("%s: rtw_efuse_access Fail!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+#else
+		rtw_write8(padapter, 0x35, 0x1);
+
+		if (rtw_efuse_access(padapter, false, addr, mapLen, rawdata) == _FAIL) {
+			RTW_INFO("%s: rtw_efuse_access Fail!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+#endif
+		memset(extra, '\0', strlen(extra));
+
+		shift = blksz * bt_raw_order;
+		rawdata += shift;
+		cnt = mapLen - shift;
+		if (cnt > blksz) {
+			cnt = blksz;
+			bt_raw_order++;
+		} else
+			bt_raw_order = 0;
+
+		sprintf(extra, "\n");
+		for (i = 0; i < cnt; i += 16) {
+			sprintf(extra + strlen(extra), "0x%02x\t", shift + i);
+			for (j = 0; j < 8; j++)
+				sprintf(extra + strlen(extra), "%02X ", rawdata[i + j]);
+			sprintf(extra + strlen(extra), "\t");
+			for (; j < 16; j++)
+				sprintf(extra + strlen(extra), "%02X ", rawdata[i + j]);
+			sprintf(extra + strlen(extra), "\n");
+		}
+		if ((shift + cnt) < mapLen)
+			sprintf(extra + strlen(extra), "\t...more (left:%d/%d)\n", mapLen-(shift + cnt), mapLen);
+
+	} else if (strcmp(tmp[0], "mac") == 0) {
+		if (hal_efuse_macaddr_offset(padapter) == -1) {
+			err = -EFAULT;
+			goto exit;
+		}
+
+		addr = hal_efuse_macaddr_offset(padapter);
+		cnts = 6;
+
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, false);
+		if ((addr + cnts) > max_available_len) {
+			RTW_INFO("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		if (rtw_efuse_mask_map_read(padapter, addr, cnts, data) == _FAIL) {
+			RTW_INFO("%s: rtw_efuse_mask_map_read error!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		/*		RTW_INFO("%s: MAC address={", __func__); */
+		*extra = 0;
+		for (i = 0; i < cnts; i++) {
+			/*			RTW_INFO("%02X", data[i]); */
+			sprintf(extra + strlen(extra), "%02X", data[i]);
+			if (i != (cnts - 1)) {
+				/*				RTW_INFO(":"); */
+				sprintf(extra + strlen(extra), ":");
+			}
+		}
+		/*		RTW_INFO("}\n"); */
+	} else if (strcmp(tmp[0], "vidpid") == 0) {
+		addr = EEPROM_VID_88EU;
+		cnts = 4;
+
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, false);
+		if ((addr + cnts) > max_available_len) {
+			RTW_INFO("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+			err = -EFAULT;
+			goto exit;
+		}
+		if (rtw_efuse_mask_map_read(padapter, addr, cnts, data) == _FAIL) {
+			RTW_INFO("%s: rtw_efuse_access error!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		/*		RTW_INFO("%s: {VID,PID}={", __func__); */
+		*extra = 0;
+		for (i = 0; i < cnts; i++) {
+			/*			RTW_INFO("0x%02x", data[i]); */
+			sprintf(extra + strlen(extra), "0x%02X", data[i]);
+			if (i != (cnts - 1)) {
+				/*				RTW_INFO(","); */
+				sprintf(extra + strlen(extra), ",");
+			}
+		}
+		/*		RTW_INFO("}\n"); */
+	} else if (strcmp(tmp[0], "ableraw") == 0) {
+#ifdef RTW_HALMAC
+		raw_maxsize = efuse_GetavailableSize(padapter);
+#else
+		efuse_GetCurrentSize(padapter, &raw_cursize);
+		raw_maxsize = efuse_GetMaxSize(padapter);
+#endif
+		sprintf(extra, "[available raw size]= %d bytes\n", raw_maxsize - raw_cursize);
+	} else if (strcmp(tmp[0], "btableraw") == 0) {
+		efuse_bt_GetCurrentSize(padapter, &raw_cursize);
+		raw_maxsize = efuse_bt_GetMaxSize(padapter);
+		sprintf(extra, "[available raw size]= %d bytes\n", raw_maxsize - raw_cursize);
+	} else if (strcmp(tmp[0], "btfmap") == 0) {
+
+		BTEfuse_PowerSwitch(padapter, 1, true);
+
+		mapLen = EFUSE_BT_MAX_MAP_LEN;
+		if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
+			RTW_INFO("%s: rtw_BT_efuse_map_read Fail!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		/*		RTW_INFO("OFFSET\tVALUE(hex)\n"); */
+		sprintf(extra, "\n");
+		for (i = 0; i < 512; i += 16) { /* set 512 because the iwpriv's extra size have limit 0x7FF */
+			/*			RTW_INFO("0x%03x\t", i); */
+			sprintf(extra + strlen(extra), "0x%03x\t", i);
+			for (j = 0; j < 8; j++) {
+				/*				RTW_INFO("%02X ", pEfuseHal->BTEfuseInitMap[i+j]); */
+				sprintf(extra + strlen(extra), "%02X ", pEfuseHal->BTEfuseInitMap[i + j]);
+			}
+			/*			RTW_INFO("\t"); */
+			sprintf(extra + strlen(extra), "\t");
+			for (; j < 16; j++) {
+				/*				RTW_INFO("%02X ", pEfuseHal->BTEfuseInitMap[i+j]); */
+				sprintf(extra + strlen(extra), "%02X ", pEfuseHal->BTEfuseInitMap[i + j]);
+			}
+			/*			RTW_INFO("\n"); */
+			sprintf(extra + strlen(extra), "\n");
+		}
+		/*		RTW_INFO("\n"); */
+	} else if (strcmp(tmp[0], "btbmap") == 0) {
+		BTEfuse_PowerSwitch(padapter, 1, true);
+
+		mapLen = EFUSE_BT_MAX_MAP_LEN;
+		if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
+			RTW_INFO("%s: rtw_BT_efuse_map_read Fail!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		/*		RTW_INFO("OFFSET\tVALUE(hex)\n"); */
+		sprintf(extra, "\n");
+		for (i = 512; i < 1024 ; i += 16) {
+			/*			RTW_INFO("0x%03x\t", i); */
+			sprintf(extra + strlen(extra), "0x%03x\t", i);
+			for (j = 0; j < 8; j++) {
+				/*				RTW_INFO("%02X ", data[i+j]); */
+				sprintf(extra + strlen(extra), "%02X ", pEfuseHal->BTEfuseInitMap[i + j]);
+			}
+			/*			RTW_INFO("\t"); */
+			sprintf(extra + strlen(extra), "\t");
+			for (; j < 16; j++) {
+				/*				RTW_INFO("%02X ", data[i+j]); */
+				sprintf(extra + strlen(extra), "%02X ", pEfuseHal->BTEfuseInitMap[i + j]);
+			}
+			/*			RTW_INFO("\n"); */
+			sprintf(extra + strlen(extra), "\n");
+		}
+		/*		RTW_INFO("\n"); */
+	} else if (strcmp(tmp[0], "btrmap") == 0) {
+		u8 BTStatus;
+
+		rtw_write8(padapter, 0xa3, 0x05); /* For 8723AB ,8821S ? */
+		BTStatus = rtw_read8(padapter, 0xa0);
+
+		RTW_INFO("%s: Check 0xa0 BT Status =0x%x\n", __func__, BTStatus);
+		if (BTStatus != 0x04) {
+			sprintf(extra, "BT Status not Active ,can't to read BT eFuse\n");
+			goto exit;
+		}
+
+		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		BTEfuse_PowerSwitch(padapter, 1, true);
+
+		/* rmap addr cnts */
+		addr = simple_strtoul(tmp[1], &ptmp, 16);
+		RTW_INFO("%s: addr=0x%X\n", __func__, addr);
+
+		cnts = simple_strtoul(tmp[2], &ptmp, 10);
+		if (cnts == 0) {
+			RTW_INFO("%s: btrmap Fail!! cnts error!\n", __func__);
+			err = -EINVAL;
+			goto exit;
+		}
+		RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+#ifndef RTW_HALMAC
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, false);
+		if ((addr + cnts) > max_available_len) {
+			RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+			err = -EFAULT;
+			goto exit;
+		}
+#endif
+		if (rtw_BT_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
+			RTW_INFO("%s: rtw_BT_efuse_map_read error!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		*extra = 0;
+		/*		RTW_INFO("%s: bt efuse data={", __func__); */
+		for (i = 0; i < cnts; i++) {
+			/*			RTW_INFO("0x%02x ", data[i]); */
+			sprintf(extra + strlen(extra), " 0x%02X ", data[i]);
+		}
+		/*		RTW_INFO("}\n"); */
+		RTW_INFO(FUNC_ADPT_FMT ": BT MAC=[%s]\n", FUNC_ADPT_ARG(padapter), extra);
+	} else if (strcmp(tmp[0], "btffake") == 0) {
+		/*		RTW_INFO("OFFSET\tVALUE(hex)\n"); */
+		sprintf(extra, "\n");
+		for (i = 0; i < 512; i += 16) {
+			/*			RTW_INFO("0x%03x\t", i); */
+			sprintf(extra + strlen(extra), "0x%03x\t", i);
+			for (j = 0; j < 8; j++) {
+				/*				RTW_INFO("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]); */
+				sprintf(extra + strlen(extra), "%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
+			}
+			/*			RTW_INFO("\t"); */
+			sprintf(extra + strlen(extra), "\t");
+			for (; j < 16; j++) {
+				/*				RTW_INFO("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]); */
+				sprintf(extra + strlen(extra), "%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
+			}
+			/*			RTW_INFO("\n"); */
+			sprintf(extra + strlen(extra), "\n");
+		}
+		/*		RTW_INFO("\n"); */
+	} else if (strcmp(tmp[0], "btbfake") == 0) {
+		/*		RTW_INFO("OFFSET\tVALUE(hex)\n"); */
+		sprintf(extra, "\n");
+		for (i = 512; i < 1024; i += 16) {
+			/*			RTW_INFO("0x%03x\t", i); */
+			sprintf(extra + strlen(extra), "0x%03x\t", i);
+			for (j = 0; j < 8; j++) {
+				/*				RTW_INFO("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]); */
+				sprintf(extra + strlen(extra), "%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
+			}
+			/*			RTW_INFO("\t"); */
+			sprintf(extra + strlen(extra), "\t");
+			for (; j < 16; j++) {
+				/*				RTW_INFO("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]); */
+				sprintf(extra + strlen(extra), "%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
+			}
+			/*			RTW_INFO("\n"); */
+			sprintf(extra + strlen(extra), "\n");
+		}
+		/*		RTW_INFO("\n"); */
+	} else if (strcmp(tmp[0], "wlrfkmap") == 0) {
+		static u8 fk_order = 0;
+		u8 *efuse;
+		u32 shift, cnt;
+		u32 blksz = 0x200; /* The size of one time show, default 512 */
+
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&mapLen, false);
+		efuse = pEfuseHal->fakeEfuseModifiedMap;
+
+		shift = blksz * fk_order;
+		efuse += shift;
+		cnt = mapLen - shift;
+		if (cnt > blksz) {
+			cnt = blksz;
+			fk_order++;
+		} else
+			fk_order = 0;
+
+		sprintf(extra, "\n");
+		for (i = 0; i < cnt; i += 16) {
+			sprintf(extra + strlen(extra), "0x%02x\t", shift + i);
+			for (j = 0; j < 8; j++)
+				sprintf(extra + strlen(extra), "%02X ", efuse[i + j]);
+			sprintf(extra + strlen(extra), "\t");
+			for (; j < 16; j++)
+				sprintf(extra + strlen(extra), "%02X ", efuse[i + j]);
+			sprintf(extra + strlen(extra), "\n");
+		}
+		if ((shift + cnt) < mapLen)
+			sprintf(extra + strlen(extra), "\t...more\n");
+
+	} else if (strcmp(tmp[0], "wlrfkrmap") == 0) {
+		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
+			RTW_INFO("%s: rmap Fail!! Parameters error!\n", __func__);
+			err = -EINVAL;
+			goto exit;
+		}
+		/* rmap addr cnts */
+		addr = simple_strtoul(tmp[1], &ptmp, 16);
+		RTW_INFO("%s: addr=%x\n", __func__, addr);
+
+		cnts = simple_strtoul(tmp[2], &ptmp, 10);
+		if (cnts == 0) {
+			RTW_INFO("%s: rmap Fail!! cnts error!\n", __func__);
+			err = -EINVAL;
+			goto exit;
+		}
+		RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+
+		/*		RTW_INFO("%s: data={", __func__); */
+		*extra = 0;
+		for (i = 0; i < cnts; i++) {
+			RTW_INFO("wlrfkrmap = 0x%02x\n", pEfuseHal->fakeEfuseModifiedMap[addr + i]);
+			sprintf(extra + strlen(extra), "0x%02X ", pEfuseHal->fakeEfuseModifiedMap[addr + i]);
+		}
+	} else if (strcmp(tmp[0], "btrfkrmap") == 0) {
+		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
+			RTW_INFO("%s: rmap Fail!! Parameters error!\n", __func__);
+			err = -EINVAL;
+			goto exit;
+		}
+		/* rmap addr cnts */
+		addr = simple_strtoul(tmp[1], &ptmp, 16);
+		RTW_INFO("%s: addr=%x\n", __func__, addr);
+
+		cnts = simple_strtoul(tmp[2], &ptmp, 10);
+		if (cnts == 0) {
+			RTW_INFO("%s: rmap Fail!! cnts error!\n", __func__);
+			err = -EINVAL;
+			goto exit;
+		}
+		RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+
+		/*		RTW_INFO("%s: data={", __func__); */
+		*extra = 0;
+		for (i = 0; i < cnts; i++) {
+			RTW_INFO("wlrfkrmap = 0x%02x\n", pEfuseHal->fakeBTEfuseModifiedMap[addr + i]);
+			sprintf(extra + strlen(extra), "0x%02X ", pEfuseHal->fakeBTEfuseModifiedMap[addr + i]);
+		}
+	} else if (strcmp(tmp[0], "mask") == 0) {
+		*extra = 0;
+		mask_len = sizeof(u8) * rtw_get_efuse_mask_arraylen(padapter);
+		rtw_efuse_mask_array(padapter, mask_buf);
+
+		if (padapter->registrypriv.bFileMaskEfuse )
+			memcpy(mask_buf, maskfileBuffer, mask_len);
+
+		sprintf(extra, "\n");
+		for (i = 0; i < mask_len; i++)
+			sprintf(extra + strlen(extra), "0x%02X\n", mask_buf[i]);
+
+	} else
+		sprintf(extra, "Command not found!");
+
+exit:
+	if (data)
+		rtw_mfree(data, EFUSE_BT_MAX_MAP_LEN);
+	if (rawdata)
+		rtw_mfree(rawdata, EFUSE_BT_MAX_MAP_LEN);
+	if (!err)
+		wrqu->length = strlen(extra);
+
+	if (padapter->registrypriv.mp_mode == 0) {
+#ifdef CONFIG_IPS
+		rtw_pm_set_ips(padapter, ips_mode);
+#endif /* CONFIG_IPS */
+
+#ifdef CONFIG_LPS
+		rtw_pm_set_lps(padapter, lps_mode);
+#endif /* CONFIG_LPS */
+	}
+
+#ifdef CONFIG_IOL
+	padapter->registrypriv.fw_iol = org_fw_iol;/* 0:Disable, 1:enable, 2:by usb speed */
+#endif
+	return err;
+}
+
+static int rtw_mp_efuse_set(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wdata, char *extra)
+{
+	struct iw_point *wrqu;
+	PADAPTER padapter;
+	struct pwrctrl_priv *pwrctrlpriv ;
+	PHAL_DATA_TYPE pHalData;
+	PEFUSE_HAL pEfuseHal;
+	struct hal_ops *pHalFunc;
+	struct mp_priv *pmp_priv;
+
+	u8 ips_mode = IPS_NUM; /* init invalid value */
+	u8 lps_mode = PS_MODE_NUM; /* init invalid value */
+	u32 i = 0, j = 0, jj, kk;
+	u8 *setdata = NULL;
+	u8 *ShadowMapBT = NULL;
+	u8 *ShadowMapWiFi = NULL;
+	u8 *setrawdata = NULL;
+	char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL};
+	u16 addr = 0xFF, cnts = 0, BTStatus = 0 , max_available_len = 0;
+	u16 wifimaplen;
+	int err;
+
+	wrqu = (struct iw_point *)wdata;
+	padapter = rtw_netdev_priv(dev);
+	pwrctrlpriv = adapter_to_pwrctl(padapter);
+	pHalData = GET_HAL_DATA(padapter);
+	pEfuseHal = &pHalData->EfuseHal;
+	pHalFunc = &padapter->hal_func;
+	pmp_priv = &padapter->mppriv;
+
+	err = 0;
+
+	if (copy_from_user(extra, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&wifimaplen, false);
+
+	setdata = rtw_zmalloc(1024);
+	if (setdata == NULL) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	ShadowMapBT = rtw_malloc(EFUSE_BT_MAX_MAP_LEN);
+	if (ShadowMapBT == NULL) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	ShadowMapWiFi = rtw_malloc(wifimaplen);
+	if (ShadowMapWiFi == NULL) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	setrawdata = rtw_malloc(EFUSE_MAX_SIZE);
+	if (setrawdata == NULL) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+#ifdef CONFIG_LPS
+	lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
+	rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
+#endif
+
+#ifdef CONFIG_IPS
+	ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
+	rtw_pm_set_ips(padapter, IPS_NONE);
+#endif
+
+	pch = extra;
+	RTW_INFO("%s: in=%s\n", __func__, extra);
+
+	i = 0;
+	while ((token = strsep(&pch, ",")) != NULL) {
+		if (i > 2)
+			break;
+		tmp[i] = token;
+		i++;
+	}
+
+	/* tmp[0],[1],[2] */
+	/* wmap,addr,00e04c871200 */
+	if (strcmp(tmp[0], "wmap") == 0) {
+		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+#ifndef RTW_HALMAC
+		/* unknown bug workaround, need to fix later */
+		addr = 0x1ff;
+		rtw_write8(padapter, EFUSE_CTRL + 1, (addr & 0xff));
+		rtw_msleep_os(10);
+		rtw_write8(padapter, EFUSE_CTRL + 2, ((addr >> 8) & 0x03));
+		rtw_msleep_os(10);
+		rtw_write8(padapter, EFUSE_CTRL + 3, 0x72);
+		rtw_msleep_os(10);
+		rtw_read8(padapter, EFUSE_CTRL);
+#endif /* RTW_HALMAC */
+
+		addr = simple_strtoul(tmp[1], &ptmp, 16);
+		addr &= 0xFFF;
+
+		cnts = strlen(tmp[2]);
+		if (cnts % 2) {
+			err = -EINVAL;
+			goto exit;
+		}
+		cnts /= 2;
+		if (cnts == 0) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		RTW_INFO("%s: addr=0x%X\n", __func__, addr);
+		RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+		RTW_INFO("%s: map data=%s\n", __func__, tmp[2]);
+
+		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+			setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
+
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, false);
+
+		if ((addr + cnts) > max_available_len) {
+			RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
+			RTW_INFO("%s: rtw_efuse_map_write error!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+		*extra = 0;
+		RTW_INFO("%s: after rtw_efuse_map_write to !memcmp\n", __func__);
+		if (rtw_efuse_mask_map_read(padapter, addr, cnts, ShadowMapWiFi) == _SUCCESS) {
+			if (!memcmp((void *)ShadowMapWiFi , (void *)setdata, cnts)) {
+				RTW_INFO("%s: WiFi write map afterf compare success\n", __func__);
+				sprintf(extra, "WiFi write map compare OK\n");
+				err = 0;
+				goto exit;
+			} else {
+				sprintf(extra, "WiFi write map compare FAIL\n");
+				RTW_INFO("%s: WiFi write map compare Fail\n", __func__);
+				err = 0;
+				goto exit;
+			}
+		}
+	} else if (strcmp(tmp[0], "wraw") == 0) {
+		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		addr = simple_strtoul(tmp[1], &ptmp, 16);
+		addr &= 0xFFF;
+
+		cnts = strlen(tmp[2]);
+		if (cnts % 2) {
+			err = -EINVAL;
+			goto exit;
+		}
+		cnts /= 2;
+		if (cnts == 0) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		RTW_INFO("%s: addr=0x%X\n", __func__, addr);
+		RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+		RTW_INFO("%s: raw data=%s\n", __func__, tmp[2]);
+
+		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+			setrawdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
+
+		if (rtw_efuse_access(padapter, true, addr, cnts, setrawdata) == _FAIL) {
+			RTW_INFO("%s: rtw_efuse_access error!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+	} else if (strcmp(tmp[0], "btwraw") == 0) {
+		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		addr = simple_strtoul(tmp[1], &ptmp, 16);
+		addr &= 0xFFF;
+
+		cnts = strlen(tmp[2]);
+		if (cnts % 2) {
+			err = -EINVAL;
+			goto exit;
+		}
+		cnts /= 2;
+		if (cnts == 0) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		RTW_INFO("%s: addr=0x%X\n", __func__, addr);
+		RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+		RTW_INFO("%s: raw data=%s\n", __func__, tmp[2]);
+
+		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+			setrawdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
+#ifdef RTW_HALMAC
+		if (rtw_efuse_bt_access(padapter, true, addr, cnts, setrawdata) == _FAIL) {
+			RTW_INFO("%s: rtw_efuse_access error!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+#else
+		rtw_write8(padapter, 0x35, 1); /* switch bank 1 (BT)*/
+		if (rtw_efuse_access(padapter, true, addr, cnts, setrawdata) == _FAIL) {
+			RTW_INFO("%s: rtw_efuse_access error!!\n", __func__);
+			rtw_write8(padapter, 0x35, 0); /* switch bank 0 (WiFi)*/
+			err = -EFAULT;
+			goto exit;
+		}
+		rtw_write8(padapter, 0x35, 0); /* switch bank 0 (WiFi)*/
+#endif
+	} else if (strcmp(tmp[0], "mac") == 0) {
+		if (tmp[1] == NULL) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		/* mac,00e04c871200 */
+
+		if (hal_efuse_macaddr_offset(padapter) == -1) {
+			err = -EFAULT;
+			goto exit;
+		}
+
+		addr = hal_efuse_macaddr_offset(padapter);
+		cnts = strlen(tmp[1]);
+		if (cnts % 2) {
+			err = -EINVAL;
+			goto exit;
+		}
+		cnts /= 2;
+		if (cnts == 0) {
+			err = -EINVAL;
+			goto exit;
+		}
+		if (cnts > 6) {
+			RTW_INFO("%s: error data for mac addr=\"%s\"\n", __func__, tmp[1]);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		RTW_INFO("%s: addr=0x%X\n", __func__, addr);
+		RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+		RTW_INFO("%s: MAC address=%s\n", __func__, tmp[1]);
+
+		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+			setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
+
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, false);
+
+		if ((addr + cnts) > max_available_len) {
+			RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
+			RTW_INFO("%s: rtw_efuse_map_write error!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+	} else if (strcmp(tmp[0], "vidpid") == 0) {
+		if (tmp[1] == NULL) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		/* pidvid,da0b7881		 */
+		addr = EEPROM_VID_88EU;
+		cnts = strlen(tmp[1]);
+		if (cnts % 2) {
+			err = -EINVAL;
+			goto exit;
+		}
+		cnts /= 2;
+		if (cnts == 0) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		RTW_INFO("%s: addr=0x%X\n", __func__, addr);
+		RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+		RTW_INFO("%s: VID/PID=%s\n", __func__, tmp[1]);
+
+		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+			setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
+
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, false);
+		if ((addr + cnts) > max_available_len) {
+			RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
+			RTW_INFO("%s: rtw_efuse_map_write error!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+	} else if (strcmp(tmp[0], "wldumpfake") == 0) {
+		if (wifimaplen > EFUSE_MAX_MAP_LEN)
+			cnts = EFUSE_MAX_MAP_LEN;
+		else
+			cnts = wifimaplen;
+		if (rtw_efuse_mask_map_read(padapter, 0, cnts, pEfuseHal->fakeEfuseModifiedMap) == _SUCCESS)
+			RTW_INFO("%s: WiFi hw efuse dump to Fake map success\n", __func__);
+		else {
+			RTW_INFO("%s: WiFi hw efuse dump to Fake map Fail\n", __func__);
+			err = -EFAULT;
+		}
+	} else if (strcmp(tmp[0], "btwmap") == 0) {
+		rtw_write8(padapter, 0xa3, 0x05); /* For 8723AB ,8821S ? */
+		BTStatus = rtw_read8(padapter, 0xa0);
+		RTW_INFO("%s: btwmap before read 0xa0 BT Status =0x%x\n", __func__, BTStatus);
+		if (BTStatus != 0x04) {
+			sprintf(extra, "BT Status not Active ,can't do Write\n");
+			goto exit;
+		}
+
+		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+#ifndef RTW_HALMAC
+		BTEfuse_PowerSwitch(padapter, 1, true);
+		addr = 0x1ff;
+		rtw_write8(padapter, EFUSE_CTRL + 1, (addr & 0xff));
+		rtw_msleep_os(10);
+		rtw_write8(padapter, EFUSE_CTRL + 2, ((addr >> 8) & 0x03));
+		rtw_msleep_os(10);
+		rtw_write8(padapter, EFUSE_CTRL + 3, 0x72);
+		rtw_msleep_os(10);
+		rtw_read8(padapter, EFUSE_CTRL);
+		BTEfuse_PowerSwitch(padapter, 1, false);
+#endif /* RTW_HALMAC */
+
+		addr = simple_strtoul(tmp[1], &ptmp, 16);
+		addr &= 0xFFF;
+
+		cnts = strlen(tmp[2]);
+		if (cnts % 2) {
+			err = -EINVAL;
+			goto exit;
+		}
+		cnts /= 2;
+		if (cnts == 0) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		RTW_INFO("%s: addr=0x%X\n", __func__, addr);
+		RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+		RTW_INFO("%s: BT data=%s\n", __func__, tmp[2]);
+
+		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+			setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
+#ifndef RTW_HALMAC
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, false);
+		if ((addr + cnts) > max_available_len) {
+			RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+			err = -EFAULT;
+			goto exit;
+		}
+#endif
+		if (rtw_BT_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
+			RTW_INFO("%s: rtw_BT_efuse_map_write error!!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+		*extra = 0;
+		RTW_INFO("%s: after rtw_BT_efuse_map_write to !memcmp\n", __func__);
+		if ((rtw_BT_efuse_map_read(padapter, addr, cnts, ShadowMapBT) == _SUCCESS)) {
+			if (!memcmp((void *)ShadowMapBT , (void *)setdata, cnts)) {
+				RTW_INFO("%s: BT write map compare OK BTStatus=0x%x\n", __func__, BTStatus);
+				sprintf(extra, "BT write map compare OK");
+				err = 0;
+				goto exit;
+			} else {
+				sprintf(extra, "BT write map compare FAIL");
+				RTW_INFO("%s: BT write map compare FAIL BTStatus=0x%x\n", __func__, BTStatus);
+				err = 0;
+				goto exit;
+			}
+		}
+	} else if (strcmp(tmp[0], "btwfake") == 0) {
+		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		addr = simple_strtoul(tmp[1], &ptmp, 16);
+		addr &= 0xFFF;
+
+		cnts = strlen(tmp[2]);
+		if (cnts % 2) {
+			err = -EINVAL;
+			goto exit;
+		}
+		cnts /= 2;
+		if (cnts == 0) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		RTW_INFO("%s: addr=0x%X\n", __func__, addr);
+		RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+		RTW_INFO("%s: BT tmp data=%s\n", __func__, tmp[2]);
+
+		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+			pEfuseHal->fakeBTEfuseModifiedMap[addr + jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
+	} else if (strcmp(tmp[0], "btdumpfake") == 0) {
+		if (rtw_BT_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _SUCCESS)
+			RTW_INFO("%s: BT read all map success\n", __func__);
+		else {
+			RTW_INFO("%s: BT read all map Fail!\n", __func__);
+			err = -EFAULT;
+		}
+	} else if (strcmp(tmp[0], "btfk2map") == 0) {
+		rtw_write8(padapter, 0xa3, 0x05);
+		BTStatus = rtw_read8(padapter, 0xa0);
+		RTW_INFO("%s: btwmap before read 0xa0 BT Status =0x%x\n", __func__, BTStatus);
+		if (BTStatus != 0x04) {
+			sprintf(extra, "BT Status not Active Write FAIL\n");
+			goto exit;
+		}
+#ifndef RTW_HALMAC
+		BTEfuse_PowerSwitch(padapter, 1, true);
+		addr = 0x1ff;
+		rtw_write8(padapter, EFUSE_CTRL + 1, (addr & 0xff));
+		rtw_msleep_os(10);
+		rtw_write8(padapter, EFUSE_CTRL + 2, ((addr >> 8) & 0x03));
+		rtw_msleep_os(10);
+		rtw_write8(padapter, EFUSE_CTRL + 3, 0x72);
+		rtw_msleep_os(10);
+		rtw_read8(padapter, EFUSE_CTRL);
+		BTEfuse_PowerSwitch(padapter, 1, false);
+#endif /* RTW_HALMAC */
+		memcpy(pEfuseHal->BTEfuseModifiedMap, pEfuseHal->fakeBTEfuseModifiedMap, EFUSE_BT_MAX_MAP_LEN);
+
+		if (rtw_BT_efuse_map_write(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _FAIL) {
+			RTW_INFO("%s: rtw_BT_efuse_map_write error!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		RTW_INFO("pEfuseHal->fakeBTEfuseModifiedMap OFFSET\tVALUE(hex)\n");
+		for (i = 0; i < EFUSE_BT_MAX_MAP_LEN; i += 16) {
+			printk("0x%02x\t", i);
+			for (j = 0; j < 8; j++)
+				printk("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
+			printk("\t");
+
+			for (; j < 16; j++)
+				printk("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
+			printk("\n");
+		}
+		printk("\n");
+		err = -EFAULT;
+		RTW_INFO("%s: rtw_BT_efuse_map_read !memcmp\n", __func__);
+		if ((rtw_BT_efuse_map_read(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseInitMap) == _SUCCESS)) {
+			if (!memcmp((void *)pEfuseHal->fakeBTEfuseModifiedMap, (void *)pEfuseHal->fakeBTEfuseInitMap, EFUSE_BT_MAX_MAP_LEN)) {
+				sprintf(extra, "BT write map compare OK");
+				RTW_INFO("%s: BT write map afterf compare success BTStatus=0x%x\n", __func__, BTStatus);
+				err = 0;
+				goto exit;
+			} else {
+				sprintf(extra, "BT write map compare FAIL");
+				if (rtw_BT_efuse_map_write(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _FAIL)
+					RTW_INFO("%s: rtw_BT_efuse_map_write compare error,retry = %d!\n", __func__, i);
+
+				if (rtw_BT_efuse_map_read(padapter, EFUSE_BT, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseInitMap) == _SUCCESS) {
+					RTW_INFO("pEfuseHal->fakeBTEfuseInitMap OFFSET\tVALUE(hex)\n");
+
+					for (i = 0; i < EFUSE_BT_MAX_MAP_LEN; i += 16) {
+						printk("0x%02x\t", i);
+						for (j = 0; j < 8; j++)
+							printk("%02X ", pEfuseHal->fakeBTEfuseInitMap[i + j]);
+						printk("\t");
+						for (; j < 16; j++)
+							printk("%02X ", pEfuseHal->fakeBTEfuseInitMap[i + j]);
+						printk("\n");
+					}
+					printk("\n");
+				}
+				RTW_INFO("%s: BT write map afterf compare not match to write efuse try write Map again , BTStatus=0x%x\n", __func__, BTStatus);
+				goto exit;
+			}
+		}
+	} else if (strcmp(tmp[0], "wlfk2map") == 0) {
+		*extra = 0;
+
+		if (padapter->registrypriv.bFileMaskEfuse != true && pmp_priv->bloadefusemap ) {
+			RTW_INFO("%s: File eFuse mask file not to be loaded\n", __func__);
+			sprintf(extra, "Not load eFuse mask file yet, Please use the efuse_mask CMD.\n");
+			err = 0;
+			goto exit;
+		}
+
+		if (wifimaplen > EFUSE_MAX_MAP_LEN)
+			cnts = EFUSE_MAX_MAP_LEN;
+		else
+			cnts = wifimaplen;
+		if (rtw_efuse_map_write(padapter, 0x00, cnts, pEfuseHal->fakeEfuseModifiedMap) == _FAIL) {
+			RTW_INFO("%s: rtw_efuse_map_write fakeEfuseModifiedMap error!\n", __func__);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		if (rtw_efuse_mask_map_read(padapter, 0x00, wifimaplen, ShadowMapWiFi) == _SUCCESS) {
+			if (!memcmp((void *)ShadowMapWiFi , (void *)pEfuseHal->fakeEfuseModifiedMap, cnts)) {
+				RTW_INFO("%s: WiFi write map afterf compare OK\n", __func__);
+				sprintf(extra, "WiFi write map compare OK\n");
+				err = 0;
+				goto exit;
+			} else {
+				sprintf(extra, "WiFi write map compare FAIL\n");
+				RTW_INFO("%s: WiFi write map compare Fail\n", __func__);
+				err = 0;
+				goto exit;
+			}
+		}
+	} else if (strcmp(tmp[0], "wlwfake") == 0) {
+		if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		addr = simple_strtoul(tmp[1], &ptmp, 16);
+		addr &= 0xFFF;
+
+		cnts = strlen(tmp[2]);
+		if (cnts % 2) {
+			err = -EINVAL;
+			goto exit;
+		}
+		cnts /= 2;
+		if (cnts == 0) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		RTW_INFO("%s: addr=0x%X\n", __func__, addr);
+		RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+		RTW_INFO("%s: map tmp data=%s\n", __func__, tmp[2]);
+
+		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+			pEfuseHal->fakeEfuseModifiedMap[addr + jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
+		memset(extra, '\0', strlen(extra));
+		sprintf(extra, "wlwfake OK\n");
+
+	}
+	else if (strcmp(tmp[0], "wfakemac") == 0) {
+		if (tmp[1] == NULL) {
+			err = -EINVAL;
+			goto exit;
+		}
+		/* wfakemac,00e04c871200 */
+		if (hal_efuse_macaddr_offset(padapter) == -1) {
+			err = -EFAULT;
+			goto exit;
+		}
+
+		addr = hal_efuse_macaddr_offset(padapter);
+		cnts = strlen(tmp[1]);
+		if (cnts % 2) {
+			err = -EINVAL;
+			goto exit;
+		}
+		cnts /= 2;
+		if (cnts == 0) {
+			err = -EINVAL;
+			goto exit;
+		}
+		if (cnts > 6) {
+			RTW_INFO("%s: error data for mac addr=\"%s\"\n", __func__, tmp[1]);
+			err = -EFAULT;
+			goto exit;
+		}
+
+		RTW_INFO("%s: addr=0x%X\n", __func__, addr);
+		RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+		RTW_INFO("%s: MAC address=%s\n", __func__, tmp[1]);
+
+		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+			pEfuseHal->fakeEfuseModifiedMap[addr + jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
+
+		memset(extra, '\0', strlen(extra));
+		sprintf(extra, "write mac addr to fake map OK\n");
+	} else if(strcmp(tmp[0], "update") == 0) {
+		RTW_INFO("To Use new eFuse map\n");
+		/*step read efuse/eeprom data and get mac_addr*/
+		rtw_hal_read_chip_info(padapter);
+		/* set mac addr*/
+		rtw_macaddr_cfg(adapter_mac_addr(padapter), get_hal_mac_addr(padapter));
+		memcpy(padapter->pnetdev->dev_addr, get_hal_mac_addr(padapter), ETH_ALEN); /* set mac addr to net_device */
+
+#ifdef CONFIG_P2P
+		rtw_init_wifidirect_addrs(padapter, adapter_mac_addr(padapter), adapter_mac_addr(padapter));
+#endif
+#ifdef CONFIG_MI_WITH_MBSSID_CAM
+		rtw_hal_change_macaddr_mbid(padapter, adapter_mac_addr(padapter));
+#else
+		rtw_hal_set_hwreg(padapter, HW_VAR_MAC_ADDR, adapter_mac_addr(padapter)); /* set mac addr to mac register */
+#endif
+		/*pHalFunc->hal_deinit(padapter);*/
+		if (pHalFunc->hal_init(padapter) == _FAIL) {
+			err = -EINVAL;
+			goto exit;
+		}
+		memset(extra, '\0', strlen(extra));
+		sprintf(extra, "eFuse Update OK\n");
+	}
+
+exit:
+	if (setdata)
+		rtw_mfree(setdata, 1024);
+	if (ShadowMapBT)
+		rtw_mfree(ShadowMapBT, EFUSE_BT_MAX_MAP_LEN);
+	if (ShadowMapWiFi)
+		rtw_mfree(ShadowMapWiFi, wifimaplen);
+	if (setrawdata)
+		rtw_mfree(setrawdata, EFUSE_MAX_SIZE);
+
+	wrqu->length = strlen(extra);
+
+	if (padapter->registrypriv.mp_mode == 0) {
+#ifdef CONFIG_IPS
+		rtw_pm_set_ips(padapter, ips_mode);
+#endif /* CONFIG_IPS */
+
+#ifdef CONFIG_LPS
+		rtw_pm_set_lps(padapter, lps_mode);
+#endif /* CONFIG_LPS */
+	}
+
+	return err;
+}
+
+#ifdef CONFIG_MP_INCLUDED
+
+#ifdef CONFIG_RTW_CUSTOMER_STR
+static int rtw_mp_customer_str(
+	struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu, char *extra)
+{
+	_adapter *adapter = rtw_netdev_priv(dev);
+	u32 len;
+	u8 *pbuf = NULL, *pch;
+	char *ptmp;
+	u8 param[RTW_CUSTOMER_STR_LEN];
+	u8 count = 0;
+	u8 tmp;
+	u8 i;
+	u32 pos;
+	u8 ret;
+	u8 read = 0;
+
+	if (adapter->registrypriv.mp_mode != 1
+		|| !adapter->registrypriv.mp_customer_str)
+		return -EFAULT;
+
+	len = wrqu->data.length;
+
+	pbuf = (u8 *)rtw_zmalloc(len);
+	if (pbuf == NULL) {
+		RTW_WARN("%s: no memory!\n", __func__);
+		return -ENOMEM;
+	}
+
+	if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
+		rtw_mfree(pbuf, len);
+		RTW_WARN("%s: copy from user fail!\n", __func__);
+		return -EFAULT;
+	}
+	RTW_INFO("%s: string=\"%s\"\n", __func__, pbuf);
+
+	ptmp = (char *)pbuf;
+	pch = strsep(&ptmp, ",");
+	if ((pch == NULL) || (strlen(pch) == 0)) {
+		rtw_mfree(pbuf, len);
+		RTW_INFO("%s: parameter error(no cmd)!\n", __func__);
+		return -EFAULT;
+	}
+
+	memset(param, 0xFF, RTW_CUSTOMER_STR_LEN);
+
+	if (strcmp(pch, "read") == 0) {
+		read = 1;
+		ret = rtw_hal_customer_str_read(adapter, param);
+
+	} else if (strcmp(pch, "write") == 0) {
+		do {
+			pch = strsep(&ptmp, ":");
+			if ((pch == NULL) || (strlen(pch) == 0))
+				break;
+			if (strlen(pch) != 2
+				|| IsHexDigit(*pch) == false
+				|| IsHexDigit(*(pch + 1)) == false
+				|| sscanf(pch, "%hhx", &tmp) != 1
+			) {
+				RTW_WARN("%s: invalid 8-bit hex!\n", __func__);
+				rtw_mfree(pbuf, len);
+				return -EFAULT;
+			}
+
+			param[count++] = tmp;
+
+		} while (count < RTW_CUSTOMER_STR_LEN);
+
+		if (count == 0) {
+			rtw_mfree(pbuf, len);
+			RTW_WARN("%s: no input!\n", __func__);
+			return -EFAULT;
+		}
+		ret = rtw_hal_customer_str_write(adapter, param);
+	} else {
+		rtw_mfree(pbuf, len);
+		RTW_INFO("%s: parameter error(unknown cmd)!\n", __func__);
+		return -EFAULT;
+	}
+
+	pos = sprintf(extra, "%s: ", read ? "read" : "write");
+	if (read == 0 || ret == _SUCCESS) {
+		for (i = 0; i < RTW_CUSTOMER_STR_LEN; i++)
+			pos += sprintf(extra + pos, "%02x:", param[i]);
+		extra[pos] = 0;
+		pos--;
+	}
+	pos += sprintf(extra + pos, " %s", ret == _SUCCESS ? "OK" : "FAIL");
+
+	wrqu->data.length = strlen(extra) + 1;
+
+free_buf:
+	rtw_mfree(pbuf, len);
+	return 0;
+}
+#endif /* CONFIG_RTW_CUSTOMER_STR */
+
+static int rtw_priv_mp_set(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wdata, char *extra)
+{
+
+	struct iw_point *wrqu = (struct iw_point *)wdata;
+	u32 subcmd = wrqu->flags;
+
+	switch (subcmd) {
+	case CTA_TEST:
+		RTW_INFO("set CTA_TEST\n");
+		rtw_cta_test_start(dev, info, wdata, extra);
+		break;
+	case MP_DISABLE_BT_COEXIST:
+		RTW_INFO("set case MP_DISABLE_BT_COEXIST\n");
+		rtw_mp_disable_bt_coexist(dev, info, wdata, extra);
+		break;
+	case MP_IQK:
+		RTW_INFO("set MP_IQK\n");
+		rtw_mp_iqk(dev, info, wrqu, extra);
+		break;
+	case MP_LCK:
+		RTW_INFO("set MP_LCK\n");
+		rtw_mp_lck(dev, info, wrqu, extra);
+	break;
+
+	default:
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int rtw_priv_mp_get(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wdata, char *extra)
+{
+
+	struct iw_point *wrqu = (struct iw_point *)wdata;
+	u32 subcmd = wrqu->flags;
+
+	switch (subcmd) {
+	case MP_START:
+		RTW_INFO("set case mp_start\n");
+		rtw_mp_start(dev, info, wrqu, extra);
+		break;
+	case MP_STOP:
+		RTW_INFO("set case mp_stop\n");
+		rtw_mp_stop(dev, info, wrqu, extra);
+		break;
+	case MP_BANDWIDTH:
+		RTW_INFO("set case mp_bandwidth\n");
+		rtw_mp_bandwidth(dev, info, wrqu, extra);
+		break;
+	case MP_RESET_STATS:
+		RTW_INFO("set case MP_RESET_STATS\n");
+		rtw_mp_reset_stats(dev, info, wrqu, extra);
+		break;
+	case MP_SetRFPathSwh:
+		RTW_INFO("set MP_SetRFPathSwitch\n");
+		rtw_mp_SetRFPath(dev, info, wrqu, extra);
+		break;
+	case WRITE_REG:
+		rtw_mp_write_reg(dev, info, wrqu, extra);
+		break;
+	case WRITE_RF:
+		rtw_mp_write_rf(dev, info, wrqu, extra);
+		break;
+	case MP_PHYPARA:
+		RTW_INFO("mp_get  MP_PHYPARA\n");
+		rtw_mp_phypara(dev, info, wrqu, extra);
+		break;
+	case MP_CHANNEL:
+		RTW_INFO("set case mp_channel\n");
+		rtw_mp_channel(dev , info, wrqu, extra);
+		break;
+	case READ_REG:
+		RTW_INFO("mp_get  READ_REG\n");
+		rtw_mp_read_reg(dev, info, wrqu, extra);
+		break;
+	case READ_RF:
+		RTW_INFO("mp_get  READ_RF\n");
+		rtw_mp_read_rf(dev, info, wrqu, extra);
+		break;
+	case MP_RATE:
+		RTW_INFO("set case mp_rate\n");
+		rtw_mp_rate(dev, info, wrqu, extra);
+		break;
+	case MP_TXPOWER:
+		RTW_INFO("set case MP_TXPOWER\n");
+		rtw_mp_txpower(dev, info, wrqu, extra);
+		break;
+	case MP_ANT_TX:
+		RTW_INFO("set case MP_ANT_TX\n");
+		rtw_mp_ant_tx(dev, info, wrqu, extra);
+		break;
+	case MP_ANT_RX:
+		RTW_INFO("set case MP_ANT_RX\n");
+		rtw_mp_ant_rx(dev, info, wrqu, extra);
+		break;
+	case MP_QUERY:
+		rtw_mp_trx_query(dev, info, wrqu, extra);
+		break;
+	case MP_CTX:
+		RTW_INFO("set case MP_CTX\n");
+		rtw_mp_ctx(dev, info, wrqu, extra);
+		break;
+	case MP_ARX:
+		RTW_INFO("set case MP_ARX\n");
+		rtw_mp_arx(dev, info, wrqu, extra);
+		break;
+	case MP_DUMP:
+		RTW_INFO("set case MP_DUMP\n");
+		rtw_mp_dump(dev, info, wrqu, extra);
+		break;
+	case MP_PSD:
+		RTW_INFO("set case MP_PSD\n");
+		rtw_mp_psd(dev, info, wrqu, extra);
+		break;
+	case MP_THER:
+		RTW_INFO("set case MP_THER\n");
+		rtw_mp_thermal(dev, info, wrqu, extra);
+		break;
+	case MP_PwrCtlDM:
+		RTW_INFO("set MP_PwrCtlDM\n");
+		rtw_mp_PwrCtlDM(dev, info, wrqu, extra);
+		break;
+	case MP_QueryDrvStats:
+		RTW_INFO("mp_get MP_QueryDrvStats\n");
+		rtw_mp_QueryDrv(dev, info, wdata, extra);
+		break;
+	case MP_PWRTRK:
+		RTW_INFO("set case MP_PWRTRK\n");
+		rtw_mp_pwrtrk(dev, info, wrqu, extra);
+		break;
+	case EFUSE_SET:
+		RTW_INFO("set case efuse set\n");
+		rtw_mp_efuse_set(dev, info, wdata, extra);
+		break;
+	case EFUSE_GET:
+		RTW_INFO("efuse get EFUSE_GET\n");
+		rtw_mp_efuse_get(dev, info, wdata, extra);
+		break;
+	case MP_GET_TXPOWER_INX:
+		RTW_INFO("mp_get MP_GET_TXPOWER_INX\n");
+		rtw_mp_txpower_index(dev, info, wrqu, extra);
+		break;
+	case MP_GETVER:
+		RTW_INFO("mp_get MP_GETVER\n");
+		rtw_mp_getver(dev, info, wdata, extra);
+		break;
+	case MP_MON:
+		RTW_INFO("mp_get MP_MON\n");
+		rtw_mp_mon(dev, info, wdata, extra);
+		break;
+	case EFUSE_MASK:
+		RTW_INFO("mp_get EFUSE_MASK\n");
+		rtw_efuse_mask_file(dev, info, wdata, extra);
+		break;
+	case  EFUSE_FILE:
+		RTW_INFO("mp_get EFUSE_FILE\n");
+		rtw_efuse_file_map(dev, info, wdata, extra);
+		break;
+	case  MP_TX:
+		RTW_INFO("mp_get MP_TX\n");
+		rtw_mp_tx(dev, info, wdata, extra);
+		break;
+	case  MP_RX:
+		RTW_INFO("mp_get MP_RX\n");
+		rtw_mp_rx(dev, info, wdata, extra);
+		break;
+	case MP_HW_TX_MODE:
+		RTW_INFO("mp_get MP_HW_TX_MODE\n");
+		rtw_mp_hwtx(dev, info, wdata, extra);
+		break;
+#ifdef CONFIG_RTW_CUSTOMER_STR
+	case MP_CUSTOMER_STR:
+		RTW_INFO("customer str\n");
+		rtw_mp_customer_str(dev, info, wdata, extra);
+		break;
+#endif
+	default:
+		return -EIO;
+	}
+
+	return 0;
+}
+#endif /*#if defined(CONFIG_MP_INCLUDED)*/
+
+
+#ifdef CONFIG_SDIO_INDIRECT_ACCESS
+#define DBG_MP_SDIO_INDIRECT_ACCESS 1
+static int rtw_mp_sd_iread(struct net_device *dev
+			   , struct iw_request_info *info
+			   , struct iw_point *wrqu
+			   , char *extra)
+{
+	char input[16];
+	u8 width;
+	unsigned long addr;
+	u32 ret = 0;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+
+	if (wrqu->length > 16) {
+		RTW_INFO(FUNC_ADPT_FMT" wrqu->length:%d\n", FUNC_ADPT_ARG(padapter), wrqu->length);
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
+		RTW_INFO(FUNC_ADPT_FMT" copy_from_user fail\n", FUNC_ADPT_ARG(padapter));
+		ret = -EFAULT;
+		goto exit;
+	}
+
+	memset(extra, 0, wrqu->length);
+
+	if (sscanf(input, "%hhu,%lx", &width, &addr) != 2) {
+		RTW_INFO(FUNC_ADPT_FMT" sscanf fail\n", FUNC_ADPT_ARG(padapter));
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (addr > 0x3FFF) {
+		RTW_INFO(FUNC_ADPT_FMT" addr:0x%lx\n", FUNC_ADPT_ARG(padapter), addr);
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (DBG_MP_SDIO_INDIRECT_ACCESS)
+		RTW_INFO(FUNC_ADPT_FMT" width:%u, addr:0x%lx\n", FUNC_ADPT_ARG(padapter), width, addr);
+
+	switch (width) {
+	case 1:
+		sprintf(extra, "0x%02x", rtw_sd_iread8(padapter, addr));
+		wrqu->length = strlen(extra);
+		break;
+	case 2:
+		sprintf(extra, "0x%04x", rtw_sd_iread16(padapter, addr));
+		wrqu->length = strlen(extra);
+		break;
+	case 4:
+		sprintf(extra, "0x%08x", rtw_sd_iread32(padapter, addr));
+		wrqu->length = strlen(extra);
+		break;
+	default:
+		wrqu->length = 0;
+		ret = -EINVAL;
+		break;
+	}
+
+exit:
+	return ret;
+}
+
+static int rtw_mp_sd_iwrite(struct net_device *dev
+			    , struct iw_request_info *info
+			    , struct iw_point *wrqu
+			    , char *extra)
+{
+	char width;
+	unsigned long addr, data;
+	int ret = 0;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	char input[32];
+
+	if (wrqu->length > 32) {
+		RTW_INFO(FUNC_ADPT_FMT" wrqu->length:%d\n", FUNC_ADPT_ARG(padapter), wrqu->length);
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
+		RTW_INFO(FUNC_ADPT_FMT" copy_from_user fail\n", FUNC_ADPT_ARG(padapter));
+		ret = -EFAULT;
+		goto exit;
+	}
+
+	memset(extra, 0, wrqu->length);
+
+	if (sscanf(input, "%hhu,%lx,%lx", &width, &addr, &data) != 3) {
+		RTW_INFO(FUNC_ADPT_FMT" sscanf fail\n", FUNC_ADPT_ARG(padapter));
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (addr > 0x3FFF) {
+		RTW_INFO(FUNC_ADPT_FMT" addr:0x%lx\n", FUNC_ADPT_ARG(padapter), addr);
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (DBG_MP_SDIO_INDIRECT_ACCESS)
+		RTW_INFO(FUNC_ADPT_FMT" width:%u, addr:0x%lx, data:0x%lx\n", FUNC_ADPT_ARG(padapter), width, addr, data);
+
+	switch (width) {
+	case 1:
+		if (data > 0xFF) {
+			ret = -EINVAL;
+			break;
+		}
+		rtw_sd_iwrite8(padapter, addr, data);
+		break;
+	case 2:
+		if (data > 0xFFFF) {
+			ret = -EINVAL;
+			break;
+		}
+		rtw_sd_iwrite16(padapter, addr, data);
+		break;
+	case 4:
+		rtw_sd_iwrite32(padapter, addr, data);
+		break;
+	default:
+		wrqu->length = 0;
+		ret = -EINVAL;
+		break;
+	}
+
+exit:
+	return ret;
+}
+#endif /* CONFIG_SDIO_INDIRECT_ACCESS */
+
+static int rtw_priv_set(struct net_device *dev,
+			struct iw_request_info *info,
+			union iwreq_data *wdata, char *extra)
+{
+	struct iw_point *wrqu = (struct iw_point *)wdata;
+	u32 subcmd = wrqu->flags;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+
+	if (padapter == NULL)
+		return -ENETDOWN;
+
+	if (padapter->bup == false) {
+		RTW_INFO(" %s fail =>(padapter->bup == false )\n", __func__);
+		return -ENETDOWN;
+	}
+
+	if (RTW_CANNOT_RUN(padapter)) {
+		RTW_INFO("%s fail =>(bSurpriseRemoved ) || ( bDriverStopped == true)\n", __func__);
+		return -ENETDOWN;
+	}
+
+	if (extra == NULL) {
+		wrqu->length = 0;
+		return -EIO;
+	}
+
+	if (subcmd < MP_NULL) {
+#ifdef CONFIG_MP_INCLUDED
+		rtw_priv_mp_set(dev, info, wdata, extra);
+#endif
+		return 0;
+	}
+
+	switch (subcmd) {
+#ifdef CONFIG_WOWLAN
+	case MP_WOW_ENABLE:
+		RTW_INFO("set case MP_WOW_ENABLE: %s\n", extra);
+
+		rtw_wowlan_ctrl(dev, info, wdata, extra);
+		break;
+	case MP_WOW_SET_PATTERN:
+		RTW_INFO("set case MP_WOW_SET_PATTERN: %s\n", extra);
+		rtw_wowlan_set_pattern(dev, info, wdata, extra);
+		break;
+#endif
+#ifdef CONFIG_AP_WOWLAN
+	case MP_AP_WOW_ENABLE:
+		RTW_INFO("set case MP_AP_WOW_ENABLE: %s\n", extra);
+		rtw_ap_wowlan_ctrl(dev, info, wdata, extra);
+		break;
+#endif
+#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
+	case VENDOR_IE_SET:
+		RTW_INFO("set case VENDOR_IE_SET\n");
+		rtw_vendor_ie_set(dev , info , wdata , extra);
+		break;
+#endif
+	default:
+		return -EIO;
+	}
+
+	return 0;
+}
+
+
+static int rtw_priv_get(struct net_device *dev,
+			struct iw_request_info *info,
+			union iwreq_data *wdata, char *extra)
+{
+	struct iw_point *wrqu = (struct iw_point *)wdata;
+	u32 subcmd = wrqu->flags;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+
+
+	if (padapter == NULL)
+		return -ENETDOWN;
+
+	if (padapter->bup == false) {
+		RTW_INFO(" %s fail =>(padapter->bup == false )\n", __func__);
+		return -ENETDOWN;
+	}
+
+	if (RTW_CANNOT_RUN(padapter)) {
+		RTW_INFO("%s fail =>(padapter->bSurpriseRemoved ) || ( padapter->bDriverStopped == true)\n", __func__);
+		return -ENETDOWN;
+	}
+
+	if (extra == NULL) {
+		wrqu->length = 0;
+		return -EIO;
+	}
+
+	if (subcmd < MP_NULL) {
+#ifdef CONFIG_MP_INCLUDED
+		rtw_priv_mp_get(dev, info, wdata, extra);
+#endif		
+		return 0;
+	}
+
+	switch (subcmd) {
+#ifdef CONFIG_SDIO_INDIRECT_ACCESS
+	case MP_SD_IREAD:
+		rtw_mp_sd_iread(dev, info, wrqu, extra);
+		break;
+	case MP_SD_IWRITE:
+		rtw_mp_sd_iwrite(dev, info, wrqu, extra);
+		break;
+#endif
+#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
+	case VENDOR_IE_GET:
+		RTW_INFO("get case VENDOR_IE_GET\n");
+		rtw_vendor_ie_get(dev , info , wdata , extra);
+		break;
+#endif
+	default:
+		return -EIO;
+	}
+
+	rtw_msleep_os(10); /* delay 5ms for sending pkt before exit adb shell operation */
+	return 0;
+}
+
+
+
+static int rtw_wx_tdls_wfd_enable(struct net_device *dev,
+				  struct iw_request_info *info,
+				  union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_WFD
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	RTW_INFO("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
+
+	if (extra[0] == '0')
+		rtw_tdls_wfd_enable(padapter, 0);
+	else
+		rtw_tdls_wfd_enable(padapter, 1);
+
+#endif /* CONFIG_WFD */
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_weaksec(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+
+	u8 i, j;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	RTW_INFO("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
+
+	if (extra[0] == '0')
+		padapter->wdinfo.wfd_tdls_weaksec = 0;
+	else
+		padapter->wdinfo.wfd_tdls_weaksec = 1;
+
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+
+static int rtw_tdls_enable(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_info	*ptdlsinfo = &padapter->tdlsinfo;
+	unsigned long	 irqL;
+	_list	*plist, *phead;
+	s32	index;
+	struct sta_info *psta = NULL;
+	struct	sta_priv *pstapriv = &padapter->stapriv;
+	u8 tdls_sta[NUM_STA][ETH_ALEN];
+	u8 empty_hwaddr[ETH_ALEN] = { 0x00 };
+	struct tdls_txmgmt txmgmt;
+
+	RTW_INFO("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
+
+	memset(tdls_sta, 0x00, sizeof(tdls_sta));
+	memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+
+	if (extra[0] == '0') {
+		ptdlsinfo->tdls_enable = 0;
+
+		if (pstapriv->asoc_sta_count == 1)
+			return ret;
+
+		_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 (psta->tdls_sta_state != TDLS_STATE_NONE)
+					memcpy(tdls_sta[index], psta->hwaddr, ETH_ALEN);
+			}
+		}
+		_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+
+		for (index = 0; index < NUM_STA; index++) {
+			if (memcmp(tdls_sta[index], empty_hwaddr, ETH_ALEN)) {
+				RTW_INFO("issue tear down to "MAC_FMT"\n", MAC_ARG(tdls_sta[index]));
+				txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;
+				memcpy(txmgmt.peer, tdls_sta[index], ETH_ALEN);
+				issue_tdls_teardown(padapter, &txmgmt, true);
+			}
+		}
+		rtw_tdls_cmd(padapter, NULL, TDLS_RS_RCR);
+		rtw_reset_tdls_info(padapter);
+	}	else if (extra[0] == '1')
+		ptdlsinfo->tdls_enable = 1;
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_setup(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+#ifdef CONFIG_TDLS
+	u8 i, j;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_txmgmt txmgmt;
+#ifdef CONFIG_WFD
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+#endif /* CONFIG_WFD */
+
+	RTW_INFO("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
+
+	if (wrqu->data.length - 1 != 17) {
+		RTW_INFO("[%s] length:%d != 17\n", __func__, (wrqu->data.length - 1));
+		return ret;
+	}
+
+	memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
+		txmgmt.peer[i] = key_2char2num(*(extra + j), *(extra + j + 1));
+
+#ifdef CONFIG_WFD
+	if (_AES_ != padapter->securitypriv.dot11PrivacyAlgrthm) {
+		/* Weak Security situation with AP. */
+		if (0 == pwdinfo->wfd_tdls_weaksec)	{
+			/* Can't send the tdls setup request out!! */
+			RTW_INFO("[%s] Current link is not AES, "
+				"SKIP sending the tdls setup request!!\n", __func__);
+		} else
+			issue_tdls_setup_req(padapter, &txmgmt, true);
+	} else
+#endif /* CONFIG_WFD */
+	{
+		issue_tdls_setup_req(padapter, &txmgmt, true);
+	}
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_teardown(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+
+	u8 i, j;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct sta_info *ptdls_sta = NULL;
+	struct tdls_txmgmt txmgmt;
+
+	RTW_INFO("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
+
+	if (wrqu->data.length - 1 != 17 && wrqu->data.length - 1 != 19) {
+		RTW_INFO("[%s] length:%d != 17 or 19\n",
+			 __func__, (wrqu->data.length - 1));
+		return ret;
+	}
+
+	memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	for (i = 0, j = 0; i < ETH_ALEN; i++, j += 3)
+		txmgmt.peer[i] = key_2char2num(*(extra + j), *(extra + j + 1));
+
+	ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), txmgmt.peer);
+
+	if (ptdls_sta != NULL) {
+		txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;
+		if (wrqu->data.length - 1 == 19)
+			issue_tdls_teardown(padapter, &txmgmt, false);
+		else
+			issue_tdls_teardown(padapter, &txmgmt, true);
+	} else
+		RTW_INFO("TDLS peer not found\n");
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_discovery(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_txmgmt	txmgmt;
+	int i = 0, j = 0;
+
+	RTW_INFO("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
+
+	memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
+		txmgmt.peer[i] = key_2char2num(*(extra + j), *(extra + j + 1));
+
+	issue_tdls_dis_req(padapter, &txmgmt);
+
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_ch_switch(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_TDLS_CH_SW
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
+	u8 i, j;
+	struct sta_info *ptdls_sta = NULL;
+	u8 take_care_iqk;
+
+	RTW_INFO("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
+
+	if (rtw_tdls_is_chsw_allowed(padapter) == false) {
+		RTW_INFO("TDLS channel switch is not allowed\n");
+		return ret;
+	}
+
+	for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
+		pchsw_info->addr[i] = key_2char2num(*(extra + j), *(extra + j + 1));
+
+	ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pchsw_info->addr);
+	if (ptdls_sta == NULL)
+		return ret;
+
+	pchsw_info->ch_sw_state |= TDLS_CH_SW_INITIATOR_STATE;
+
+	if (ptdls_sta != NULL) {
+		if (pchsw_info->off_ch_num == 0)
+			pchsw_info->off_ch_num = 11;
+	} else
+		RTW_INFO("TDLS peer not found\n");
+
+	rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
+
+	rtw_hal_get_hwreg(padapter, HW_VAR_CH_SW_NEED_TO_TAKE_CARE_IQK_INFO, &take_care_iqk);
+	if (take_care_iqk ) {
+		u8 central_chnl;
+		u8 bw_mode;
+
+		bw_mode = (pchsw_info->ch_offset) ? CHANNEL_WIDTH_40 : CHANNEL_WIDTH_20;
+		central_chnl = rtw_get_center_ch(pchsw_info->off_ch_num, bw_mode, pchsw_info->ch_offset);
+		if (rtw_hal_ch_sw_iqk_info_search(padapter, central_chnl, bw_mode) >= 0)
+			rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_START);
+		else
+			rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_PREPARE);
+	} else
+		rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_START);
+
+	/* issue_tdls_ch_switch_req(padapter, ptdls_sta); */
+	/* RTW_INFO("issue tdls ch switch req\n"); */
+
+#endif /* CONFIG_TDLS_CH_SW */
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_ch_switch_off(struct net_device *dev,
+				  struct iw_request_info *info,
+				  union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_TDLS_CH_SW
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
+	u8 i, j, mac_addr[ETH_ALEN];
+	struct sta_info *ptdls_sta = NULL;
+	struct tdls_txmgmt txmgmt;
+
+	memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+
+	RTW_INFO("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
+
+	if (rtw_tdls_is_chsw_allowed(padapter) == false) {
+		RTW_INFO("TDLS channel switch is not allowed\n");
+		return ret;
+	}
+
+	if (wrqu->data.length >= 17) {
+		for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
+			mac_addr[i] = key_2char2num(*(extra + j), *(extra + j + 1));
+		ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
+	}
+
+	if (ptdls_sta == NULL)
+		return ret;
+
+	rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_END_TO_BASE_CHNL);
+
+	pchsw_info->ch_sw_state &= ~(TDLS_CH_SW_INITIATOR_STATE |
+				     TDLS_CH_SWITCH_ON_STATE |
+				     TDLS_PEER_AT_OFF_STATE);
+	memset(pchsw_info->addr, 0x00, ETH_ALEN);
+
+	ptdls_sta->ch_switch_time = 0;
+	ptdls_sta->ch_switch_timeout = 0;
+	_cancel_timer_ex(&ptdls_sta->ch_sw_timer);
+	_cancel_timer_ex(&ptdls_sta->delay_timer);
+	_cancel_timer_ex(&ptdls_sta->stay_on_base_chnl_timer);
+	_cancel_timer_ex(&ptdls_sta->ch_sw_monitor_timer);
+
+	rtw_pm_set_lps(padapter, PS_MODE_MAX);
+#endif /* CONFIG_TDLS_CH_SW */
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_dump_ch(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_TDLS_CH_SW
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+
+	RTW_INFO("[%s] dump_stack:%s\n", __func__, extra);
+
+	extra[wrqu->data.length] = 0x00;
+	ptdlsinfo->chsw_info.dump_stack = rtw_atoi(extra);
+
+	return ret;
+
+#endif
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_off_ch_num(struct net_device *dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_TDLS_CH_SW
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+
+	RTW_INFO("[%s] off_ch_num:%s\n", __func__, extra);
+
+	extra[wrqu->data.length] = 0x00;
+	ptdlsinfo->chsw_info.off_ch_num = rtw_atoi(extra);
+
+	return ret;
+
+#endif
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_ch_offset(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_TDLS_CH_SW
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+
+	RTW_INFO("[%s] ch_offset:%s\n", __func__, extra);
+
+	extra[wrqu->data.length] = 0x00;
+	switch (rtw_atoi(extra)) {
+	case SCA:
+		ptdlsinfo->chsw_info.ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+		break;
+
+	case SCB:
+		ptdlsinfo->chsw_info.ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+		break;
+
+	default:
+		ptdlsinfo->chsw_info.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		break;
+	}
+
+	return ret;
+
+#endif
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_pson(struct net_device *dev,
+			 struct iw_request_info *info,
+			 union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 i, j, mac_addr[ETH_ALEN];
+	struct sta_info *ptdls_sta = NULL;
+
+	RTW_INFO("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
+
+	for (i = 0, j = 0; i < ETH_ALEN; i++, j += 3)
+		mac_addr[i] = key_2char2num(*(extra + j), *(extra + j + 1));
+
+	ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
+
+	issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 1, 3, 500);
+
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_psoff(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 i, j, mac_addr[ETH_ALEN];
+	struct sta_info *ptdls_sta = NULL;
+
+	RTW_INFO("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
+
+	for (i = 0, j = 0; i < ETH_ALEN; i++, j += 3)
+		mac_addr[i] = key_2char2num(*(extra + j), *(extra + j + 1));
+
+	ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
+
+	if (ptdls_sta)
+		issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 0, 3, 500);
+
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_setip(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_WFD
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+	struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
+	u8 i = 0, j = 0, k = 0, tag = 0;
+
+	RTW_INFO("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
+
+	while (i < 4) {
+		for (j = 0; j < 4; j++) {
+			if (*(extra + j + tag) == '.' || *(extra + j + tag) == '\0') {
+				if (j == 1)
+					pwfd_info->ip_address[i] = convert_ip_addr('0', '0', *(extra + (j - 1) + tag));
+				if (j == 2)
+					pwfd_info->ip_address[i] = convert_ip_addr('0', *(extra + (j - 2) + tag), *(extra + (j - 1) + tag));
+				if (j == 3)
+					pwfd_info->ip_address[i] = convert_ip_addr(*(extra + (j - 3) + tag), *(extra + (j - 2) + tag), *(extra + (j - 1) + tag));
+
+				tag += j + 1;
+				break;
+			}
+		}
+		i++;
+	}
+
+	RTW_INFO("[%s] Set IP = %u.%u.%u.%u\n", __func__,
+		 ptdlsinfo->wfd_info->ip_address[0],
+		 ptdlsinfo->wfd_info->ip_address[1],
+		 ptdlsinfo->wfd_info->ip_address[2],
+		 ptdlsinfo->wfd_info->ip_address[3]);
+
+#endif /* CONFIG_WFD */
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_getip(struct net_device *dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_WFD
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+	struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
+
+	RTW_INFO("[%s]\n", __func__);
+
+	sprintf(extra, "\n\n%u.%u.%u.%u\n",
+		pwfd_info->peer_ip_address[0], pwfd_info->peer_ip_address[1],
+		pwfd_info->peer_ip_address[2], pwfd_info->peer_ip_address[3]);
+
+	RTW_INFO("[%s] IP=%u.%u.%u.%u\n", __func__,
+		 pwfd_info->peer_ip_address[0], pwfd_info->peer_ip_address[1],
+		 pwfd_info->peer_ip_address[2], pwfd_info->peer_ip_address[3]);
+
+	wrqu->data.length = strlen(extra);
+
+#endif /* CONFIG_WFD */
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+static int rtw_tdls_getport(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_WFD
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+	struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
+
+	RTW_INFO("[%s]\n", __func__);
+
+	sprintf(extra, "\n\n%d\n", pwfd_info->peer_rtsp_ctrlport);
+	RTW_INFO("[%s] remote port = %d\n",
+		 __func__, pwfd_info->peer_rtsp_ctrlport);
+
+	wrqu->data.length = strlen(extra);
+
+#endif /* CONFIG_WFD */
+#endif /* CONFIG_TDLS */
+
+	return ret;
+
+}
+
+/* WFDTDLS, for sigma test */
+static int rtw_tdls_dis_result(struct net_device *dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_WFD
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+
+	RTW_INFO("[%s]\n", __func__);
+
+	if (ptdlsinfo->dev_discovered ) {
+		sprintf(extra, "\n\nDis=1\n");
+		ptdlsinfo->dev_discovered = false;
+	}
+
+	wrqu->data.length = strlen(extra);
+
+#endif /* CONFIG_WFD */
+#endif /* CONFIG_TDLS */
+
+	return ret;
+
+}
+
+/* WFDTDLS, for sigma test */
+static int rtw_wfd_tdls_status(struct net_device *dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+
+	RTW_INFO("[%s]\n", __func__);
+
+	sprintf(extra, "\nlink_established:%d\n"
+		"sta_cnt:%d\n"
+		"sta_maximum:%d\n"
+		"cur_channel:%d\n"
+		"tdls_enable:%d"
+#ifdef CONFIG_TDLS_CH_SW
+		"ch_sw_state:%08x\n"
+		"chsw_on:%d\n"
+		"off_ch_num:%d\n"
+		"cur_time:%d\n"
+		"ch_offset:%d\n"
+		"delay_swtich_back:%d"
+#endif
+		,
+		ptdlsinfo->link_established, ptdlsinfo->sta_cnt,
+		ptdlsinfo->sta_maximum, ptdlsinfo->cur_channel,
+		ptdlsinfo->tdls_enable
+#ifdef CONFIG_TDLS_CH_SW
+		,
+		ptdlsinfo->chsw_info.ch_sw_state,
+		ATOMIC_READ(&padapter->tdlsinfo.chsw_info.chsw_on),
+		ptdlsinfo->chsw_info.off_ch_num,
+		ptdlsinfo->chsw_info.cur_time,
+		ptdlsinfo->chsw_info.ch_offset,
+		ptdlsinfo->chsw_info.delay_switch_back
+#endif
+	       );
+
+	wrqu->data.length = strlen(extra);
+
+#endif /* CONFIG_TDLS */
+
+	return ret;
+
+}
+
+static int rtw_tdls_getsta(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+
+	int ret = 0;
+#ifdef CONFIG_TDLS
+	u8 i, j;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 addr[ETH_ALEN] = {0};
+	char charmac[17];
+	struct sta_info *ptdls_sta = NULL;
+
+	RTW_INFO("[%s] %s %d\n", __func__,
+		 (char *)wrqu->data.pointer, wrqu->data.length - 1);
+
+	if (copy_from_user(charmac, wrqu->data.pointer + 9, 17)) {
+		ret = -EFAULT;
+		goto exit;
+	}
+
+	RTW_INFO("[%s] %d, charmac:%s\n", __func__, __LINE__, charmac);
+	for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
+		addr[i] = key_2char2num(*(charmac + j), *(charmac + j + 1));
+
+	RTW_INFO("[%s] %d, charmac:%s, addr:"MAC_FMT"\n",
+		 __func__, __LINE__, charmac, MAC_ARG(addr));
+	ptdls_sta = rtw_get_stainfo(&padapter->stapriv, addr);
+	if (ptdls_sta) {
+		sprintf(extra, "\n\ntdls_sta_state=0x%08x\n", ptdls_sta->tdls_sta_state);
+		RTW_INFO("\n\ntdls_sta_state=%d\n", ptdls_sta->tdls_sta_state);
+	} else {
+		sprintf(extra, "\n\nNot found this sta\n");
+		RTW_INFO("\n\nNot found this sta\n");
+	}
+	wrqu->data.length = strlen(extra);
+
+#endif /* CONFIG_TDLS */
+exit:
+	return ret;
+
+}
+
+static int rtw_tdls_get_best_ch(struct net_device *dev,
+				struct iw_request_info *info,
+				union iwreq_data *wrqu, char *extra)
+{
+#ifdef CONFIG_FIND_BEST_CHANNEL
+	_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; pmlmeext->channel_set[i].ChannelNum != 0; i++) {
+		/* 2.4G */
+		if (pmlmeext->channel_set[i].ChannelNum == 6 || pmlmeext->channel_set[i].ChannelNum == 11) {
+			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;
+			}
+		}
+		RTW_INFO("The rx cnt of channel %3d = %d\n",
+			 pmlmeext->channel_set[i].ChannelNum,
+			 pmlmeext->channel_set[i].rx_count);
+	}
+
+	sprintf(extra, "\nbest_channel_24G = %d\n", best_channel_24G);
+	RTW_INFO("best_channel_24G = %d\n", best_channel_24G);
+
+	if (index_5G != 0) {
+		sprintf(extra, "best_channel_5G = %d\n", best_channel_5G);
+		RTW_INFO("best_channel_5G = %d\n", best_channel_5G);
+	}
+
+	wrqu->data.length = strlen(extra);
+
+#endif
+
+	return 0;
+
+}
+
+static int rtw_tdls(struct net_device *dev,
+		    struct iw_request_info *info,
+		    union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	RTW_INFO("[%s] extra = %s\n", __func__, extra);
+
+	if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == false) {
+		RTW_INFO("Discard tdls oper since hal doesn't support tdls\n");
+		return 0;
+	}
+
+	if (padapter->tdlsinfo.tdls_enable == 0) {
+		RTW_INFO("tdls haven't enabled\n");
+		return 0;
+	}
+
+	/* WFD Sigma will use the tdls enable command to let the driver know we want to test the tdls now! */
+
+	if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
+		if (!memcmp(extra, "wfdenable=", 10)) {
+			wrqu->data.length -= 10;
+			rtw_wx_tdls_wfd_enable(dev, info, wrqu, &extra[10]);
+			return ret;
+		}
+	}
+
+	if (!memcmp(extra, "weaksec=", 8)) {
+		wrqu->data.length -= 8;
+		rtw_tdls_weaksec(dev, info, wrqu, &extra[8]);
+		return ret;
+	} else if (!memcmp(extra, "tdlsenable=", 11)) {
+		wrqu->data.length -= 11;
+		rtw_tdls_enable(dev, info, wrqu, &extra[11]);
+		return ret;
+	}
+
+	if (!memcmp(extra, "setup=", 6)) {
+		wrqu->data.length -= 6;
+		rtw_tdls_setup(dev, info, wrqu, &extra[6]);
+	} else if (!memcmp(extra, "tear=", 5)) {
+		wrqu->data.length -= 5;
+		rtw_tdls_teardown(dev, info, wrqu, &extra[5]);
+	} else if (!memcmp(extra, "dis=", 4)) {
+		wrqu->data.length -= 4;
+		rtw_tdls_discovery(dev, info, wrqu, &extra[4]);
+	} else if (!memcmp(extra, "swoff=", 6)) {
+		wrqu->data.length -= 6;
+		rtw_tdls_ch_switch_off(dev, info, wrqu, &extra[6]);
+	} else if (!memcmp(extra, "sw=", 3)) {
+		wrqu->data.length -= 3;
+		rtw_tdls_ch_switch(dev, info, wrqu, &extra[3]);
+	} else if (!memcmp(extra, "dumpstack=", 10)) {
+		wrqu->data.length -= 10;
+		rtw_tdls_dump_ch(dev, info, wrqu, &extra[10]);
+	} else if (!memcmp(extra, "offchnum=", 9)) {
+		wrqu->data.length -= 9;
+		rtw_tdls_off_ch_num(dev, info, wrqu, &extra[9]);
+	} else if (!memcmp(extra, "choffset=", 9)) {
+		wrqu->data.length -= 9;
+		rtw_tdls_ch_offset(dev, info, wrqu, &extra[9]);
+	} else if (!memcmp(extra, "pson=", 5)) {
+		wrqu->data.length -= 5;
+		rtw_tdls_pson(dev, info, wrqu, &extra[5]);
+	} else if (!memcmp(extra, "psoff=", 6)) {
+		wrqu->data.length -= 6;
+		rtw_tdls_psoff(dev, info, wrqu, &extra[6]);
+	}
+
+#ifdef CONFIG_WFD
+	if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
+		if (!memcmp(extra, "setip=", 6)) {
+			wrqu->data.length -= 6;
+			rtw_tdls_setip(dev, info, wrqu, &extra[6]);
+		} else if (!memcmp(extra, "tprobe=", 6))
+			issue_tunneled_probe_req((_adapter *)rtw_netdev_priv(dev));
+	}
+#endif /* CONFIG_WFD */
+
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+
+static int rtw_tdls_get(struct net_device *dev,
+			struct iw_request_info *info,
+			union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TDLS
+
+	RTW_INFO("[%s] extra = %s\n", __func__, (char *) wrqu->data.pointer);
+
+	if (!memcmp(wrqu->data.pointer, "ip", 2))
+		rtw_tdls_getip(dev, info, wrqu, extra);
+	else if (!memcmp(wrqu->data.pointer, "port", 4))
+		rtw_tdls_getport(dev, info, wrqu, extra);
+	/* WFDTDLS, for sigma test */
+	else if (!memcmp(wrqu->data.pointer, "dis", 3))
+		rtw_tdls_dis_result(dev, info, wrqu, extra);
+	else if (!memcmp(wrqu->data.pointer, "status", 6))
+		rtw_wfd_tdls_status(dev, info, wrqu, extra);
+	else if (!memcmp(wrqu->data.pointer, "tdls_sta=", 9))
+		rtw_tdls_getsta(dev, info, wrqu, extra);
+	else if (!memcmp(wrqu->data.pointer, "best_ch", 7))
+		rtw_tdls_get_best_ch(dev, info, wrqu, extra);
+#endif /* CONFIG_TDLS */
+
+	return ret;
+}
+
+
+
+
+
+#ifdef CONFIG_INTEL_WIDI
+static int rtw_widi_set(struct net_device *dev,
+			struct iw_request_info *info,
+			union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	process_intel_widi_cmd(padapter, extra);
+
+	return ret;
+}
+
+static int rtw_widi_set_probe_request(struct net_device *dev,
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu, char *extra)
+{
+	int	ret = 0;
+	u8	*pbuf = NULL;
+	_adapter	*padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	pbuf = rtw_malloc(sizeof(l2_msg_t));
+	if (pbuf) {
+		if (copy_from_user(pbuf, wrqu->data.pointer, wrqu->data.length))
+			ret = -EFAULT;
+		/* memcpy(pbuf, wrqu->data.pointer, wrqu->data.length); */
+
+		if (wrqu->data.flags == 0)
+			intel_widi_wk_cmd(padapter, INTEL_WIDI_ISSUE_PROB_WK, pbuf, sizeof(l2_msg_t));
+		else if (wrqu->data.flags == 1)
+			rtw_set_wfd_rds_sink_info(padapter, (l2_msg_t *)pbuf);
+	}
+	return ret;
+}
+#endif /* CONFIG_INTEL_WIDI */
+
+#ifdef CONFIG_MAC_LOOPBACK_DRIVER
+
+#include <rtl8188e_hal.h>
+extern void rtl8188e_cal_txdesc_chksum(struct tx_desc *ptxdesc);
+#define cal_txdesc_chksum rtl8188e_cal_txdesc_chksum
+
+static s32 initLoopback(PADAPTER padapter)
+{
+	PLOOPBACKDATA ploopback;
+
+	if (padapter->ploopback == NULL) {
+		ploopback = (PLOOPBACKDATA)rtw_zmalloc(sizeof(LOOPBACKDATA));
+		if (ploopback == NULL)
+			return -ENOMEM;
+
+		sema_init(&ploopback->sema, 0);
+		ploopback->bstop = true;
+		ploopback->cnt = 0;
+		ploopback->size = 300;
+		memset(ploopback->msg, 0, sizeof(ploopback->msg));
+
+		padapter->ploopback = ploopback;
+	}
+
+	return 0;
+}
+
+static void freeLoopback(PADAPTER padapter)
+{
+	PLOOPBACKDATA ploopback;
+
+
+	ploopback = padapter->ploopback;
+	if (ploopback) {
+		rtw_mfree((u8 *)ploopback, sizeof(LOOPBACKDATA));
+		padapter->ploopback = NULL;
+	}
+}
+
+static s32 initpseudoadhoc(PADAPTER padapter)
+{
+	NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
+	s32 err;
+
+	networkType = Ndis802_11IBSS;
+	err = rtw_set_802_11_infrastructure_mode(padapter, networkType);
+	if (err == false)
+		return _FAIL;
+
+	err = rtw_setopmode_cmd(padapter, networkType, true);
+	if (err == _FAIL)
+		return _FAIL;
+
+	return _SUCCESS;
+}
+
+static s32 createpseudoadhoc(PADAPTER padapter)
+{
+	NDIS_802_11_AUTHENTICATION_MODE authmode;
+	struct mlme_priv *pmlmepriv;
+	NDIS_802_11_SSID *passoc_ssid;
+	WLAN_BSSID_EX *pdev_network;
+	u8 *pibss;
+	u8 ssid[] = "pseduo_ad-hoc";
+	s32 err;
+	unsigned long irqL;
+
+
+	pmlmepriv = &padapter->mlmepriv;
+
+	authmode = Ndis802_11AuthModeOpen;
+	err = rtw_set_802_11_authentication_mode(padapter, authmode);
+	if (err == false)
+		return _FAIL;
+
+	passoc_ssid = &pmlmepriv->assoc_ssid;
+	memset(passoc_ssid, 0, sizeof(NDIS_802_11_SSID));
+	passoc_ssid->SsidLength = sizeof(ssid) - 1;
+	memcpy(passoc_ssid->Ssid, ssid, passoc_ssid->SsidLength);
+
+	pdev_network = &padapter->registrypriv.dev_network;
+	pibss = padapter->registrypriv.dev_network.MacAddress;
+	memcpy(&pdev_network->Ssid, passoc_ssid, sizeof(NDIS_802_11_SSID));
+
+	rtw_update_registrypriv_dev_network(padapter);
+	rtw_generate_random_ibss(pibss);
+
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+	/*pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;*/
+	init_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
+
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+	{
+		struct wlan_network *pcur_network;
+		struct sta_info *psta;
+
+		/* 3  create a new psta */
+		pcur_network = &pmlmepriv->cur_network;
+
+		/* clear psta in the cur_network, if any */
+		psta = rtw_get_stainfo(&padapter->stapriv, pcur_network->network.MacAddress);
+		if (psta)
+			rtw_free_stainfo(padapter, psta);
+
+		psta = rtw_alloc_stainfo(&padapter->stapriv, pibss);
+		if (psta == NULL)
+			return _FAIL;
+
+		/* 3  join psudo AdHoc */
+		pcur_network->join_res = 1;
+		pcur_network->aid = psta->aid = 1;
+		memcpy(&pcur_network->network, pdev_network, get_WLAN_BSSID_EX_sz(pdev_network));
+
+		/* set msr to WIFI_FW_ADHOC_STATE */
+		padapter->hw_port = HW_PORT0;
+		Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
+
+	}
+
+	return _SUCCESS;
+}
+
+static struct xmit_frame *createloopbackpkt(PADAPTER padapter, u32 size)
+{
+	struct xmit_priv *pxmitpriv;
+	struct xmit_frame *pframe;
+	struct xmit_buf *pxmitbuf;
+	struct pkt_attrib *pattrib;
+	struct tx_desc *desc;
+	u8 *pkt_start, *pkt_end, *ptr;
+	struct rtw_ieee80211_hdr *hdr;
+	s32 bmcast;
+	unsigned long irqL;
+
+
+	if ((TXDESC_SIZE + WLANHDR_OFFSET + size) > MAX_XMITBUF_SZ)
+		return NULL;
+
+	pxmitpriv = &padapter->xmitpriv;
+	pframe = NULL;
+
+	/* 2 1. allocate xmit frame */
+	pframe = rtw_alloc_xmitframe(pxmitpriv);
+	if (pframe == NULL)
+		return NULL;
+	pframe->padapter = padapter;
+
+	/* 2 2. allocate xmit buffer */
+	_enter_critical_bh(&pxmitpriv->lock, &irqL);
+	pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
+	_exit_critical_bh(&pxmitpriv->lock, &irqL);
+	if (pxmitbuf == NULL) {
+		rtw_free_xmitframe(pxmitpriv, pframe);
+		return NULL;
+	}
+
+	pframe->pxmitbuf = pxmitbuf;
+	pframe->buf_addr = pxmitbuf->pbuf;
+	pxmitbuf->priv_data = pframe;
+
+	/* 2 3. update_attrib() */
+	pattrib = &pframe->attrib;
+
+	/* init xmitframe attribute */
+	memset(pattrib, 0, sizeof(struct pkt_attrib));
+
+	pattrib->ether_type = 0x8723;
+	memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+	memset(pattrib->dst, 0xFF, ETH_ALEN);
+	memcpy(pattrib->ra, pattrib->dst, 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;
+
+	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->pktlen = size;
+	pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->pktlen;
+
+	/* 2 4. fill TX descriptor */
+	desc = (struct tx_desc *)pframe->buf_addr;
+	memset(desc, 0, TXDESC_SIZE);
+
+	fill_default_txdesc(pframe, (u8 *)desc);
+
+	/* Hw set sequence number */
+	((PTXDESC)desc)->hwseq_en = 0; /* HWSEQ_EN, 0:disable, 1:enable
+ * ((PTXDESC)desc)->hwseq_sel = 0;  */ /* HWSEQ_SEL */
+
+	((PTXDESC)desc)->disdatafb = 1;
+
+	/* convert to little endian */
+	desc->txdw0 = cpu_to_le32(desc->txdw0);
+	desc->txdw1 = cpu_to_le32(desc->txdw1);
+	desc->txdw2 = cpu_to_le32(desc->txdw2);
+	desc->txdw3 = cpu_to_le32(desc->txdw3);
+	desc->txdw4 = cpu_to_le32(desc->txdw4);
+	desc->txdw5 = cpu_to_le32(desc->txdw5);
+	desc->txdw6 = cpu_to_le32(desc->txdw6);
+	desc->txdw7 = cpu_to_le32(desc->txdw7);
+	cal_txdesc_chksum(desc);
+
+	/* 2 5. coalesce */
+	pkt_start = pframe->buf_addr + TXDESC_SIZE;
+	pkt_end = pkt_start + pattrib->last_txcmdsz;
+
+	/* 3 5.1. make wlan header, make_wlanhdr() */
+	hdr = (struct rtw_ieee80211_hdr *)pkt_start;
+	set_frame_sub_type(&hdr->frame_ctl, pattrib->subtype);
+	memcpy(hdr->addr1, pattrib->dst, ETH_ALEN); /* DA */
+	memcpy(hdr->addr2, pattrib->src, ETH_ALEN); /* SA */
+	memcpy(hdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN); /* RA, BSSID */
+
+	/* 3 5.2. make payload */
+	ptr = pkt_start + pattrib->hdrlen;
+	get_random_bytes(ptr, pkt_end - ptr);
+
+	pxmitbuf->len = TXDESC_SIZE + pattrib->last_txcmdsz;
+	pxmitbuf->ptail += pxmitbuf->len;
+
+	return pframe;
+}
+
+static void freeloopbackpkt(PADAPTER padapter, struct xmit_frame *pframe)
+{
+	struct xmit_priv *pxmitpriv;
+	struct xmit_buf *pxmitbuf;
+
+
+	pxmitpriv = &padapter->xmitpriv;
+	pxmitbuf = pframe->pxmitbuf;
+
+	rtw_free_xmitframe(pxmitpriv, pframe);
+	rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+}
+
+static void printdata(u8 *pbuf, u32 len)
+{
+	u32 i, val;
+
+
+	for (i = 0; (i + 4) <= len; i += 4) {
+		printk("%08X", *(u32 *)(pbuf + i));
+		if ((i + 4) & 0x1F)
+			printk(" ");
+		else
+			printk("\n");
+	}
+
+	if (i < len) {
+#ifdef __BIG_ENDIAN
+		for (; i < len, i++)
+			printk("%02X", pbuf + i);
+#else /* __LITTLE_ENDIAN */
+		u8 str[9];
+		u8 n;
+		val = 0;
+		n = len - i;
+		memcpy(&val, pbuf + i, n);
+		sprintf(str, "%08X", val);
+		n = (4 - n) * 2;
+		printk("%8s", str + n);
+#endif /* __LITTLE_ENDIAN */
+	}
+	printk("\n");
+}
+
+static u8 pktcmp(PADAPTER padapter, u8 *txbuf, u32 txsz, u8 *rxbuf, u32 rxsz)
+{
+	PHAL_DATA_TYPE phal;
+	struct recv_stat *prxstat;
+	struct recv_stat report;
+	PRXREPORT prxreport;
+	u32 drvinfosize;
+	u32 rxpktsize;
+	u8 fcssize;
+	u8 ret = false;
+
+	prxstat = (struct recv_stat *)rxbuf;
+	report.rxdw0 = le32_to_cpu(prxstat->rxdw0);
+	report.rxdw1 = le32_to_cpu(prxstat->rxdw1);
+	report.rxdw2 = le32_to_cpu(prxstat->rxdw2);
+	report.rxdw3 = le32_to_cpu(prxstat->rxdw3);
+	report.rxdw4 = le32_to_cpu(prxstat->rxdw4);
+	report.rxdw5 = le32_to_cpu(prxstat->rxdw5);
+
+	prxreport = (PRXREPORT)&report;
+	drvinfosize = prxreport->drvinfosize << 3;
+	rxpktsize = prxreport->pktlen;
+
+	phal = GET_HAL_DATA(padapter);
+	if (phal->ReceiveConfig & RCR_APPFCS)
+		fcssize = IEEE80211_FCS_LEN;
+	else
+		fcssize = 0;
+
+	if ((txsz - TXDESC_SIZE) != (rxpktsize - fcssize)) {
+		RTW_INFO("%s: ERROR! size not match tx/rx=%d/%d !\n",
+			 __func__, txsz - TXDESC_SIZE, rxpktsize - fcssize);
+		ret = false;
+	} else {
+		ret = !memcmp(txbuf + TXDESC_SIZE, \
+				  rxbuf + RXDESC_SIZE + drvinfosize, \
+				  txsz - TXDESC_SIZE);
+		if (ret == false)
+			RTW_INFO("%s: ERROR! pkt content mismatch!\n", __func__);
+	}
+
+	if (ret == false) {
+		RTW_INFO("\n%s: TX PKT total=%d, desc=%d, content=%d\n",
+			 __func__, txsz, TXDESC_SIZE, txsz - TXDESC_SIZE);
+		RTW_INFO("%s: TX DESC size=%d\n", __func__, TXDESC_SIZE);
+		printdata(txbuf, TXDESC_SIZE);
+		RTW_INFO("%s: TX content size=%d\n", __func__, txsz - TXDESC_SIZE);
+		printdata(txbuf + TXDESC_SIZE, txsz - TXDESC_SIZE);
+
+		RTW_INFO("\n%s: RX PKT read=%d offset=%d(%d,%d) content=%d\n",
+			__func__, rxsz, RXDESC_SIZE + drvinfosize, RXDESC_SIZE, drvinfosize, rxpktsize);
+		if (rxpktsize != 0) {
+			RTW_INFO("%s: RX DESC size=%d\n", __func__, RXDESC_SIZE);
+			printdata(rxbuf, RXDESC_SIZE);
+			RTW_INFO("%s: RX drvinfo size=%d\n", __func__, drvinfosize);
+			printdata(rxbuf + RXDESC_SIZE, drvinfosize);
+			RTW_INFO("%s: RX content size=%d\n", __func__, rxpktsize);
+			printdata(rxbuf + RXDESC_SIZE + drvinfosize, rxpktsize);
+		} else {
+			RTW_INFO("%s: RX data size=%d\n", __func__, rxsz);
+			printdata(rxbuf, rxsz);
+		}
+	}
+
+	return ret;
+}
+
+thread_return lbk_thread(thread_context context)
+{
+	s32 err;
+	PADAPTER padapter;
+	PLOOPBACKDATA ploopback;
+	struct xmit_frame *pxmitframe;
+	u32 cnt, ok, fail, headerlen;
+	u32 pktsize;
+	u32 ff_hwaddr;
+
+
+	padapter = (PADAPTER)context;
+	ploopback = padapter->ploopback;
+	if (ploopback == NULL)
+		return -1;
+	cnt = 0;
+	ok = 0;
+	fail = 0;
+
+	daemonize("%s", "RTW_LBK_THREAD");
+	allow_signal(SIGTERM);
+
+	do {
+		if (ploopback->size == 0) {
+			get_random_bytes(&pktsize, 4);
+			pktsize = (pktsize % 1535) + 1; /* 1~1535 */
+		} else
+			pktsize = ploopback->size;
+
+		pxmitframe = createloopbackpkt(padapter, pktsize);
+		if (pxmitframe == NULL) {
+			sprintf(ploopback->msg, "loopback FAIL! 3. create Packet FAIL!");
+			break;
+		}
+
+		ploopback->txsize = TXDESC_SIZE + pxmitframe->attrib.last_txcmdsz;
+		memcpy(ploopback->txbuf, pxmitframe->buf_addr, ploopback->txsize);
+		ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
+		cnt++;
+		RTW_INFO("%s: wirte port cnt=%d size=%d\n", __func__, cnt, ploopback->txsize);
+		pxmitframe->pxmitbuf->pdata = ploopback->txbuf;
+		rtw_write_port(padapter, ff_hwaddr, ploopback->txsize, (u8 *)pxmitframe->pxmitbuf);
+
+		/* wait for rx pkt */
+		_rtw_down_sema(&ploopback->sema);
+
+		err = pktcmp(padapter, ploopback->txbuf, ploopback->txsize, ploopback->rxbuf, ploopback->rxsize);
+		if (err )
+			ok++;
+		else
+			fail++;
+
+		ploopback->txsize = 0;
+		memset(ploopback->txbuf, 0, 0x8000);
+		ploopback->rxsize = 0;
+		memset(ploopback->rxbuf, 0, 0x8000);
+
+		freeloopbackpkt(padapter, pxmitframe);
+		pxmitframe = NULL;
+
+		if (signal_pending(current))
+			flush_signals(current);
+
+		if ((ploopback->bstop ) ||
+		    ((ploopback->cnt != 0) && (ploopback->cnt == cnt))) {
+			u32 ok_rate, fail_rate, all;
+			all = cnt;
+			ok_rate = (ok * 100) / all;
+			fail_rate = (fail * 100) / all;
+			sprintf(ploopback->msg, \
+				"loopback result: ok=%d%%(%d/%d),error=%d%%(%d/%d)", \
+				ok_rate, ok, all, fail_rate, fail, all);
+			break;
+		}
+	} while (1);
+
+	ploopback->bstop = true;
+
+	thread_exit();
+}
+
+static void loopbackTest(PADAPTER padapter, u32 cnt, u32 size, u8 *pmsg)
+{
+	PLOOPBACKDATA ploopback;
+	u32 len;
+	s32 err;
+
+
+	ploopback = padapter->ploopback;
+
+	if (ploopback) {
+		if (ploopback->bstop == false) {
+			ploopback->bstop = true;
+			up(&ploopback->sema);
+		}
+		len = 0;
+		do {
+			len = strlen(ploopback->msg);
+			if (len)
+				break;
+			rtw_msleep_os(1);
+		} while (1);
+		memcpy(pmsg, ploopback->msg, len + 1);
+		freeLoopback(padapter);
+
+		return;
+	}
+
+	/* disable dynamic algorithm	 */
+	rtw_phydm_ability_backup(padapter);
+	rtw_phydm_func_disable_all(padapter);
+
+	/* create pseudo ad-hoc connection */
+	err = initpseudoadhoc(padapter);
+	if (err == _FAIL) {
+		sprintf(pmsg, "loopback FAIL! 1.1 init ad-hoc FAIL!");
+		return;
+	}
+
+	err = createpseudoadhoc(padapter);
+	if (err == _FAIL) {
+		sprintf(pmsg, "loopback FAIL! 1.2 create ad-hoc master FAIL!");
+		return;
+	}
+
+	err = initLoopback(padapter);
+	if (err) {
+		sprintf(pmsg, "loopback FAIL! 2. init FAIL! error code=%d", err);
+		return;
+	}
+
+	ploopback = padapter->ploopback;
+
+	ploopback->bstop = false;
+	ploopback->cnt = cnt;
+	ploopback->size = size;
+	ploopback->lbkthread = kthread_run(lbk_thread, padapter, "RTW_LBK_THREAD");
+	if (IS_ERR(padapter->lbkthread)) {
+		freeLoopback(padapter);
+		sprintf(pmsg, "loopback start FAIL! cnt=%d", cnt);
+		return;
+	}
+
+	sprintf(pmsg, "loopback start! cnt=%d", cnt);
+}
+#endif /* CONFIG_MAC_LOOPBACK_DRIVER */
+
+static int rtw_test(
+	struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu, char *extra)
+{
+	u32 len;
+	u8 *pbuf, *pch;
+	char *ptmp;
+	u8 *delim = ",";
+	PADAPTER padapter = rtw_netdev_priv(dev);
+
+
+	RTW_INFO("+%s\n", __func__);
+	len = wrqu->data.length;
+
+	pbuf = (u8 *)rtw_zmalloc(len);
+	if (pbuf == NULL) {
+		RTW_INFO("%s: no memory!\n", __func__);
+		return -ENOMEM;
+	}
+
+	if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
+		rtw_mfree(pbuf, len);
+		RTW_INFO("%s: copy from user fail!\n", __func__);
+		return -EFAULT;
+	}
+	RTW_INFO("%s: string=\"%s\"\n", __func__, pbuf);
+
+	ptmp = (char *)pbuf;
+	pch = strsep(&ptmp, delim);
+	if ((pch == NULL) || (strlen(pch) == 0)) {
+		rtw_mfree(pbuf, len);
+		RTW_INFO("%s: parameter error(level 1)!\n", __func__);
+		return -EFAULT;
+	}
+
+#ifdef CONFIG_MAC_LOOPBACK_DRIVER
+	if (strcmp(pch, "loopback") == 0) {
+		s32 cnt = 0;
+		u32 size = 64;
+
+		pch = strsep(&ptmp, delim);
+		if ((pch == NULL) || (strlen(pch) == 0)) {
+			rtw_mfree(pbuf, len);
+			RTW_INFO("%s: parameter error(level 2)!\n", __func__);
+			return -EFAULT;
+		}
+
+		sscanf(pch, "%d", &cnt);
+		RTW_INFO("%s: loopback cnt=%d\n", __func__, cnt);
+
+		pch = strsep(&ptmp, delim);
+		if ((pch == NULL) || (strlen(pch) == 0)) {
+			rtw_mfree(pbuf, len);
+			RTW_INFO("%s: parameter error(level 2)!\n", __func__);
+			return -EFAULT;
+		}
+
+		sscanf(pch, "%d", &size);
+		RTW_INFO("%s: loopback size=%d\n", __func__, size);
+
+		loopbackTest(padapter, cnt, size, extra);
+		wrqu->data.length = strlen(extra) + 1;
+
+		goto free_buf;
+	}
+#endif
+
+
+#ifdef CONFIG_BT_COEXIST
+	if (strcmp(pch, "bton") == 0) {
+		rtw_btcoex_SetManualControl(padapter, false);
+		goto free_buf;
+	} else if (strcmp(pch, "btoff") == 0) {
+		rtw_btcoex_SetManualControl(padapter, true);
+		goto free_buf;
+	}
+#endif
+
+	if (strcmp(pch, "h2c") == 0) {
+		u8 param[8];
+		u8 count = 0;
+		u32 tmp;
+		u8 i;
+		u32 pos;
+		u8 ret;
+
+		do {
+			pch = strsep(&ptmp, delim);
+			if ((pch == NULL) || (strlen(pch) == 0))
+				break;
+
+			sscanf(pch, "%x", &tmp);
+			param[count++] = (u8)tmp;
+		} while (count < 8);
+
+		if (count == 0) {
+			rtw_mfree(pbuf, len);
+			RTW_INFO("%s: parameter error(level 2)!\n", __func__);
+			return -EFAULT;
+		}
+
+		ret = rtw_test_h2c_cmd(padapter, param, count);
+
+		pos = sprintf(extra, "H2C ID=0x%02x content=", param[0]);
+		for (i = 1; i < count; i++)
+			pos += sprintf(extra + pos, "%02x,", param[i]);
+		extra[pos] = 0;
+		pos--;
+		pos += sprintf(extra + pos, " %s", ret == _FAIL ? "FAIL" : "OK");
+
+		wrqu->data.length = strlen(extra) + 1;
+
+		goto free_buf;
+	}
+
+free_buf:
+	rtw_mfree(pbuf, len);
+	return 0;
+}
+
+static iw_handler rtw_handlers[] = {
+	NULL,					/* SIOCSIWCOMMIT */
+	rtw_wx_get_name,		/* SIOCGIWNAME */
+	dummy,					/* SIOCSIWNWID */
+	dummy,					/* SIOCGIWNWID */
+	rtw_wx_set_freq,		/* SIOCSIWFREQ */
+	rtw_wx_get_freq,		/* SIOCGIWFREQ */
+	rtw_wx_set_mode,		/* SIOCSIWMODE */
+	rtw_wx_get_mode,		/* SIOCGIWMODE */
+	dummy,					/* SIOCSIWSENS */
+	rtw_wx_get_sens,		/* SIOCGIWSENS */
+	NULL,					/* SIOCSIWRANGE */
+	rtw_wx_get_range,		/* SIOCGIWRANGE */
+	rtw_wx_set_priv,		/* SIOCSIWPRIV */
+	NULL,					/* SIOCGIWPRIV */
+	NULL,					/* SIOCSIWSTATS */
+	NULL,					/* SIOCGIWSTATS */
+	dummy,					/* SIOCSIWSPY */
+	dummy,					/* SIOCGIWSPY */
+	NULL,					/* SIOCGIWTHRSPY */
+	NULL,					/* SIOCWIWTHRSPY */
+	rtw_wx_set_wap,		/* SIOCSIWAP */
+	rtw_wx_get_wap,		/* SIOCGIWAP */
+	rtw_wx_set_mlme,		/* request MLME operation; uses struct iw_mlme */
+	dummy,					/* SIOCGIWAPLIST -- depricated */
+	rtw_wx_set_scan,		/* SIOCSIWSCAN */
+	rtw_wx_get_scan,		/* SIOCGIWSCAN */
+	rtw_wx_set_essid,		/* SIOCSIWESSID */
+	rtw_wx_get_essid,		/* SIOCGIWESSID */
+	dummy,					/* SIOCSIWNICKN */
+	rtw_wx_get_nick,		/* SIOCGIWNICKN */
+	NULL,					/* -- hole -- */
+	NULL,					/* -- hole -- */
+	rtw_wx_set_rate,		/* SIOCSIWRATE */
+	rtw_wx_get_rate,		/* SIOCGIWRATE */
+	rtw_wx_set_rts,			/* SIOCSIWRTS */
+	rtw_wx_get_rts,			/* SIOCGIWRTS */
+	rtw_wx_set_frag,		/* SIOCSIWFRAG */
+	rtw_wx_get_frag,		/* SIOCGIWFRAG */
+	dummy,					/* SIOCSIWTXPOW */
+	dummy,					/* SIOCGIWTXPOW */
+	dummy,					/* SIOCSIWRETRY */
+	rtw_wx_get_retry,		/* SIOCGIWRETRY */
+	rtw_wx_set_enc,			/* SIOCSIWENCODE */
+	rtw_wx_get_enc,			/* SIOCGIWENCODE */
+	dummy,					/* SIOCSIWPOWER */
+	rtw_wx_get_power,		/* SIOCGIWPOWER */
+	NULL,					/*---hole---*/
+	NULL,					/*---hole---*/
+	rtw_wx_set_gen_ie,		/* SIOCSIWGENIE */
+	NULL,					/* SIOCGWGENIE */
+	rtw_wx_set_auth,		/* SIOCSIWAUTH */
+	NULL,					/* SIOCGIWAUTH */
+	rtw_wx_set_enc_ext,		/* SIOCSIWENCODEEXT */
+	NULL,					/* SIOCGIWENCODEEXT */
+	rtw_wx_set_pmkid,		/* SIOCSIWPMKSA */
+	NULL,					/*---hole---*/
+};
+
+
+static const struct iw_priv_args rtw_private_args[] = {
+	{
+		SIOCIWFIRSTPRIV + 0x0,
+		IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x1,
+		IW_PRIV_TYPE_CHAR | 0x7FF,
+		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x4,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x5,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x6,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
+	},
+	/* for PLATFORM_MT53XX	 */
+	{
+		SIOCIWFIRSTPRIV + 0x7,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x8,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x9,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
+	},
+
+	/* for RTK_DMP_PLATFORM	 */
+	{
+		SIOCIWFIRSTPRIV + 0xA,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
+	},
+
+	{
+		SIOCIWFIRSTPRIV + 0xB,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0xC,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0xD,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x10,
+		IW_PRIV_TYPE_CHAR | 1024, 0, "p2p_set"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x11,
+		IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , "p2p_get"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x12, 0, 0, "NULL"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x13,
+		IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64 , "p2p_get2"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x14,
+		IW_PRIV_TYPE_CHAR  | 64, 0, "tdls"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x15,
+		IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024 , "tdls_get"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x16,
+		IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
+	},
+
+	{SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ , 0 , "rereg_nd_name"},
+#ifdef CONFIG_MP_INCLUDED
+	{SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0,  "NULL"},
+	{SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "NULL"},
+#else
+	{SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"},
+	{SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
+#endif
+	{
+		SIOCIWFIRSTPRIV + 0x1D,
+		IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
+	},
+
+#ifdef CONFIG_INTEL_WIDI
+	{
+		SIOCIWFIRSTPRIV + 0x1E,
+		IW_PRIV_TYPE_CHAR | 1024, 0, "widi_set"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x1F,
+		IW_PRIV_TYPE_CHAR | 128, 0, "widi_prob_req"
+	},
+#endif /* CONFIG_INTEL_WIDI */
+
+	{ SIOCIWFIRSTPRIV + 0x0E, IW_PRIV_TYPE_CHAR | 1024, 0 , ""},  /* set  */
+	{ SIOCIWFIRSTPRIV + 0x0F, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , ""},/* get
+ * --- sub-ioctls definitions --- */
+
+#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
+	{ VENDOR_IE_SET, IW_PRIV_TYPE_CHAR | 1024 , 0 , "vendor_ie_set" },
+	{ VENDOR_IE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "vendor_ie_get" },
+#endif
+#ifdef CONFIG_WOWLAN
+	{ MP_WOW_ENABLE , IW_PRIV_TYPE_CHAR | 1024, 0, "wow_mode" },
+	{ MP_WOW_SET_PATTERN , IW_PRIV_TYPE_CHAR | 1024, 0, "wow_set_pattern" },
+#endif
+#ifdef CONFIG_AP_WOWLAN
+	{ MP_AP_WOW_ENABLE , IW_PRIV_TYPE_CHAR | 1024, 0, "ap_wow_mode" }, /* set  */
+#endif
+#ifdef CONFIG_SDIO_INDIRECT_ACCESS
+	{ MP_SD_IREAD, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "sd_iread" },
+	{ MP_SD_IWRITE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "sd_iwrite" },
+#endif
+};
+
+
+static const struct iw_priv_args rtw_mp_private_args[] = {
+	/* --- sub-ioctls definitions --- */
+#ifdef CONFIG_MP_INCLUDED
+	{ MP_START , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_start" },
+	{ MP_PHYPARA, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_phypara" },
+	{ MP_STOP , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_stop" },
+	{ MP_CHANNEL , IW_PRIV_TYPE_CHAR | 1024 , IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_channel" },
+	{ MP_BANDWIDTH , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_bandwidth"},
+	{ MP_RATE , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate" },
+	{ MP_RESET_STATS , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_reset_stats"},
+	{ MP_QUERY , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , "mp_query"},
+	{ READ_REG , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_reg" },
+	{ MP_RATE , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate" },
+	{ READ_RF , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_rf" },
+	{ MP_PSD , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_psd"},
+	{ MP_DUMP, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_dump" },
+	{ MP_TXPOWER , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_txpower"},
+	{ MP_ANT_TX , IW_PRIV_TYPE_CHAR | 1024,  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_tx"},
+	{ MP_ANT_RX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_rx"},
+	{ WRITE_REG , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_reg" },
+	{ WRITE_RF , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_rf" },
+	{ MP_CTX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ctx"},
+	{ MP_ARX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_arx"},
+	{ MP_THER , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ther"},
+	{ EFUSE_SET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_set" },
+	{ EFUSE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get" },
+	{ MP_PWRTRK , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_pwrtrk"},
+	{ MP_QueryDrvStats, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_drvquery" },
+	{ MP_IOCTL, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_ioctl"},
+	{ MP_SetRFPathSwh, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_setrfpath" },
+	{ MP_PwrCtlDM, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_pwrctldm" },
+	{ MP_GET_TXPOWER_INX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_get_txpower" },
+	{ MP_GETVER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_priv_ver" },
+	{ MP_MON, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_mon" },
+	{ EFUSE_MASK, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_mask" },
+	{ EFUSE_FILE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_file" },
+	{ MP_TX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_tx" },
+	{ MP_RX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rx" },
+	{ MP_HW_TX_MODE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_hxtx" },
+	{ CTA_TEST, IW_PRIV_TYPE_CHAR | 1024, 0, "cta_test"},
+	{ MP_IQK, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_iqk"},
+	{ MP_LCK, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_lck"},
+#ifdef CONFIG_RTW_CUSTOMER_STR
+	{ MP_CUSTOMER_STR, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "customer_str" },
+#endif
+
+#endif /* CONFIG_MP_INCLUDED */
+};
+
+static iw_handler rtw_private_handler[] = {
+	rtw_wx_write32,					/* 0x00 */
+	rtw_wx_read32,					/* 0x01 */
+	rtw_drvext_hdl,					/* 0x02 */
+#ifdef MP_IOCTL_HDL
+	rtw_mp_ioctl_hdl,				/* 0x03 */
+#else
+	rtw_wx_priv_null,
+#endif
+	/* for MM DTV platform */
+	rtw_get_ap_info,					/* 0x04 */
+
+	rtw_set_pid,						/* 0x05 */
+	rtw_wps_start,					/* 0x06 */
+
+	/* for PLATFORM_MT53XX */
+	rtw_wx_get_sensitivity,			/* 0x07 */
+	rtw_wx_set_mtk_wps_probe_ie,	/* 0x08 */
+	rtw_wx_set_mtk_wps_ie,			/* 0x09 */
+
+	/* for RTK_DMP_PLATFORM
+	 * Set Channel depend on the country code */
+	rtw_wx_set_channel_plan,		/* 0x0A */
+
+	rtw_dbg_port,					/* 0x0B */
+	rtw_wx_write_rf,					/* 0x0C */
+	rtw_wx_read_rf,					/* 0x0D */
+
+	rtw_priv_set,					/*0x0E*/
+	rtw_priv_get,					/*0x0F*/
+
+	rtw_p2p_set,					/* 0x10 */
+	rtw_p2p_get,					/* 0x11 */
+	NULL,							/* 0x12 */
+	rtw_p2p_get2,					/* 0x13 */
+
+	rtw_tdls,						/* 0x14 */
+	rtw_tdls_get,					/* 0x15 */
+
+	rtw_pm_set,						/* 0x16 */
+	rtw_wx_priv_null,				/* 0x17 */
+	rtw_rereg_nd_name,				/* 0x18 */
+	rtw_wx_priv_null,				/* 0x19 */
+#ifdef CONFIG_MP_INCLUDED
+	rtw_wx_priv_null,				/* 0x1A */
+	rtw_wx_priv_null,				/* 0x1B */
+#else
+	rtw_mp_efuse_set,				/* 0x1A */
+	rtw_mp_efuse_get,				/* 0x1B */
+#endif
+	NULL,							/* 0x1C is reserved for hostapd */
+	rtw_test,						/* 0x1D */
+#ifdef CONFIG_INTEL_WIDI
+	rtw_widi_set,					/* 0x1E */
+	rtw_widi_set_probe_request,		/* 0x1F */
+#endif /* CONFIG_INTEL_WIDI */
+};
+
+#if WIRELESS_EXT >= 17
+static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct iw_statistics *piwstats = &padapter->iwstats;
+	int tmp_level = 0;
+	int tmp_qual = 0;
+	int tmp_noise = 0;
+
+	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
+		piwstats->qual.qual = 0;
+		piwstats->qual.level = 0;
+		piwstats->qual.noise = 0;
+		/* RTW_INFO("No link  level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise); */
+	} else {
+#ifdef CONFIG_SIGNAL_DISPLAY_DBM
+		tmp_level = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);
+#else
+#ifdef CONFIG_SIGNAL_SCALE_MAPPING
+		tmp_level = padapter->recvpriv.signal_strength;
+#else
+		{
+			/* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */
+
+			HAL_DATA_TYPE *pHal = GET_HAL_DATA(padapter);
+
+			tmp_level = (u8)odm_signal_scale_mapping(&pHal->odmpriv, padapter->recvpriv.signal_strength);
+		}
+#endif
+#endif
+
+		tmp_qual = padapter->recvpriv.signal_qual;
+		rtw_get_noise(padapter);
+		tmp_noise = padapter->recvpriv.noise;
+		/* RTW_INFO("level:%d, qual:%d, noise:%d, rssi (%d)\n", tmp_level, tmp_qual, tmp_noise,padapter->recvpriv.rssi); */
+
+		piwstats->qual.level = tmp_level;
+		piwstats->qual.qual = tmp_qual;
+		piwstats->qual.noise = tmp_noise;
+	}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14))
+	piwstats->qual.updated = IW_QUAL_ALL_UPDATED ;/* |IW_QUAL_DBM; */
+#else
+#ifdef RTK_DMP_PLATFORM
+	/* IW_QUAL_DBM= 0x8, if driver use this flag, wireless extension will show value of dbm. */
+	/* remove this flag for show percentage 0~100 */
+	piwstats->qual.updated = 0x07;
+#else
+	piwstats->qual.updated = 0x0f;
+#endif
+#endif
+
+#ifdef CONFIG_SIGNAL_DISPLAY_DBM
+	piwstats->qual.updated = piwstats->qual.updated | IW_QUAL_DBM;
+#endif
+
+	return &padapter->iwstats;
+}
+#endif
+
+#ifdef CONFIG_WIRELESS_EXT
+struct iw_handler_def rtw_handlers_def = {
+	.standard = rtw_handlers,
+	.num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) || defined(CONFIG_WEXT_PRIV)
+	.private = rtw_private_handler,
+	.private_args = (struct iw_priv_args *)rtw_private_args,
+	.num_private = sizeof(rtw_private_handler) / sizeof(iw_handler),
+	.num_private_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args),
+#endif
+#if WIRELESS_EXT >= 17
+	.get_wireless_stats = rtw_get_wireless_stats,
+#endif
+};
+#endif
+
+/* copy from net/wireless/wext.c start
+ * ----------------------------------------------------------------
+ *
+ * Calculate size of private arguments
+ */
+static const char iw_priv_type_size[] = {
+	0,                              /* IW_PRIV_TYPE_NONE */
+	1,                              /* IW_PRIV_TYPE_BYTE */
+	1,                              /* IW_PRIV_TYPE_CHAR */
+	0,                              /* Not defined */
+	sizeof(__u32),                  /* IW_PRIV_TYPE_INT */
+	sizeof(struct iw_freq),         /* IW_PRIV_TYPE_FLOAT */
+	sizeof(struct sockaddr),        /* IW_PRIV_TYPE_ADDR */
+	0,                              /* Not defined */
+};
+
+static int get_priv_size(__u16 args)
+{
+	int num = args & IW_PRIV_SIZE_MASK;
+	int type = (args & IW_PRIV_TYPE_MASK) >> 12;
+
+	return num * iw_priv_type_size[type];
+}
+/* copy from net/wireless/wext.c end */
+
+
+static int _rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data)
+{
+	int err = 0;
+	u8 *input = NULL;
+	u32 input_len = 0;
+	const char delim[] = " ";
+	u8 *output = NULL;
+	u32 output_len = 0;
+	u32 count = 0;
+	u8 *buffer = NULL;
+	u32 buffer_len = 0;
+	char *ptr = NULL;
+	u8 cmdname[17] = {0}; /* IFNAMSIZ+1 */
+	u32 cmdlen;
+	s32 len;
+	u8 *extra = NULL;
+	u32 extra_size = 0;
+
+	s32 k;
+	const iw_handler *priv;		/* Private ioctl */
+	const struct iw_priv_args *priv_args;	/* Private ioctl description */
+	const struct iw_priv_args *mp_priv_args;	/*MP Private ioctl description */
+	const struct iw_priv_args *sel_priv_args;	/*Selected Private ioctl description */
+	u32 num_priv;				/* Number of ioctl */
+	u32 num_priv_args;			/* Number of descriptions */
+	u32 num_mp_priv_args;			/*Number of MP descriptions */
+	u32 num_sel_priv_args;			/*Number of Selected descriptions */
+	iw_handler handler;
+	int temp;
+	int subcmd = 0;				/* sub-ioctl index */
+	int offset = 0;				/* Space for sub-ioctl index */
+
+	union iwreq_data wdata;
+
+	memcpy(&wdata, wrq_data, sizeof(wdata));
+
+	input_len = wdata.data.length;
+	if (!input_len)
+		return -EINVAL;
+	input = rtw_zmalloc(input_len);
+	if (NULL == input)
+		return -ENOMEM;
+	if (copy_from_user(input, wdata.data.pointer, input_len)) {
+		err = -EFAULT;
+		goto exit;
+	}
+	input[input_len - 1] = '\0';
+	ptr = input;
+	len = input_len;
+
+	if (ptr == NULL) {
+		err = -EOPNOTSUPP;
+		goto exit;
+	}
+
+	sscanf(ptr, "%16s", cmdname);
+	cmdlen = strlen(cmdname);
+	RTW_INFO("%s: cmd=%s\n", __func__, cmdname);
+
+	/* skip command string */
+	if (cmdlen > 0)
+		cmdlen += 1; /* skip one space */
+	ptr += cmdlen;
+	len -= cmdlen;
+	RTW_INFO("%s: parameters=%s\n", __func__, ptr);
+
+	priv = rtw_private_handler;
+	priv_args = rtw_private_args;
+	mp_priv_args = rtw_mp_private_args;
+	num_priv = sizeof(rtw_private_handler) / sizeof(iw_handler);
+	num_priv_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args);
+	num_mp_priv_args = sizeof(rtw_mp_private_args) / sizeof(struct iw_priv_args);
+
+	if (num_priv_args == 0) {
+		err = -EOPNOTSUPP;
+		goto exit;
+	}
+
+	/* Search the correct ioctl */
+	k = -1;
+	sel_priv_args = priv_args;
+	num_sel_priv_args = num_priv_args;
+	while
+	((++k < num_sel_priv_args) && strcmp(sel_priv_args[k].name, cmdname))
+		;
+
+	/* If not found... */
+	if (k == num_sel_priv_args) {
+		k = -1;
+		sel_priv_args = mp_priv_args;
+		num_sel_priv_args = num_mp_priv_args;
+		while
+		((++k < num_sel_priv_args) && strcmp(sel_priv_args[k].name, cmdname))
+			;
+
+		if (k == num_sel_priv_args) {
+			err = -EOPNOTSUPP;
+			goto exit;
+		}
+	}
+
+	/* Watch out for sub-ioctls ! */
+	if (sel_priv_args[k].cmd < SIOCDEVPRIVATE) {
+		int j = -1;
+
+		/* Find the matching *real* ioctl */
+		while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') ||
+			 (priv_args[j].set_args != sel_priv_args[k].set_args) ||
+			 (priv_args[j].get_args != sel_priv_args[k].get_args)))
+			;
+
+		/* If not found... */
+		if (j == num_priv_args) {
+			err = -EINVAL;
+			goto exit;
+		}
+
+		/* Save sub-ioctl number */
+		subcmd = sel_priv_args[k].cmd;
+		/* Reserve one int (simplify alignment issues) */
+		offset = sizeof(__u32);
+		/* Use real ioctl definition from now on */
+		k = j;
+	}
+
+	buffer = rtw_zmalloc(4096);
+	if (NULL == buffer) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	/* If we have to set some data */
+	if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) &&
+	    (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) {
+		u8 *str;
+
+		switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) {
+		case IW_PRIV_TYPE_BYTE:
+			/* Fetch args */
+			count = 0;
+			do {
+				str = strsep(&ptr, delim);
+				if (NULL == str)
+					break;
+				sscanf(str, "%i", &temp);
+				buffer[count++] = (u8)temp;
+			} while (1);
+			buffer_len = count;
+
+			/* Number of args to fetch */
+			wdata.data.length = count;
+			if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
+				wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
+
+			break;
+
+		case IW_PRIV_TYPE_INT:
+			/* Fetch args */
+			count = 0;
+			do {
+				str = strsep(&ptr, delim);
+				if (NULL == str)
+					break;
+				sscanf(str, "%i", &temp);
+				((s32 *)buffer)[count++] = (s32)temp;
+			} while (1);
+			buffer_len = count * sizeof(s32);
+
+			/* Number of args to fetch */
+			wdata.data.length = count;
+			if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
+				wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
+
+			break;
+
+		case IW_PRIV_TYPE_CHAR:
+			if (len > 0) {
+				/* Size of the string to fetch */
+				wdata.data.length = len;
+				if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
+					wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
+
+				/* Fetch string */
+				memcpy(buffer, ptr, wdata.data.length);
+			} else {
+				wdata.data.length = 1;
+				buffer[0] = '\0';
+			}
+			buffer_len = wdata.data.length;
+			break;
+
+		default:
+			RTW_INFO("%s: Not yet implemented...\n", __func__);
+			err = -1;
+			goto exit;
+		}
+
+		if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
+		    (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK))) {
+			RTW_INFO("%s: The command %s needs exactly %d argument(s)...\n",
+				__func__, cmdname, priv_args[k].set_args & IW_PRIV_SIZE_MASK);
+			err = -EINVAL;
+			goto exit;
+		}
+	}   /* if args to set */
+	else
+		wdata.data.length = 0L;
+
+	/* Those two tests are important. They define how the driver
+	* will have to handle the data */
+	if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
+	    ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ)) {
+		/* First case : all SET args fit within wrq */
+		if (offset)
+			wdata.mode = subcmd;
+		memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset);
+	} else {
+		if ((priv_args[k].set_args == 0) &&
+		    (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
+		    (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) {
+			/* Second case : no SET args, GET args fit within wrq */
+			if (offset)
+				wdata.mode = subcmd;
+		} else {
+			/* Third case : args won't fit in wrq, or variable number of args */
+			if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) {
+				err = -EFAULT;
+				goto exit;
+			}
+			wdata.data.flags = subcmd;
+		}
+	}
+
+	rtw_mfree(input, input_len);
+	input = NULL;
+
+	extra_size = 0;
+	if (IW_IS_SET(priv_args[k].cmd)) {
+		/* Size of set arguments */
+		extra_size = get_priv_size(priv_args[k].set_args);
+
+		/* Does it fits in iwr ? */
+		if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
+		    ((extra_size + offset) <= IFNAMSIZ))
+			extra_size = 0;
+	} else {
+		/* Size of get arguments */
+		extra_size = get_priv_size(priv_args[k].get_args);
+
+		/* Does it fits in iwr ? */
+		if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
+		    (extra_size <= IFNAMSIZ))
+			extra_size = 0;
+	}
+
+	if (extra_size == 0) {
+		extra = (u8 *)&wdata;
+		rtw_mfree(buffer, 4096);
+		buffer = NULL;
+	} else
+		extra = buffer;
+
+	handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV];
+	err = handler(dev, NULL, &wdata, extra);
+
+	/* If we have to get some data */
+	if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) &&
+	    (priv_args[k].get_args & IW_PRIV_SIZE_MASK)) {
+		int j;
+		int n = 0;	/* number of args */
+		u8 str[20] = {0};
+
+		/* Check where is the returned data */
+		if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
+		    (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
+			n = priv_args[k].get_args & IW_PRIV_SIZE_MASK;
+		else
+			n = wdata.data.length;
+
+		output = rtw_zmalloc(4096);
+		if (NULL == output) {
+			err =  -ENOMEM;
+			goto exit;
+		}
+
+		switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) {
+		case IW_PRIV_TYPE_BYTE:
+			/* Display args */
+			for (j = 0; j < n; j++) {
+				sprintf(str, "%d  ", extra[j]);
+				len = strlen(str);
+				output_len = strlen(output);
+				if ((output_len + len + 1) > 4096) {
+					err = -E2BIG;
+					goto exit;
+				}
+				memcpy(output + output_len, str, len);
+			}
+			break;
+
+		case IW_PRIV_TYPE_INT:
+			/* Display args */
+			for (j = 0; j < n; j++) {
+				sprintf(str, "%d  ", ((__s32 *)extra)[j]);
+				len = strlen(str);
+				output_len = strlen(output);
+				if ((output_len + len + 1) > 4096) {
+					err = -E2BIG;
+					goto exit;
+				}
+				memcpy(output + output_len, str, len);
+			}
+			break;
+
+		case IW_PRIV_TYPE_CHAR:
+			/* Display args */
+			memcpy(output, extra, n);
+			break;
+
+		default:
+			RTW_INFO("%s: Not yet implemented...\n", __func__);
+			err = -1;
+			goto exit;
+		}
+
+		output_len = strlen(output) + 1;
+		wrq_data->data.length = output_len;
+		if (copy_to_user(wrq_data->data.pointer, output, output_len)) {
+			err = -EFAULT;
+			goto exit;
+		}
+	}   /* if args to set */
+	else
+		wrq_data->data.length = 0;
+
+exit:
+	if (input)
+		rtw_mfree(input, input_len);
+	if (buffer)
+		rtw_mfree(buffer, 4096);
+	if (output)
+		rtw_mfree(output, 4096);
+
+	return err;
+}
+
+#ifdef CONFIG_COMPAT
+static int rtw_ioctl_compat_wext_private(struct net_device *dev, struct ifreq *rq)
+{
+	struct compat_iw_point iwp_compat;
+	union iwreq_data wrq_data;
+	int err = 0;
+	RTW_INFO("%s:...\n", __func__);
+	if (copy_from_user(&iwp_compat, rq->ifr_ifru.ifru_data, sizeof(struct compat_iw_point)))
+		return -EFAULT;
+
+	wrq_data.data.pointer = compat_ptr(iwp_compat.pointer);
+	wrq_data.data.length = iwp_compat.length;
+	wrq_data.data.flags = iwp_compat.flags;
+
+	err = _rtw_ioctl_wext_private(dev, &wrq_data);
+
+	iwp_compat.pointer = ptr_to_compat(wrq_data.data.pointer);
+	iwp_compat.length = wrq_data.data.length;
+	iwp_compat.flags = wrq_data.data.flags;
+	if (copy_to_user(rq->ifr_ifru.ifru_data, &iwp_compat, sizeof(struct compat_iw_point)))
+		return -EFAULT;
+
+	return err;
+}
+#endif /* CONFIG_COMPAT */
+
+static int rtw_ioctl_standard_wext_private(struct net_device *dev, struct ifreq *rq)
+{
+	struct iw_point *iwp;
+	struct ifreq ifrq;
+	union iwreq_data wrq_data;
+	int err = 0;
+	iwp = &wrq_data.data;
+	RTW_INFO("%s:...\n", __func__);
+	if (copy_from_user(iwp, rq->ifr_ifru.ifru_data, sizeof(struct iw_point)))
+		return -EFAULT;
+
+	err = _rtw_ioctl_wext_private(dev, &wrq_data);
+
+	if (copy_to_user(rq->ifr_ifru.ifru_data, iwp, sizeof(struct iw_point)))
+		return -EFAULT;
+
+	return err;
+}
+
+static int rtw_ioctl_wext_private(struct net_device *dev, struct ifreq *rq)
+{
+#ifdef CONFIG_COMPAT
+#if (KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE)
+	if (is_compat_task())
+#else
+	if (in_compat_syscall())
+#endif
+		return rtw_ioctl_compat_wext_private(dev, rq);
+	else
+#endif /* CONFIG_COMPAT */
+		return rtw_ioctl_standard_wext_private(dev, rq);
+}
+
+int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct iwreq *wrq = (struct iwreq *)rq;
+	int ret = 0;
+
+	switch (cmd) {
+	case RTL_IOCTL_WPA_SUPPLICANT:
+		ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
+		break;
+#ifdef CONFIG_AP_MODE
+	case RTL_IOCTL_HOSTAPD:
+		ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
+		break;
+#ifdef CONFIG_WIRELESS_EXT
+	case SIOCSIWMODE:
+		ret = rtw_wx_set_mode(dev, NULL, &wrq->u, NULL);
+		break;
+#endif
+#endif /* CONFIG_AP_MODE */
+	case SIOCDEVPRIVATE:
+		ret = rtw_ioctl_wext_private(dev, rq);
+		break;
+	case (SIOCDEVPRIVATE+1):
+		ret = rtw_android_priv_cmd(dev, rq, cmd);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_mp.c b/drivers/staging/rtl8188eu/os_dep/ioctl_mp.c
new file mode 100644
index 000000000000..d08bb3bffdfb
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_mp.c
@@ -0,0 +1,2028 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+#if defined(CONFIG_MP_INCLUDED)
+
+#include <drv_types.h>
+#include <rtw_mp.h>
+#include <rtw_mp_ioctl.h>
+#include "../../hal/phydm_precomp.h"
+
+/*
+ * Input Format: %s,%d,%d
+ *	%s is width, could be
+ *		"b" for 1 byte
+ *		"w" for WORD (2 bytes)
+ *		"dw" for DWORD (4 bytes)
+ *	1st %d is address(offset)
+ *	2st %d is data to write
+ */
+int rtw_mp_write_reg(struct net_device *dev,
+		     struct iw_request_info *info,
+		     struct iw_point *wrqu, char *extra)
+{
+	char *pch, *pnext, *ptmp;
+	char *width_str;
+	char width, buf[5];
+	u32 addr, data;
+	int ret;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	char input[128];
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	memset(extra, 0, wrqu->length);
+
+	pch = input;
+
+	pnext = strpbrk(pch, " ,.-");
+	if (pnext == NULL)
+		return -EINVAL;
+	*pnext = 0;
+	width_str = pch;
+
+	pch = pnext + 1;
+	pnext = strpbrk(pch, " ,.-");
+	if (pnext == NULL)
+		return -EINVAL;
+	*pnext = 0;
+	/*addr = simple_strtoul(pch, &ptmp, 16);
+	memset(buf, '\0', sizeof(buf));
+	memcpy(buf, pch, pnext-pch);
+	ret = kstrtoul(buf, 16, &addr);*/
+	ret = sscanf(pch, "%x", &addr);
+	if (addr > 0x3FFF)
+		return -EINVAL;
+
+	pch = pnext + 1;
+	pnext = strpbrk(pch, " ,.-");
+	if ((pch - input) >= wrqu->length)
+		return -EINVAL;
+	/*data = simple_strtoul(pch, &ptmp, 16);*/
+	ret = sscanf(pch, "%x", &data);
+	RTW_INFO("data=%x,addr=%x\n", (u32)data, (u32)addr);
+	ret = 0;
+	width = width_str[0];
+	switch (width) {
+	case 'b':
+		/* 1 byte*/
+		if (data > 0xFF) {
+			ret = -EINVAL;
+			break;
+		}
+		rtw_write8(padapter, addr, data);
+		break;
+	case 'w':
+		/* 2 bytes*/
+		if (data > 0xFFFF) {
+			ret = -EINVAL;
+			break;
+		}
+		rtw_write16(padapter, addr, data);
+		break;
+	case 'd':
+		/* 4 bytes*/
+		rtw_write32(padapter, addr, data);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+
+/*
+ * Input Format: %s,%d
+ *	%s is width, could be
+ *		"b" for 1 byte
+ *		"w" for WORD (2 bytes)
+ *		"dw" for DWORD (4 bytes)
+ *	%d is address(offset)
+ *
+ * Return:
+ *	%d for data readed
+ */
+int rtw_mp_read_reg(struct net_device *dev,
+		    struct iw_request_info *info,
+		    struct iw_point *wrqu, char *extra)
+{
+	char input[128];
+	char *pch, *pnext, *ptmp;
+	char *width_str;
+	char width;
+	char data[20], tmp[20], buf[3];
+	u32 addr = 0, strtout = 0;
+	u32 i = 0, j = 0, ret = 0, data32 = 0;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	memset(extra, 0, wrqu->length);
+	memset(data, '\0', sizeof(data));
+	memset(tmp, '\0', sizeof(tmp));
+	pch = input;
+	pnext = strpbrk(pch, " ,.-");
+	if (pnext == NULL)
+		return -EINVAL;
+	*pnext = 0;
+	width_str = pch;
+
+	pch = pnext + 1;
+
+	ret = sscanf(pch, "%x", &addr);
+	if (addr > 0x3FFF)
+		return -EINVAL;
+
+	ret = 0;
+	width = width_str[0];
+
+	switch (width) {
+	case 'b':
+		data32 = rtw_read8(padapter, addr);
+		RTW_INFO("%x\n", data32);
+		sprintf(extra, "%d", data32);
+		wrqu->length = strlen(extra);
+		break;
+	case 'w':
+		/* 2 bytes*/
+		sprintf(data, "%04x\n", rtw_read16(padapter, addr));
+
+		for (i = 0 ; i <= strlen(data) ; i++) {
+			if (i % 2 == 0) {
+				tmp[j] = ' ';
+				j++;
+			}
+			if (data[i] != '\0')
+				tmp[j] = data[i];
+
+			j++;
+		}
+		pch = tmp;
+		RTW_INFO("pch=%s", pch);
+
+		while (*pch != '\0') {
+			pnext = strpbrk(pch, " ");
+			if (!pnext || ((pnext - tmp) > 4))
+				break;
+
+			pnext++;
+			if (*pnext != '\0') {
+				/*strtout = simple_strtoul(pnext , &ptmp, 16);*/
+				ret = sscanf(pnext, "%x", &strtout);
+				sprintf(extra + strlen(extra), " %d", strtout);
+			} else
+				break;
+			pch = pnext;
+		}
+		wrqu->length = strlen(extra);
+		break;
+	case 'd':
+		/* 4 bytes */
+		sprintf(data, "%08x", rtw_read32(padapter, addr));
+		/*add read data format blank*/
+		for (i = 0 ; i <= strlen(data) ; i++) {
+			if (i % 2 == 0) {
+				tmp[j] = ' ';
+				j++;
+			}
+			if (data[i] != '\0')
+				tmp[j] = data[i];
+
+			j++;
+		}
+		pch = tmp;
+		RTW_INFO("pch=%s", pch);
+
+		while (*pch != '\0') {
+			pnext = strpbrk(pch, " ");
+			if (!pnext)
+				break;
+
+			pnext++;
+			if (*pnext != '\0') {
+				ret = sscanf(pnext, "%x", &strtout);
+				sprintf(extra + strlen(extra), " %d", strtout);
+			} else
+				break;
+			pch = pnext;
+		}
+		wrqu->length = strlen(extra);
+		break;
+
+	default:
+		wrqu->length = 0;
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+
+/*
+ * Input Format: %d,%x,%x
+ *	%d is RF path, should be smaller than MAX_RF_PATH_NUMS
+ *	1st %x is address(offset)
+ *	2st %x is data to write
+ */
+int rtw_mp_write_rf(struct net_device *dev,
+		    struct iw_request_info *info,
+		    struct iw_point *wrqu, char *extra)
+{
+
+	u32 path, addr, data;
+	int ret;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	char input[128];
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	memset(input, 0, wrqu->length);
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+
+	ret = sscanf(input, "%d,%x,%x", &path, &addr, &data);
+	if (ret < 3)
+		return -EINVAL;
+
+	if (path >= GET_HAL_RFPATH_NUM(padapter))
+		return -EINVAL;
+	if (addr > 0xFF)
+		return -EINVAL;
+	if (data > 0xFFFFF)
+		return -EINVAL;
+
+	memset(extra, 0, wrqu->length);
+
+	write_rfreg(padapter, path, addr, data);
+
+	sprintf(extra, "write_rf completed\n");
+	wrqu->length = strlen(extra);
+
+	return 0;
+}
+
+
+/*
+ * Input Format: %d,%x
+ *	%d is RF path, should be smaller than MAX_RF_PATH_NUMS
+ *	%x is address(offset)
+ *
+ * Return:
+ *	%d for data readed
+ */
+int rtw_mp_read_rf(struct net_device *dev,
+		   struct iw_request_info *info,
+		   struct iw_point *wrqu, char *extra)
+{
+	char input[128];
+	char *pch, *pnext, *ptmp;
+	char data[20], tmp[20], buf[3];
+	u32 path, addr, strtou;
+	u32 ret, i = 0 , j = 0;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	memset(input, 0, wrqu->length);
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	ret = sscanf(input, "%d,%x", &path, &addr);
+	if (ret < 2)
+		return -EINVAL;
+
+	if (path >= GET_HAL_RFPATH_NUM(padapter))
+		return -EINVAL;
+	if (addr > 0xFF)
+		return -EINVAL;
+
+	memset(extra, 0, wrqu->length);
+
+	sprintf(data, "%08x", read_rfreg(padapter, path, addr));
+	/*add read data format blank*/
+	for (i = 0 ; i <= strlen(data) ; i++) {
+		if (i % 2 == 0) {
+			tmp[j] = ' ';
+			j++;
+		}
+		tmp[j] = data[i];
+		j++;
+	}
+	pch = tmp;
+	RTW_INFO("pch=%s", pch);
+
+	while (*pch != '\0') {
+		pnext = strpbrk(pch, " ");
+		if (!pnext)
+			break;
+		pnext++;
+		if (*pnext != '\0') {
+			/*strtou =simple_strtoul(pnext , &ptmp, 16);*/
+			ret = sscanf(pnext, "%x", &strtou);
+			sprintf(extra + strlen(extra), " %d", strtou);
+		} else
+			break;
+		pch = pnext;
+	}
+	wrqu->length = strlen(extra);
+
+	return 0;
+}
+
+
+int rtw_mp_start(struct net_device *dev,
+		 struct iw_request_info *info,
+		 struct iw_point *wrqu, char *extra)
+{
+	int ret = 0;
+	u8 val8;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+	struct hal_ops *pHalFunc = &padapter->hal_func;
+
+	rtw_pm_set_ips(padapter, IPS_NONE);
+	LeaveAllPowerSaveMode(padapter);
+
+	if (rtw_mi_check_fwstate(padapter, _FW_UNDER_SURVEY))
+		rtw_mi_scan_abort(padapter, false);
+
+	if (rtw_mp_cmd(padapter, MP_START, RTW_CMDF_WAIT_ACK) != _SUCCESS)
+		ret = -EPERM;
+
+	memset(extra, 0, wrqu->length);
+	sprintf(extra, "mp_start %s\n", ret == 0 ? "ok" : "fail");
+	wrqu->length = strlen(extra);
+
+	return ret;
+}
+
+
+
+int rtw_mp_stop(struct net_device *dev,
+		struct iw_request_info *info,
+		struct iw_point *wrqu, char *extra)
+{
+	int ret = 0;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	struct hal_ops *pHalFunc = &padapter->hal_func;
+
+	if (rtw_mp_cmd(padapter, MP_STOP, RTW_CMDF_WAIT_ACK) != _SUCCESS)
+		ret = -EPERM;
+
+	memset(extra, 0, wrqu->length);
+	sprintf(extra, "mp_stop %s\n", ret == 0 ? "ok" : "fail");
+	wrqu->length = strlen(extra);
+
+	return ret;
+}
+
+
+int rtw_mp_rate(struct net_device *dev,
+		struct iw_request_info *info,
+		struct iw_point *wrqu, char *extra)
+{
+	u32 rate = MPT_RATE_1M;
+	u8		input[128];
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	PMPT_CONTEXT		pMptCtx = &(padapter->mppriv.mpt_ctx);
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	rate = rtw_mpRateParseFunc(padapter, input);
+	padapter->mppriv.rateidx = rate;
+
+	if (rate == 0 && strcmp(input, "1M") != 0) {
+		rate = rtw_atoi(input);
+		padapter->mppriv.rateidx = MRateToHwRate(rate);
+		/*if (rate <= 0x7f)
+			rate = wifirate2_ratetbl_inx((u8)rate);
+		else if (rate < 0xC8)
+			rate = (rate - 0x79 + MPT_RATE_MCS0);
+		HT  rate 0x80(MCS0)  ~ 0x8F(MCS15) ~ 0x9F(MCS31) 128~159
+		VHT1SS~2SS rate 0xA0 (VHT1SS_MCS0 44) ~ 0xB3 (VHT2SS_MCS9 #63) 160~179
+		VHT rate 0xB4 (VHT3SS_MCS0 64) ~ 0xC7 (VHT2SS_MCS9 #83) 180~199
+		else
+		VHT rate 0x90(VHT1SS_MCS0) ~ 0x99(VHT1SS_MCS9) 144~153
+		rate =(rate - MPT_RATE_VHT1SS_MCS0);
+		*/
+	}
+	memset(extra, 0, wrqu->length);
+
+	sprintf(extra, "Set data rate to %s index %d" , input, padapter->mppriv.rateidx);
+	RTW_INFO("%s: %s rate index=%d\n", __func__, input, padapter->mppriv.rateidx);
+
+	if (padapter->mppriv.rateidx >= DESC_RATEVHTSS4MCS9)
+		return -EINVAL;
+
+	pMptCtx->mpt_rate_index = HwRateToMPTRate(padapter->mppriv.rateidx);
+	SetDataRate(padapter);
+
+	wrqu->length = strlen(extra);
+	return 0;
+}
+
+
+int rtw_mp_channel(struct net_device *dev,
+		   struct iw_request_info *info,
+		   struct iw_point *wrqu, char *extra)
+{
+
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(padapter);
+	u8		input[128];
+	u32	channel = 1;
+	int cur_ch_offset;
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	channel = rtw_atoi(input);
+	/*RTW_INFO("%s: channel=%d\n", __func__, channel);*/
+	memset(extra, 0, wrqu->length);
+	sprintf(extra, "Change channel %d to channel %d", padapter->mppriv.channel , channel);
+	padapter->mppriv.channel = channel;
+	SetChannel(padapter);
+	pHalData->current_channel = channel;
+
+	wrqu->length = strlen(extra);
+	return 0;
+}
+
+
+int rtw_mp_bandwidth(struct net_device *dev,
+		     struct iw_request_info *info,
+		     struct iw_point *wrqu, char *extra)
+{
+	u32 bandwidth = 0, sg = 0;
+	int cur_ch_offset;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(padapter);
+	u8		input[128];
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	if (sscanf(input, "40M=%d,shortGI=%d", &bandwidth, &sg) > 0)
+		RTW_INFO("%s: bw=%d sg=%d\n", __func__, bandwidth , sg);
+
+	if (bandwidth == 1)
+		bandwidth = CHANNEL_WIDTH_40;
+	else if (bandwidth == 2)
+		bandwidth = CHANNEL_WIDTH_80;
+
+	padapter->mppriv.bandwidth = (u8)bandwidth;
+	padapter->mppriv.preamble = sg;
+	memset(extra, 0, wrqu->length);
+	sprintf(extra, "Change BW %d to BW %d\n", pHalData->current_channel_bw , bandwidth);
+
+	SetBandwidth(padapter);
+	pHalData->current_channel_bw = bandwidth;
+	/*cur_ch_offset =  rtw_get_offset_by_ch(padapter->mppriv.channel);*/
+	/*set_channel_bwmode(padapter, padapter->mppriv.channel, cur_ch_offset, bandwidth);*/
+	wrqu->length = strlen(extra);
+
+	return 0;
+}
+
+
+int rtw_mp_txpower_index(struct net_device *dev,
+			 struct iw_request_info *info,
+			 struct iw_point *wrqu, char *extra)
+{
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	char input[128];
+	u32 rfpath;
+	u32 txpower_inx;
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	rfpath = rtw_atoi(input);
+	txpower_inx = mpt_ProQueryCalTxPower(padapter, rfpath);
+	sprintf(extra, " %d", txpower_inx);
+	wrqu->length = strlen(extra);
+
+	return 0;
+}
+
+
+int rtw_mp_txpower(struct net_device *dev,
+		   struct iw_request_info *info,
+		   struct iw_point *wrqu, char *extra)
+{
+	u32 idx_a = 0, idx_b = 0, idx_c = 0, idx_d = 0, status = 0;
+	int MsetPower = 1;
+	u8		input[128];
+
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	PMPT_CONTEXT		pMptCtx = &(padapter->mppriv.mpt_ctx);
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	MsetPower = strncmp(input, "off", 3);
+	if (MsetPower == 0) {
+		padapter->mppriv.bSetTxPower = 0;
+		sprintf(extra, "MP Set power off");
+	} else {
+		if (sscanf(input, "patha=%d,pathb=%d,pathc=%d,pathd=%d", &idx_a, &idx_b, &idx_c, &idx_d) < 3)
+			RTW_INFO("Invalid format on line %s ,patha=%d,pathb=%d,pathc=%d,pathd=%d\n", input , idx_a , idx_b , idx_c , idx_d);
+
+		sprintf(extra, "Set power level path_A:%d path_B:%d path_C:%d path_D:%d", idx_a , idx_b , idx_c , idx_d);
+		padapter->mppriv.txpoweridx = (u8)idx_a;
+
+		pMptCtx->TxPwrLevel[ODM_RF_PATH_A] = (u8)idx_a;
+		pMptCtx->TxPwrLevel[ODM_RF_PATH_B] = (u8)idx_b;
+		pMptCtx->TxPwrLevel[ODM_RF_PATH_C] = (u8)idx_c;
+		pMptCtx->TxPwrLevel[ODM_RF_PATH_D]  = (u8)idx_d;
+		padapter->mppriv.bSetTxPower = 1;
+
+		SetTxPower(padapter);
+	}
+
+	wrqu->length = strlen(extra);
+	return 0;
+}
+
+
+int rtw_mp_ant_tx(struct net_device *dev,
+		  struct iw_request_info *info,
+		  struct iw_point *wrqu, char *extra)
+{
+	u8 i;
+	u8		input[128];
+	u16 antenna = 0;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	sprintf(extra, "switch Tx antenna to %s", input);
+
+	for (i = 0; i < strlen(input); i++) {
+		switch (input[i]) {
+		case 'a':
+			antenna |= ANTENNA_A;
+			break;
+		case 'b':
+			antenna |= ANTENNA_B;
+			break;
+		case 'c':
+			antenna |= ANTENNA_C;
+			break;
+		case 'd':
+			antenna |= ANTENNA_D;
+			break;
+		}
+	}
+	/*antenna |= BIT(extra[i]-'a');*/
+	RTW_INFO("%s: antenna=0x%x\n", __func__, antenna);
+	padapter->mppriv.antenna_tx = antenna;
+	padapter->mppriv.antenna_rx = antenna;
+	/*RTW_INFO("%s:mppriv.antenna_rx=%d\n", __func__, padapter->mppriv.antenna_tx);*/
+	pHalData->antenna_tx_path = antenna;
+
+	SetAntenna(padapter);
+
+	wrqu->length = strlen(extra);
+	return 0;
+}
+
+
+int rtw_mp_ant_rx(struct net_device *dev,
+		  struct iw_request_info *info,
+		  struct iw_point *wrqu, char *extra)
+{
+	u8 i;
+	u16 antenna = 0;
+	u8		input[128];
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+	/*RTW_INFO("%s: input=%s\n", __func__, input);*/
+	memset(extra, 0, wrqu->length);
+
+	sprintf(extra, "switch Rx antenna to %s", input);
+
+	for (i = 0; i < strlen(input); i++) {
+		switch (input[i]) {
+		case 'a':
+			antenna |= ANTENNA_A;
+			break;
+		case 'b':
+			antenna |= ANTENNA_B;
+			break;
+		case 'c':
+			antenna |= ANTENNA_C;
+			break;
+		case 'd':
+			antenna |= ANTENNA_D;
+			break;
+		}
+	}
+
+	RTW_INFO("%s: antenna=0x%x\n", __func__, antenna);
+	padapter->mppriv.antenna_tx = antenna;
+	padapter->mppriv.antenna_rx = antenna;
+	pHalData->AntennaRxPath = antenna;
+	/*RTW_INFO("%s:mppriv.antenna_rx=%d\n", __func__, padapter->mppriv.antenna_rx);*/
+	SetAntenna(padapter);
+	wrqu->length = strlen(extra);
+
+	return 0;
+}
+
+
+int rtw_set_ctx_destAddr(struct net_device *dev,
+			 struct iw_request_info *info,
+			 struct iw_point *wrqu, char *extra)
+{
+	int jj, kk = 0;
+
+	struct pkt_attrib *pattrib;
+	struct mp_priv *pmp_priv;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+
+	pmp_priv = &padapter->mppriv;
+	pattrib = &pmp_priv->tx.attrib;
+
+	if (strlen(extra) < 5)
+		return _FAIL;
+
+	RTW_INFO("%s: in=%s\n", __func__, extra);
+	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+		pattrib->dst[jj] = key_2char2num(extra[kk], extra[kk + 1]);
+
+	RTW_INFO("pattrib->dst:%x %x %x %x %x %x\n", pattrib->dst[0], pattrib->dst[1], pattrib->dst[2], pattrib->dst[3], pattrib->dst[4], pattrib->dst[5]);
+	return 0;
+}
+
+
+
+int rtw_mp_ctx(struct net_device *dev,
+	       struct iw_request_info *info,
+	       struct iw_point *wrqu, char *extra)
+{
+	u32 pkTx = 1;
+	int countPkTx = 1, cotuTx = 1, CarrSprTx = 1, scTx = 1, sgleTx = 1, stop = 1;
+	u32 bStartTest = 1;
+	u32 count = 0, pktinterval = 0, pktlen = 0;
+	u8 status;
+	struct mp_priv *pmp_priv;
+	struct pkt_attrib *pattrib;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+
+	pmp_priv = &padapter->mppriv;
+	pattrib = &pmp_priv->tx.attrib;
+
+	if (copy_from_user(extra, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	RTW_INFO("%s: in=%s\n", __func__, extra);
+#ifdef CONFIG_CONCURRENT_MODE
+	if (!is_primary_adapter(padapter)) {
+		sprintf(extra, "Error: MP mode can't support Virtual Adapter, Please to use main Adapter.\n");
+		wrqu->length = strlen(extra);
+		return 0;
+	}
+#endif
+	countPkTx = strncmp(extra, "count=", 5); /* strncmp true is 0*/
+	cotuTx = strncmp(extra, "background", 20);
+	CarrSprTx = strncmp(extra, "background,cs", 20);
+	scTx = strncmp(extra, "background,sc", 20);
+	sgleTx = strncmp(extra, "background,stone", 20);
+	pkTx = strncmp(extra, "background,pkt", 20);
+	stop = strncmp(extra, "stop", 4);
+	if (sscanf(extra, "count=%d,pkt", &count) > 0)
+		RTW_INFO("count= %d\n", count);
+	if (sscanf(extra, "pktinterval=%d", &pktinterval) > 0)
+		RTW_INFO("pktinterval= %d\n", pktinterval);
+
+	if (sscanf(extra, "pktlen=%d", &pktlen) > 0)
+		RTW_INFO("pktlen= %d\n", pktlen);
+
+	if (!memcmp(extra, "destmac=", 8)) {
+		wrqu->length -= 8;
+		rtw_set_ctx_destAddr(dev, info, wrqu, &extra[8]);
+		sprintf(extra, "Set dest mac OK !\n");
+		return 0;
+	}
+
+	/*RTW_INFO("%s: count=%d countPkTx=%d cotuTx=%d CarrSprTx=%d scTx=%d sgleTx=%d pkTx=%d stop=%d\n", __func__, count, countPkTx, cotuTx, CarrSprTx, pkTx, sgleTx, scTx, stop);*/
+	memset(extra, '\0', strlen(extra));
+
+	if (pktinterval != 0) {
+		sprintf(extra, "Pkt Interval = %d", pktinterval);
+		padapter->mppriv.pktInterval = pktinterval;
+		wrqu->length = strlen(extra);
+		return 0;
+	}
+	if (pktlen != 0) {
+		sprintf(extra, "Pkt len = %d", pktlen);
+		pattrib->pktlen = pktlen;
+		wrqu->length = strlen(extra);
+		return 0;
+	}
+	if (stop == 0) {
+		bStartTest = 0; /* To set Stop*/
+		pmp_priv->tx.stop = 1;
+		sprintf(extra, "Stop continuous Tx");
+		odm_write_dig(&pHalData->odmpriv, 0x20);
+	} else {
+		bStartTest = 1;
+		odm_write_dig(&pHalData->odmpriv, 0x7f);
+		if (pmp_priv->mode != MP_ON) {
+			if (pmp_priv->tx.stop != 1) {
+				RTW_INFO("%s: MP_MODE != ON %d\n", __func__, pmp_priv->mode);
+				return	-EFAULT;
+			}
+		}
+	}
+
+	pmp_priv->tx.count = count;
+
+	if (pkTx == 0 || countPkTx == 0)
+		pmp_priv->mode = MP_PACKET_TX;
+	if (sgleTx == 0)
+		pmp_priv->mode = MP_SINGLE_TONE_TX;
+	if (cotuTx == 0)
+		pmp_priv->mode = MP_CONTINUOUS_TX;
+	if (CarrSprTx == 0)
+		pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX;
+	if (scTx == 0)
+		pmp_priv->mode = MP_SINGLE_CARRIER_TX;
+
+	status = rtw_mp_pretx_proc(padapter, bStartTest, extra);
+
+	wrqu->length = strlen(extra);
+	return status;
+}
+
+
+
+int rtw_mp_disable_bt_coexist(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+	PADAPTER padapter = (PADAPTER)rtw_netdev_priv(dev);
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+	struct hal_ops *pHalFunc = &padapter->hal_func;
+
+	u8 input[128];
+	u32 bt_coexist;
+
+	if (wrqu->data.length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length))
+		return -EFAULT;
+
+	bt_coexist = rtw_atoi(input);
+
+	if (bt_coexist == 0) {
+		RTW_INFO("Set OID_RT_SET_DISABLE_BT_COEXIST: disable BT_COEXIST\n");
+#ifdef CONFIG_BT_COEXIST
+		rtw_btcoex_HaltNotify(padapter);
+		rtw_btcoex_SetManualControl(padapter, true);
+		/* Force to switch Antenna to WiFi*/
+		rtw_write16(padapter, 0x870, 0x300);
+		rtw_write16(padapter, 0x860, 0x110);
+#endif
+		/* CONFIG_BT_COEXIST */
+	} else {
+#ifdef CONFIG_BT_COEXIST
+		rtw_btcoex_SetManualControl(padapter, false);
+#endif
+	}
+
+	return 0;
+}
+
+
+int rtw_mp_arx(struct net_device *dev,
+	       struct iw_request_info *info,
+	       struct iw_point *wrqu, char *extra)
+{
+	int bStartRx = 0, bStopRx = 0, bQueryPhy = 0, bQueryMac = 0, bSetBssid = 0;
+	int bmac_filter = 0, bfilter_init = 0, bmon = 0, bSmpCfg = 0, bloopbk = 0;
+	u8		input[128];
+	char *pch, *ptmp, *token, *tmp[2] = {NULL, NULL};
+	u32 i = 0, ii = 0, jj = 0, kk = 0, cnts = 0, ret;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	struct mp_priv *pmppriv = &padapter->mppriv;
+	struct dbg_rx_counter rx_counter;
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	RTW_INFO("%s: %s\n", __func__, input);
+#ifdef CONFIG_CONCURRENT_MODE
+	if (!is_primary_adapter(padapter)) {
+		sprintf(extra, "Error: MP mode can't support Virtual Adapter, Please to use main Adapter.\n");
+		wrqu->length = strlen(extra);
+		return 0;
+	}
+#endif
+	bStartRx = (strncmp(input, "start", 5) == 0) ? 1 : 0; /* strncmp true is 0*/
+	bStopRx = (strncmp(input, "stop", 5) == 0) ? 1 : 0; /* strncmp true is 0*/
+	bQueryPhy = (strncmp(input, "phy", 3) == 0) ? 1 : 0; /* strncmp true is 0*/
+	bQueryMac = (strncmp(input, "mac", 3) == 0) ? 1 : 0; /* strncmp true is 0*/
+	bSetBssid = (strncmp(input, "setbssid=", 8) == 0) ? 1 : 0; /* strncmp true is 0*/
+	/*bfilter_init = (strncmp(input, "filter_init",11)==0)?1:0;*/
+	bmac_filter = (strncmp(input, "accept_mac", 10) == 0) ? 1 : 0;
+	bmon = (strncmp(input, "mon=", 4) == 0) ? 1 : 0;
+	bSmpCfg = (strncmp(input , "smpcfg=" , 7) == 0) ? 1 : 0;
+	pmppriv->bloopback = (strncmp(input, "loopbk", 6) == 0) ? 1 : 0; /* strncmp true is 0*/
+
+	if (bSetBssid == 1) {
+		pch = input;
+		while ((token = strsep(&pch, "=")) != NULL) {
+			if (i > 1)
+				break;
+			tmp[i] = token;
+			i++;
+		}
+		if ((tmp[0] != NULL) && (tmp[1] != NULL)) {
+			cnts = strlen(tmp[1]) / 2;
+			if (cnts < 1)
+				return -EFAULT;
+			RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+			RTW_INFO("%s: data=%s\n", __func__, tmp[1]);
+			for (jj = 0, kk = 0; jj < cnts ; jj++, kk += 2) {
+				pmppriv->network_macaddr[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
+				RTW_INFO("network_macaddr[%d]=%x\n", jj, pmppriv->network_macaddr[jj]);
+			}
+		} else
+			return -EFAULT;
+
+		pmppriv->bSetRxBssid = true;
+	}
+
+	if (bmac_filter) {
+		pmppriv->bmac_filter = bmac_filter;
+		pch = input;
+		while ((token = strsep(&pch, "=")) != NULL) {
+			if (i > 1)
+				break;
+			tmp[i] = token;
+			i++;
+		}
+		if ((tmp[0] != NULL) && (tmp[1] != NULL)) {
+			cnts = strlen(tmp[1]) / 2;
+			if (cnts < 1)
+				return -EFAULT;
+			RTW_INFO("%s: cnts=%d\n", __func__, cnts);
+			RTW_INFO("%s: data=%s\n", __func__, tmp[1]);
+			for (jj = 0, kk = 0; jj < cnts ; jj++, kk += 2) {
+				pmppriv->mac_filter[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
+				RTW_INFO("%s mac_filter[%d]=%x\n", __func__, jj, pmppriv->mac_filter[jj]);
+			}
+		} else
+			return -EFAULT;
+
+	}
+
+	if (bStartRx) {
+		sprintf(extra, "start");
+		SetPacketRx(padapter, bStartRx, false);
+	} else if (bStopRx) {
+		SetPacketRx(padapter, bStartRx, false);
+		pmppriv->bmac_filter = false;
+		pmppriv->bSetRxBssid = false;
+		sprintf(extra, "Received packet OK:%d CRC error:%d ,Filter out:%d", padapter->mppriv.rx_pktcount, padapter->mppriv.rx_crcerrpktcount, padapter->mppriv.rx_pktcount_filter_out);
+	} else if (bQueryPhy) {
+		memset(&rx_counter, 0, sizeof(struct dbg_rx_counter));
+		rtw_dump_phy_rx_counters(padapter, &rx_counter);
+
+		RTW_INFO("%s: OFDM_FA =%d\n", __func__, rx_counter.rx_ofdm_fa);
+		RTW_INFO("%s: CCK_FA =%d\n", __func__, rx_counter.rx_cck_fa);
+		sprintf(extra, "Phy Received packet OK:%d CRC error:%d FA Counter: %d", rx_counter.rx_pkt_ok, rx_counter.rx_pkt_crc_error, rx_counter.rx_cck_fa + rx_counter.rx_ofdm_fa);
+
+
+	} else if (bQueryMac) {
+		memset(&rx_counter, 0, sizeof(struct dbg_rx_counter));
+		rtw_dump_mac_rx_counters(padapter, &rx_counter);
+		sprintf(extra, "Mac Received packet OK: %d , CRC error: %d , Drop Packets: %d\n",
+			rx_counter.rx_pkt_ok, rx_counter.rx_pkt_crc_error, rx_counter.rx_pkt_drop);
+
+	}
+
+	if (bmon == 1) {
+		ret = sscanf(input, "mon=%d", &bmon);
+
+		if (bmon == 1) {
+			pmppriv->rx_bindicatePkt = true;
+			sprintf(extra, "Indicating Receive Packet to network start\n");
+		} else {
+			pmppriv->rx_bindicatePkt = false;
+			sprintf(extra, "Indicating Receive Packet to network Stop\n");
+		}
+	}
+	if (bSmpCfg == 1) {
+		ret = sscanf(input, "smpcfg=%d", &bSmpCfg);
+
+		if (bSmpCfg == 1) {
+			pmppriv->bRTWSmbCfg = true;
+			sprintf(extra , "Indicate By Simple Config Format\n");
+			SetPacketRx(padapter, true, true);
+		} else {
+			pmppriv->bRTWSmbCfg = false;
+			sprintf(extra , "Indicate By Normal Format\n");
+			SetPacketRx(padapter, true, false);
+		}
+	}
+
+	if (pmppriv->bloopback == true) {
+		sprintf(extra , "Enter MAC LoopBack mode\n");
+		_rtw_write32(padapter, 0x100, 0xB0106FF);
+		RTW_INFO("0x100 :0x%x" , _rtw_read32(padapter, 0x100));
+		_rtw_write16(padapter, 0x608, 0x30c);
+		RTW_INFO("0x100 :0x%x" , _rtw_read32(padapter, 0x608));
+	}
+
+	wrqu->length = strlen(extra) + 1;
+
+	return 0;
+}
+
+
+int rtw_mp_trx_query(struct net_device *dev,
+		     struct iw_request_info *info,
+		     struct iw_point *wrqu, char *extra)
+{
+	u32 txok, txfail, rxok, rxfail, rxfilterout;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	PMPT_CONTEXT	pMptCtx		=	&(padapter->mppriv.mpt_ctx);
+	RT_PMAC_TX_INFO	PMacTxInfo	=	pMptCtx->PMacTxInfo;
+
+	if (PMacTxInfo.bEnPMacTx == true)
+		txok = hal_mpt_query_phytxok(padapter);
+	else
+		txok = padapter->mppriv.tx.sended;
+
+	txfail = 0;
+	rxok = padapter->mppriv.rx_pktcount;
+	rxfail = padapter->mppriv.rx_crcerrpktcount;
+	rxfilterout = padapter->mppriv.rx_pktcount_filter_out;
+
+	memset(extra, '\0', 128);
+
+	sprintf(extra, "Tx OK:%d, Tx Fail:%d, Rx OK:%d, CRC error:%d ,Rx Filter out:%d\n", txok, txfail, rxok, rxfail, rxfilterout);
+
+	wrqu->length = strlen(extra) + 1;
+
+	return 0;
+}
+
+
+int rtw_mp_pwrtrk(struct net_device *dev,
+		  struct iw_request_info *info,
+		  struct iw_point *wrqu, char *extra)
+{
+	u8 enable;
+	u32 thermal;
+	s32 ret;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	HAL_DATA_TYPE			*pHalData = GET_HAL_DATA(padapter);
+	u8		input[128];
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	memset(extra, 0, wrqu->length);
+
+	enable = 1;
+	if (wrqu->length > 1) {
+		/* not empty string*/
+		if (strncmp(input, "stop", 4) == 0) {
+			enable = 0;
+			sprintf(extra, "mp tx power tracking stop");
+		} else if (sscanf(input, "ther=%d", &thermal) == 1) {
+			ret = SetThermalMeter(padapter, (u8)thermal);
+			if (ret == _FAIL)
+				return -EPERM;
+			sprintf(extra, "mp tx power tracking start,target value=%d ok", thermal);
+		} else
+			return -EINVAL;
+	}
+
+	ret = SetPowerTracking(padapter, enable);
+	if (ret == _FAIL)
+		return -EPERM;
+
+	wrqu->length = strlen(extra);
+
+	return 0;
+}
+
+
+
+int rtw_mp_psd(struct net_device *dev,
+	       struct iw_request_info *info,
+	       struct iw_point *wrqu, char *extra)
+{
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	u8		input[128];
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	strcpy(extra, input);
+
+	wrqu->length = mp_query_psd(padapter, extra);
+
+	return 0;
+}
+
+
+int rtw_mp_thermal(struct net_device *dev,
+		   struct iw_request_info *info,
+		   struct iw_point *wrqu, char *extra)
+{
+	u8 val;
+	int bwrite = 1;
+	u16 addr = EEPROM_THERMAL_METER_88E;
+	u16 cnt = 1;
+	u16 max_available_size = 0;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+
+	if (copy_from_user(extra, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	bwrite = strncmp(extra, "write", 6);/* strncmp true is 0*/
+
+	GetThermalMeter(padapter, &val);
+
+	if (bwrite == 0) {
+		/*RTW_INFO("to write val:%d",val);*/
+		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+		if (2 > max_available_size) {
+			RTW_INFO("no available efuse!\n");
+			return -EFAULT;
+		}
+		if (rtw_efuse_map_write(padapter, addr, cnt, &val) == _FAIL) {
+			RTW_INFO("rtw_efuse_map_write error\n");
+			return -EFAULT;
+		}
+		sprintf(extra, " efuse write ok :%d", val);
+	} else
+		sprintf(extra, "%d", val);
+	wrqu->length = strlen(extra);
+
+	return 0;
+}
+
+
+
+int rtw_mp_reset_stats(struct net_device *dev,
+		       struct iw_request_info *info,
+		       struct iw_point *wrqu, char *extra)
+{
+	struct mp_priv *pmp_priv;
+	struct pkt_attrib *pattrib;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+
+	pmp_priv = &padapter->mppriv;
+
+	pmp_priv->tx.sended = 0;
+	pmp_priv->tx_pktcount = 0;
+	pmp_priv->rx_pktcount = 0;
+	pmp_priv->rx_pktcount_filter_out = 0;
+	pmp_priv->rx_crcerrpktcount = 0;
+
+	rtw_reset_phy_rx_counters(padapter);
+	rtw_reset_mac_rx_counters(padapter);
+
+	memset(extra, 0, wrqu->length);
+	sprintf(extra, "mp_reset_stats ok\n");
+	wrqu->length = strlen(extra);
+
+	return 0;
+}
+
+
+int rtw_mp_dump(struct net_device *dev,
+		struct iw_request_info *info,
+		struct iw_point *wrqu, char *extra)
+{
+	struct mp_priv *pmp_priv;
+	struct pkt_attrib *pattrib;
+	u32 value;
+	u8		input[128];
+	u8 rf_type, path_nums = 0;
+	u32 i, j = 1, path;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+
+	pmp_priv = &padapter->mppriv;
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	if (strncmp(input, "all", 4) == 0) {
+		mac_reg_dump(RTW_DBGDUMP, padapter);
+		bb_reg_dump(RTW_DBGDUMP, padapter);
+		rf_reg_dump(RTW_DBGDUMP, padapter);
+	}
+	return 0;
+}
+
+
+int rtw_mp_phypara(struct net_device *dev,
+		   struct iw_request_info *info,
+		   struct iw_point *wrqu, char *extra)
+{
+
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(padapter);
+	char	input[128];
+	u32		valxcap, ret;
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	RTW_INFO("%s:iwpriv in=%s\n", __func__, input);
+
+	ret = sscanf(input, "xcap=%d", &valxcap);
+
+	pHalData->crystal_cap = (u8)valxcap;
+	hal_set_crystal_cap(padapter , valxcap);
+
+	sprintf(extra, "Set xcap=%d", valxcap);
+	wrqu->length = strlen(extra) + 1;
+
+	return 0;
+
+}
+
+
+int rtw_mp_SetRFPath(struct net_device *dev,
+		     struct iw_request_info *info,
+		     struct iw_point *wrqu, char *extra)
+{
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	char	input[128];
+	int		bMain = 1, bTurnoff = 1;
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	RTW_INFO("%s:iwpriv in=%s\n", __func__, input);
+
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	bMain = strncmp(input, "1", 2); /* strncmp true is 0*/
+	bTurnoff = strncmp(input, "0", 3); /* strncmp true is 0*/
+
+	memset(extra, 0, wrqu->length);
+
+	if (bMain == 0) {
+		MP_PHY_SetRFPathSwitch(padapter, true);
+		RTW_INFO("%s:PHY_SetRFPathSwitch=true\n", __func__);
+		sprintf(extra, "mp_setrfpath Main\n");
+
+	} else if (bTurnoff == 0) {
+		MP_PHY_SetRFPathSwitch(padapter, false);
+		RTW_INFO("%s:PHY_SetRFPathSwitch=false\n", __func__);
+		sprintf(extra, "mp_setrfpath Aux\n");
+	} else {
+		bMain = MP_PHY_QueryRFPathSwitch(padapter);
+		RTW_INFO("%s:PHY_SetRFPathSwitch = %s\n", __func__, (bMain ? "Main":"Aux"));
+		sprintf(extra, "mp_setrfpath %s\n" , (bMain ? "Main":"Aux"));
+	}
+
+	wrqu->length = strlen(extra);
+
+	return 0;
+}
+
+
+int rtw_mp_QueryDrv(struct net_device *dev,
+		    struct iw_request_info *info,
+		    union iwreq_data *wrqu, char *extra)
+{
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	char	input[128];
+	int	qAutoLoad = 1;
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
+
+	if (wrqu->data.length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length))
+		return -EFAULT;
+	RTW_INFO("%s:iwpriv in=%s\n", __func__, input);
+
+	qAutoLoad = strncmp(input, "autoload", 8); /* strncmp true is 0*/
+
+	if (qAutoLoad == 0) {
+		RTW_INFO("%s:qAutoLoad\n", __func__);
+
+		if (pHalData->bautoload_fail_flag)
+			sprintf(extra, "fail");
+		else
+			sprintf(extra, "ok");
+	}
+	wrqu->data.length = strlen(extra) + 1;
+	return 0;
+}
+
+
+int rtw_mp_PwrCtlDM(struct net_device *dev,
+		    struct iw_request_info *info,
+		    struct iw_point *wrqu, char *extra)
+{
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	u8		input[128];
+	int		bstart = 1;
+
+	if (wrqu->length > 128)
+		return -EFAULT;
+	if (copy_from_user(input, wrqu->pointer, wrqu->length))
+		return -EFAULT;
+
+	bstart = strncmp(input, "start", 5); /* strncmp true is 0*/
+	if (bstart == 0) {
+		sprintf(extra, "PwrCtlDM start\n");
+		MPT_PwrCtlDM(padapter, 1);
+	} else {
+		sprintf(extra, "PwrCtlDM stop\n");
+		MPT_PwrCtlDM(padapter, 0);
+	}
+	wrqu->length = strlen(extra);
+
+	return 0;
+}
+
+int rtw_mp_iqk(struct net_device *dev,
+		 struct iw_request_info *info,
+		 struct iw_point *wrqu, char *extra)
+{
+	PADAPTER padapter = rtw_netdev_priv(dev);
+
+	rtw_mp_trigger_iqk(padapter);
+
+	return 0;
+}
+
+int rtw_mp_lck(struct net_device *dev,
+		 struct iw_request_info *info,
+		 struct iw_point *wrqu, char *extra)
+{
+	PADAPTER padapter = rtw_netdev_priv(dev);
+
+	rtw_mp_trigger_lck(padapter);
+
+	return 0;
+}
+
+int rtw_mp_getver(struct net_device *dev,
+		  struct iw_request_info *info,
+		  union iwreq_data *wrqu, char *extra)
+{
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	struct mp_priv *pmp_priv;
+
+	pmp_priv = &padapter->mppriv;
+
+	if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
+		return -EFAULT;
+
+	sprintf(extra, "rtwpriv=%d\n", RTWPRIV_VER_INFO);
+	wrqu->data.length = strlen(extra);
+	return 0;
+}
+
+
+int rtw_mp_mon(struct net_device *dev,
+	       struct iw_request_info *info,
+	       union iwreq_data *wrqu, char *extra)
+{
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct hal_ops *pHalFunc = &padapter->hal_func;
+	NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
+	int bstart = 1, bstop = 1;
+
+	networkType = Ndis802_11Infrastructure;
+	if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
+		return -EFAULT;
+
+	rtw_pm_set_ips(padapter, IPS_NONE);
+	LeaveAllPowerSaveMode(padapter);
+
+#ifdef CONFIG_MP_INCLUDED
+	if (init_mp_priv(padapter) == _FAIL)
+		RTW_INFO("%s: initialize MP private data Fail!\n", __func__);
+	padapter->mppriv.channel = 6;
+
+	bstart = strncmp(extra, "start", 5); /* strncmp true is 0*/
+	bstop = strncmp(extra, "stop", 4); /* strncmp true is 0*/
+	if (bstart == 0) {
+		mp_join(padapter, WIFI_FW_ADHOC_STATE);
+		SetPacketRx(padapter, true, false);
+		SetChannel(padapter);
+		pmp_priv->rx_bindicatePkt = true;
+		pmp_priv->bRTWSmbCfg = true;
+		sprintf(extra, "monitor mode start\n");
+	} else if (bstop == 0) {
+		SetPacketRx(padapter, false, false);
+		pmp_priv->rx_bindicatePkt = false;
+		pmp_priv->bRTWSmbCfg = false;
+		padapter->registrypriv.mp_mode = 1;
+		pHalFunc->hal_deinit(padapter);
+		padapter->registrypriv.mp_mode = 0;
+		pHalFunc->hal_init(padapter);
+		/*rtw_disassoc_cmd(padapter, 0, true);*/
+		if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+			rtw_disassoc_cmd(padapter, 500, true);
+			rtw_indicate_disconnect(padapter, 0, false);
+			/*rtw_free_assoc_resources(padapter, 1);*/
+		}
+		rtw_pm_set_ips(padapter, IPS_NORMAL);
+		sprintf(extra, "monitor mode Stop\n");
+	}
+#endif
+	wrqu->data.length = strlen(extra);
+	return 0;
+}
+
+int rtw_mp_pretx_proc(PADAPTER padapter, u8 bStartTest, char *extra)
+{
+	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(padapter);
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+	PMPT_CONTEXT		pMptCtx = &(padapter->mppriv.mpt_ctx);
+
+	switch (pmp_priv->mode) {
+
+	case MP_PACKET_TX:
+		if (bStartTest == 0) {
+			pmp_priv->tx.stop = 1;
+			pmp_priv->mode = MP_ON;
+			sprintf(extra, "Stop continuous Tx");
+		} else if (pmp_priv->tx.stop == 1) {
+			sprintf(extra + strlen(extra), "\nStart continuous DA=ffffffffffff len=1500 count=%u\n", pmp_priv->tx.count);
+			pmp_priv->tx.stop = 0;
+			SetPacketTx(padapter);
+		} else
+			return -EFAULT;
+		return 0;
+	case MP_SINGLE_TONE_TX:
+		if (bStartTest != 0)
+			sprintf(extra + strlen(extra), "\nStart continuous DA=ffffffffffff len=1500\n infinite=yes.");
+		SetSingleToneTx(padapter, (u8)bStartTest);
+		break;
+	case MP_CONTINUOUS_TX:
+		if (bStartTest != 0)
+			sprintf(extra + strlen(extra), "\nStart continuous DA=ffffffffffff len=1500\n infinite=yes.");
+		SetContinuousTx(padapter, (u8)bStartTest);
+		break;
+	case MP_CARRIER_SUPPRISSION_TX:
+		if (bStartTest != 0) {
+			if (HwRateToMPTRate(pmp_priv->rateidx) <= MPT_RATE_11M)
+				sprintf(extra + strlen(extra), "\nStart continuous DA=ffffffffffff len=1500\n infinite=yes.");
+			else
+				sprintf(extra + strlen(extra), "\nSpecify carrier suppression but not CCK rate");
+		}
+		SetCarrierSuppressionTx(padapter, (u8)bStartTest);
+		break;
+	case MP_SINGLE_CARRIER_TX:
+		if (bStartTest != 0)
+			sprintf(extra + strlen(extra), "\nStart continuous DA=ffffffffffff len=1500\n infinite=yes.");
+		SetSingleCarrierTx(padapter, (u8)bStartTest);
+		break;
+
+	default:
+		sprintf(extra, "Error! Continuous-Tx is not on-going.");
+		return -EFAULT;
+	}
+
+	if (bStartTest == 1 && pmp_priv->mode != MP_ON) {
+		struct mp_priv *pmp_priv = &padapter->mppriv;
+
+		if (pmp_priv->tx.stop == 0) {
+			pmp_priv->tx.stop = 1;
+			rtw_msleep_os(5);
+		}
+		pmp_priv->tx.attrib.ht_en = 1;
+		pmp_priv->tx.stop = 0;
+		pmp_priv->tx.count = 1;
+		SetPacketTx(padapter);
+	} else
+		pmp_priv->mode = MP_ON;
+
+	return 0;
+}
+
+int rtw_mp_tx(struct net_device *dev,
+	      struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(padapter);
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+	PMPT_CONTEXT		pMptCtx = &(padapter->mppriv.mpt_ctx);
+	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+
+	u32 bandwidth = 0, sg = 0, channel = 6, txpower = 40, rate = 108, ant = 0, txmode = 1, count = 0;
+	u8 i = 0, j = 0, bStartTest = 1, status = 0, Idx = 0, tmpU1B = 0;
+	u16 antenna = 0;
+
+	if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
+		return -EFAULT;
+	RTW_INFO("extra = %s\n", extra);
+#ifdef CONFIG_CONCURRENT_MODE
+	if (!is_primary_adapter(padapter)) {
+		sprintf(extra, "Error: MP mode can't support Virtual Adapter, Please to use main Adapter.\n");
+		wrqu->data.length = strlen(extra);
+		return 0;
+	}
+#endif
+
+	if (strncmp(extra, "stop", 3) == 0) {
+		bStartTest = 0; /* To set Stop*/
+		pmp_priv->tx.stop = 1;
+		sprintf(extra, "Stop continuous Tx");
+		status = rtw_mp_pretx_proc(padapter, bStartTest, extra);
+		wrqu->data.length = strlen(extra);
+		return status;
+	} else if (strncmp(extra, "count", 5) == 0) {
+		if (sscanf(extra, "count=%d", &count) < 1)
+			RTW_INFO("Got Count=%d]\n", count);
+		pmp_priv->tx.count = count;
+		return 0;
+	} else if (strncmp(extra, "setting", 7) == 0) {
+		memset(extra, 0, wrqu->data.length);
+		sprintf(extra, "Current Setting :\n Channel:%d", pmp_priv->channel);
+		sprintf(extra + strlen(extra), "\n Bandwidth:%d", pmp_priv->bandwidth);
+		sprintf(extra + strlen(extra), "\n Rate index:%d", pmp_priv->rateidx);
+		sprintf(extra + strlen(extra), "\n TxPower index:%d", pmp_priv->txpoweridx);
+		sprintf(extra + strlen(extra), "\n Antenna TxPath:%d", pmp_priv->antenna_tx);
+		sprintf(extra + strlen(extra), "\n Antenna RxPath:%d", pmp_priv->antenna_rx);
+		sprintf(extra + strlen(extra), "\n MP Mode:%d", pmp_priv->mode);
+		wrqu->data.length = strlen(extra);
+		return 0;
+#ifdef CONFIG_MP_VHT_HW_TX_MODE
+	} else if (strncmp(extra, "pmact", 5) == 0) {
+		if (strncmp(extra, "pmact=", 6) == 0) {
+			memset(&pMptCtx->PMacTxInfo, 0, sizeof(pMptCtx->PMacTxInfo));
+			if (strncmp(extra, "pmact=start", 11) == 0) {
+				pMptCtx->PMacTxInfo.bEnPMacTx = true;
+				sprintf(extra, "Set PMac Tx Mode start\n");
+			} else {
+				pMptCtx->PMacTxInfo.bEnPMacTx = false;
+				sprintf(extra, "Set PMac Tx Mode Stop\n");
+			}
+			if (pMptCtx->bldpc == true)
+				pMptCtx->PMacTxInfo.bLDPC = true;
+
+			if (pMptCtx->bstbc == true)
+				pMptCtx->PMacTxInfo.bSTBC = true;
+
+			pMptCtx->PMacTxInfo.bSPreamble = pmp_priv->preamble;
+			pMptCtx->PMacTxInfo.bSGI = pmp_priv->preamble;
+			pMptCtx->PMacTxInfo.BandWidth = pmp_priv->bandwidth;
+			pMptCtx->PMacTxInfo.TX_RATE = HwRateToMPTRate(pmp_priv->rateidx);
+
+			pMptCtx->PMacTxInfo.Mode = pMptCtx->HWTxmode;
+
+			pMptCtx->PMacTxInfo.NDP_sound = false;/*(Adapter.PacketType == NDP_PKT)?true:false;*/
+
+			if (padapter->mppriv.pktInterval == 0)
+				pMptCtx->PMacTxInfo.PacketPeriod = 100;
+			else
+				pMptCtx->PMacTxInfo.PacketPeriod = padapter->mppriv.pktInterval;
+
+			if (padapter->mppriv.pktLength < 1000)
+				pMptCtx->PMacTxInfo.PacketLength = 1000;
+			else
+				pMptCtx->PMacTxInfo.PacketLength = padapter->mppriv.pktLength;
+
+			pMptCtx->PMacTxInfo.PacketPattern  = rtw_random32() % 0xFF;
+
+			if (padapter->mppriv.tx_pktcount != 0)
+				pMptCtx->PMacTxInfo.PacketCount = padapter->mppriv.tx_pktcount;
+
+			pMptCtx->PMacTxInfo.Ntx = 0;
+			for (Idx = 16; Idx < 20; Idx++) {
+				tmpU1B = (padapter->mppriv.antenna_tx >> Idx) & 1;
+				if (tmpU1B)
+					pMptCtx->PMacTxInfo.Ntx++;
+			}
+
+			memset(pMptCtx->PMacTxInfo.MacAddress, 0xFF, ETH_ALEN);
+
+			PMAC_Get_Pkt_Param(&pMptCtx->PMacTxInfo, &pMptCtx->PMacPktInfo);
+
+			if (MPT_IS_CCK_RATE(pMptCtx->PMacTxInfo.TX_RATE))
+
+				CCK_generator(&pMptCtx->PMacTxInfo, &pMptCtx->PMacPktInfo);
+			else {
+				PMAC_Nsym_generator(&pMptCtx->PMacTxInfo, &pMptCtx->PMacPktInfo);
+				/* 24 BIT*/
+				L_SIG_generator(pMptCtx->PMacPktInfo.N_sym, &pMptCtx->PMacTxInfo, &pMptCtx->PMacPktInfo);
+			}
+			/*	48BIT*/
+			if (MPT_IS_HT_RATE(pMptCtx->PMacTxInfo.TX_RATE))
+				HT_SIG_generator(&pMptCtx->PMacTxInfo, &pMptCtx->PMacPktInfo);
+			else if (MPT_IS_VHT_RATE(pMptCtx->PMacTxInfo.TX_RATE)) {
+				/*	48BIT*/
+				VHT_SIG_A_generator(&pMptCtx->PMacTxInfo, &pMptCtx->PMacPktInfo);
+
+				/*	26/27/29 BIT  & CRC 8 BIT*/
+				VHT_SIG_B_generator(&pMptCtx->PMacTxInfo);
+
+				/* 32 BIT*/
+				VHT_Delimiter_generator(&pMptCtx->PMacTxInfo);
+			}
+
+			mpt_ProSetPMacTx(padapter);
+
+		} else if (strncmp(extra, "pmact,mode=", 11) == 0) {
+			int txmode = 0;
+
+			if (sscanf(extra, "pmact,mode=%d", &txmode) > 0) {
+				if (txmode == 1) {
+					pMptCtx->HWTxmode = CONTINUOUS_TX;
+					sprintf(extra, "\t Config HW Tx mode = CONTINUOUS_TX\n");
+				} else if (txmode == 2) {
+					pMptCtx->HWTxmode = OFDM_Single_Tone_TX;
+					sprintf(extra, "\t Config HW Tx mode = OFDM_Single_Tone_TX\n");
+				} else {
+					pMptCtx->HWTxmode = PACKETS_TX;
+					sprintf(extra, "\t Config HW Tx mode = PACKETS_TX\n");
+				}
+			} else {
+				pMptCtx->HWTxmode = PACKETS_TX;
+				sprintf(extra, "\t Config HW Tx mode=\n 0 = PACKETS_TX\n 1 = CONTINUOUS_TX\n 2 = OFDM_Single_Tone_TX");
+			}
+		} else if (strncmp(extra, "pmact,", 6) == 0) {
+			int PacketPeriod = 0, PacketLength = 0, PacketCout = 0;
+			int bldpc = 0, bstbc = 0;
+
+			if (sscanf(extra, "pmact,period=%d", &PacketPeriod) > 0) {
+				padapter->mppriv.pktInterval = PacketPeriod;
+				RTW_INFO("PacketPeriod=%d\n", padapter->mppriv.pktInterval);
+				sprintf(extra, "PacketPeriod [1~255]= %d\n", padapter->mppriv.pktInterval);
+
+			} else if (sscanf(extra, "pmact,length=%d", &PacketLength) > 0) {
+				padapter->mppriv.pktLength = PacketLength;
+				RTW_INFO("PacketPeriod=%d\n", padapter->mppriv.pktLength);
+				sprintf(extra, "PacketLength[~65535]=%d\n", padapter->mppriv.pktLength);
+
+			} else if (sscanf(extra, "pmact,count=%d", &PacketCout) > 0) {
+				padapter->mppriv.tx_pktcount = PacketCout;
+				RTW_INFO("Packet Cout =%d\n", padapter->mppriv.tx_pktcount);
+				sprintf(extra, "Packet Cout =%d\n", padapter->mppriv.tx_pktcount);
+
+			} else if (sscanf(extra, "pmact,ldpc=%d", &bldpc) > 0) {
+				pMptCtx->bldpc = bldpc;
+				RTW_INFO("Set LDPC =%d\n", pMptCtx->bldpc);
+				sprintf(extra, "Set LDPC =%d\n", pMptCtx->bldpc);
+
+			} else if (sscanf(extra, "pmact,stbc=%d", &bstbc) > 0) {
+				pMptCtx->bstbc = bstbc;
+				RTW_INFO("Set STBC =%d\n", pMptCtx->bstbc);
+				sprintf(extra, "Set STBC =%d\n", pMptCtx->bstbc);
+			} else
+				sprintf(extra, "\n period={1~255}\n length={1000~65535}\n count={0~}\n ldpc={0/1}\n stbc={0/1}");
+
+		}
+
+		wrqu->data.length = strlen(extra);
+		return 0;
+#endif
+	} else {
+
+		if (sscanf(extra, "ch=%d,bw=%d,rate=%d,pwr=%d,ant=%d,tx=%d", &channel, &bandwidth, &rate, &txpower, &ant, &txmode) < 6) {
+			RTW_INFO("Invalid format [ch=%d,bw=%d,rate=%d,pwr=%d,ant=%d,tx=%d]\n", channel, bandwidth, rate, txpower, ant, txmode);
+			memset(extra, 0, wrqu->data.length);
+			sprintf(extra, "\n Please input correct format as bleow:\n");
+			sprintf(extra + strlen(extra), "\t ch=%d,bw=%d,rate=%d,pwr=%d,ant=%d,tx=%d\n", channel, bandwidth, rate, txpower, ant, txmode);
+			sprintf(extra + strlen(extra), "\n [ ch : BGN = <1~14> , A or AC = <36~165> ]");
+			sprintf(extra + strlen(extra), "\n [ bw : Bandwidth: 0 = 20M, 1 = 40M, 2 = 80M ]");
+			sprintf(extra + strlen(extra), "\n [ rate :	CCK: 1 2 5.5 11M X 2 = < 2 4 11 22 >]");
+			sprintf(extra + strlen(extra), "\n [		OFDM: 6 9 12 18 24 36 48 54M X 2 = < 12 18 24 36 48 72 96 108>");
+			sprintf(extra + strlen(extra), "\n [		HT 1S2SS MCS0 ~ MCS15 : < [MCS0]=128 ~ [MCS7]=135 ~ [MCS15]=143 >");
+			sprintf(extra + strlen(extra), "\n [		HT 3SS MCS16 ~ MCS32 : < [MCS16]=144 ~ [MCS23]=151 ~ [MCS32]=159 >");
+			sprintf(extra + strlen(extra), "\n [		VHT 1SS MCS0 ~ MCS9 : < [MCS0]=160 ~ [MCS9]=169 >");
+			sprintf(extra + strlen(extra), "\n [ txpower : 1~63 power index");
+			sprintf(extra + strlen(extra), "\n [ ant : <A = 1, B = 2, C = 4, D = 8> ,2T ex: AB=3 BC=6 CD=12");
+			sprintf(extra + strlen(extra), "\n [ txmode : < 0 = CONTINUOUS_TX, 1 = PACKET_TX, 2 = SINGLE_TONE_TX, 3 = CARRIER_SUPPRISSION_TX, 4 = SINGLE_CARRIER_TX>\n");
+			wrqu->data.length = strlen(extra);
+			return status;
+
+		} else {
+			RTW_INFO("Got format [ch=%d,bw=%d,rate=%d,pwr=%d,ant=%d,tx=%d]\n", channel, bandwidth, rate, txpower, ant, txmode);
+			memset(extra, 0, wrqu->data.length);
+			sprintf(extra, "Change Current channel %d to channel %d", padapter->mppriv.channel , channel);
+			padapter->mppriv.channel = channel;
+			SetChannel(padapter);
+			pHalData->current_channel = channel;
+
+			if (bandwidth == 1)
+				bandwidth = CHANNEL_WIDTH_40;
+			else if (bandwidth == 2)
+				bandwidth = CHANNEL_WIDTH_80;
+			sprintf(extra + strlen(extra), "\nChange Current Bandwidth %d to Bandwidth %d", padapter->mppriv.bandwidth , bandwidth);
+			padapter->mppriv.bandwidth = (u8)bandwidth;
+			padapter->mppriv.preamble = sg;
+			SetBandwidth(padapter);
+			pHalData->current_channel_bw = bandwidth;
+
+			sprintf(extra + strlen(extra), "\nSet power level :%d", txpower);
+			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;
+
+			RTW_INFO("%s: bw=%d sg=%d\n", __func__, bandwidth, sg);
+
+			if (rate <= 0x7f)
+				rate = wifirate2_ratetbl_inx((u8)rate);
+			else if (rate < 0xC8)
+				rate = (rate - 0x80 + MPT_RATE_MCS0);
+			/*HT  rate 0x80(MCS0)  ~ 0x8F(MCS15) ~ 0x9F(MCS31) 128~159
+			VHT1SS~2SS rate 0xA0 (VHT1SS_MCS0 44) ~ 0xB3 (VHT2SS_MCS9 #63) 160~179
+			VHT rate 0xB4 (VHT3SS_MCS0 64) ~ 0xC7 (VHT2SS_MCS9 #83) 180~199
+			else
+			VHT rate 0x90(VHT1SS_MCS0) ~ 0x99(VHT1SS_MCS9) 144~153
+			rate =(rate - MPT_RATE_VHT1SS_MCS0);
+			*/
+			RTW_INFO("%s: rate index=%d\n", __func__, rate);
+			if (rate >= MPT_RATE_LAST)
+				return -EINVAL;
+			sprintf(extra + strlen(extra), "\nSet data rate to %d index %d", padapter->mppriv.rateidx, rate);
+
+			padapter->mppriv.rateidx = rate;
+			pMptCtx->mpt_rate_index = rate;
+			SetDataRate(padapter);
+
+			sprintf(extra + strlen(extra), "\nSet Antenna Path :%d", ant);
+			switch (ant) {
+			case 1:
+				antenna = ANTENNA_A;
+				break;
+			case 2:
+				antenna = ANTENNA_B;
+				break;
+			case 4:
+				antenna = ANTENNA_C;
+				break;
+			case 8:
+				antenna = ANTENNA_D;
+				break;
+			case 3:
+				antenna = ANTENNA_AB;
+				break;
+			case 5:
+				antenna = ANTENNA_AC;
+				break;
+			case 9:
+				antenna = ANTENNA_AD;
+				break;
+			case 6:
+				antenna = ANTENNA_BC;
+				break;
+			case 10:
+				antenna = ANTENNA_BD;
+				break;
+			case 12:
+				antenna = ANTENNA_CD;
+				break;
+			case 7:
+				antenna = ANTENNA_ABC;
+				break;
+			case 14:
+				antenna = ANTENNA_BCD;
+				break;
+			case 11:
+				antenna = ANTENNA_ABD;
+				break;
+			case 15:
+				antenna = ANTENNA_ABCD;
+				break;
+			}
+			RTW_INFO("%s: antenna=0x%x\n", __func__, antenna);
+			padapter->mppriv.antenna_tx = antenna;
+			padapter->mppriv.antenna_rx = antenna;
+			pHalData->antenna_tx_path = antenna;
+			SetAntenna(padapter);
+
+			if (txmode == 0)
+				pmp_priv->mode = MP_CONTINUOUS_TX;
+			else if (txmode == 1) {
+				pmp_priv->mode = MP_PACKET_TX;
+				pmp_priv->tx.count = count;
+			} else if (txmode == 2)
+				pmp_priv->mode = MP_SINGLE_TONE_TX;
+			else if (txmode == 3)
+				pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX;
+			else if (txmode == 4)
+				pmp_priv->mode = MP_SINGLE_CARRIER_TX;
+
+			status = rtw_mp_pretx_proc(padapter, bStartTest, extra);
+		}
+
+	}
+
+	wrqu->data.length = strlen(extra);
+	return status;
+}
+
+
+int rtw_mp_rx(struct net_device *dev,
+	      struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(padapter);
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+	PMPT_CONTEXT		pMptCtx = &(padapter->mppriv.mpt_ctx);
+
+	u32 bandwidth = 0, sg = 0, channel = 6, ant = 0;
+	u16 antenna = 0;
+	u8 bStartRx = 0;
+
+	if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
+		return -EFAULT;
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (!is_primary_adapter(padapter)) {
+		sprintf(extra, "Error: MP mode can't support Virtual Adapter, Please to use main Adapter.\n");
+		wrqu->data.length = strlen(extra);
+		return 0;
+	}
+#endif
+
+	if (strncmp(extra, "stop", 4) == 0) {
+		memset(extra, 0, wrqu->data.length);
+		SetPacketRx(padapter, bStartRx, false);
+		pmp_priv->bmac_filter = false;
+		sprintf(extra, "Received packet OK:%d CRC error:%d ,Filter out:%d", padapter->mppriv.rx_pktcount, padapter->mppriv.rx_crcerrpktcount, padapter->mppriv.rx_pktcount_filter_out);
+		wrqu->data.length = strlen(extra);
+		return 0;
+
+	} else if (sscanf(extra, "ch=%d,bw=%d,ant=%d", &channel, &bandwidth, &ant) < 3) {
+		RTW_INFO("Invalid format [ch=%d,bw=%d,ant=%d]\n", channel, bandwidth, ant);
+		memset(extra, 0, wrqu->data.length);
+		sprintf(extra, "\n Please input correct format as bleow:\n");
+		sprintf(extra + strlen(extra), "\t ch=%d,bw=%d,ant=%d\n", channel, bandwidth, ant);
+		sprintf(extra + strlen(extra), "\n [ ch : BGN = <1~14> , A or AC = <36~165> ]");
+		sprintf(extra + strlen(extra), "\n [ bw : Bandwidth: 0 = 20M, 1 = 40M, 2 = 80M ]");
+		sprintf(extra + strlen(extra), "\n [ ant : <A = 1, B = 2, C = 4, D = 8> ,2T ex: AB=3 BC=6 CD=12");
+		wrqu->data.length = strlen(extra);
+		return 0;
+
+	} else {
+		bStartRx = 1;
+		RTW_INFO("Got format [ch=%d,bw=%d,ant=%d]\n", channel, bandwidth, ant);
+		memset(extra, 0, wrqu->data.length);
+		sprintf(extra, "Change Current channel %d to channel %d", padapter->mppriv.channel , channel);
+		padapter->mppriv.channel = channel;
+		SetChannel(padapter);
+		pHalData->current_channel = channel;
+
+		if (bandwidth == 1)
+			bandwidth = CHANNEL_WIDTH_40;
+		else if (bandwidth == 2)
+			bandwidth = CHANNEL_WIDTH_80;
+		sprintf(extra + strlen(extra), "\nChange Current Bandwidth %d to Bandwidth %d", padapter->mppriv.bandwidth , bandwidth);
+		padapter->mppriv.bandwidth = (u8)bandwidth;
+		padapter->mppriv.preamble = sg;
+		SetBandwidth(padapter);
+		pHalData->current_channel_bw = bandwidth;
+
+		sprintf(extra + strlen(extra), "\nSet Antenna Path :%d", ant);
+		switch (ant) {
+		case 1:
+			antenna = ANTENNA_A;
+			break;
+		case 2:
+			antenna = ANTENNA_B;
+			break;
+		case 4:
+			antenna = ANTENNA_C;
+			break;
+		case 8:
+			antenna = ANTENNA_D;
+			break;
+		case 3:
+			antenna = ANTENNA_AB;
+			break;
+		case 5:
+			antenna = ANTENNA_AC;
+			break;
+		case 9:
+			antenna = ANTENNA_AD;
+			break;
+		case 6:
+			antenna = ANTENNA_BC;
+			break;
+		case 10:
+			antenna = ANTENNA_BD;
+			break;
+		case 12:
+			antenna = ANTENNA_CD;
+			break;
+		case 7:
+			antenna = ANTENNA_ABC;
+			break;
+		case 14:
+			antenna = ANTENNA_BCD;
+			break;
+		case 11:
+			antenna = ANTENNA_ABD;
+			break;
+		case 15:
+			antenna = ANTENNA_ABCD;
+			break;
+		}
+		RTW_INFO("%s: antenna=0x%x\n", __func__, antenna);
+		padapter->mppriv.antenna_tx = antenna;
+		padapter->mppriv.antenna_rx = antenna;
+		pHalData->antenna_tx_path = antenna;
+		SetAntenna(padapter);
+
+		sprintf(extra + strlen(extra), "\nstart Rx");
+		SetPacketRx(padapter, bStartRx, false);
+	}
+	wrqu->data.length = strlen(extra);
+	return 0;
+}
+
+
+int rtw_mp_hwtx(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(padapter);
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+	PMPT_CONTEXT		pMptCtx = &(padapter->mppriv.mpt_ctx);
+
+	return 0;
+}
+
+int rtw_efuse_mask_file(struct net_device *dev,
+			struct iw_request_info *info,
+			union iwreq_data *wrqu, char *extra)
+{
+	char *rtw_efuse_mask_file_path;
+	u8 Status;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+
+	memset(maskfileBuffer, 0x00, sizeof(maskfileBuffer));
+
+	if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
+		return -EFAULT;
+
+	if (strncmp(extra, "off", 3) == 0 && strlen(extra) < 4) {
+		padapter->registrypriv.boffefusemask = 1;
+		sprintf(extra, "Turn off Efuse Mask\n");
+		wrqu->data.length = strlen(extra);
+		return 0;
+	}
+	if (strncmp(extra, "on", 2) == 0 && strlen(extra) < 3) {
+		padapter->registrypriv.boffefusemask = 0;
+		sprintf(extra, "Turn on Efuse Mask\n");
+		wrqu->data.length = strlen(extra);
+		return 0;
+	}
+	if (strncmp(extra, "data,", 5) == 0) {
+		u8	*pch, *pdata;
+		char	*ptmp, tmp;
+		u8	count = 0;
+		u8	i = 0;
+		u32	datalen = 0;
+
+		ptmp = extra;
+		pch = strsep(&ptmp, ",");
+
+		if ((pch == NULL) || (strlen(pch) == 0)) {
+			RTW_INFO("%s: parameter error(no cmd)!\n", __func__);
+			return -EFAULT;
+		}
+
+		do {
+			pch = strsep(&ptmp, ":");
+			if ((pch == NULL) || (strlen(pch) == 0))
+				break;
+			if (strlen(pch) != 2
+				|| IsHexDigit(*pch) == false
+				|| IsHexDigit(*(pch + 1)) == false
+				|| sscanf(pch, "%hhx", &tmp) != 1
+			) {
+				RTW_INFO("%s: invalid 8-bit hex! input format: data,01:23:45:67:89:ab:cd:ef...\n", __func__);
+				return -EFAULT;
+			}
+			maskfileBuffer[count++] = tmp;
+
+		 } while (count < 64);
+
+		for (i = 0; i < count; i++)
+			sprintf(extra + strlen(extra), ":%02x", maskfileBuffer[i]);
+
+		padapter->registrypriv.bFileMaskEfuse = true;
+
+		sprintf(extra + strlen(extra), "\nLoad Efuse Mask data %d hex ok\n", count);
+		wrqu->data.length = strlen(extra);
+		return 0;
+	}
+	rtw_efuse_mask_file_path = extra;
+
+	if (rtw_is_file_readable(rtw_efuse_mask_file_path) == true) {
+		RTW_INFO("%s do rtw_efuse_mask_file_read = %s! ,sizeof maskfileBuffer %zu\n", __func__, rtw_efuse_mask_file_path, sizeof(maskfileBuffer));
+		Status = rtw_efuse_file_read(padapter, rtw_efuse_mask_file_path, maskfileBuffer, sizeof(maskfileBuffer));
+		if (Status == true)
+			padapter->registrypriv.bFileMaskEfuse = true;
+		sprintf(extra, "efuse mask file read OK\n");
+	} else {
+		padapter->registrypriv.bFileMaskEfuse = false;
+		sprintf(extra, "efuse mask file readable FAIL\n");
+		RTW_INFO("%s rtw_is_file_readable fail!\n", __func__);
+	}
+	wrqu->data.length = strlen(extra);
+	return 0;
+}
+
+
+int rtw_efuse_file_map(struct net_device *dev,
+		       struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+	char *rtw_efuse_file_map_path;
+	u8 Status;
+	PEFUSE_HAL pEfuseHal;
+	PADAPTER padapter = rtw_netdev_priv(dev);
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+
+	pEfuseHal = &pHalData->EfuseHal;
+	if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
+		return -EFAULT;
+
+	rtw_efuse_file_map_path = extra;
+
+	memset(pEfuseHal->fakeEfuseModifiedMap, 0xFF, EFUSE_MAX_MAP_LEN);
+
+	if (rtw_is_file_readable(rtw_efuse_file_map_path) == true) {
+		RTW_INFO("%s do rtw_efuse_mask_file_read = %s!\n", __func__, rtw_efuse_file_map_path);
+		Status = rtw_efuse_file_read(padapter, rtw_efuse_file_map_path, pEfuseHal->fakeEfuseModifiedMap, sizeof(pEfuseHal->fakeEfuseModifiedMap));
+		if (Status == true) {
+			pmp_priv->bloadefusemap = true;
+			sprintf(extra, "efuse file file_read OK\n");
+		} else {
+			pmp_priv->bloadefusemap = false;
+			sprintf(extra, "efuse file file_read FAIL\n");
+		}
+	} else {
+		sprintf(extra, "efuse file readable FAIL\n");
+		RTW_INFO("%s rtw_is_file_readable fail!\n", __func__);
+	}
+	wrqu->data.length = strlen(extra);
+	return 0;
+}
+
+#endif
diff --git a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
new file mode 100644
index 000000000000..12fe36975d92
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
@@ -0,0 +1,726 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+
+
+#define _MLME_OSDEP_C_
+
+#include <drv_types.h>
+#include <rtw_mlme.h>
+
+#ifdef RTK_DMP_PLATFORM
+void Linkup_workitem_callback(struct work_struct *work)
+{
+	struct mlme_priv *pmlmepriv = container_of(work, struct mlme_priv, Linkup_workitem);
+	_adapter *padapter = container_of(pmlmepriv, _adapter, mlmepriv);
+
+
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12))
+	kobject_uevent(&padapter->pnetdev->dev.kobj, KOBJ_LINKUP);
+#else
+	kobject_hotplug(&padapter->pnetdev->class_dev.kobj, KOBJ_LINKUP);
+#endif
+
+}
+
+void Linkdown_workitem_callback(struct work_struct *work)
+{
+	struct mlme_priv *pmlmepriv = container_of(work, struct mlme_priv, Linkdown_workitem);
+	_adapter *padapter = container_of(pmlmepriv, _adapter, mlmepriv);
+
+
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12))
+	kobject_uevent(&padapter->pnetdev->dev.kobj, KOBJ_LINKDOWN);
+#else
+	kobject_hotplug(&padapter->pnetdev->class_dev.kobj, KOBJ_LINKDOWN);
+#endif
+
+}
+#endif
+
+
+/*
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+void sitesurvey_ctrl_handler(void *FunctionContext)
+#else
+void sitesurvey_ctrl_handler(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_adapter *adapter = (_adapter *)FunctionContext;
+#else
+	_adapter *adapter = from_timer(adapter, t, sitesurveyctrl.sitesurvey_ctrl_timer);
+#endif
+
+	_sitesurvey_ctrl_handler(adapter);
+
+	_set_timer(&adapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer, 3000);
+}
+*/
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+void rtw_join_timeout_handler(void *FunctionContext)
+#else
+void rtw_join_timeout_handler(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_adapter *adapter = (_adapter *)FunctionContext;
+#else
+	_adapter *adapter = from_timer(adapter, t, mlmepriv.assoc_timer);
+#endif
+
+	_rtw_join_timeout_handler(adapter);
+}
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+void _rtw_scan_timeout_handler(void *FunctionContext)
+#else
+void _rtw_scan_timeout_handler(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_adapter *adapter = (_adapter *)FunctionContext;
+#else
+	_adapter *adapter = from_timer(adapter, t, mlmepriv.scan_to_timer);
+#endif
+
+	rtw_scan_timeout_handler(adapter);
+}
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+void _dynamic_check_timer_handler (void *FunctionContext)
+#else
+void _dynamic_check_timer_handler(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	struct dvobj_priv *pdvobj = (struct dvobj_priv *)FunctionContext;
+#else
+	struct dvobj_priv *pdvobj = from_timer(pdvobj, t, dynamic_chk_timer);
+#endif
+	_adapter *adapter = dvobj_get_primary_adapter(pdvobj);
+
+#if (MP_DRIVER == 1)
+	if (adapter->registrypriv.mp_mode == 1 && adapter->mppriv.mp_dm == 0) { /* for MP ODM dynamic Tx power tracking */
+		/* RTW_INFO("_dynamic_check_timer_handler mp_dm =0 return\n"); */
+		_set_timer(&pdvobj->dynamic_chk_timer, 2000);
+		return;
+	}
+#endif
+
+	rtw_dynamic_check_timer_handler(adapter);
+
+	_set_timer(&pdvobj->dynamic_chk_timer, 2000);
+}
+
+#ifdef CONFIG_SET_SCAN_DENY_TIMER
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+static void _rtw_set_scan_deny_timer_hdl(void *FunctionContext)
+#else
+static void _rtw_set_scan_deny_timer_hdl(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_adapter *adapter = (_adapter *)FunctionContext;
+#else
+	_adapter *adapter = from_timer(adapter, t, mlmepriv.set_scan_deny_timer);
+#endif
+
+	rtw_set_scan_deny_timer_hdl(adapter);
+}
+#endif
+
+void rtw_init_mlme_timer(_adapter *padapter)
+{
+	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_init_timer(&pmlmepriv->assoc_timer, padapter->pnetdev, rtw_join_timeout_handler, padapter);
+	/* _init_timer(&pmlmepriv->sitesurveyctrl.sitesurvey_ctrl_timer, padapter->pnetdev, sitesurvey_ctrl_handler, padapter); */
+	_init_timer(&pmlmepriv->scan_to_timer, padapter->pnetdev, _rtw_scan_timeout_handler, padapter);
+
+#ifdef CONFIG_DFS_MASTER
+	_init_timer(&pmlmepriv->dfs_master_timer, padapter->pnetdev, rtw_dfs_master_timer_hdl, padapter);
+#endif
+
+#ifdef CONFIG_SET_SCAN_DENY_TIMER
+	_init_timer(&pmlmepriv->set_scan_deny_timer, padapter->pnetdev, _rtw_set_scan_deny_timer_hdl, padapter);
+#endif
+#else
+	timer_setup(&pmlmepriv->assoc_timer, rtw_join_timeout_handler, 0);
+	/* timer_setup(&pmlmepriv->sitesurveyctrl.sitesurvey_ctrl_timer, sitesurvey_ctrl_handler, 0); */
+	timer_setup(&pmlmepriv->scan_to_timer, _rtw_scan_timeout_handler, 0);
+
+#ifdef CONFIG_DFS_MASTER
+	timer_setup(&pmlmepriv->dfs_master_timer, rtw_dfs_master_timer_hdl, 0);
+#endif
+
+#ifdef CONFIG_SET_SCAN_DENY_TIMER
+	timer_setup(&pmlmepriv->set_scan_deny_timer, _rtw_set_scan_deny_timer_hdl, 0);
+#endif
+#endif
+#ifdef RTK_DMP_PLATFORM
+	_init_workitem(&(pmlmepriv->Linkup_workitem), Linkup_workitem_callback, padapter);
+	_init_workitem(&(pmlmepriv->Linkdown_workitem), Linkdown_workitem_callback, padapter);
+#endif
+
+}
+
+void rtw_os_indicate_connect(_adapter *adapter)
+{
+	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
+	    (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
+		rtw_cfg80211_ibss_indicate_connect(adapter);
+	else
+		rtw_cfg80211_indicate_connect(adapter);
+#endif /* CONFIG_IOCTL_CFG80211 */
+
+	rtw_indicate_wx_assoc_event(adapter);
+	netif_carrier_on(adapter->pnetdev);
+
+	if (adapter->pid[2] != 0)
+		rtw_signal_process(adapter->pid[2], SIGALRM);
+
+#ifdef RTK_DMP_PLATFORM
+	_set_workitem(&adapter->mlmepriv.Linkup_workitem);
+#endif
+
+
+}
+
+extern void indicate_wx_scan_complete_event(_adapter *padapter);
+void rtw_os_indicate_scan_done(_adapter *padapter, bool aborted)
+{
+#ifdef CONFIG_IOCTL_CFG80211
+	rtw_cfg80211_indicate_scan_done(padapter, aborted);
+#endif
+	indicate_wx_scan_complete_event(padapter);
+}
+
+static RT_PMKID_LIST   backupPMKIDList[NUM_PMKID_CACHE];
+void rtw_reset_securitypriv(_adapter *adapter)
+{
+	u8	backupPMKIDIndex = 0;
+	u8	backupTKIPCountermeasure = 0x00;
+	u32	backupTKIPcountermeasure_time = 0;
+	/* add for CONFIG_IEEE80211W, none 11w also can use */
+	unsigned long irqL;
+	struct mlme_ext_priv	*pmlmeext = &adapter->mlmeextpriv;
+
+	_enter_critical_bh(&adapter->security_key_mutex, &irqL);
+
+	if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802.1x */
+		/* Added by Albert 2009/02/18 */
+		/* We have to backup the PMK information for WiFi PMK Caching test item. */
+		/*  */
+		/* Backup the btkip_countermeasure information. */
+		/* When the countermeasure is trigger, the driver have to disconnect with AP for 60 seconds. */
+
+		memset(&backupPMKIDList[0], 0x00, sizeof(RT_PMKID_LIST) * NUM_PMKID_CACHE);
+
+		memcpy(&backupPMKIDList[0], &adapter->securitypriv.PMKIDList[0], sizeof(RT_PMKID_LIST) * NUM_PMKID_CACHE);
+		backupPMKIDIndex = adapter->securitypriv.PMKIDIndex;
+		backupTKIPCountermeasure = adapter->securitypriv.btkip_countermeasure;
+		backupTKIPcountermeasure_time = adapter->securitypriv.btkip_countermeasure_time;
+#ifdef CONFIG_IEEE80211W
+		/* reset RX BIP packet number */
+		pmlmeext->mgnt_80211w_IPN_rx = 0;
+#endif /* CONFIG_IEEE80211W */
+		memset((unsigned char *)&adapter->securitypriv, 0, sizeof(struct security_priv));
+		/* _init_timer(&(adapter->securitypriv.tkip_timer),adapter->pnetdev, rtw_use_tkipkey_handler, adapter); */
+
+		/* Added by Albert 2009/02/18 */
+		/* Restore the PMK information to securitypriv structure for the following connection. */
+		memcpy(&adapter->securitypriv.PMKIDList[0], &backupPMKIDList[0], sizeof(RT_PMKID_LIST) * NUM_PMKID_CACHE);
+		adapter->securitypriv.PMKIDIndex = backupPMKIDIndex;
+		adapter->securitypriv.btkip_countermeasure = backupTKIPCountermeasure;
+		adapter->securitypriv.btkip_countermeasure_time = backupTKIPcountermeasure_time;
+
+		adapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
+		adapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
+
+	} else { /* reset values in securitypriv */
+		/* if(adapter->mlmepriv.fw_state & WIFI_STATION_STATE) */
+		/* { */
+		struct security_priv *psec_priv = &adapter->securitypriv;
+
+		psec_priv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
+		psec_priv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+		psec_priv->dot11PrivacyKeyIndex = 0;
+
+		psec_priv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+		psec_priv->dot118021XGrpKeyid = 1;
+
+		psec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
+		psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
+		/* } */
+	}
+	/* add for CONFIG_IEEE80211W, none 11w also can use */
+	_exit_critical_bh(&adapter->security_key_mutex, &irqL);
+
+	RTW_INFO(FUNC_ADPT_FMT" - End to Disconnect\n", FUNC_ADPT_ARG(adapter));
+}
+
+void rtw_os_indicate_disconnect(_adapter *adapter,  u16 reason, u8 locally_generated)
+{
+	/* RT_PMKID_LIST   backupPMKIDList[NUM_PMKID_CACHE]; */
+
+
+	netif_carrier_off(adapter->pnetdev); /* Do it first for tx broadcast pkt after disconnection issue! */
+
+#ifdef CONFIG_IOCTL_CFG80211
+	rtw_cfg80211_indicate_disconnect(adapter,  reason, locally_generated);
+#endif /* CONFIG_IOCTL_CFG80211 */
+
+	rtw_indicate_wx_disassoc_event(adapter);
+
+#ifdef RTK_DMP_PLATFORM
+	_set_workitem(&adapter->mlmepriv.Linkdown_workitem);
+#endif
+	/* modify for CONFIG_IEEE80211W, none 11w also can use the same command */
+	rtw_reset_securitypriv_cmd(adapter);
+
+
+}
+
+void rtw_report_sec_ie(_adapter *adapter, u8 authmode, u8 *sec_ie)
+{
+	uint	len;
+	u8	*buff, *p, i;
+	union iwreq_data wrqu;
+
+
+
+	buff = NULL;
+	if (authmode == _WPA_IE_ID_) {
+
+		buff = rtw_zmalloc(IW_CUSTOM_MAX);
+		if (NULL == buff) {
+			RTW_INFO(FUNC_ADPT_FMT ": alloc memory FAIL!!\n",
+				 FUNC_ADPT_ARG(adapter));
+			return;
+		}
+		p = buff;
+
+		p += sprintf(p, "ASSOCINFO(ReqIEs=");
+
+		len = sec_ie[1] + 2;
+		len = (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX;
+
+		for (i = 0; i < len; i++)
+			p += sprintf(p, "%02x", sec_ie[i]);
+
+		p += sprintf(p, ")");
+
+		memset(&wrqu, 0, sizeof(wrqu));
+
+		wrqu.data.length = p - buff;
+
+		wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ? wrqu.data.length : IW_CUSTOM_MAX;
+
+#ifndef CONFIG_IOCTL_CFG80211
+		wireless_send_event(adapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
+#endif
+
+		rtw_mfree(buff, IW_CUSTOM_MAX);
+	}
+
+
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+static void _survey_timer_hdl(void *FunctionContext)
+#else
+static void _survey_timer_hdl(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_adapter *padapter = (_adapter *)FunctionContext;
+#else
+	_adapter *padapter = from_timer(padapter, t, mlmeextpriv.survey_timer);
+#endif
+
+	survey_timer_hdl(padapter);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+static void _link_timer_hdl(void *FunctionContext)
+#else
+static void _link_timer_hdl(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_adapter *padapter = (_adapter *)FunctionContext;
+#else
+	_adapter *padapter = from_timer(padapter, t, mlmeextpriv.link_timer);
+#endif
+
+	link_timer_hdl(padapter);
+}
+
+#ifdef CONFIG_RTW_80211R
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+void _ft_link_timer_hdl(void *FunctionContext)
+#else
+void _ft_link_timer_hdl(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_adapter *padapter = (_adapter *)FunctionContext;
+#else
+	_adapter *padapter = from_timer(ipadapter, t, ft_link_timer);
+#endif
+
+	ft_link_timer_hdl(padapter);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+void _ft_roam_timer_hdl(void *FunctionContext)
+#else
+void _ft_roam_timer_hdl(struct timer_list *t);
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_adapter *padapter = (_adapter *)FunctionContext;
+#else
+	_adapter *padapter = from_timer(adapter, t, ft_roam_timer);
+#endif
+
+	ft_roam_timer_hdl(padapter);
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+static void _addba_timer_hdl(void *FunctionContext)
+#else
+static void _addba_timer_hdl(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	struct sta_info *psta = (struct sta_info *)FunctionContext;
+#else
+	struct sta_info *psta = from_timer(psta, t, addba_retry_timer);
+#endif
+
+	addba_timer_hdl(psta);
+}
+
+#ifdef CONFIG_IEEE80211W
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+void _sa_query_timer_hdl(void *FunctionContext)
+#else
+void _sa_query_timer_hdl(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	struct sta_info *psta = (struct sta_info *)FunctionContext;
+#else
+	struct sta_info *psta = from_timer(psta, t, dot11w_expire_timer);
+#endif
+
+	sa_query_timer_hdl(psta);
+}
+
+void init_dot11w_expire_timer(_adapter *padapter, struct sta_info *psta)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_init_timer(&psta->dot11w_expire_timer, padapter->pnetdev, _sa_query_timer_hdl, psta);
+#else
+	timer_setip(&psta->dot11w_expire_timer, _sa_query_timer_hdl, 0);
+#endif
+}
+
+#endif /* CONFIG_IEEE80211W */
+
+void init_addba_retry_timer(_adapter *padapter, struct sta_info *psta)
+{
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_init_timer(&psta->addba_retry_timer, padapter->pnetdev, _addba_timer_hdl, psta);
+#else
+	timer_setup(&psta->addba_retry_timer, _addba_timer_hdl, 0);
+#endif
+}
+
+/*
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+void _reauth_timer_hdl(void *FunctionContext)
+#else
+void _reauth_timer_hdl(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_adapter *padapter = (_adapter *)FunctionContext;
+#else
+	_adapter *padapter = from_timer(adapter, t, reauth_timer);
+#endif
+
+	reauth_timer_hdl(padapter);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+void _reassoc_timer_hdl(void *FunctionContext)
+#else
+void _reassoc_timer_hdl(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_adapter *padapter = (_adapter *)FunctionContext;
+#else
+	_adapter *padapter = from_timer(adapter, t, reassoc_timer);
+#endif
+
+`	reassoc_timer_hdl(padapter);
+}
+*/
+
+void init_mlme_ext_timer(_adapter *padapter)
+{
+	struct	mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_init_timer(&pmlmeext->survey_timer, padapter->pnetdev, _survey_timer_hdl, padapter);
+	_init_timer(&pmlmeext->link_timer, padapter->pnetdev, _link_timer_hdl, padapter);
+#ifdef CONFIG_RTW_80211R
+	_init_timer(&pmlmeext->ft_link_timer, padapter->pnetdev, _ft_link_timer_hdl, padapter);
+	_init_timer(&pmlmeext->ft_roam_timer, padapter->pnetdev, _ft_roam_timer_hdl, padapter);
+#endif
+
+	/* _init_timer(&pmlmeext->ADDBA_timer, padapter->pnetdev, _addba_timer_hdl, padapter); */
+
+	/* _init_timer(&pmlmeext->reauth_timer, padapter->pnetdev, _reauth_timer_hdl, padapter); */
+	/* _init_timer(&pmlmeext->reassoc_timer, padapter->pnetdev, _reassoc_timer_hdl, padapter); */
+#else
+	timer_setup(&pmlmeext->survey_timer, _survey_timer_hdl, 0);
+	timer_setup(&pmlmeext->link_timer, _link_timer_hdl, 0);
+#ifdef CONFIG_RTW_80211R
+	timer_setup(&pmlmeext->ft_link_timer, _ft_link_timer_hdl, 0);
+	timer_setup(&pmlmeext->ft_roam_timer, _ft_roam_timer_hdl, 0);
+#endif
+
+	/* timer_setup(&pmlmeext->ADDBA_timer, _addba_timer_hdl, 0); */
+
+	/* timer_setup(&pmlmeext->reauth_timer, _reauth_timer_hdl, 0); */
+	/* timer_setup(&pmlmeext->reassoc_timer, _reassoc_timer_hdl, 0); */
+#endif
+}
+
+#ifdef CONFIG_AP_MODE
+
+void rtw_indicate_sta_assoc_event(_adapter *padapter, struct sta_info *psta)
+{
+	union iwreq_data wrqu;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	if (psta == NULL)
+		return;
+
+	if (psta->aid > NUM_STA)
+		return;
+
+	if (pstapriv->sta_aid[psta->aid - 1] != psta)
+		return;
+
+
+	wrqu.addr.sa_family = ARPHRD_ETHER;
+
+	memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
+
+	RTW_INFO("+rtw_indicate_sta_assoc_event\n");
+
+#ifndef CONFIG_IOCTL_CFG80211
+	wireless_send_event(padapter->pnetdev, IWEVREGISTERED, &wrqu, NULL);
+#endif
+
+}
+
+void rtw_indicate_sta_disassoc_event(_adapter *padapter, struct sta_info *psta)
+{
+	union iwreq_data wrqu;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	if (psta == NULL)
+		return;
+
+	if (psta->aid > NUM_STA)
+		return;
+
+	if (pstapriv->sta_aid[psta->aid - 1] != psta)
+		return;
+
+
+	wrqu.addr.sa_family = ARPHRD_ETHER;
+
+	memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
+
+	RTW_INFO("+rtw_indicate_sta_disassoc_event\n");
+
+#ifndef CONFIG_IOCTL_CFG80211
+	wireless_send_event(padapter->pnetdev, IWEVEXPIRED, &wrqu, NULL);
+#endif
+
+}
+
+
+#ifdef CONFIG_HOSTAPD_MLME
+
+static int mgnt_xmit_entry(struct sk_buff *skb, struct net_device *pnetdev)
+{
+	struct hostapd_priv *phostapdpriv = rtw_netdev_priv(pnetdev);
+	_adapter *padapter = (_adapter *)phostapdpriv->padapter;
+
+	/* RTW_INFO("%s\n", __func__); */
+
+	return rtw_hal_hostap_mgnt_xmit_entry(padapter, skb);
+}
+
+static int mgnt_netdev_open(struct net_device *pnetdev)
+{
+	struct hostapd_priv *phostapdpriv = rtw_netdev_priv(pnetdev);
+
+	RTW_INFO("mgnt_netdev_open: MAC Address:" MAC_FMT "\n", MAC_ARG(pnetdev->dev_addr));
+
+
+	init_usb_anchor(&phostapdpriv->anchored);
+
+	rtw_netif_wake_queue(pnetdev);
+
+	netif_carrier_on(pnetdev);
+
+	/* rtw_write16(phostapdpriv->padapter, 0x0116, 0x0100); */ /* only excluding beacon */
+
+	return 0;
+}
+static int mgnt_netdev_close(struct net_device *pnetdev)
+{
+	struct hostapd_priv *phostapdpriv = rtw_netdev_priv(pnetdev);
+
+	RTW_INFO("%s\n", __func__);
+
+	usb_kill_anchored_urbs(&phostapdpriv->anchored);
+
+	netif_carrier_off(pnetdev);
+
+	rtw_netif_stop_queue(pnetdev);
+
+	/* rtw_write16(phostapdpriv->padapter, 0x0116, 0x3f3f); */
+
+	return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+static const struct net_device_ops rtl871x_mgnt_netdev_ops = {
+	.ndo_open = mgnt_netdev_open,
+	.ndo_stop = mgnt_netdev_close,
+	.ndo_start_xmit = mgnt_xmit_entry,
+};
+#endif
+
+int hostapd_mode_init(_adapter *padapter)
+{
+	unsigned char mac[ETH_ALEN];
+	struct hostapd_priv *phostapdpriv;
+	struct net_device *pnetdev;
+
+	pnetdev = rtw_alloc_etherdev(sizeof(struct hostapd_priv));
+	if (!pnetdev)
+		return -ENOMEM;
+
+	/* SET_MODULE_OWNER(pnetdev); */
+	ether_setup(pnetdev);
+
+	/* pnetdev->type = ARPHRD_IEEE80211; */
+
+	phostapdpriv = rtw_netdev_priv(pnetdev);
+	phostapdpriv->pmgnt_netdev = pnetdev;
+	phostapdpriv->padapter = padapter;
+	padapter->phostapdpriv = phostapdpriv;
+
+	/* pnetdev->init = NULL; */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+
+	RTW_INFO("register rtl871x_mgnt_netdev_ops to netdev_ops\n");
+
+	pnetdev->netdev_ops = &rtl871x_mgnt_netdev_ops;
+
+#else
+
+	pnetdev->open = mgnt_netdev_open;
+
+	pnetdev->stop = mgnt_netdev_close;
+
+	pnetdev->hard_start_xmit = mgnt_xmit_entry;
+
+	/* pnetdev->set_mac_address = r871x_net_set_mac_address; */
+
+	/* pnetdev->get_stats = r871x_net_get_stats; */
+
+	/* pnetdev->do_ioctl = r871x_mp_ioctl; */
+
+#endif
+
+	pnetdev->watchdog_timeo = HZ; /* 1 second timeout */
+
+	/* pnetdev->wireless_handlers = NULL; */
+
+#ifdef CONFIG_TCP_CSUM_OFFLOAD_TX
+	pnetdev->features |= NETIF_F_IP_CSUM;
+#endif
+
+
+
+	if (dev_alloc_name(pnetdev, "mgnt.wlan%d") < 0)
+		RTW_INFO("hostapd_mode_init(): dev_alloc_name, fail!\n");
+
+
+	/* SET_NETDEV_DEV(pnetdev, pintfpriv->udev); */
+
+
+	mac[0] = 0x00;
+	mac[1] = 0xe0;
+	mac[2] = 0x4c;
+	mac[3] = 0x87;
+	mac[4] = 0x11;
+	mac[5] = 0x12;
+
+	memcpy(pnetdev->dev_addr, mac, ETH_ALEN);
+
+
+	netif_carrier_off(pnetdev);
+
+
+	/* Tell the network stack we exist */
+	if (register_netdev(pnetdev) != 0) {
+		RTW_INFO("hostapd_mode_init(): register_netdev fail!\n");
+
+		if (pnetdev)
+			rtw_free_netdev(pnetdev);
+	}
+
+	return 0;
+
+}
+
+void hostapd_mode_unload(_adapter *padapter)
+{
+	struct hostapd_priv *phostapdpriv = padapter->phostapdpriv;
+	struct net_device *pnetdev = phostapdpriv->pmgnt_netdev;
+
+	unregister_netdev(pnetdev);
+	rtw_free_netdev(pnetdev);
+
+}
+
+#endif
+#endif
diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
new file mode 100644
index 000000000000..38f6aae673d6
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
@@ -0,0 +1,4311 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+#define _OS_INTFS_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+#include <rtw_debug.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek Wireless Lan Driver");
+MODULE_AUTHOR("Realtek Semiconductor Corp.");
+MODULE_VERSION(DRIVERVERSION);
+
+/* module param defaults */
+static int rtw_chip_version = 0x00;
+static int rtw_rfintfs = HWPI;
+static int rtw_lbkmode = 0;/* RTL8712_AIR_TRX; */
+static int rtw_network_mode = Ndis802_11IBSS;/* Ndis802_11Infrastructure; */ /* infra, ad-hoc, auto */
+/* NDIS_802_11_SSID	ssid; */
+static int rtw_channel = 1;/* ad-hoc support requirement */
+static int rtw_wireless_mode = WIRELESS_MODE_MAX;
+static int rtw_vrtl_carrier_sense = AUTO_VCS;
+static int rtw_vcs_type = RTS_CTS;
+static int rtw_rts_thresh = 2347;
+static int rtw_frag_thresh = 2346;
+static int rtw_preamble = PREAMBLE_LONG;/* long, short, auto */
+static int rtw_scan_mode = 1;/* active, passive */
+static int rtw_adhoc_tx_pwr = 1;
+static int rtw_soft_ap = 0;
+/* int smart_ps = 1; */
+#ifdef CONFIG_POWER_SAVING
+	static int rtw_power_mgnt = PS_MODE_MAX;
+	#ifdef CONFIG_IPS_LEVEL_2
+		static int rtw_ips_mode = IPS_LEVEL_2;
+	#else
+		static int rtw_ips_mode = IPS_NORMAL;
+	#endif
+#else
+	static int rtw_power_mgnt = PS_MODE_ACTIVE;
+	static int rtw_ips_mode = IPS_NONE;
+#endif
+module_param(rtw_ips_mode, int, 0644);
+MODULE_PARM_DESC(rtw_ips_mode, "The default IPS mode");
+
+static int rtw_smart_ps = 2;
+
+static int rtw_check_fw_ps = 1;
+
+#ifdef CONFIG_TX_EARLY_MODE
+static int rtw_early_mode = 1;
+#endif
+
+static int rtw_usb_rxagg_mode = 2;/* RX_AGG_DMA=1, RX_AGG_USB=2 */
+module_param(rtw_usb_rxagg_mode, int, 0644);
+
+/* set log level when inserting driver module, default log level is _DRV_INFO_ = 4,
+* please refer to "How_to_set_driver_debug_log_level.doc" to set the available level.
+*/
+#ifdef RTW_LOG_LEVEL
+	uint rtw_drv_log_level = (uint)RTW_LOG_LEVEL; /* from Makefile */
+#else
+	uint rtw_drv_log_level = _DRV_INFO_;
+#endif
+module_param(rtw_drv_log_level, uint, 0644);
+MODULE_PARM_DESC(rtw_drv_log_level, "set log level when insert driver module, default log level is _DRV_INFO_ = 4");
+
+static int rtw_radio_enable = 1;
+static int rtw_long_retry_lmt = 7;
+static int rtw_short_retry_lmt = 7;
+static int rtw_busy_thresh = 40;
+/* int qos_enable = 0; */ /* * */
+static int rtw_ack_policy = NORMAL_ACK;
+
+static int rtw_mp_mode = 0;
+
+#if defined(CONFIG_MP_INCLUDED) && defined(CONFIG_RTW_CUSTOMER_STR)
+static uint rtw_mp_customer_str = 0;
+module_param(rtw_mp_customer_str, uint, 0644);
+MODULE_PARM_DESC(rtw_mp_customer_str, "Whether or not to enable customer str support on MP mode");
+#endif
+
+static int rtw_software_encrypt = 0;
+static int rtw_software_decrypt = 0;
+
+static int rtw_acm_method = 0;/* 0:By SW 1:By HW. */
+
+static int rtw_wmm_enable = 1;/* default is set to enable the wmm. */
+static int rtw_uapsd_enable = 0;
+static int rtw_uapsd_max_sp = NO_LIMIT;
+static int rtw_uapsd_acbk_en = 0;
+static int rtw_uapsd_acbe_en = 0;
+static int rtw_uapsd_acvi_en = 0;
+static int rtw_uapsd_acvo_en = 0;
+static int rtw_pwrtrim_enable = 0; /* Default Enalbe  power trim by efuse config */
+
+static uint rtw_tx_bw_mode = 0x21;
+module_param(rtw_tx_bw_mode, uint, 0644);
+MODULE_PARM_DESC(rtw_tx_bw_mode, "The max tx bw for 2.4G and 5G. format is the same as rtw_bw_mode");
+
+static int rtw_led_enable = 1;
+
+int rtw_ht_enable = 1;
+/* 0: 20 MHz, 1: 40 MHz, 2: 80 MHz, 3: 160MHz, 4: 80+80MHz
+* 2.4G use bit 0 ~ 3, 5G use bit 4 ~ 7
+* 0x21 means enable 2.4G 40MHz & 5G 80MHz */
+int rtw_bw_mode = 0x21;
+int rtw_ampdu_enable = 1;/* for enable tx_ampdu , */ /* 0: disable, 0x1:enable */
+static int rtw_rx_stbc = 1;/* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
+static int rtw_ampdu_amsdu = 0;/* 0: disabled, 1:enabled, 2:auto . There is an IOT issu with DLINK DIR-629 when the flag turn on */
+/* Short GI support Bit Map
+* BIT0 - 20MHz, 0: non-support, 1: support
+* BIT1 - 40MHz, 0: non-support, 1: support
+* BIT2 - 80MHz, 0: non-support, 1: support
+* BIT3 - 160MHz, 0: non-support, 1: support */
+static int rtw_short_gi = 0xf;
+/* BIT0: Enable VHT LDPC Rx, BIT1: Enable VHT LDPC Tx, BIT4: Enable HT LDPC Rx, BIT5: Enable HT LDPC Tx */
+static int rtw_ldpc_cap = 0x33;
+/* BIT0: Enable VHT STBC Rx, BIT1: Enable VHT STBC Tx, BIT4: Enable HT STBC Rx, BIT5: Enable HT STBC Tx */
+static int rtw_stbc_cap = 0x13;
+/*
+* BIT0: Enable VHT SU Beamformer
+* BIT1: Enable VHT SU Beamformee
+* BIT2: Enable VHT MU Beamformer, depend on VHT SU Beamformer
+* BIT3: Enable VHT MU Beamformee, depend on VHT SU Beamformee
+* BIT4: Enable HT Beamformer
+* BIT5: Enable HT Beamformee
+*/
+static int rtw_beamform_cap = BIT(1) | BIT(3);
+static int rtw_bfer_rf_number = 0; /*BeamformerCapRfNum Rf path number, 0 for auto, others for manual*/
+static int rtw_bfee_rf_number = 0; /*BeamformeeCapRfNum  Rf path number, 0 for auto, others for manual*/
+
+static int rtw_lowrate_two_xmit = 1;/* Use 2 path Tx to transmit MCS0~7 and legacy mode */
+
+static int rtw_rf_config = RF_TYPE_AUTO;
+module_param(rtw_rf_config, int, 0644);
+
+/* 0: not check in watch dog, 1: check in watch dog  */
+static int rtw_check_hw_status = 0;
+
+static int rtw_low_power = 0;
+#ifdef CONFIG_WIFI_TEST
+	static int rtw_wifi_spec = 1;/* for wifi test */
+#else
+	static int rtw_wifi_spec = 0;
+#endif
+
+#ifdef CONFIG_DEFAULT_PATTERNS_EN
+	static bool	rtw_support_default_patterns = true;
+#else
+	static bool	rtw_support_default_patterns = false;
+#endif
+
+static int rtw_special_rf_path = 0; /* 0: 2T2R ,1: only turn on path A 1T1R */
+
+static char rtw_country_unspecified[] = {0xFF, 0xFF, 0x00};
+static char *rtw_country_code = rtw_country_unspecified;
+module_param(rtw_country_code, charp, 0644);
+MODULE_PARM_DESC(rtw_country_code, "The default country code (in alpha2)");
+
+static int rtw_channel_plan = RTW_CHPLAN_MAX;
+module_param(rtw_channel_plan, int, 0644);
+MODULE_PARM_DESC(rtw_channel_plan, "The default chplan ID when rtw_alpha2 is not specified or valid");
+
+static uint rtw_excl_chs[MAX_CHANNEL_NUM] = CONFIG_RTW_EXCL_CHS;
+static int rtw_excl_chs_num = 0;
+module_param_array(rtw_excl_chs, uint, &rtw_excl_chs_num, 0644);
+MODULE_PARM_DESC(rtw_excl_chs, "exclusive channel array");
+
+/*if concurrent softap + p2p(GO) is needed, this param lets p2p response full channel list.
+But Softap must be SHUT DOWN once P2P decide to set up connection and become a GO.*/
+#ifdef CONFIG_FULL_CH_IN_P2P_HANDSHAKE
+	static int rtw_full_ch_in_p2p_handshake = 1; /* reply full channel list*/
+#else
+	static int rtw_full_ch_in_p2p_handshake = 0; /* reply only softap channel*/
+#endif
+
+#ifdef CONFIG_BT_COEXIST
+static int rtw_btcoex_enable = 2;
+module_param(rtw_btcoex_enable, int, 0644);
+MODULE_PARM_DESC(rtw_btcoex_enable, "BT co-existence on/off, 0:off, 1:on, 2:by efuse");
+
+static int rtw_ant_num = 0;
+module_param(rtw_ant_num, int, 0644);
+MODULE_PARM_DESC(rtw_ant_num, "Antenna number setting, 0:by efuse");
+
+static int rtw_bt_iso = 2;/* 0:Low, 1:High, 2:From Efuse */
+static int rtw_bt_sco = 3;/* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter, 4.Busy, 5.OtherBusy */
+static int rtw_bt_ampdu = 1 ; /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */
+#endif /* CONFIG_BT_COEXIST */
+
+static int rtw_AcceptAddbaReq = true;/* 0:Reject AP's Add BA req, 1:Accept AP's Add BA req. */
+
+static int rtw_antdiv_cfg = 2; /* 0:OFF , 1:ON, 2:decide by Efuse config */
+static int rtw_antdiv_type = 0
+	; /* 0:decide by efuse  1: for 88EE, 1Tx and 1RxCG are diversity.(2 Ant with SPDT), 2:  for 88EE, 1Tx and 2Rx are diversity.( 2 Ant, Tx and RxCG are both on aux port, RxCS is on main port ), 3: for 88EE, 1Tx and 1RxCG are fixed.(1Ant, Tx and RxCG are both on aux port) */
+
+static int rtw_drv_ant_band_switch = 1; /* 0:OFF , 1:ON, Driver control antenna band switch*/
+
+/* 0: doesn't switch, 1: switch from usb2.0 to usb 3.0 2: switch from usb3.0 to usb 2.0 */
+static int rtw_switch_usb_mode = 0;
+
+#ifdef CONFIG_USB_AUTOSUSPEND
+static int rtw_enusbss = 1;/* 0:disable,1:enable */
+#else
+static int rtw_enusbss = 0;/* 0:disable,1:enable */
+#endif
+
+static int rtw_hwpdn_mode = 2; /* 0:disable,1:enable,2: by EFUSE config */
+
+#ifdef CONFIG_HW_PWRP_DETECTION
+static int rtw_hwpwrp_detect = 1;
+#else
+static int rtw_hwpwrp_detect = 0; /* HW power  ping detect 0:disable , 1:enable */
+#endif
+
+static int rtw_hw_wps_pbc = 1;
+
+#ifdef CONFIG_TX_MCAST2UNI
+int rtw_mc2u_disable = 0;
+#endif /* CONFIG_TX_MCAST2UNI */
+
+#ifdef CONFIG_80211D
+static int rtw_80211d = 0;
+#endif
+
+#ifdef CONFIG_SPECIAL_SETTING_FOR_FUNAI_TV
+static int rtw_force_ant = 2;/* 0 :normal, 1:Main ant, 2:Aux ant */
+static int rtw_force_igi = 0; /* 0 :normal */
+module_param(rtw_force_ant, int, 0644);
+module_param(rtw_force_igi, int, 0644);
+#endif
+
+static int rtw_force_igi_lb = CONFIG_RTW_FORCE_IGI_LB;
+module_param(rtw_force_igi_lb, int, 0644);
+MODULE_PARM_DESC(rtw_force_igi_lb, "force IGI low-bound, 0:no specified");
+
+#ifdef CONFIG_QOS_OPTIMIZATION
+static int rtw_qos_opt_enable = 1; /* 0: disable,1:enable */
+#else
+static int rtw_qos_opt_enable = 0; /* 0: disable,1:enable */
+#endif
+module_param(rtw_qos_opt_enable, int, 0644);
+
+#ifdef CONFIG_AUTO_CHNL_SEL_NHM
+static int rtw_acs_mode = 1; /*0:disable, 1:enable*/
+module_param(rtw_acs_mode, int, 0644);
+
+static int rtw_acs_auto_scan = 0; /*0:disable, 1:enable*/
+module_param(rtw_acs_auto_scan, int, 0644);
+
+#endif
+
+static char *ifname = "wlan%d";
+module_param(ifname, charp, 0644);
+MODULE_PARM_DESC(ifname, "The default name to allocate for first interface");
+
+static char *if2name = "wlan%d";
+module_param(if2name, charp, 0644);
+MODULE_PARM_DESC(if2name, "The default name to allocate for second interface");
+
+char *rtw_initmac = NULL;  /* temp mac address if users want to use instead of the mac address in Efuse */
+
+#ifdef CONFIG_CONCURRENT_MODE
+
+	#if (CONFIG_IFACE_NUMBER > 2)
+		int rtw_virtual_iface_num = CONFIG_IFACE_NUMBER - 1;
+		module_param(rtw_virtual_iface_num, int, 0644);
+	#else
+		int rtw_virtual_iface_num = 1;
+	#endif
+
+#endif
+
+module_param(rtw_pwrtrim_enable, int, 0644);
+module_param(rtw_initmac, charp, 0644);
+module_param(rtw_special_rf_path, int, 0644);
+module_param(rtw_chip_version, int, 0644);
+module_param(rtw_rfintfs, int, 0644);
+module_param(rtw_lbkmode, int, 0644);
+module_param(rtw_network_mode, int, 0644);
+module_param(rtw_channel, int, 0644);
+module_param(rtw_mp_mode, int, 0644);
+module_param(rtw_wmm_enable, int, 0644);
+module_param(rtw_vrtl_carrier_sense, int, 0644);
+module_param(rtw_vcs_type, int, 0644);
+module_param(rtw_busy_thresh, int, 0644);
+module_param(rtw_led_enable, int, 0644);
+module_param(rtw_ht_enable, int, 0644);
+module_param(rtw_bw_mode, int, 0644);
+module_param(rtw_ampdu_enable, int, 0644);
+module_param(rtw_rx_stbc, int, 0644);
+module_param(rtw_ampdu_amsdu, int, 0644);
+
+#ifdef CONFIG_BEAMFORMING
+module_param(rtw_beamform_cap, int, 0644);
+#endif
+module_param(rtw_lowrate_two_xmit, int, 0644);
+
+module_param(rtw_power_mgnt, int, 0644);
+module_param(rtw_smart_ps, int, 0644);
+module_param(rtw_low_power, int, 0644);
+module_param(rtw_wifi_spec, int, 0644);
+
+module_param(rtw_full_ch_in_p2p_handshake, int, 0644);
+module_param(rtw_antdiv_cfg, int, 0644);
+module_param(rtw_antdiv_type, int, 0644);
+
+module_param(rtw_drv_ant_band_switch, int, 0644);
+
+module_param(rtw_switch_usb_mode, int, 0644);
+
+module_param(rtw_enusbss, int, 0644);
+module_param(rtw_hwpdn_mode, int, 0644);
+module_param(rtw_hwpwrp_detect, int, 0644);
+
+module_param(rtw_hw_wps_pbc, int, 0644);
+module_param(rtw_check_hw_status, int, 0644);
+
+#ifdef CONFIG_TX_EARLY_MODE
+module_param(rtw_early_mode, int, 0644);
+#endif
+#ifdef CONFIG_ADAPTOR_INFO_CACHING_FILE
+static char *rtw_adaptor_info_caching_file_path = "/data/misc/wifi/rtw_cache";
+module_param(rtw_adaptor_info_caching_file_path, charp, 0644);
+MODULE_PARM_DESC(rtw_adaptor_info_caching_file_path, "The path of adapter info cache file");
+#endif /* CONFIG_ADAPTOR_INFO_CACHING_FILE */
+
+#ifdef CONFIG_LAYER2_ROAMING
+static uint rtw_max_roaming_times = 2;
+module_param(rtw_max_roaming_times, uint, 0644);
+MODULE_PARM_DESC(rtw_max_roaming_times, "The max roaming times to try");
+#endif /* CONFIG_LAYER2_ROAMING */
+
+#ifdef CONFIG_IOL
+static int rtw_fw_iol = 1;
+module_param(rtw_fw_iol, int, 0644);
+MODULE_PARM_DESC(rtw_fw_iol, "FW IOL. 0:Disable, 1:enable, 2:by usb speed");
+#endif /* CONFIG_IOL */
+
+#ifdef CONFIG_FILE_FWIMG
+static char *rtw_fw_file_path = "/system/etc/firmware/rtlwifi/FW_NIC.BIN";
+module_param(rtw_fw_file_path, charp, 0644);
+MODULE_PARM_DESC(rtw_fw_file_path, "The path of fw image");
+
+static char *rtw_fw_wow_file_path = "/system/etc/firmware/rtlwifi/FW_WoWLAN.BIN";
+module_param(rtw_fw_wow_file_path, charp, 0644);
+MODULE_PARM_DESC(rtw_fw_wow_file_path, "The path of fw for Wake on Wireless image");
+
+#ifdef CONFIG_MP_INCLUDED
+static char *rtw_fw_mp_bt_file_path = "";
+module_param(rtw_fw_mp_bt_file_path, charp, 0644);
+MODULE_PARM_DESC(rtw_fw_mp_bt_file_path, "The path of fw for MP-BT image");
+#endif /* CONFIG_MP_INCLUDED */
+#endif /* CONFIG_FILE_FWIMG */
+
+#ifdef CONFIG_TX_MCAST2UNI
+module_param(rtw_mc2u_disable, int, 0644);
+#endif /* CONFIG_TX_MCAST2UNI */
+
+#ifdef CONFIG_80211D
+module_param(rtw_80211d, int, 0644);
+MODULE_PARM_DESC(rtw_80211d, "Enable 802.11d mechanism");
+#endif
+
+static uint rtw_notch_filter = RTW_NOTCH_FILTER;
+module_param(rtw_notch_filter, uint, 0644);
+MODULE_PARM_DESC(rtw_notch_filter, "0:Disable, 1:Enable, 2:Enable only for P2P");
+
+static uint rtw_hiq_filter = CONFIG_RTW_HIQ_FILTER;
+module_param(rtw_hiq_filter, uint, 0644);
+MODULE_PARM_DESC(rtw_hiq_filter, "0:allow all, 1:allow special, 2:deny all");
+
+static uint rtw_adaptivity_en = CONFIG_RTW_ADAPTIVITY_EN;
+module_param(rtw_adaptivity_en, uint, 0644);
+MODULE_PARM_DESC(rtw_adaptivity_en, "0:disable, 1:enable");
+
+static uint rtw_adaptivity_mode = CONFIG_RTW_ADAPTIVITY_MODE;
+module_param(rtw_adaptivity_mode, uint, 0644);
+MODULE_PARM_DESC(rtw_adaptivity_mode, "0:normal, 1:carrier sense");
+
+static uint rtw_adaptivity_dml = CONFIG_RTW_ADAPTIVITY_DML;
+module_param(rtw_adaptivity_dml, uint, 0644);
+MODULE_PARM_DESC(rtw_adaptivity_dml, "0:disable, 1:enable");
+
+static uint rtw_adaptivity_dc_backoff = CONFIG_RTW_ADAPTIVITY_DC_BACKOFF;
+module_param(rtw_adaptivity_dc_backoff, uint, 0644);
+MODULE_PARM_DESC(rtw_adaptivity_dc_backoff, "DC backoff for Adaptivity");
+
+static int rtw_adaptivity_th_l2h_ini = CONFIG_RTW_ADAPTIVITY_TH_L2H_INI;
+module_param(rtw_adaptivity_th_l2h_ini, int, 0644);
+MODULE_PARM_DESC(rtw_adaptivity_th_l2h_ini, "th_l2h_ini for Adaptivity");
+
+static int rtw_adaptivity_th_edcca_hl_diff = CONFIG_RTW_ADAPTIVITY_TH_EDCCA_HL_DIFF;
+module_param(rtw_adaptivity_th_edcca_hl_diff, int, 0644);
+MODULE_PARM_DESC(rtw_adaptivity_th_edcca_hl_diff, "th_edcca_hl_diff for Adaptivity");
+
+#ifdef CONFIG_DFS_MASTER
+static uint rtw_dfs_region_domain = CONFIG_RTW_DFS_REGION_DOMAIN;
+module_param(rtw_dfs_region_domain, uint, 0644);
+MODULE_PARM_DESC(rtw_dfs_region_domain, "0:UNKNOWN, 1:FCC, 2:MKK, 3:ETSI");
+#endif
+
+static uint rtw_amplifier_type_2g = CONFIG_RTW_AMPLIFIER_TYPE_2G;
+module_param(rtw_amplifier_type_2g, uint, 0644);
+MODULE_PARM_DESC(rtw_amplifier_type_2g, "BIT3:2G ext-PA, BIT4:2G ext-LNA");
+
+static uint rtw_amplifier_type_5g = CONFIG_RTW_AMPLIFIER_TYPE_5G;
+module_param(rtw_amplifier_type_5g, uint, 0644);
+MODULE_PARM_DESC(rtw_amplifier_type_5g, "BIT6:5G ext-PA, BIT7:5G ext-LNA");
+
+static uint rtw_RFE_type = CONFIG_RTW_RFE_TYPE;
+module_param(rtw_RFE_type, uint, 0644);
+MODULE_PARM_DESC(rtw_RFE_type, "default init value:64");
+
+static uint rtw_powertracking_type = 64;
+module_param(rtw_powertracking_type, uint, 0644);
+MODULE_PARM_DESC(rtw_powertracking_type, "default init value:64");
+
+static uint rtw_GLNA_type = CONFIG_RTW_GLNA_TYPE;
+module_param(rtw_GLNA_type, uint, 0644);
+MODULE_PARM_DESC(rtw_GLNA_type, "default init value:0");
+
+static uint rtw_TxBBSwing_2G = 0xFF;
+module_param(rtw_TxBBSwing_2G, uint, 0644);
+MODULE_PARM_DESC(rtw_TxBBSwing_2G, "default init value:0xFF");
+
+static uint rtw_TxBBSwing_5G = 0xFF;
+module_param(rtw_TxBBSwing_5G, uint, 0644);
+MODULE_PARM_DESC(rtw_TxBBSwing_5G, "default init value:0xFF");
+
+static uint rtw_OffEfuseMask = 0;
+module_param(rtw_OffEfuseMask, uint, 0644);
+MODULE_PARM_DESC(rtw_OffEfuseMask, "default open Efuse Mask value:0");
+
+static uint rtw_FileMaskEfuse = 0;
+module_param(rtw_FileMaskEfuse, uint, 0644);
+MODULE_PARM_DESC(rtw_FileMaskEfuse, "default drv Mask Efuse value:0");
+
+static uint rtw_rxgain_offset_2g = 0;
+module_param(rtw_rxgain_offset_2g, uint, 0644);
+MODULE_PARM_DESC(rtw_rxgain_offset_2g, "default RF Gain 2G Offset value:0");
+
+static uint rtw_rxgain_offset_5gl = 0;
+module_param(rtw_rxgain_offset_5gl, uint, 0644);
+MODULE_PARM_DESC(rtw_rxgain_offset_5gl, "default RF Gain 5GL Offset value:0");
+
+static uint rtw_rxgain_offset_5gm = 0;
+module_param(rtw_rxgain_offset_5gm, uint, 0644);
+MODULE_PARM_DESC(rtw_rxgain_offset_5gm, "default RF Gain 5GM Offset value:0");
+
+static uint rtw_rxgain_offset_5gh = 0;
+module_param(rtw_rxgain_offset_5gh, uint, 0644);
+MODULE_PARM_DESC(rtw_rxgain_offset_5gm, "default RF Gain 5GL Offset value:0");
+
+static uint rtw_pll_ref_clk_sel = CONFIG_RTW_PLL_REF_CLK_SEL;
+module_param(rtw_pll_ref_clk_sel, uint, 0644);
+MODULE_PARM_DESC(rtw_pll_ref_clk_sel, "force pll_ref_clk_sel, 0xF:use autoload value");
+
+static int rtw_tx_pwr_by_rate = CONFIG_TXPWR_BY_RATE_EN;
+module_param(rtw_tx_pwr_by_rate, int, 0644);
+MODULE_PARM_DESC(rtw_tx_pwr_by_rate, "0:Disable, 1:Enable, 2: Depend on efuse");
+
+static int rtw_tx_pwr_lmt_enable = CONFIG_TXPWR_LIMIT_EN;
+module_param(rtw_tx_pwr_lmt_enable, int, 0644);
+MODULE_PARM_DESC(rtw_tx_pwr_lmt_enable, "0:Disable, 1:Enable, 2: Depend on efuse");
+
+static int rtw_target_tx_pwr_2g_a[RATE_SECTION_NUM] = CONFIG_RTW_TARGET_TX_PWR_2G_A;
+static int rtw_target_tx_pwr_2g_a_num = 0;
+module_param_array(rtw_target_tx_pwr_2g_a, int, &rtw_target_tx_pwr_2g_a_num, 0644);
+MODULE_PARM_DESC(rtw_target_tx_pwr_2g_a, "2.4G target tx power (unit:dBm) of RF path A for each rate section, should match the real calibrate power, -1: undefined");
+
+static int rtw_target_tx_pwr_2g_b[RATE_SECTION_NUM] = CONFIG_RTW_TARGET_TX_PWR_2G_B;
+static int rtw_target_tx_pwr_2g_b_num = 0;
+module_param_array(rtw_target_tx_pwr_2g_b, int, &rtw_target_tx_pwr_2g_b_num, 0644);
+MODULE_PARM_DESC(rtw_target_tx_pwr_2g_b, "2.4G target tx power (unit:dBm) of RF path B for each rate section, should match the real calibrate power, -1: undefined");
+
+static int rtw_target_tx_pwr_2g_c[RATE_SECTION_NUM] = CONFIG_RTW_TARGET_TX_PWR_2G_C;
+static int rtw_target_tx_pwr_2g_c_num = 0;
+module_param_array(rtw_target_tx_pwr_2g_c, int, &rtw_target_tx_pwr_2g_c_num, 0644);
+MODULE_PARM_DESC(rtw_target_tx_pwr_2g_c, "2.4G target tx power (unit:dBm) of RF path C for each rate section, should match the real calibrate power, -1: undefined");
+
+static int rtw_target_tx_pwr_2g_d[RATE_SECTION_NUM] = CONFIG_RTW_TARGET_TX_PWR_2G_D;
+static int rtw_target_tx_pwr_2g_d_num = 0;
+module_param_array(rtw_target_tx_pwr_2g_d, int, &rtw_target_tx_pwr_2g_d_num, 0644);
+MODULE_PARM_DESC(rtw_target_tx_pwr_2g_d, "2.4G target tx power (unit:dBm) of RF path D for each rate section, should match the real calibrate power, -1: undefined");
+
+#ifdef CONFIG_IEEE80211_BAND_5GHZ
+static int rtw_target_tx_pwr_5g_a[RATE_SECTION_NUM - 1] = CONFIG_RTW_TARGET_TX_PWR_5G_A;
+static int rtw_target_tx_pwr_5g_a_num = 0;
+module_param_array(rtw_target_tx_pwr_5g_a, int, &rtw_target_tx_pwr_5g_a_num, 0644);
+MODULE_PARM_DESC(rtw_target_tx_pwr_5g_a, "5G target tx power (unit:dBm) of RF path A for each rate section, should match the real calibrate power, -1: undefined");
+
+static int rtw_target_tx_pwr_5g_b[RATE_SECTION_NUM - 1] = CONFIG_RTW_TARGET_TX_PWR_5G_B;
+static int rtw_target_tx_pwr_5g_b_num = 0;
+module_param_array(rtw_target_tx_pwr_5g_b, int, &rtw_target_tx_pwr_5g_b_num, 0644);
+MODULE_PARM_DESC(rtw_target_tx_pwr_5g_b, "5G target tx power (unit:dBm) of RF path B for each rate section, should match the real calibrate power, -1: undefined");
+
+static int rtw_target_tx_pwr_5g_c[RATE_SECTION_NUM - 1] = CONFIG_RTW_TARGET_TX_PWR_5G_C;
+static int rtw_target_tx_pwr_5g_c_num = 0;
+module_param_array(rtw_target_tx_pwr_5g_c, int, &rtw_target_tx_pwr_5g_c_num, 0644);
+MODULE_PARM_DESC(rtw_target_tx_pwr_5g_c, "5G target tx power (unit:dBm) of RF path C for each rate section, should match the real calibrate power, -1: undefined");
+
+static int rtw_target_tx_pwr_5g_d[RATE_SECTION_NUM - 1] = CONFIG_RTW_TARGET_TX_PWR_5G_D;
+static int rtw_target_tx_pwr_5g_d_num = 0;
+module_param_array(rtw_target_tx_pwr_5g_d, int, &rtw_target_tx_pwr_5g_d_num, 0644);
+MODULE_PARM_DESC(rtw_target_tx_pwr_5g_d, "5G target tx power (unit:dBm) of RF path D for each rate section, should match the real calibrate power, -1: undefined");
+#endif /* CONFIG_IEEE80211_BAND_5GHZ */
+
+#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE
+char *rtw_phy_file_path = REALTEK_CONFIG_PATH;
+module_param(rtw_phy_file_path, charp, 0644);
+MODULE_PARM_DESC(rtw_phy_file_path, "The path of phy parameter");
+/* PHY FILE Bit Map
+* BIT0 - MAC,				0: non-support, 1: support
+* BIT1 - BB,					0: non-support, 1: support
+* BIT2 - BB_PG,				0: non-support, 1: support
+* BIT3 - BB_MP,				0: non-support, 1: support
+* BIT4 - RF,					0: non-support, 1: support
+* BIT5 - RF_TXPWR_TRACK,	0: non-support, 1: support
+* BIT6 - RF_TXPWR_LMT,		0: non-support, 1: support */
+static int rtw_load_phy_file = (BIT2 | BIT6);
+module_param(rtw_load_phy_file, int, 0644);
+MODULE_PARM_DESC(rtw_load_phy_file, "PHY File Bit Map");
+static int rtw_decrypt_phy_file = 0;
+module_param(rtw_decrypt_phy_file, int, 0644);
+MODULE_PARM_DESC(rtw_decrypt_phy_file, "Enable Decrypt PHY File");
+#endif
+
+#ifdef CONFIG_SUPPORT_TRX_SHARED
+#ifdef DFT_TRX_SHARE_MODE
+int rtw_trx_share_mode = DFT_TRX_SHARE_MODE;
+#else
+int rtw_trx_share_mode = 0;
+#endif
+module_param(rtw_trx_share_mode, int, 0644);
+MODULE_PARM_DESC(rtw_trx_share_mode, "TRx FIFO Shared");
+#endif
+
+int _netdev_open(struct net_device *pnetdev);
+int netdev_open(struct net_device *pnetdev);
+static int netdev_close(struct net_device *pnetdev);
+#ifdef CONFIG_PLATFORM_INTEL_BYT
+extern int rtw_sdio_set_power(int on);
+#endif /* CONFIG_PLATFORM_INTEL_BYT */
+
+#ifdef CONFIG_MCC_MODE
+/* enable MCC mode or not */
+static int rtw_en_mcc = 1;
+/* can referece following value before insmod driver */
+static int rtw_mcc_ap_bw20_target_tx_tp = MCC_AP_BW20_TARGET_TX_TP;
+static int rtw_mcc_ap_bw40_target_tx_tp = MCC_AP_BW40_TARGET_TX_TP;
+static int rtw_mcc_ap_bw80_target_tx_tp = MCC_AP_BW80_TARGET_TX_TP;
+static int rtw_mcc_sta_bw20_target_tx_tp = MCC_STA_BW20_TARGET_TX_TP;
+static int rtw_mcc_sta_bw40_target_tx_tp = MCC_STA_BW40_TARGET_TX_TP;
+static int rtw_mcc_sta_bw80_target_tx_tp = MCC_STA_BW80_TARGET_TX_TP;
+static int rtw_mcc_single_tx_cri = MCC_SINGLE_TX_CRITERIA;
+static int rtw_mcc_policy_table_idx = 0;
+static int rtw_mcc_duration = 0;
+static int rtw_mcc_tsf_sync_offset = 0;
+static int rtw_mcc_start_time_offset = 0;
+static int rtw_mcc_interval = 0;
+static int rtw_mcc_guard_offset0 = -1;
+static int rtw_mcc_guard_offset1 = -1;
+module_param(rtw_en_mcc, int, 0644);
+module_param(rtw_mcc_single_tx_cri, int, 0644);
+module_param(rtw_mcc_ap_bw20_target_tx_tp, int, 0644);
+module_param(rtw_mcc_ap_bw40_target_tx_tp, int, 0644);
+module_param(rtw_mcc_ap_bw80_target_tx_tp, int, 0644);
+module_param(rtw_mcc_sta_bw20_target_tx_tp, int, 0644);
+module_param(rtw_mcc_sta_bw40_target_tx_tp, int, 0644);
+module_param(rtw_mcc_sta_bw80_target_tx_tp, int, 0644);
+module_param(rtw_mcc_policy_table_idx, int, 0644);
+module_param(rtw_mcc_duration, int, 0644);
+module_param(rtw_mcc_tsf_sync_offset, int, 0644);
+module_param(rtw_mcc_start_time_offset, int, 0644);
+module_param(rtw_mcc_interval, int, 0644);
+module_param(rtw_mcc_guard_offset0, int, 0644);
+module_param(rtw_mcc_guard_offset1, int, 0644);
+#endif /*CONFIG_MCC_MODE */
+
+#ifdef CONFIG_RTW_NAPI
+/*following setting should define NAPI in Makefile
+enable napi only = 1, disable napi = 0*/
+static int rtw_en_napi = 1;
+module_param(rtw_en_napi, int, 0644);
+#ifdef CONFIG_RTW_GRO
+/*following setting should define GRO in Makefile
+enable gro = 1, disable gro = 0*/
+static int rtw_en_gro = 1;
+module_param(rtw_en_gro, int, 0644);
+#endif /* CONFIG_RTW_GRO */
+#endif /* CONFIG_RTW_NAPI */
+
+static void rtw_regsty_load_target_tx_power(struct registry_priv *regsty)
+{
+	int path, rs;
+	int *target_tx_pwr;
+
+	for (path = RF_PATH_A; path < RF_PATH_MAX; path++) {
+		if (path == RF_PATH_A)
+			target_tx_pwr = rtw_target_tx_pwr_2g_a;
+		else if (path == RF_PATH_B)
+			target_tx_pwr = rtw_target_tx_pwr_2g_b;
+		else if (path == RF_PATH_C)
+			target_tx_pwr = rtw_target_tx_pwr_2g_c;
+		else if (path == RF_PATH_D)
+			target_tx_pwr = rtw_target_tx_pwr_2g_d;
+
+		for (rs = CCK; rs < RATE_SECTION_NUM; rs++)
+			regsty->target_tx_pwr_2g[path][rs] = target_tx_pwr[rs];
+	}
+
+#ifdef CONFIG_IEEE80211_BAND_5GHZ
+	for (path = RF_PATH_A; path < RF_PATH_MAX; path++) {
+		if (path == RF_PATH_A)
+			target_tx_pwr = rtw_target_tx_pwr_5g_a;
+		else if (path == RF_PATH_B)
+			target_tx_pwr = rtw_target_tx_pwr_5g_b;
+		else if (path == RF_PATH_C)
+			target_tx_pwr = rtw_target_tx_pwr_5g_c;
+		else if (path == RF_PATH_D)
+			target_tx_pwr = rtw_target_tx_pwr_5g_d;
+
+		for (rs = OFDM; rs < RATE_SECTION_NUM; rs++)
+			regsty->target_tx_pwr_5g[path][rs - 1] = target_tx_pwr[rs - 1];
+	}
+#endif /* CONFIG_IEEE80211_BAND_5GHZ */
+}
+
+inline void rtw_regsty_load_excl_chs(struct registry_priv *regsty)
+{
+	int i;
+	int ch_num = 0;
+
+	for (i = 0; i < MAX_CHANNEL_NUM; i++)
+		if (((u8)rtw_excl_chs[i]) != 0)
+			regsty->excl_chs[ch_num++] = (u8)rtw_excl_chs[i];
+
+	if (ch_num < MAX_CHANNEL_NUM)
+		regsty->excl_chs[ch_num] = 0;
+}
+
+uint loadparam(_adapter *padapter)
+{
+	uint status = _SUCCESS;
+	struct registry_priv  *registry_par = &padapter->registrypriv;
+
+
+#ifdef CONFIG_RTW_DEBUG
+	if (rtw_drv_log_level >= _DRV_MAX_)
+		rtw_drv_log_level = _DRV_DEBUG_;
+#endif
+
+	registry_par->chip_version = (u8)rtw_chip_version;
+	registry_par->rfintfs = (u8)rtw_rfintfs;
+	registry_par->lbkmode = (u8)rtw_lbkmode;
+	/* registry_par->hci = (u8)hci; */
+	registry_par->network_mode  = (u8)rtw_network_mode;
+
+	memcpy(registry_par->ssid.Ssid, "ANY", 3);
+	registry_par->ssid.SsidLength = 3;
+
+	registry_par->channel = (u8)rtw_channel;
+	registry_par->wireless_mode = (u8)rtw_wireless_mode;
+
+	if (IsSupported24G(registry_par->wireless_mode) && (!is_supported_5g(registry_par->wireless_mode))
+	    && (registry_par->channel > 14))
+		registry_par->channel = 1;
+	else if (is_supported_5g(registry_par->wireless_mode) && (!IsSupported24G(registry_par->wireless_mode))
+		 && (registry_par->channel <= 14))
+		registry_par->channel = 36;
+
+	registry_par->vrtl_carrier_sense = (u8)rtw_vrtl_carrier_sense ;
+	registry_par->vcs_type = (u8)rtw_vcs_type;
+	registry_par->rts_thresh = (u16)rtw_rts_thresh;
+	registry_par->frag_thresh = (u16)rtw_frag_thresh;
+	registry_par->preamble = (u8)rtw_preamble;
+	registry_par->scan_mode = (u8)rtw_scan_mode;
+	registry_par->adhoc_tx_pwr = (u8)rtw_adhoc_tx_pwr;
+	registry_par->soft_ap = (u8)rtw_soft_ap;
+	registry_par->smart_ps = (u8)rtw_smart_ps;
+	registry_par->check_fw_ps = (u8)rtw_check_fw_ps;
+	registry_par->power_mgnt = (u8)rtw_power_mgnt;
+	registry_par->ips_mode = (u8)rtw_ips_mode;
+	registry_par->radio_enable = (u8)rtw_radio_enable;
+	registry_par->long_retry_lmt = (u8)rtw_long_retry_lmt;
+	registry_par->short_retry_lmt = (u8)rtw_short_retry_lmt;
+	registry_par->busy_thresh = (u16)rtw_busy_thresh;
+	/* registry_par->qos_enable = (u8)rtw_qos_enable; */
+	registry_par->ack_policy = (u8)rtw_ack_policy;
+	registry_par->mp_mode = (u8)rtw_mp_mode;
+#if defined(CONFIG_MP_INCLUDED) && defined(CONFIG_RTW_CUSTOMER_STR)
+	registry_par->mp_customer_str = (u8)rtw_mp_customer_str;
+#endif
+	registry_par->software_encrypt = (u8)rtw_software_encrypt;
+	registry_par->software_decrypt = (u8)rtw_software_decrypt;
+
+	registry_par->acm_method = (u8)rtw_acm_method;
+	registry_par->usb_rxagg_mode = (u8)rtw_usb_rxagg_mode;
+
+	/* UAPSD */
+	registry_par->wmm_enable = (u8)rtw_wmm_enable;
+	registry_par->uapsd_enable = (u8)rtw_uapsd_enable;
+	registry_par->uapsd_max_sp = (u8)rtw_uapsd_max_sp;
+	registry_par->uapsd_acbk_en = (u8)rtw_uapsd_acbk_en;
+	registry_par->uapsd_acbe_en = (u8)rtw_uapsd_acbe_en;
+	registry_par->uapsd_acvi_en = (u8)rtw_uapsd_acvi_en;
+	registry_par->uapsd_acvo_en = (u8)rtw_uapsd_acvo_en;
+
+	registry_par->RegPwrTrimEnable = (u8)rtw_pwrtrim_enable;
+	registry_par->led_enable = (u8)rtw_led_enable;
+	registry_par->tx_bw_mode = (u8)rtw_tx_bw_mode;
+
+	registry_par->ht_enable = (u8)rtw_ht_enable;
+	registry_par->bw_mode = (u8)rtw_bw_mode;
+	registry_par->ampdu_enable = (u8)rtw_ampdu_enable;
+	registry_par->rx_stbc = (u8)rtw_rx_stbc;
+	registry_par->ampdu_amsdu = (u8)rtw_ampdu_amsdu;
+	registry_par->short_gi = (u8)rtw_short_gi;
+	registry_par->ldpc_cap = (u8)rtw_ldpc_cap;
+	registry_par->stbc_cap = (u8)rtw_stbc_cap;
+	registry_par->beamform_cap = (u8)rtw_beamform_cap;
+	registry_par->beamformer_rf_num = (u8)rtw_bfer_rf_number;
+	registry_par->beamformee_rf_num = (u8)rtw_bfee_rf_number;
+
+#ifdef CONFIG_TX_EARLY_MODE
+	registry_par->early_mode = (u8)rtw_early_mode;
+#endif
+	registry_par->lowrate_two_xmit = (u8)rtw_lowrate_two_xmit;
+	registry_par->rf_config = (u8)rtw_rf_config;
+	registry_par->low_power = (u8)rtw_low_power;
+
+	registry_par->check_hw_status = (u8)rtw_check_hw_status;
+
+	registry_par->wifi_spec = (u8)rtw_wifi_spec;
+
+	if (strlen(rtw_country_code) != 2
+		|| is_alpha(rtw_country_code[0]) == false
+		|| is_alpha(rtw_country_code[1]) == false
+	) {
+		if (rtw_country_code != rtw_country_unspecified)
+			RTW_ERR("%s discard rtw_country_code not in alpha2\n", __func__);
+		memset(registry_par->alpha2, 0xFF, 2);
+	} else
+		memcpy(registry_par->alpha2, rtw_country_code, 2);
+
+	registry_par->channel_plan = (u8)rtw_channel_plan;
+	rtw_regsty_load_excl_chs(registry_par);
+
+	registry_par->special_rf_path = (u8)rtw_special_rf_path;
+
+	registry_par->full_ch_in_p2p_handshake = (u8)rtw_full_ch_in_p2p_handshake;
+#ifdef CONFIG_BT_COEXIST
+	registry_par->btcoex = (u8)rtw_btcoex_enable;
+	registry_par->bt_iso = (u8)rtw_bt_iso;
+	registry_par->bt_sco = (u8)rtw_bt_sco;
+	registry_par->bt_ampdu = (u8)rtw_bt_ampdu;
+	registry_par->ant_num = (u8)rtw_ant_num;
+#endif
+
+	registry_par->bAcceptAddbaReq = (u8)rtw_AcceptAddbaReq;
+
+	registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg;
+	registry_par->antdiv_type = (u8)rtw_antdiv_type;
+
+	registry_par->drv_ant_band_switch = (u8) rtw_drv_ant_band_switch;
+
+	registry_par->switch_usb_mode = (u8)rtw_switch_usb_mode;
+
+#ifdef CONFIG_AUTOSUSPEND
+	registry_par->usbss_enable = (u8)rtw_enusbss;/* 0:disable,1:enable */
+#endif
+#ifdef SUPPORT_HW_RFOFF_DETECTED
+	registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode;/* 0:disable,1:enable,2:by EFUSE config */
+	registry_par->hwpwrp_detect = (u8)rtw_hwpwrp_detect;/* 0:disable,1:enable */
+#endif
+
+	registry_par->hw_wps_pbc = (u8)rtw_hw_wps_pbc;
+
+#ifdef CONFIG_ADAPTOR_INFO_CACHING_FILE
+	snprintf(registry_par->adaptor_info_caching_file_path, PATH_LENGTH_MAX, "%s", rtw_adaptor_info_caching_file_path);
+	registry_par->adaptor_info_caching_file_path[PATH_LENGTH_MAX - 1] = 0;
+#endif
+
+#ifdef CONFIG_LAYER2_ROAMING
+	registry_par->max_roaming_times = (u8)rtw_max_roaming_times;
+#ifdef CONFIG_INTEL_WIDI
+	registry_par->max_roaming_times = (u8)rtw_max_roaming_times + 2;
+#endif /* CONFIG_INTEL_WIDI */
+#endif
+
+#ifdef CONFIG_IOL
+	registry_par->fw_iol = rtw_fw_iol;
+#endif
+
+#ifdef CONFIG_80211D
+	registry_par->enable80211d = (u8)rtw_80211d;
+#endif
+
+	snprintf(registry_par->ifname, 16, "%s", ifname);
+	snprintf(registry_par->if2name, 16, "%s", if2name);
+
+	registry_par->notch_filter = (u8)rtw_notch_filter;
+
+#ifdef CONFIG_SPECIAL_SETTING_FOR_FUNAI_TV
+	registry_par->force_ant = (u8)rtw_force_ant;
+	registry_par->force_igi = (u8)rtw_force_igi;
+#endif
+
+#ifdef CONFIG_CONCURRENT_MODE
+	registry_par->virtual_iface_num = (u8)rtw_virtual_iface_num;
+#endif
+
+	registry_par->force_igi_lb = (u8)rtw_force_igi_lb;
+
+	registry_par->pll_ref_clk_sel = (u8)rtw_pll_ref_clk_sel;
+
+	registry_par->RegEnableTxPowerLimit = (u8)rtw_tx_pwr_lmt_enable;
+	registry_par->RegEnableTxPowerByRate = (u8)rtw_tx_pwr_by_rate;
+
+	rtw_regsty_load_target_tx_power(registry_par);
+
+	registry_par->RegPowerBase = 14;
+	registry_par->TxBBSwing_2G = (s8)rtw_TxBBSwing_2G;
+	registry_par->TxBBSwing_5G = (s8)rtw_TxBBSwing_5G;
+	registry_par->bEn_RFE = 1;
+	registry_par->RFE_Type = (u8)rtw_RFE_type;
+	registry_par->PowerTracking_Type = (u8)rtw_powertracking_type;
+	registry_par->AmplifierType_2G = (u8)rtw_amplifier_type_2g;
+	registry_par->AmplifierType_5G = (u8)rtw_amplifier_type_5g;
+	registry_par->GLNA_Type = (u8)rtw_GLNA_type;
+#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE
+	registry_par->load_phy_file = (u8)rtw_load_phy_file;
+	registry_par->RegDecryptCustomFile = (u8)rtw_decrypt_phy_file;
+#endif
+	registry_par->qos_opt_enable = (u8)rtw_qos_opt_enable;
+
+	registry_par->hiq_filter = (u8)rtw_hiq_filter;
+
+	registry_par->adaptivity_en = (u8)rtw_adaptivity_en;
+	registry_par->adaptivity_mode = (u8)rtw_adaptivity_mode;
+	registry_par->adaptivity_dml = (u8)rtw_adaptivity_dml;
+	registry_par->adaptivity_dc_backoff = (u8)rtw_adaptivity_dc_backoff;
+	registry_par->adaptivity_th_l2h_ini = (s8)rtw_adaptivity_th_l2h_ini;
+	registry_par->adaptivity_th_edcca_hl_diff = (s8)rtw_adaptivity_th_edcca_hl_diff;
+
+	registry_par->boffefusemask = (u8)rtw_OffEfuseMask;
+	registry_par->bFileMaskEfuse = (u8)rtw_FileMaskEfuse;
+#ifdef CONFIG_AUTO_CHNL_SEL_NHM
+	registry_par->acs_mode = (u8)rtw_acs_mode;
+	registry_par->acs_auto_scan = (u8)rtw_acs_auto_scan;
+#endif
+	registry_par->reg_rxgain_offset_2g = (u32) rtw_rxgain_offset_2g;
+	registry_par->reg_rxgain_offset_5gl = (u32) rtw_rxgain_offset_5gl;
+	registry_par->reg_rxgain_offset_5gm = (u32) rtw_rxgain_offset_5gm;
+	registry_par->reg_rxgain_offset_5gh = (u32) rtw_rxgain_offset_5gh;
+
+#ifdef CONFIG_DFS_MASTER
+	registry_par->dfs_region_domain = (u8)rtw_dfs_region_domain;
+#endif
+
+#ifdef CONFIG_MCC_MODE
+	registry_par->en_mcc = (u8)rtw_en_mcc;
+	registry_par->rtw_mcc_ap_bw20_target_tx_tp = (u32)rtw_mcc_ap_bw20_target_tx_tp;
+	registry_par->rtw_mcc_ap_bw40_target_tx_tp = (u32)rtw_mcc_ap_bw40_target_tx_tp;
+	registry_par->rtw_mcc_ap_bw80_target_tx_tp = (u32)rtw_mcc_ap_bw80_target_tx_tp;
+	registry_par->rtw_mcc_sta_bw20_target_tx_tp = (u32)rtw_mcc_sta_bw20_target_tx_tp;
+	registry_par->rtw_mcc_sta_bw40_target_tx_tp = (u32)rtw_mcc_sta_bw40_target_tx_tp;
+	registry_par->rtw_mcc_sta_bw80_target_tx_tp = (u32)rtw_mcc_sta_bw80_target_tx_tp;
+	registry_par->rtw_mcc_single_tx_cri = (u32)rtw_mcc_single_tx_cri;
+	registry_par->rtw_mcc_policy_table_idx = rtw_mcc_policy_table_idx;
+	registry_par->rtw_mcc_duration = (u8)rtw_mcc_duration;
+	registry_par->rtw_mcc_tsf_sync_offset = (u8)rtw_mcc_tsf_sync_offset;
+	registry_par->rtw_mcc_start_time_offset = (u8)rtw_mcc_start_time_offset;
+	registry_par->rtw_mcc_interval = (u8)rtw_mcc_interval;
+	registry_par->rtw_mcc_guard_offset0 = rtw_mcc_guard_offset0;
+	registry_par->rtw_mcc_guard_offset1 = rtw_mcc_guard_offset1;
+#endif /*CONFIG_MCC_MODE */
+#ifdef CONFIG_DEFAULT_PATTERNS_EN
+	registry_par->default_patterns_en = rtw_support_default_patterns;
+#endif
+
+#ifdef CONFIG_SUPPORT_TRX_SHARED
+	registry_par->trx_share_mode = rtw_trx_share_mode;
+#endif
+
+#ifdef CONFIG_RTW_NAPI
+	registry_par->en_napi = (u8)rtw_en_napi;
+#ifdef CONFIG_RTW_GRO
+	registry_par->en_gro = (u8)rtw_en_gro;
+	if (!registry_par->en_napi && registry_par->en_gro) {
+		registry_par->en_gro = 0;
+		RTW_WARN("Disable GRO because NAPI is not enabled\n");
+	}
+#endif /* CONFIG_RTW_GRO */
+#endif /* CONFIG_RTW_NAPI */
+
+	return status;
+}
+
+/**
+ * rtw_net_set_mac_address
+ * This callback function is used for the Media Access Control address
+ * of each net_device needs to be changed.
+ *
+ * Arguments:
+ * @pnetdev: net_device pointer.
+ * @addr: new MAC address.
+ *
+ * Return:
+ * ret = 0: Permit to change net_device's MAC address.
+ * ret = -1 (Default): Operation not permitted.
+ *
+ * Auther: Arvin Liu
+ * Date: 2015/05/29
+ */
+static int rtw_net_set_mac_address(struct net_device *pnetdev, void *addr)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct sockaddr *sa = (struct sockaddr *)addr;
+	int ret = -1;
+
+	/* only the net_device is in down state to permit modifying mac addr */
+	if ((pnetdev->flags & IFF_UP) == true) {
+		RTW_INFO(FUNC_ADPT_FMT": The net_device's is not in down state\n"
+			 , FUNC_ADPT_ARG(padapter));
+
+		return ret;
+	}
+
+	/* if the net_device is linked, it's not permit to modify mac addr */
+	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) ||
+	    check_fwstate(pmlmepriv, _FW_LINKED) ||
+	    check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
+		RTW_INFO(FUNC_ADPT_FMT": The net_device's is not idle currently\n"
+			 , FUNC_ADPT_ARG(padapter));
+
+		return ret;
+	}
+
+	/* check whether the input mac address is valid to permit modifying mac addr */
+	if (rtw_check_invalid_mac_address(sa->sa_data, false) == true) {
+		RTW_INFO(FUNC_ADPT_FMT": Invalid Mac Addr for "MAC_FMT"\n"
+			 , FUNC_ADPT_ARG(padapter), MAC_ARG(sa->sa_data));
+
+		return ret;
+	}
+
+	memcpy(adapter_mac_addr(padapter), sa->sa_data, ETH_ALEN); /* set mac addr to adapter */
+	memcpy(pnetdev->dev_addr, sa->sa_data, ETH_ALEN); /* set mac addr to net_device */
+
+	rtw_ps_deny(padapter, PS_DENY_IOCTL);
+	LeaveAllPowerSaveModeDirect(padapter); /* leave PS mode for guaranteeing to access hw register successfully */
+#ifdef CONFIG_MI_WITH_MBSSID_CAM
+	rtw_hal_change_macaddr_mbid(padapter, sa->sa_data);
+#else
+	rtw_hal_set_hwreg(padapter, HW_VAR_MAC_ADDR, sa->sa_data); /* set mac addr to mac register */
+#endif
+	rtw_ps_deny_cancel(padapter, PS_DENY_IOCTL);
+
+	RTW_INFO(FUNC_ADPT_FMT": Set Mac Addr to "MAC_FMT" Successfully\n"
+		 , FUNC_ADPT_ARG(padapter), MAC_ARG(sa->sa_data));
+
+	ret = 0;
+
+	return ret;
+}
+
+static struct net_device_stats *rtw_net_get_stats(struct net_device *pnetdev)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+	struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+	struct recv_priv *precvpriv = &(padapter->recvpriv);
+
+	padapter->stats.tx_packets = pxmitpriv->tx_pkts;/* pxmitpriv->tx_pkts++; */
+	padapter->stats.rx_packets = precvpriv->rx_pkts;/* precvpriv->rx_pkts++; */
+	padapter->stats.tx_dropped = pxmitpriv->tx_drop;
+	padapter->stats.rx_dropped = precvpriv->rx_drop;
+	padapter->stats.tx_bytes = pxmitpriv->tx_bytes;
+	padapter->stats.rx_bytes = precvpriv->rx_bytes;
+
+	return &padapter->stats;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+/*
+ * AC to queue mapping
+ *
+ * AC_VO -> queue 0
+ * AC_VI -> queue 1
+ * AC_BE -> queue 2
+ * AC_BK -> queue 3
+ */
+static const u16 rtw_1d_to_queue[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
+
+/* Given a data frame determine the 802.1p/1d tag to use. */
+static unsigned int rtw_classify8021d(struct sk_buff *skb)
+{
+	unsigned int dscp;
+
+	/* skb->priority values from 256->263 are magic values to
+	 * directly indicate a specific 802.1d priority.  This is used
+	 * to allow 802.1d priority to be passed directly in from VLAN
+	 * tags, etc.
+	 */
+	if (skb->priority >= 256 && skb->priority <= 263)
+		return skb->priority - 256;
+
+	switch (skb->protocol) {
+	case htons(ETH_P_IP):
+		dscp = ip_hdr(skb)->tos & 0xfc;
+		break;
+	default:
+		return 0;
+	}
+
+	return dscp >> 5;
+}
+
+
+static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
+			    ,struct net_device *sb_dev
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
+			    ,struct net_device *sb_dev
+                            ,select_queue_fallback_t fallback
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+ 			    ,void *unused
+                             ,select_queue_fallback_t fallback
+#endif
+)
+{
+	_adapter	*padapter = rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+	skb->priority = rtw_classify8021d(skb);
+
+	if (pmlmepriv->acm_mask != 0)
+		skb->priority = qos_acm(pmlmepriv->acm_mask, skb->priority);
+
+	return rtw_1d_to_queue[skb->priority];
+}
+
+u16 rtw_recv_select_queue(struct sk_buff *skb)
+{
+	struct iphdr *piphdr;
+	unsigned int dscp;
+	__be16	eth_type;
+	u32 priority;
+	u8 *pdata = skb->data;
+
+	memcpy(&eth_type, pdata + (ETH_ALEN << 1), 2);
+
+	switch (eth_type) {
+	case htons(ETH_P_IP):
+		piphdr = (struct iphdr *)(pdata + ETH_HLEN);
+		dscp = piphdr->tos & 0xfc;
+		priority = dscp >> 5;
+		break;
+	default:
+		priority = 0;
+	}
+
+	return rtw_1d_to_queue[priority];
+}
+
+#endif
+static int rtw_ndev_notifier_call(struct notifier_block *nb, unsigned long state, void *ptr)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+#else
+	struct net_device *dev = ptr;
+#endif
+
+	if (dev == NULL)
+		return NOTIFY_DONE;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+	if (dev->netdev_ops == NULL)
+		return NOTIFY_DONE;
+
+	if (dev->netdev_ops->ndo_do_ioctl == NULL)
+		return NOTIFY_DONE;
+
+	if (dev->netdev_ops->ndo_do_ioctl != rtw_ioctl)
+#else
+	if (dev->do_ioctl == NULL)
+		return NOTIFY_DONE;
+
+	if (dev->do_ioctl != rtw_ioctl)
+#endif
+		return NOTIFY_DONE;
+
+	RTW_INFO(FUNC_NDEV_FMT" state:%lu\n", FUNC_NDEV_ARG(dev), state);
+
+	switch (state) {
+	case NETDEV_CHANGENAME:
+		rtw_adapter_proc_replace(dev);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block rtw_ndev_notifier = {
+	.notifier_call = rtw_ndev_notifier_call,
+};
+
+int rtw_ndev_notifier_register(void)
+{
+	return register_netdevice_notifier(&rtw_ndev_notifier);
+}
+
+void rtw_ndev_notifier_unregister(void)
+{
+	unregister_netdevice_notifier(&rtw_ndev_notifier);
+}
+
+static int rtw_ndev_init(struct net_device *dev)
+{
+	_adapter *adapter = rtw_netdev_priv(dev);
+
+	RTW_INFO(FUNC_ADPT_FMT" if%d mac_addr="MAC_FMT"\n"
+		, FUNC_ADPT_ARG(adapter), (adapter->iface_id + 1), MAC_ARG(dev->dev_addr));
+	strncpy(adapter->old_ifname, dev->name, IFNAMSIZ);
+	adapter->old_ifname[IFNAMSIZ - 1] = '\0';
+	rtw_adapter_proc_init(dev);
+
+	return 0;
+}
+
+static void rtw_ndev_uninit(struct net_device *dev)
+{
+	_adapter *adapter = rtw_netdev_priv(dev);
+
+	RTW_INFO(FUNC_ADPT_FMT" if%d\n"
+		  , FUNC_ADPT_ARG(adapter), (adapter->iface_id + 1));
+	rtw_adapter_proc_deinit(dev);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+static const struct net_device_ops rtw_netdev_ops = {
+	.ndo_init = rtw_ndev_init,
+	.ndo_uninit = rtw_ndev_uninit,
+	.ndo_open = netdev_open,
+	.ndo_stop = netdev_close,
+	.ndo_start_xmit = rtw_xmit_entry,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	.ndo_select_queue	= rtw_select_queue,
+#endif
+	.ndo_set_mac_address = rtw_net_set_mac_address,
+	.ndo_get_stats = rtw_net_get_stats,
+	.ndo_do_ioctl = rtw_ioctl,
+};
+#endif
+
+int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname)
+{
+	_adapter *padapter = rtw_netdev_priv(pnetdev);
+
+#ifdef CONFIG_EASY_REPLACEMENT
+	struct net_device	*TargetNetdev = NULL;
+	_adapter *TargetAdapter = NULL;
+	struct net		*devnet = NULL;
+
+	if (padapter->bDongle == 1) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+		TargetNetdev = dev_get_by_name("wlan0");
+#else
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
+		devnet = pnetdev->nd_net;
+#else
+		devnet = dev_net(pnetdev);
+#endif
+		TargetNetdev = dev_get_by_name(devnet, "wlan0");
+#endif
+		if (TargetNetdev) {
+			RTW_INFO("Force onboard module driver disappear !!!\n");
+			TargetAdapter = rtw_netdev_priv(TargetNetdev);
+			TargetAdapter->DriverState = DRIVER_DISAPPEAR;
+
+			padapter->pid[0] = TargetAdapter->pid[0];
+			padapter->pid[1] = TargetAdapter->pid[1];
+			padapter->pid[2] = TargetAdapter->pid[2];
+
+			dev_put(TargetNetdev);
+			unregister_netdev(TargetNetdev);
+
+			padapter->DriverState = DRIVER_REPLACE_DONGLE;
+		}
+	}
+#endif /* CONFIG_EASY_REPLACEMENT */
+
+	if (dev_alloc_name(pnetdev, ifname) < 0)
+		RTW_ERR("dev_alloc_name, fail!\n");
+
+	netif_carrier_off(pnetdev);
+	/* rtw_netif_stop_queue(pnetdev); */
+
+	return 0;
+}
+
+static void rtw_hook_if_ops(struct net_device *ndev)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+	ndev->netdev_ops = &rtw_netdev_ops;
+#else
+	ndev->init = rtw_ndev_init;
+	ndev->uninit = rtw_ndev_uninit;
+	ndev->open = netdev_open;
+	ndev->stop = netdev_close;
+	ndev->hard_start_xmit = rtw_xmit_entry;
+	ndev->set_mac_address = rtw_net_set_mac_address;
+	ndev->get_stats = rtw_net_get_stats;
+	ndev->do_ioctl = rtw_ioctl;
+#endif
+}
+
+#ifdef CONFIG_CONCURRENT_MODE
+static void rtw_hook_vir_if_ops(struct net_device *ndev);
+#endif
+struct net_device *rtw_init_netdev(_adapter *old_padapter)
+{
+	_adapter *padapter;
+	struct net_device *pnetdev;
+
+	if (old_padapter != NULL) {
+		rtw_os_ndev_free(old_padapter);
+		pnetdev = rtw_alloc_etherdev_with_old_priv(sizeof(_adapter), (void *)old_padapter);
+	} else
+		pnetdev = rtw_alloc_etherdev(sizeof(_adapter));
+
+	if (!pnetdev)
+		return NULL;
+
+	padapter = rtw_netdev_priv(pnetdev);
+	padapter->pnetdev = pnetdev;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+	SET_MODULE_OWNER(pnetdev);
+#endif
+
+	rtw_hook_if_ops(pnetdev);
+#ifdef CONFIG_CONCURRENT_MODE
+	if (!is_primary_adapter(padapter))
+		rtw_hook_vir_if_ops(pnetdev);
+#endif /* CONFIG_CONCURRENT_MODE */
+
+#ifdef CONFIG_TCP_CSUM_OFFLOAD_TX
+	pnetdev->features |= NETIF_F_IP_CSUM;
+#endif
+
+	/* pnetdev->tx_timeout = NULL; */
+	pnetdev->watchdog_timeo = HZ * 3; /* 3 second timeout */
+
+#ifdef CONFIG_WIRELESS_EXT
+	pnetdev->wireless_handlers = (struct iw_handler_def *)&rtw_handlers_def;
+#endif
+
+#ifdef WIRELESS_SPY
+	/* priv->wireless_data.spy_data = &priv->spy_data; */
+	/* pnetdev->wireless_data = &priv->wireless_data; */
+#endif
+
+	return pnetdev;
+}
+
+static int rtw_os_ndev_alloc(_adapter *adapter)
+{
+	int ret = _FAIL;
+	struct net_device *ndev = NULL;
+
+	ndev = rtw_init_netdev(adapter);
+	if (ndev == NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)
+	SET_NETDEV_DEV(ndev, dvobj_to_dev(adapter_to_dvobj(adapter)));
+#endif
+
+#if defined(CONFIG_IOCTL_CFG80211)
+	if (rtw_cfg80211_ndev_res_alloc(adapter) != _SUCCESS) {
+		rtw_warn_on(1);
+		goto free_ndev;
+	}
+#endif
+
+	ret = _SUCCESS;
+
+free_ndev:
+	if (ret != _SUCCESS && ndev)
+		rtw_free_netdev(ndev);
+exit:
+	return ret;
+}
+
+void rtw_os_ndev_free(_adapter *adapter)
+{
+#if defined(CONFIG_IOCTL_CFG80211)
+	rtw_cfg80211_ndev_res_free(adapter);
+#endif
+
+	if (adapter->pnetdev) {
+		rtw_free_netdev(adapter->pnetdev);
+		adapter->pnetdev = NULL;
+	}
+}
+
+static int rtw_os_ndev_register(_adapter *adapter, const char *name)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	int ret = _SUCCESS;
+	struct net_device *ndev = adapter->pnetdev;
+	u8 rtnl_lock_needed = rtw_rtnl_lock_needed(dvobj);
+
+#ifdef CONFIG_RTW_NAPI
+	netif_napi_add(ndev, &adapter->napi, rtw_recv_napi_poll, RTL_NAPI_WEIGHT);
+#endif /* CONFIG_RTW_NAPI */
+
+#if defined(CONFIG_IOCTL_CFG80211)
+	if (rtw_cfg80211_ndev_res_register(adapter) != _SUCCESS) {
+		rtw_warn_on(1);
+		ret = _FAIL;
+		goto exit;
+	}
+#endif
+
+	/* alloc netdev name */
+	rtw_init_netdev_name(ndev, name);
+
+	memcpy(ndev->dev_addr, adapter_mac_addr(adapter), ETH_ALEN);
+
+	/* Tell the network stack we exist */
+
+	if (rtnl_lock_needed)
+		ret = (register_netdev(ndev) == 0) ? _SUCCESS : _FAIL;
+	else
+		ret = (register_netdevice(ndev) == 0) ? _SUCCESS : _FAIL;
+
+	if (ret == _SUCCESS)
+		adapter->registered = 1;
+	else
+		RTW_INFO(FUNC_NDEV_FMT" if%d Failed!\n", FUNC_NDEV_ARG(ndev), (adapter->iface_id + 1));
+
+#if defined(CONFIG_IOCTL_CFG80211)
+	if (ret != _SUCCESS) {
+		rtw_cfg80211_ndev_res_unregister(adapter);
+		#if !defined(RTW_SINGLE_WIPHY)
+		rtw_wiphy_unregister(adapter_to_wiphy(adapter));
+		#endif
+	}
+#endif
+
+exit:
+#ifdef CONFIG_RTW_NAPI
+	if (ret != _SUCCESS)
+		netif_napi_del(&adapter->napi);
+#endif /* CONFIG_RTW_NAPI */
+
+	return ret;
+}
+
+void rtw_os_ndev_unregister(_adapter *adapter)
+{
+	struct net_device *netdev = NULL;
+
+	if (adapter == NULL || adapter->registered == 0)
+		return;
+
+	adapter->ndev_unregistering = 1;
+
+	netdev = adapter->pnetdev;
+
+#if defined(CONFIG_IOCTL_CFG80211)
+	rtw_cfg80211_ndev_res_unregister(adapter);
+#endif
+
+	if ((adapter->DriverState != DRIVER_DISAPPEAR) && netdev) {
+		struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+		u8 rtnl_lock_needed = rtw_rtnl_lock_needed(dvobj);
+
+		if (rtnl_lock_needed)
+			unregister_netdev(netdev);
+		else
+			unregister_netdevice(netdev);
+	}
+
+#if defined(CONFIG_IOCTL_CFG80211) && !defined(RTW_SINGLE_WIPHY)
+#ifdef CONFIG_RFKILL_POLL
+	rtw_cfg80211_deinit_rfkill(adapter_to_wiphy(adapter));
+#endif
+	rtw_wiphy_unregister(adapter_to_wiphy(adapter));
+#endif
+
+#ifdef CONFIG_RTW_NAPI
+	if (adapter->napi_state == NAPI_ENABLE) {
+		napi_disable(&adapter->napi);
+		adapter->napi_state = NAPI_DISABLE;
+	}
+	netif_napi_del(&adapter->napi);
+#endif /* CONFIG_RTW_NAPI */
+
+	adapter->registered = 0;
+	adapter->ndev_unregistering = 0;
+}
+
+/**
+ * rtw_os_ndev_init - Allocate and register OS layer net device and relating structures for @adapter
+ * @adapter: the adapter on which this function applies
+ * @name: the requesting net device name
+ *
+ * Returns:
+ * _SUCCESS or _FAIL
+ */
+int rtw_os_ndev_init(_adapter *adapter, const char *name)
+{
+	int ret = _FAIL;
+
+	if (rtw_os_ndev_alloc(adapter) != _SUCCESS)
+		goto exit;
+
+	if (rtw_os_ndev_register(adapter, name) != _SUCCESS)
+		goto os_ndev_free;
+
+	ret = _SUCCESS;
+
+os_ndev_free:
+	if (ret != _SUCCESS)
+		rtw_os_ndev_free(adapter);
+exit:
+	return ret;
+}
+
+/**
+ * rtw_os_ndev_deinit - Unregister and free OS layer net device and relating structures for @adapter
+ * @adapter: the adapter on which this function applies
+ */
+void rtw_os_ndev_deinit(_adapter *adapter)
+{
+	rtw_os_ndev_unregister(adapter);
+	rtw_os_ndev_free(adapter);
+}
+
+static int rtw_os_ndevs_alloc(struct dvobj_priv *dvobj)
+{
+	int i, status = _SUCCESS;
+	_adapter *adapter;
+
+#if defined(CONFIG_IOCTL_CFG80211)
+	if (rtw_cfg80211_dev_res_alloc(dvobj) != _SUCCESS) {
+		rtw_warn_on(1);
+		status = _FAIL;
+		goto exit;
+	}
+#endif
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+
+		if (i >= CONFIG_IFACE_NUMBER) {
+			RTW_ERR("%s %d >= CONFIG_IFACE_NUMBER(%d)\n", __func__, i, CONFIG_IFACE_NUMBER);
+			rtw_warn_on(1);
+			continue;
+		}
+
+		adapter = dvobj->padapters[i];
+		if (adapter && !adapter->pnetdev) {
+
+			#ifdef CONFIG_RTW_DYNAMIC_NDEV
+			if (!is_primary_adapter(adapter))
+				continue;
+			#endif
+
+			status = rtw_os_ndev_alloc(adapter);
+			if (status != _SUCCESS) {
+				rtw_warn_on(1);
+				break;
+			}
+		}
+	}
+
+	if (status != _SUCCESS) {
+		for (; i >= 0; i--) {
+			adapter = dvobj->padapters[i];
+			if (adapter && adapter->pnetdev)
+				rtw_os_ndev_free(adapter);
+		}
+	}
+
+#if defined(CONFIG_IOCTL_CFG80211)
+	if (status != _SUCCESS)
+		rtw_cfg80211_dev_res_free(dvobj);
+#endif
+exit:
+	return status;
+}
+
+static void rtw_os_ndevs_free(struct dvobj_priv *dvobj)
+{
+	int i;
+	_adapter *adapter = NULL;
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+
+		if (i >= CONFIG_IFACE_NUMBER) {
+			RTW_ERR("%s %d >= CONFIG_IFACE_NUMBER(%d)\n", __func__, i, CONFIG_IFACE_NUMBER);
+			rtw_warn_on(1);
+			continue;
+		}
+
+		adapter = dvobj->padapters[i];
+
+		if (adapter == NULL)
+			continue;
+
+		rtw_os_ndev_free(adapter);
+	}
+
+#if defined(CONFIG_IOCTL_CFG80211)
+	rtw_cfg80211_dev_res_free(dvobj);
+#endif
+}
+
+u32 rtw_start_drv_threads(_adapter *padapter)
+{
+	u32 _status = _SUCCESS;
+
+
+#ifdef CONFIG_XMIT_THREAD_MODE
+	padapter->xmitThread = kthread_run(rtw_xmit_thread, padapter, "RTW_XMIT_THREAD");
+	if (IS_ERR(padapter->xmitThread))
+		_status = _FAIL;
+#endif /* #ifdef CONFIG_XMIT_THREAD_MODE */
+
+#ifdef CONFIG_RECV_THREAD_MODE
+	if (is_primary_adapter(padapter)) {
+		padapter->recvThread = kthread_run(rtw_recv_thread, padapter, "RTW_RECV_THREAD");
+		if (IS_ERR(padapter->recvThread))
+			_status = _FAIL;
+	}
+#endif
+
+	if (is_primary_adapter(padapter)) {
+		padapter->cmdThread = kthread_run(rtw_cmd_thread, padapter, "RTW_CMD_THREAD");
+		if (IS_ERR(padapter->cmdThread))
+			_status = _FAIL;
+		else
+			_rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); /* wait for cmd_thread to run */
+	}
+
+
+#ifdef CONFIG_EVENT_THREAD_MODE
+	padapter->evtThread = kthread_run(event_thread, padapter, "RTW_EVENT_THREAD");
+	if (IS_ERR(padapter->evtThread))
+		_status = _FAIL;
+#endif
+
+	rtw_hal_start_thread(padapter);
+	return _status;
+
+}
+
+void rtw_stop_drv_threads(_adapter *padapter)
+{
+
+	if (is_primary_adapter(padapter))
+		rtw_stop_cmd_thread(padapter);
+
+#ifdef CONFIG_EVENT_THREAD_MODE
+	up(&padapter->evtpriv.evt_notify);
+	if (padapter->evtThread)
+		_rtw_down_sema(&padapter->evtpriv.terminate_evtthread_sema);
+#endif
+
+#ifdef CONFIG_XMIT_THREAD_MODE
+	/* Below is to termindate tx_thread... */
+	up(&padapter->xmitpriv.xmit_sema);
+	_rtw_down_sema(&padapter->xmitpriv.terminate_xmitthread_sema);
+#endif
+
+#ifdef CONFIG_RECV_THREAD_MODE
+	if (is_primary_adapter(padapter)) {
+		/* Below is to termindate rx_thread... */
+		up(&padapter->recvpriv.recv_sema);
+		_rtw_down_sema(&padapter->recvpriv.terminate_recvthread_sema);
+	}
+#endif
+
+	rtw_hal_stop_thread(padapter);
+}
+
+u8 rtw_init_default_value(_adapter *padapter);
+u8 rtw_init_default_value(_adapter *padapter)
+{
+	u8 ret  = _SUCCESS;
+	struct registry_priv *pregistrypriv = &padapter->registrypriv;
+	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+	/* xmit_priv */
+	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;
+
+	/* security_priv */
+	/* rtw_get_encrypt_decrypt_from_registrypriv(padapter); */
+	psecuritypriv->binstallGrpkey = _FAIL;
+#ifdef CONFIG_GTK_OL
+	psecuritypriv->binstallKCK_KEK = _FAIL;
+#endif /* CONFIG_GTK_OL */
+	psecuritypriv->sw_encrypt = pregistrypriv->software_encrypt;
+	psecuritypriv->sw_decrypt = pregistrypriv->software_decrypt;
+
+	psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
+	psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+
+	psecuritypriv->dot11PrivacyKeyIndex = 0;
+
+	psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+	psecuritypriv->dot118021XGrpKeyid = 1;
+
+	psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
+	psecuritypriv->ndisencryptstatus = Ndis802_11WEPDisabled;
+#ifdef CONFIG_CONCURRENT_MODE
+	psecuritypriv->dot118021x_bmc_cam_id = INVALID_SEC_MAC_CAM_ID;
+#endif
+
+
+	/* pwrctrl_priv */
+
+
+	/* registry_priv */
+	rtw_init_registrypriv_dev_network(padapter);
+	rtw_update_registrypriv_dev_network(padapter);
+
+
+	/* hal_priv */
+	rtw_hal_def_value_init(padapter);
+
+	/* misc. */
+	RTW_ENABLE_FUNC(padapter, DF_RX_BIT);
+	RTW_ENABLE_FUNC(padapter, DF_TX_BIT);
+	padapter->bLinkInfoDump = 0;
+	padapter->bNotifyChannelChange = false;
+#ifdef CONFIG_P2P
+	padapter->bShowGetP2PState = 1;
+#endif
+
+	/* for debug purpose */
+	padapter->fix_rate = 0xFF;
+	padapter->data_fb = 0;
+	padapter->fix_bw = 0xFF;
+	padapter->power_offset = 0;
+	padapter->rsvd_page_offset = 0;
+	padapter->rsvd_page_num = 0;
+
+	padapter->driver_tx_bw_mode = pregistrypriv->tx_bw_mode;
+
+	padapter->driver_ampdu_spacing = 0xFF;
+	padapter->driver_rx_ampdu_factor =  0xFF;
+	padapter->driver_rx_ampdu_spacing = 0xFF;
+	padapter->fix_rx_ampdu_accept = RX_AMPDU_ACCEPT_INVALID;
+	padapter->fix_rx_ampdu_size = RX_AMPDU_SIZE_INVALID;
+#ifdef CONFIG_TX_AMSDU
+	padapter->tx_amsdu = 2;
+	padapter->tx_amsdu_rate = 400;
+#endif
+#ifdef DBG_RX_COUNTER_DUMP
+	padapter->dump_rx_cnt_mode = 0;
+	padapter->drv_rx_cnt_ok = 0;
+	padapter->drv_rx_cnt_crcerror = 0;
+	padapter->drv_rx_cnt_drop = 0;
+#endif
+#ifdef CONFIG_RTW_NAPI
+	padapter->napi_state = NAPI_DISABLE;
+#endif
+	padapter->tsf.sync_port =  MAX_HW_PORT;
+	padapter->tsf.offset = 0;
+
+	return ret;
+}
+
+#ifdef CONFIG_SWTIMER_BASED_TXBCN
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+void _tx_beacon_timer_handler(void *FunctionContext)
+#else
+void _tx_beacon_timer_handler(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	struct dvobj_priv *pdvobj = (struct dvobj_priv *)FunctionContext;
+#else
+	struct dvobj_priv *pdvobj = from_timer(pdvobj, t, txbcn_timer);
+#endif
+
+	tx_beacon_timer_handler(pdvobj);
+}
+#endif
+
+struct dvobj_priv *devobj_init(void)
+{
+	struct dvobj_priv *pdvobj = NULL;
+	_adapter *adapter;
+
+	pdvobj = (struct dvobj_priv *)rtw_zmalloc(sizeof(*pdvobj));
+	if (pdvobj == NULL)
+		return NULL;
+
+	_rtw_mutex_init(&pdvobj->hw_init_mutex);
+	_rtw_mutex_init(&pdvobj->h2c_fwcmd_mutex);
+	_rtw_mutex_init(&pdvobj->setch_mutex);
+	_rtw_mutex_init(&pdvobj->setbw_mutex);
+	_rtw_mutex_init(&pdvobj->rf_read_reg_mutex);
+#ifdef CONFIG_SDIO_INDIRECT_ACCESS
+	_rtw_mutex_init(&pdvobj->sd_indirect_access_mutex);
+#endif
+
+#ifdef CONFIG_RTW_CUSTOMER_STR
+	_rtw_mutex_init(&pdvobj->customer_str_mutex);
+	memset(pdvobj->customer_str, 0xFF, RTW_CUSTOMER_STR_LEN);
+#endif
+
+	pdvobj->processing_dev_remove = false;
+
+	ATOMIC_SET(&pdvobj->disable_func, 0);
+
+	rtw_macid_ctl_init(&pdvobj->macid_ctl);
+	spin_lock_init(&pdvobj->cam_ctl.lock);
+	_rtw_mutex_init(&pdvobj->cam_ctl.sec_cam_access_mutex);
+#ifdef CONFIG_MBSSID_CAM
+	rtw_mbid_cam_init(pdvobj);
+#endif
+
+#ifdef CONFIG_AP_MODE
+	pdvobj->nr_ap_if = 0;
+	pdvobj->inter_bcn_space = DEFAULT_BCN_INTERVAL; /* default value is equal to the default beacon_interval (100ms) */
+	_rtw_init_queue(&pdvobj->ap_if_q);
+#ifdef CONFIG_SWTIMER_BASED_TXBCN
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_init_timer(&pdvobj->txbcn_timer, NULL, _tx_beacon_timer_handler, pdvobj);
+#else
+	timer_setup(&pdvobj->txbcn_timer, _tx_beacon_timer_handler, 0);
+#endif
+#endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_init_timer(&pdvobj->dynamic_chk_timer, NULL, _dynamic_check_timer_handler, pdvobj);
+#else
+	timer_setup(&pdvobj->dynamic_chk_timer, _dynamic_check_timer_handler, 0);
+#endif
+
+#ifdef CONFIG_MCC_MODE
+	_rtw_mutex_init(&(pdvobj->mcc_objpriv.mcc_mutex));
+	spin_lock_init(&pdvobj->mcc_objpriv.mcc_lock);
+#endif /* CONFIG_MCC_MODE */
+
+	return pdvobj;
+
+}
+
+void devobj_deinit(struct dvobj_priv *pdvobj)
+{
+	if (!pdvobj)
+		return;
+
+	/* TODO: use rtw_os_ndevs_deinit instead at the first stage of driver's dev deinit function */
+#if defined(CONFIG_IOCTL_CFG80211)
+	rtw_cfg80211_dev_res_free(pdvobj);
+#endif
+
+#ifdef CONFIG_MCC_MODE
+	_rtw_mutex_free(&(pdvobj->mcc_objpriv.mcc_mutex));
+#endif /* CONFIG_MCC_MODE */
+
+	_rtw_mutex_free(&pdvobj->hw_init_mutex);
+	_rtw_mutex_free(&pdvobj->h2c_fwcmd_mutex);
+
+#ifdef CONFIG_RTW_CUSTOMER_STR
+	_rtw_mutex_free(&pdvobj->customer_str_mutex);
+#endif
+
+	_rtw_mutex_free(&pdvobj->setch_mutex);
+	_rtw_mutex_free(&pdvobj->setbw_mutex);
+	_rtw_mutex_free(&pdvobj->rf_read_reg_mutex);
+#ifdef CONFIG_SDIO_INDIRECT_ACCESS
+	_rtw_mutex_free(&pdvobj->sd_indirect_access_mutex);
+#endif
+
+	rtw_macid_ctl_deinit(&pdvobj->macid_ctl);
+	_rtw_mutex_free(&pdvobj->cam_ctl.sec_cam_access_mutex);
+
+#ifdef CONFIG_MBSSID_CAM
+	rtw_mbid_cam_deinit(pdvobj);
+#endif
+
+	rtw_mfree((u8 *)pdvobj, sizeof(*pdvobj));
+}
+
+inline u8 rtw_rtnl_lock_needed(struct dvobj_priv *dvobj)
+{
+	if (dvobj->rtnl_lock_holder && dvobj->rtnl_lock_holder == current)
+		return 0;
+	return 1;
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
+static inline int rtnl_is_locked(void)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17))
+	if (unlikely(rtnl_trylock())) {
+		rtnl_unlock();
+#else
+	if (unlikely(down_trylock(&rtnl_sem) == 0)) {
+		up(&rtnl_sem);
+#endif
+		return 0;
+	}
+	return 1;
+}
+#endif
+
+inline void rtw_set_rtnl_lock_holder(struct dvobj_priv *dvobj, _thread_hdl_ thd_hdl)
+{
+	rtw_warn_on(!rtnl_is_locked());
+
+	if (!thd_hdl || rtnl_is_locked())
+		dvobj->rtnl_lock_holder = thd_hdl;
+
+	if (dvobj->rtnl_lock_holder && 0)
+		RTW_INFO("rtnl_lock_holder: %s:%d\n", current->comm, current->pid);
+}
+
+u8 rtw_reset_drv_sw(_adapter *padapter)
+{
+	u8	ret8 = _SUCCESS;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
+
+	/* hal_priv */
+	if (is_primary_adapter(padapter))
+		rtw_hal_def_value_init(padapter);
+
+	RTW_ENABLE_FUNC(padapter, DF_RX_BIT);
+	RTW_ENABLE_FUNC(padapter, DF_TX_BIT);
+
+	padapter->tsf.sync_port =  MAX_HW_PORT;
+	padapter->tsf.offset = 0;
+
+	padapter->bLinkInfoDump = 0;
+
+	padapter->xmitpriv.tx_pkts = 0;
+	padapter->recvpriv.rx_pkts = 0;
+
+	pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
+
+	/* pmlmepriv->LinkDetectInfo.TrafficBusyState = false; */
+	pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
+	pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
+
+	_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING);
+
+#ifdef CONFIG_AUTOSUSPEND
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34))
+	adapter_to_dvobj(padapter)->pusbdev->autosuspend_disabled = 1;/* autosuspend disabled by the user */
+#endif
+#endif
+
+#ifdef DBG_CONFIG_ERROR_DETECT
+	if (is_primary_adapter(padapter))
+		rtw_hal_sreset_reset_value(padapter);
+#endif
+	pwrctrlpriv->pwr_state_check_cnts = 0;
+
+	/* mlmeextpriv */
+	mlmeext_set_scan_state(&padapter->mlmeextpriv, SCAN_DISABLE);
+
+#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+	rtw_set_signal_stat_timer(&padapter->recvpriv);
+#endif
+
+	return ret8;
+}
+
+
+u8 rtw_init_drv_sw(_adapter *padapter)
+{
+	u8	ret8 = _SUCCESS;
+
+	INIT_LIST_HEAD(&padapter->list);
+	ret8 = rtw_init_default_value(padapter);
+
+	if ((rtw_init_cmd_priv(&padapter->cmdpriv)) == _FAIL) {
+		ret8 = _FAIL;
+		goto exit;
+	}
+
+	padapter->cmdpriv.padapter = padapter;
+
+	if ((rtw_init_evt_priv(&padapter->evtpriv)) == _FAIL) {
+		ret8 = _FAIL;
+		goto exit;
+	}
+
+	rtw_rfctl_init(padapter);
+
+	if (rtw_init_mlme_priv(padapter) == _FAIL) {
+		ret8 = _FAIL;
+		goto exit;
+	}
+
+#ifdef CONFIG_P2P
+	rtw_init_wifidirect_timers(padapter);
+	init_wifidirect_info(padapter, P2P_ROLE_DISABLE);
+	reset_global_wifidirect_info(padapter);
+	#ifdef CONFIG_IOCTL_CFG80211
+	rtw_init_cfg80211_wifidirect_info(padapter);
+	#endif
+#ifdef CONFIG_WFD
+	if (rtw_init_wifi_display_info(padapter) == _FAIL)
+		RTW_ERR("Can't init init_wifi_display_info\n");
+#endif
+#endif /* CONFIG_P2P */
+
+	if (init_mlme_ext_priv(padapter) == _FAIL) {
+		ret8 = _FAIL;
+		goto exit;
+	}
+
+#ifdef CONFIG_TDLS
+	if (rtw_init_tdls_info(padapter) == _FAIL) {
+		RTW_INFO("Can't rtw_init_tdls_info\n");
+		ret8 = _FAIL;
+		goto exit;
+	}
+#endif /* CONFIG_TDLS */
+
+	if (_rtw_init_xmit_priv(&padapter->xmitpriv, padapter) == _FAIL) {
+		RTW_INFO("Can't _rtw_init_xmit_priv\n");
+		ret8 = _FAIL;
+		goto exit;
+	}
+
+	if (_rtw_init_recv_priv(&padapter->recvpriv, padapter) == _FAIL) {
+		RTW_INFO("Can't _rtw_init_recv_priv\n");
+		ret8 = _FAIL;
+		goto exit;
+	}
+	/* add for CONFIG_IEEE80211W, none 11w also can use */
+	spin_lock_init(&padapter->security_key_mutex);
+
+	/* We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc(). */
+	/* memset((unsigned char *)&padapter->securitypriv, 0, sizeof (struct security_priv)); */
+
+	/* _init_timer(&(padapter->securitypriv.tkip_timer), padapter->pifp, rtw_use_tkipkey_handler, padapter); */
+
+	if (_rtw_init_sta_priv(&padapter->stapriv) == _FAIL) {
+		RTW_INFO("Can't _rtw_init_sta_priv\n");
+		ret8 = _FAIL;
+		goto exit;
+	}
+
+	padapter->stapriv.padapter = padapter;
+	padapter->setband = WIFI_FREQUENCY_BAND_AUTO;
+	padapter->fix_rate = 0xFF;
+	padapter->power_offset = 0;
+	padapter->rsvd_page_offset = 0;
+	padapter->rsvd_page_num = 0;
+
+	padapter->data_fb = 0;
+	padapter->fix_rx_ampdu_accept = RX_AMPDU_ACCEPT_INVALID;
+	padapter->fix_rx_ampdu_size = RX_AMPDU_SIZE_INVALID;
+#ifdef DBG_RX_COUNTER_DUMP
+	padapter->dump_rx_cnt_mode = 0;
+	padapter->drv_rx_cnt_ok = 0;
+	padapter->drv_rx_cnt_crcerror = 0;
+	padapter->drv_rx_cnt_drop = 0;
+#endif
+	rtw_init_bcmc_stainfo(padapter);
+
+	rtw_init_pwrctrl_priv(padapter);
+
+	/* memset((u8 *)&padapter->qospriv, 0, sizeof (struct qos_priv)); */ /* move to mlme_priv */
+
+#ifdef CONFIG_MP_INCLUDED
+	if (init_mp_priv(padapter) == _FAIL)
+		RTW_INFO("%s: initialize MP private data Fail!\n", __func__);
+#endif
+
+	rtw_hal_dm_init(padapter);
+#ifdef CONFIG_SW_LED
+	rtw_hal_sw_led_init(padapter);
+#endif
+#ifdef DBG_CONFIG_ERROR_DETECT
+	rtw_hal_sreset_init(padapter);
+#endif
+
+#ifdef CONFIG_INTEL_WIDI
+	if (rtw_init_intel_widi(padapter) == _FAIL) {
+		RTW_INFO("Can't rtw_init_intel_widi\n");
+		ret8 = _FAIL;
+		goto exit;
+	}
+#endif /* CONFIG_INTEL_WIDI */
+
+#ifdef CONFIG_WAPI_SUPPORT
+	padapter->WapiSupport = true; /* set true temp, will revise according to Efuse or Registry value later. */
+	rtw_wapi_init(padapter);
+#endif
+
+#ifdef CONFIG_BR_EXT
+	spin_lock_init(&padapter->br_ext_lock);
+#endif /* CONFIG_BR_EXT */
+
+#ifdef CONFIG_BEAMFORMING
+#ifdef RTW_BEAMFORMING_VERSION_2
+	rtw_bf_init(padapter);
+#endif /* RTW_BEAMFORMING_VERSION_2 */
+#endif /* CONFIG_BEAMFORMING */
+
+exit:
+
+
+
+	return ret8;
+
+}
+
+#ifdef CONFIG_WOWLAN
+void rtw_cancel_dynamic_chk_timer(_adapter *padapter)
+{
+	_cancel_timer_ex(&adapter_to_dvobj(padapter)->dynamic_chk_timer);
+}
+#endif
+
+void rtw_cancel_all_timer(_adapter *padapter)
+{
+
+	_cancel_timer_ex(&padapter->mlmepriv.assoc_timer);
+
+	_cancel_timer_ex(&padapter->mlmepriv.scan_to_timer);
+
+#ifdef CONFIG_DFS_MASTER
+	_cancel_timer_ex(&padapter->mlmepriv.dfs_master_timer);
+#endif
+
+	_cancel_timer_ex(&adapter_to_dvobj(padapter)->dynamic_chk_timer);
+
+	/* cancel sw led timer */
+	rtw_hal_sw_led_deinit(padapter);
+
+	_cancel_timer_ex(&(adapter_to_pwrctl(padapter)->pwr_state_check_timer));
+
+#ifdef CONFIG_TX_AMSDU
+	_cancel_timer_ex(&padapter->xmitpriv.amsdu_bk_timer);
+	_cancel_timer_ex(&padapter->xmitpriv.amsdu_be_timer);
+	_cancel_timer_ex(&padapter->xmitpriv.amsdu_vo_timer);
+	_cancel_timer_ex(&padapter->xmitpriv.amsdu_vi_timer);
+#endif
+
+#ifdef CONFIG_IOCTL_CFG80211
+#ifdef CONFIG_P2P
+	_cancel_timer_ex(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
+#endif /* CONFIG_P2P */
+#endif /* CONFIG_IOCTL_CFG80211 */
+
+#ifdef CONFIG_SET_SCAN_DENY_TIMER
+	_cancel_timer_ex(&padapter->mlmepriv.set_scan_deny_timer);
+	rtw_clear_scan_deny(padapter);
+#endif
+
+#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+	_cancel_timer_ex(&padapter->recvpriv.signal_stat_timer);
+#endif
+
+#ifdef CONFIG_LPS_RPWM_TIMER
+	_cancel_timer_ex(&(adapter_to_pwrctl(padapter)->pwr_rpwm_timer));
+#endif /* CONFIG_LPS_RPWM_TIMER */
+
+	/* cancel dm timer */
+	rtw_hal_dm_deinit(padapter);
+
+#ifdef CONFIG_PLATFORM_FS_MX61
+	msleep(50);
+#endif
+}
+
+u8 rtw_free_drv_sw(_adapter *padapter)
+{
+
+#ifdef CONFIG_WAPI_SUPPORT
+	rtw_wapi_free(padapter);
+#endif
+
+	/* we can call rtw_p2p_enable here, but: */
+	/* 1. rtw_p2p_enable may have IO operation */
+	/* 2. rtw_p2p_enable is bundled with wext interface */
+	#ifdef CONFIG_P2P
+	{
+		struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+		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);
+			#ifdef CONFIG_CONCURRENT_MODE
+			_cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);
+			#endif /* CONFIG_CONCURRENT_MODE */
+			rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
+		}
+	}
+	#endif
+
+#ifdef CONFIG_INTEL_WIDI
+	rtw_free_intel_widi(padapter);
+#endif /* CONFIG_INTEL_WIDI */
+
+	free_mlme_ext_priv(&padapter->mlmeextpriv);
+
+#ifdef CONFIG_TDLS
+	/* rtw_free_tdls_info(&padapter->tdlsinfo); */
+#endif /* CONFIG_TDLS */
+
+	rtw_free_cmd_priv(&padapter->cmdpriv);
+
+	rtw_free_evt_priv(&padapter->evtpriv);
+
+	rtw_free_mlme_priv(&padapter->mlmepriv);
+
+	/* free_io_queue(padapter); */
+
+	_rtw_free_xmit_priv(&padapter->xmitpriv);
+
+	_rtw_free_sta_priv(&padapter->stapriv); /* will free bcmc_stainfo here */
+
+	_rtw_free_recv_priv(&padapter->recvpriv);
+
+	rtw_free_pwrctrl_priv(padapter);
+
+	/* rtw_mfree((void *)padapter, sizeof (padapter)); */
+
+#ifdef CONFIG_DRVEXT_MODULE
+	free_drvext(&padapter->drvextpriv);
+#endif
+
+	rtw_hal_free_data(padapter);
+
+
+	/* free the old_pnetdev */
+	if (padapter->rereg_nd_name_priv.old_pnetdev) {
+		free_netdev(padapter->rereg_nd_name_priv.old_pnetdev);
+		padapter->rereg_nd_name_priv.old_pnetdev = NULL;
+	}
+
+	return _SUCCESS;
+
+}
+void rtw_intf_start(_adapter *adapter)
+{
+	if (adapter->intf_start)
+		adapter->intf_start(adapter);
+}
+void rtw_intf_stop(_adapter *adapter)
+{
+	if (adapter->intf_stop)
+		adapter->intf_stop(adapter);
+}
+
+#ifdef CONFIG_CONCURRENT_MODE
+int _netdev_vir_if_open(struct net_device *pnetdev)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+	_adapter *primary_padapter = GET_PRIMARY_ADAPTER(padapter);
+
+	RTW_INFO(FUNC_NDEV_FMT" , bup=%d\n", FUNC_NDEV_ARG(pnetdev), padapter->bup);
+
+	if (!primary_padapter)
+		goto _netdev_virtual_iface_open_error;
+
+#ifdef CONFIG_PLATFORM_INTEL_BYT
+	if (padapter->bup == false) {
+		u8 mac[ETH_ALEN];
+
+		/* get mac address from primary_padapter */
+		if (primary_padapter->bup == false)
+			rtw_macaddr_cfg(adapter_mac_addr(primary_padapter), get_hal_mac_addr(primary_padapter));
+
+		memcpy(mac, adapter_mac_addr(primary_padapter), ETH_ALEN);
+
+		/*
+		* If the BIT1 is 0, the address is universally administered.
+		* If it is 1, the address is locally administered
+		*/
+		mac[0] |= BIT(1);
+
+		memcpy(adapter_mac_addr(padapter), mac, ETH_ALEN);
+
+#ifdef CONFIG_MI_WITH_MBSSID_CAM
+		rtw_mbid_camid_alloc(padapter, adapter_mac_addr(padapter));
+#endif
+		rtw_init_wifidirect_addrs(padapter, adapter_mac_addr(padapter), adapter_mac_addr(padapter));
+		memcpy(pnetdev->dev_addr, adapter_mac_addr(padapter), ETH_ALEN);
+	}
+#endif /*CONFIG_PLATFORM_INTEL_BYT*/
+
+	if (primary_padapter->bup == false || !rtw_is_hw_init_completed(primary_padapter))
+		_netdev_open(primary_padapter->pnetdev);
+
+	if (padapter->bup == false && primary_padapter->bup == true &&
+	    rtw_is_hw_init_completed(primary_padapter)) {
+		padapter->bFWReady = primary_padapter->bFWReady;
+	}
+
+	if (padapter->bup == false) {
+		if (rtw_start_drv_threads(padapter) == _FAIL)
+			goto _netdev_virtual_iface_open_error;
+	}
+
+#ifdef CONFIG_RTW_NAPI
+	if (padapter->napi_state == NAPI_DISABLE) {
+		napi_enable(&padapter->napi);
+		padapter->napi_state = NAPI_ENABLE;
+	}
+#endif
+
+#ifdef CONFIG_IOCTL_CFG80211
+	rtw_cfg80211_init_wiphy(padapter);
+	rtw_cfg80211_init_wdev_data(padapter);
+#endif
+
+	padapter->bup = true;
+
+	padapter->net_closed = false;
+
+	rtw_netif_wake_queue(pnetdev);
+
+	RTW_INFO(FUNC_NDEV_FMT" (bup=%d) exit\n", FUNC_NDEV_ARG(pnetdev), padapter->bup);
+
+	return 0;
+
+_netdev_virtual_iface_open_error:
+
+	padapter->bup = false;
+
+#ifdef CONFIG_RTW_NAPI
+	if(padapter->napi_state == NAPI_ENABLE) {
+		napi_disable(&padapter->napi);
+		padapter->napi_state = NAPI_DISABLE;
+	}
+#endif
+
+	netif_carrier_off(pnetdev);
+	rtw_netif_stop_queue(pnetdev);
+
+	return -1;
+
+}
+
+int netdev_vir_if_open(struct net_device *pnetdev)
+{
+	int ret;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+
+	_enter_critical_mutex(&(adapter_to_dvobj(padapter)->hw_init_mutex), NULL);
+	ret = _netdev_vir_if_open(pnetdev);
+	_exit_critical_mutex(&(adapter_to_dvobj(padapter)->hw_init_mutex), NULL);
+
+#ifdef CONFIG_AUTO_AP_MODE
+	/* if(padapter->iface_id == 2) */
+	/*	rtw_start_auto_ap(padapter); */
+#endif
+
+	return ret;
+}
+
+static int netdev_vir_if_close(struct net_device *pnetdev)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+
+	RTW_INFO(FUNC_NDEV_FMT" , bup=%d\n", FUNC_NDEV_ARG(pnetdev), padapter->bup);
+	padapter->net_closed = true;
+	pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
+
+	if (pnetdev)
+		rtw_netif_stop_queue(pnetdev);
+
+#ifdef CONFIG_P2P
+	if (!rtw_p2p_chk_role(&padapter->wdinfo, P2P_ROLE_DISABLE))
+		rtw_p2p_enable(padapter, P2P_ROLE_DISABLE);
+#endif
+
+#ifdef CONFIG_IOCTL_CFG80211
+	rtw_scan_abort(padapter);
+	rtw_cfg80211_wait_scan_req_empty(padapter, 200);
+	adapter_wdev_data(padapter)->bandroid_scan = false;
+#endif
+
+	return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+static const struct net_device_ops rtw_netdev_vir_if_ops = {
+	.ndo_init = rtw_ndev_init,
+	.ndo_uninit = rtw_ndev_uninit,
+	.ndo_open = netdev_vir_if_open,
+	.ndo_stop = netdev_vir_if_close,
+	.ndo_start_xmit = rtw_xmit_entry,
+	.ndo_set_mac_address = rtw_net_set_mac_address,
+	.ndo_get_stats = rtw_net_get_stats,
+	.ndo_do_ioctl = rtw_ioctl,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	.ndo_select_queue	= rtw_select_queue,
+#endif
+};
+#endif
+
+static void rtw_hook_vir_if_ops(struct net_device *ndev)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+	ndev->netdev_ops = &rtw_netdev_vir_if_ops;
+#else
+	ndev->init = rtw_ndev_init;
+	ndev->uninit = rtw_ndev_uninit;
+	ndev->open = netdev_vir_if_open;
+	ndev->stop = netdev_vir_if_close;
+	ndev->set_mac_address = rtw_net_set_mac_address;
+#endif
+}
+_adapter *rtw_drv_add_vir_if(_adapter *primary_padapter,
+	void (*set_intf_ops)(_adapter *primary_padapter, struct _io_ops *pops))
+{
+	int res = _FAIL;
+	_adapter *padapter = NULL;
+	struct dvobj_priv *pdvobjpriv;
+	u8 mac[ETH_ALEN];
+
+	/****** init adapter ******/
+	padapter = (_adapter *)rtw_zvmalloc(sizeof(*padapter));
+	if (padapter == NULL)
+		goto exit;
+
+	if (loadparam(padapter) != _SUCCESS)
+		goto free_adapter;
+
+	memcpy(padapter, primary_padapter, sizeof(_adapter));
+
+	/*  */
+	padapter->bup = false;
+	padapter->net_closed = true;
+	padapter->dir_dev = NULL;
+	padapter->dir_odm = NULL;
+
+	/*set adapter_type/iface type*/
+	padapter->isprimary = false;
+	padapter->adapter_type = VIRTUAL_ADAPTER;
+
+#ifdef CONFIG_MI_WITH_MBSSID_CAM
+	padapter->hw_port = HW_PORT0;
+#else
+	padapter->hw_port = HW_PORT1;
+#endif
+
+
+	/****** hook vir if into dvobj ******/
+	pdvobjpriv = adapter_to_dvobj(padapter);
+	padapter->iface_id = pdvobjpriv->iface_nums;
+	pdvobjpriv->padapters[pdvobjpriv->iface_nums++] = padapter;
+
+	padapter->intf_start = primary_padapter->intf_start;
+	padapter->intf_stop = primary_padapter->intf_stop;
+
+	/* step init_io_priv */
+	if ((rtw_init_io_priv(padapter, set_intf_ops)) == _FAIL) {
+		goto free_adapter;
+	}
+
+	/*init drv data*/
+	if (rtw_init_drv_sw(padapter) != _SUCCESS)
+		goto free_drv_sw;
+
+
+	/*get mac address from primary_padapter*/
+	memcpy(mac, adapter_mac_addr(primary_padapter), ETH_ALEN);
+
+	/*
+	* If the BIT1 is 0, the address is universally administered.
+	* If it is 1, the address is locally administered
+	*/
+	mac[0] |= BIT(1);
+	if (padapter->iface_id > IFACE_ID1)
+		mac[4] ^= BIT(padapter->iface_id);
+
+	memcpy(adapter_mac_addr(padapter), mac, ETH_ALEN);
+	/* update mac-address to mbsid-cam cache*/
+#ifdef CONFIG_MI_WITH_MBSSID_CAM
+	rtw_mbid_camid_alloc(padapter, adapter_mac_addr(padapter));
+#endif
+	RTW_INFO("%s if%d mac_addr : "MAC_FMT"\n", __func__, padapter->iface_id + 1, MAC_ARG(adapter_mac_addr(padapter)));
+#ifdef CONFIG_P2P
+	rtw_init_wifidirect_addrs(padapter, adapter_mac_addr(padapter), adapter_mac_addr(padapter));
+#endif
+	res = _SUCCESS;
+
+free_drv_sw:
+	if (res != _SUCCESS && padapter)
+		rtw_free_drv_sw(padapter);
+free_adapter:
+	if (res != _SUCCESS && padapter) {
+		rtw_vmfree((u8 *)padapter, sizeof(*padapter));
+		padapter = NULL;
+	}
+exit:
+	return padapter;
+}
+
+void rtw_drv_stop_vir_if(_adapter *padapter)
+{
+	struct net_device *pnetdev = NULL;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+	if (padapter == NULL)
+		return;
+
+	pnetdev = padapter->pnetdev;
+
+	if (check_fwstate(pmlmepriv, _FW_LINKED))
+		rtw_disassoc_cmd(padapter, 0, false);
+
+#ifdef CONFIG_AP_MODE
+	if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true) {
+		free_mlme_ap_info(padapter);
+		#ifdef CONFIG_HOSTAPD_MLME
+		hostapd_mode_unload(padapter);
+		#endif
+	}
+#endif
+
+	if (padapter->bup == true) {
+		#ifdef CONFIG_XMIT_ACK
+		if (padapter->xmitpriv.ack_tx)
+			rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_DRV_STOP);
+		#endif
+
+		rtw_intf_stop(padapter);
+
+		rtw_stop_drv_threads(padapter);
+
+		padapter->bup = false;
+	}
+	/* cancel timer after thread stop */
+	rtw_cancel_all_timer(padapter);
+}
+
+void rtw_drv_free_vir_if(_adapter *padapter)
+{
+	if (padapter == NULL)
+		return;
+
+	RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+	rtw_free_drv_sw(padapter);
+
+	/* TODO: use rtw_os_ndevs_deinit instead at the first stage of driver's dev deinit function */
+	rtw_os_ndev_free(padapter);
+
+	rtw_vmfree((u8 *)padapter, sizeof(_adapter));
+}
+
+
+void rtw_drv_stop_vir_ifaces(struct dvobj_priv *dvobj)
+{
+	int i;
+
+	for (i = VIF_START_ID; i < dvobj->iface_nums; i++)
+		rtw_drv_stop_vir_if(dvobj->padapters[i]);
+}
+
+void rtw_drv_free_vir_ifaces(struct dvobj_priv *dvobj)
+{
+	int i;
+
+	for (i = VIF_START_ID; i < dvobj->iface_nums; i++)
+		rtw_drv_free_vir_if(dvobj->padapters[i]);
+}
+
+void rtw_drv_del_vir_if(_adapter *padapter)
+{
+	rtw_drv_stop_vir_if(padapter);
+	rtw_drv_free_vir_if(padapter);
+}
+
+void rtw_drv_del_vir_ifaces(_adapter *primary_padapter)
+{
+	int i;
+	struct dvobj_priv *dvobj = primary_padapter->dvobj;
+
+	for (i = VIF_START_ID; i < dvobj->iface_nums; i++)
+		rtw_drv_del_vir_if(dvobj->padapters[i]);
+
+}
+
+#endif /*end of CONFIG_CONCURRENT_MODE*/
+
+static int rtw_os_ndevs_register(struct dvobj_priv *dvobj)
+{
+	int i, status = _SUCCESS;
+	struct registry_priv *regsty = dvobj_to_regsty(dvobj);
+	_adapter *adapter;
+
+#if defined(CONFIG_IOCTL_CFG80211)
+	if (rtw_cfg80211_dev_res_register(dvobj) != _SUCCESS) {
+		rtw_warn_on(1);
+		status = _FAIL;
+		goto exit;
+	}
+#endif
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+
+		if (i >= CONFIG_IFACE_NUMBER) {
+			RTW_ERR("%s %d >= CONFIG_IFACE_NUMBER(%d)\n", __func__, i, CONFIG_IFACE_NUMBER);
+			rtw_warn_on(1);
+			continue;
+		}
+
+		adapter = dvobj->padapters[i];
+		if (adapter) {
+			char *name;
+
+			#ifdef CONFIG_RTW_DYNAMIC_NDEV
+			if (!is_primary_adapter(adapter))
+				continue;
+			#endif
+
+			if (adapter->iface_id == IFACE_ID0)
+				name = regsty->ifname;
+			else if (adapter->iface_id == IFACE_ID1)
+				name = regsty->if2name;
+			else
+				name = "wlan%d";
+
+			status = rtw_os_ndev_register(adapter, name);
+
+			if (status != _SUCCESS) {
+				rtw_warn_on(1);
+				break;
+			}
+		}
+	}
+
+	if (status != _SUCCESS) {
+		for (; i >= 0; i--) {
+			adapter = dvobj->padapters[i];
+			if (adapter)
+				rtw_os_ndev_unregister(adapter);
+		}
+	}
+
+#if defined(CONFIG_IOCTL_CFG80211)
+	if (status != _SUCCESS)
+		rtw_cfg80211_dev_res_unregister(dvobj);
+#endif
+exit:
+	return status;
+}
+
+void rtw_os_ndevs_unregister(struct dvobj_priv *dvobj)
+{
+	int i;
+	_adapter *adapter = NULL;
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		adapter = dvobj->padapters[i];
+
+		if (adapter == NULL)
+			continue;
+
+		rtw_os_ndev_unregister(adapter);
+	}
+
+#if defined(CONFIG_IOCTL_CFG80211)
+	rtw_cfg80211_dev_res_unregister(dvobj);
+#endif
+}
+
+/**
+ * rtw_os_ndevs_init - Allocate and register OS layer net devices and relating structures for @dvobj
+ * @dvobj: the dvobj on which this function applies
+ *
+ * Returns:
+ * _SUCCESS or _FAIL
+ */
+int rtw_os_ndevs_init(struct dvobj_priv *dvobj)
+{
+	int ret = _FAIL;
+
+	if (rtw_os_ndevs_alloc(dvobj) != _SUCCESS)
+		goto exit;
+
+	if (rtw_os_ndevs_register(dvobj) != _SUCCESS)
+		goto os_ndevs_free;
+
+	ret = _SUCCESS;
+
+os_ndevs_free:
+	if (ret != _SUCCESS)
+		rtw_os_ndevs_free(dvobj);
+exit:
+	return ret;
+}
+
+/**
+ * rtw_os_ndevs_deinit - Unregister and free OS layer net devices and relating structures for @dvobj
+ * @dvobj: the dvobj on which this function applies
+ */
+void rtw_os_ndevs_deinit(struct dvobj_priv *dvobj)
+{
+	rtw_os_ndevs_unregister(dvobj);
+	rtw_os_ndevs_free(dvobj);
+}
+
+#ifdef CONFIG_BR_EXT
+void netdev_br_init(struct net_device *netdev)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(netdev);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
+	rcu_read_lock();
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)) */
+
+	/* if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == true) */
+	{
+		/* struct net_bridge	*br = netdev->br_port->br; */ /* ->dev->dev_addr; */
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+		if (netdev->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)) */
+		{
+			struct net_device *br_netdev;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+			br_netdev = dev_get_by_name(CONFIG_BR_EXT_BRNAME);
+#else	/* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) */
+			struct net *devnet = NULL;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
+			devnet = netdev->nd_net;
+#else	/* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)) */
+			devnet = dev_net(netdev);
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)) */
+
+			br_netdev = dev_get_by_name(devnet, CONFIG_BR_EXT_BRNAME);
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) */
+
+			if (br_netdev) {
+				memcpy(adapter->br_mac, br_netdev->dev_addr, ETH_ALEN);
+				dev_put(br_netdev);
+			} else
+				printk("%s()-%d: dev_get_by_name(%s) failed!", __func__, __LINE__, CONFIG_BR_EXT_BRNAME);
+		}
+
+		adapter->ethBrExtInfo.addPPPoETag = 1;
+	}
+
+#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 */
+
+int _netdev_open(struct net_device *pnetdev)
+{
+	uint status;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+	struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
+#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
+	HAL_DATA_TYPE		*pHalData = GET_HAL_DATA(padapter);
+#endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
+
+
+	RTW_INFO(FUNC_NDEV_FMT" , bup=%d\n", FUNC_NDEV_ARG(pnetdev), padapter->bup);
+
+	padapter->netif_up = true;
+
+#ifdef CONFIG_PLATFORM_INTEL_BYT
+	rtw_sdio_set_power(1);
+#endif /* CONFIG_PLATFORM_INTEL_BYT */
+
+	if (pwrctrlpriv->ps_flag == true) {
+		padapter->net_closed = false;
+		goto netdev_open_normal_process;
+	}
+
+	if (padapter->bup == false) {
+#ifdef CONFIG_PLATFORM_INTEL_BYT
+		rtw_macaddr_cfg(adapter_mac_addr(padapter),  get_hal_mac_addr(padapter));
+#ifdef CONFIG_MI_WITH_MBSSID_CAM
+		rtw_mbid_camid_alloc(padapter, adapter_mac_addr(padapter));
+#endif
+		rtw_init_wifidirect_addrs(padapter, adapter_mac_addr(padapter), adapter_mac_addr(padapter));
+		memcpy(pnetdev->dev_addr, adapter_mac_addr(padapter), ETH_ALEN);
+#endif /* CONFIG_PLATFORM_INTEL_BYT */
+
+		rtw_clr_surprise_removed(padapter);
+		rtw_clr_drv_stopped(padapter);
+
+		status = rtw_hal_init(padapter);
+		if (status == _FAIL) {
+			goto netdev_open_error;
+		}
+		RTW_INFO("MAC Address = "MAC_FMT"\n", MAC_ARG(pnetdev->dev_addr));
+
+		status = rtw_start_drv_threads(padapter);
+		if (status == _FAIL) {
+			RTW_INFO("Initialize driver software resource Failed!\n");
+			goto netdev_open_error;
+		}
+
+#ifdef CONFIG_RTW_NAPI
+		if(padapter->napi_state == NAPI_DISABLE) {
+			napi_enable(&padapter->napi);
+			padapter->napi_state = NAPI_ENABLE;
+		}
+#endif
+
+#ifdef CONFIG_DRVEXT_MODULE
+		init_drvext(padapter);
+#endif
+		rtw_intf_start(padapter);
+
+#ifdef CONFIG_IOCTL_CFG80211
+		rtw_cfg80211_init_wiphy(padapter);
+		rtw_cfg80211_init_wdev_data(padapter);
+#endif
+
+		rtw_led_control(padapter, LED_CTL_NO_LINK);
+
+		padapter->bup = true;
+		pwrctrlpriv->bips_processing = false;
+
+#ifdef CONFIG_PLATFORM_INTEL_BYT
+#ifdef CONFIG_BT_COEXIST
+		rtw_btcoex_IpsNotify(padapter, IPS_NONE);
+#endif /* CONFIG_BT_COEXIST */
+#endif /* CONFIG_PLATFORM_INTEL_BYT		 */
+	}
+	padapter->net_closed = false;
+
+	_set_timer(&adapter_to_dvobj(padapter)->dynamic_chk_timer, 2000);
+
+#ifndef CONFIG_IPS_CHECK_IN_WD
+	rtw_set_pwr_state_check_timer(pwrctrlpriv);
+#endif
+
+	/* netif_carrier_on(pnetdev); */ /* call this func when rtw_joinbss_event_callback return success */
+	rtw_netif_wake_queue(pnetdev);
+
+#ifdef CONFIG_BR_EXT
+	netdev_br_init(pnetdev);
+#endif /* CONFIG_BR_EXT */
+
+#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
+	if (is_primary_adapter(padapter) && (pHalData->EEPROMBluetoothCoexist)) {
+		rtw_btcoex_init_socket(padapter);
+		padapter->coex_info.BtMgnt.ExtConfig.HCIExtensionVer = 0x04;
+		rtw_btcoex_SetHciVersion(padapter, 0x04);
+	} else
+		RTW_INFO("CONFIG_BT_COEXIST: VIRTUAL_ADAPTER\n");
+#endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
+
+
+netdev_open_normal_process:
+
+#ifdef CONFIG_CONCURRENT_MODE
+	{
+		_adapter *sec_adapter = adapter_to_dvobj(padapter)->padapters[IFACE_ID1];
+
+		#ifndef CONFIG_RTW_DYNAMIC_NDEV
+		if (sec_adapter && (sec_adapter->bup == false))
+			_netdev_vir_if_open(sec_adapter->pnetdev);
+		#endif
+	}
+#endif
+
+	RTW_INFO("-871x_drv - drv_open, bup=%d\n", padapter->bup);
+
+	return 0;
+
+netdev_open_error:
+
+	padapter->bup = false;
+
+#ifdef CONFIG_RTW_NAPI
+	if(padapter->napi_state == NAPI_ENABLE) {
+		napi_disable(&padapter->napi);
+		padapter->napi_state = NAPI_DISABLE;
+	}
+#endif
+
+	netif_carrier_off(pnetdev);
+	rtw_netif_stop_queue(pnetdev);
+
+	RTW_INFO("-871x_drv - drv_open fail, bup=%d\n", padapter->bup);
+
+	return -1;
+
+}
+
+int netdev_open(struct net_device *pnetdev)
+{
+	int ret = false;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+	struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
+
+	if (pwrctrlpriv->bInSuspend == true) {
+		RTW_INFO(" [WARN] "ADPT_FMT" %s  failed, bInSuspend=%d\n", ADPT_ARG(padapter), __func__, pwrctrlpriv->bInSuspend);
+		return 0;
+	}
+
+	_enter_critical_mutex(&(adapter_to_dvobj(padapter)->hw_init_mutex), NULL);
+	if (is_primary_adapter(padapter))
+		ret = _netdev_open(pnetdev);
+#ifdef CONFIG_CONCURRENT_MODE
+	else
+		ret = _netdev_vir_if_open(pnetdev);
+#endif
+	_exit_critical_mutex(&(adapter_to_dvobj(padapter)->hw_init_mutex), NULL);
+
+
+#ifdef CONFIG_AUTO_AP_MODE
+	if (padapter->iface_id == IFACE_ID2)
+		rtw_start_auto_ap(padapter);
+#endif
+
+	return ret;
+}
+
+#ifdef CONFIG_IPS
+static int  ips_netdrv_open(_adapter *padapter)
+{
+	int status = _SUCCESS;
+	/* struct pwrctrl_priv	*pwrpriv = adapter_to_pwrctl(padapter); */
+
+	padapter->net_closed = false;
+
+	RTW_INFO("===> %s.........\n", __func__);
+
+
+	rtw_clr_drv_stopped(padapter);
+	/* padapter->bup = true; */
+
+	status = rtw_hal_init(padapter);
+	if (status == _FAIL) {
+		goto netdev_open_error;
+	}
+	rtw_intf_start(padapter);
+
+#ifndef CONFIG_IPS_CHECK_IN_WD
+	rtw_set_pwr_state_check_timer(adapter_to_pwrctl(padapter));
+#endif
+	_set_timer(&adapter_to_dvobj(padapter)->dynamic_chk_timer, 2000);
+
+	return _SUCCESS;
+
+netdev_open_error:
+	/* padapter->bup = false; */
+	RTW_INFO("-ips_netdrv_open - drv_open failure, bup=%d\n", padapter->bup);
+
+	return _FAIL;
+}
+
+
+int rtw_ips_pwr_up(_adapter *padapter)
+{
+	int result;
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
+#ifdef DBG_CONFIG_ERROR_DETECT
+	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+#endif/* #ifdef DBG_CONFIG_ERROR_DETECT */
+	u32 start_time = jiffies;
+	RTW_INFO("===>  rtw_ips_pwr_up..............\n");
+
+#if defined(CONFIG_SWLPS_IN_IPS) || defined(CONFIG_FWLPS_IN_IPS)
+#ifdef DBG_CONFIG_ERROR_DETECT
+	if (psrtpriv->silent_reset_inprogress == true)
+#endif/* #ifdef DBG_CONFIG_ERROR_DETECT */
+#endif /* defined(CONFIG_SWLPS_IN_IPS) || defined(CONFIG_FWLPS_IN_IPS) */
+		rtw_reset_drv_sw(padapter);
+
+	result = ips_netdrv_open(padapter);
+
+	rtw_led_control(padapter, LED_CTL_NO_LINK);
+
+	RTW_INFO("<===  rtw_ips_pwr_up.............. in %dms\n", rtw_get_passing_time_ms(start_time));
+	return result;
+
+}
+
+void rtw_ips_pwr_down(_adapter *padapter)
+{
+	u32 start_time = jiffies;
+	RTW_INFO("===> rtw_ips_pwr_down...................\n");
+
+	padapter->net_closed = true;
+
+	rtw_ips_dev_unload(padapter);
+	RTW_INFO("<=== rtw_ips_pwr_down..................... in %dms\n", rtw_get_passing_time_ms(start_time));
+}
+#endif
+void rtw_ips_dev_unload(_adapter *padapter)
+{
+	struct net_device *pnetdev = (struct net_device *)padapter->pnetdev;
+	struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
+#ifdef DBG_CONFIG_ERROR_DETECT
+	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+#endif/* #ifdef DBG_CONFIG_ERROR_DETECT */
+	RTW_INFO("====> %s...\n", __func__);
+
+
+#if defined(CONFIG_SWLPS_IN_IPS) || defined(CONFIG_FWLPS_IN_IPS)
+#ifdef DBG_CONFIG_ERROR_DETECT
+	if (psrtpriv->silent_reset_inprogress == true)
+#endif /* #ifdef DBG_CONFIG_ERROR_DETECT */
+#endif /* defined(CONFIG_SWLPS_IN_IPS) || defined(CONFIG_FWLPS_IN_IPS) */
+	{
+		rtw_hal_set_hwreg(padapter, HW_VAR_FIFO_CLEARN_UP, NULL);
+		rtw_intf_stop(padapter);
+	}
+	if (!rtw_is_surprise_removed(padapter))
+		rtw_hal_deinit(padapter);
+}
+
+int pm_netdev_open(struct net_device *pnetdev, u8 bnormal)
+{
+	int status = 0;
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+
+	if (bnormal) {
+		_enter_critical_mutex(&(adapter_to_dvobj(padapter)->hw_init_mutex), NULL);
+		status = _netdev_open(pnetdev);
+		_exit_critical_mutex(&(adapter_to_dvobj(padapter)->hw_init_mutex), NULL);
+	}
+#ifdef CONFIG_IPS
+	else
+		status = (_SUCCESS == ips_netdrv_open(padapter)) ? (0) : (-1);
+#endif
+
+	return status;
+}
+
+static int netdev_close(struct net_device *pnetdev)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+	struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
+	HAL_DATA_TYPE		*pHalData = GET_HAL_DATA(padapter);
+#endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
+
+	RTW_INFO(FUNC_NDEV_FMT" , bup=%d\n", FUNC_NDEV_ARG(pnetdev), padapter->bup);
+#ifndef CONFIG_PLATFORM_INTEL_BYT
+	if (pwrctl->bInternalAutoSuspend == true) {
+		/* rtw_pwr_wakeup(padapter); */
+		if (pwrctl->rf_pwrstate == rf_off)
+			pwrctl->ps_flag = true;
+	}
+	padapter->net_closed = true;
+	padapter->netif_up = false;
+	pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
+
+	/*	if (!rtw_is_hw_init_completed(padapter)) {
+			RTW_INFO("(1)871x_drv - drv_close, bup=%d, hw_init_completed=%s\n", padapter->bup, rtw_is_hw_init_completed(padapter)?"true":"false");
+
+			rtw_set_drv_stopped(padapter);
+
+			rtw_dev_unload(padapter);
+		}
+		else*/
+	if (pwrctl->rf_pwrstate == rf_on) {
+		RTW_INFO("(2)871x_drv - drv_close, bup=%d, hw_init_completed=%s\n", padapter->bup, rtw_is_hw_init_completed(padapter) ? "true" : "false");
+
+		/* s1. */
+		if (pnetdev)
+			rtw_netif_stop_queue(pnetdev);
+
+#ifndef CONFIG_ANDROID
+		/* s2. */
+		LeaveAllPowerSaveMode(padapter);
+		rtw_disassoc_cmd(padapter, 500, false);
+		/* s2-2.  indicate disconnect to os */
+		rtw_indicate_disconnect(padapter, 0, false);
+		/* s2-3. */
+		rtw_free_assoc_resources(padapter, 1);
+		/* s2-4. */
+		rtw_free_network_queue(padapter, true);
+#endif
+		/* Close LED */
+		rtw_led_control(padapter, LED_CTL_POWER_OFF);
+	}
+
+#ifdef CONFIG_BR_EXT
+	/* if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) */
+	{
+		/* void nat25_db_cleanup(_adapter *priv); */
+		nat25_db_cleanup(padapter);
+	}
+#endif /* CONFIG_BR_EXT */
+
+#ifdef CONFIG_P2P
+	if (!rtw_p2p_chk_role(&padapter->wdinfo, P2P_ROLE_DISABLE))
+		rtw_p2p_enable(padapter, P2P_ROLE_DISABLE);
+#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_IOCTL_CFG80211
+	rtw_scan_abort(padapter);
+	rtw_cfg80211_wait_scan_req_empty(padapter, 200);
+	adapter_wdev_data(padapter)->bandroid_scan = false;
+	/* padapter->rtw_wdev->iftype = NL80211_IFTYPE_MONITOR; */ /* set this at the end */
+#endif /* CONFIG_IOCTL_CFG80211 */
+
+#ifdef CONFIG_WAPI_SUPPORT
+	rtw_wapi_disable_tx(padapter);
+#endif
+#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
+	if (is_primary_adapter(padapter) && (pHalData->EEPROMBluetoothCoexist))
+		rtw_btcoex_close_socket(padapter);
+	else
+		RTW_INFO("CONFIG_BT_COEXIST: VIRTUAL_ADAPTER\n");
+#endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
+#else /* !CONFIG_PLATFORM_INTEL_BYT */
+
+	if (pwrctl->bInSuspend == true) {
+		RTW_INFO("+871x_drv - drv_close, bInSuspend=%d\n", pwrctl->bInSuspend);
+		return 0;
+	}
+
+	rtw_scan_abort(padapter); /* stop scanning process before wifi is going to down */
+#ifdef CONFIG_IOCTL_CFG80211
+	rtw_cfg80211_wait_scan_req_empty(padapter, 200);
+#endif
+
+	RTW_INFO("netdev_close, bips_processing=%d\n", pwrctl->bips_processing);
+	while (pwrctl->bips_processing == true) /* waiting for ips_processing done before call rtw_dev_unload() */
+		rtw_msleep_os(1);
+
+	rtw_dev_unload(padapter);
+	rtw_sdio_set_power(0);
+
+#endif /* !CONFIG_PLATFORM_INTEL_BYT */
+
+	RTW_INFO("-871x_drv - drv_close, bup=%d\n", padapter->bup);
+
+	return 0;
+}
+
+static int pm_netdev_close(struct net_device *pnetdev, u8 bnormal)
+{
+	int status = 0;
+
+	status = netdev_close(pnetdev);
+
+	return status;
+}
+
+void rtw_ndev_destructor(struct net_device *ndev)
+{
+	RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if (ndev->ieee80211_ptr)
+		rtw_mfree((u8 *)ndev->ieee80211_ptr, sizeof(struct wireless_dev));
+#endif
+	free_netdev(ndev);
+}
+
+#ifdef CONFIG_ARP_KEEP_ALIVE
+struct route_info {
+	struct in_addr dst_addr;
+	struct in_addr src_addr;
+	struct in_addr gateway;
+	unsigned int dev_index;
+};
+
+static void parse_routes(struct nlmsghdr *nl_hdr, struct route_info *rt_info)
+{
+	struct rtmsg *rt_msg;
+	struct rtattr *rt_attr;
+	int rt_len;
+
+	rt_msg = (struct rtmsg *) NLMSG_DATA(nl_hdr);
+	if ((rt_msg->rtm_family != AF_INET) || (rt_msg->rtm_table != RT_TABLE_MAIN))
+		return;
+
+	rt_attr = (struct rtattr *) RTM_RTA(rt_msg);
+	rt_len = RTM_PAYLOAD(nl_hdr);
+
+	for (; RTA_OK(rt_attr, rt_len); rt_attr = RTA_NEXT(rt_attr, rt_len)) {
+		switch (rt_attr->rta_type) {
+		case RTA_OIF:
+			rt_info->dev_index = *(int *) RTA_DATA(rt_attr);
+			break;
+		case RTA_GATEWAY:
+			rt_info->gateway.s_addr = *(u_int *) RTA_DATA(rt_attr);
+			break;
+		case RTA_PREFSRC:
+			rt_info->src_addr.s_addr = *(u_int *) RTA_DATA(rt_attr);
+			break;
+		case RTA_DST:
+			rt_info->dst_addr.s_addr = *(u_int *) RTA_DATA(rt_attr);
+			break;
+		}
+	}
+}
+
+static int route_dump(u32 *gw_addr , int *gw_index)
+{
+	int err = 0;
+	struct socket *sock;
+	struct {
+		struct nlmsghdr nlh;
+		struct rtgenmsg g;
+	} req;
+	struct msghdr msg;
+	struct iovec iov;
+	struct sockaddr_nl nladdr;
+	mm_segment_t oldfs;
+	char *pg;
+	int size = 0;
+
+	err = sock_create(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, &sock);
+	if (err) {
+		printk(": Could not create a datagram socket, error = %d\n", -ENXIO);
+		return err;
+	}
+
+	memset(&nladdr, 0, sizeof(nladdr));
+	nladdr.nl_family = AF_NETLINK;
+
+	req.nlh.nlmsg_len = sizeof(req);
+	req.nlh.nlmsg_type = RTM_GETROUTE;
+	req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
+	req.nlh.nlmsg_pid = 0;
+	req.g.rtgen_family = AF_INET;
+
+	iov.iov_base = &req;
+	iov.iov_len = sizeof(req);
+
+	msg.msg_name = &nladdr;
+	msg.msg_namelen = sizeof(nladdr);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
+	/* referece:sock_xmit in kernel code
+	 * WRITE for sock_sendmsg, READ for sock_recvmsg
+	 * third parameter for msg_iovlen
+	 * last parameter for iov_len
+	 */
+	iov_iter_init(&msg.msg_iter, WRITE, &iov, 1, sizeof(req));
+#else
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+#endif
+	msg.msg_control = NULL;
+	msg.msg_controllen = 0;
+	msg.msg_flags = MSG_DONTWAIT;
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
+	err = sock_sendmsg(sock, &msg);
+#else
+	err = sock_sendmsg(sock, &msg, sizeof(req));
+#endif
+	set_fs(oldfs);
+
+	if (err < 0)
+		goto out_sock;
+
+	pg = (char *) __get_free_page(GFP_KERNEL);
+	if (pg == NULL) {
+		err = -ENOMEM;
+		goto out_sock;
+	}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+restart:
+#endif
+
+	for (;;) {
+		struct nlmsghdr *h;
+
+		iov.iov_base = pg;
+		iov.iov_len = PAGE_SIZE;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
+		iov_iter_init(&msg.msg_iter, READ, &iov, 1, PAGE_SIZE);
+#endif
+
+		oldfs = get_fs();
+		set_fs(KERNEL_DS);
+		err = sock_recvmsg(sock, &msg, PAGE_SIZE, MSG_DONTWAIT);
+		set_fs(oldfs);
+
+		if (err < 0)
+			goto out_sock_pg;
+
+		if (msg.msg_flags & MSG_TRUNC) {
+			err = -ENOBUFS;
+			goto out_sock_pg;
+		}
+
+		h = (struct nlmsghdr *) pg;
+
+		while (NLMSG_OK(h, err)) {
+			struct route_info rt_info;
+			if (h->nlmsg_type == NLMSG_DONE) {
+				err = 0;
+				goto done;
+			}
+
+			if (h->nlmsg_type == NLMSG_ERROR) {
+				struct nlmsgerr *errm = (struct nlmsgerr *) NLMSG_DATA(h);
+				err = errm->error;
+				printk("NLMSG error: %d\n", errm->error);
+				goto done;
+			}
+
+			if (h->nlmsg_type == RTM_GETROUTE)
+				printk("RTM_GETROUTE: NLMSG: %d\n", h->nlmsg_type);
+			if (h->nlmsg_type != RTM_NEWROUTE) {
+				printk("NLMSG: %d\n", h->nlmsg_type);
+				err = -EINVAL;
+				goto done;
+			}
+
+			memset(&rt_info, 0, sizeof(struct route_info));
+			parse_routes(h, &rt_info);
+			if (!rt_info.dst_addr.s_addr && rt_info.gateway.s_addr && rt_info.dev_index) {
+				*gw_addr = rt_info.gateway.s_addr;
+				*gw_index = rt_info.dev_index;
+
+			}
+			h = NLMSG_NEXT(h, err);
+		}
+
+		if (err) {
+			printk("!!!Remnant of size %d %d %d\n", err, h->nlmsg_len, h->nlmsg_type);
+			err = -EINVAL;
+			break;
+		}
+	}
+
+done:
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	if (!err && req.g.rtgen_family == AF_INET) {
+		req.g.rtgen_family = AF_INET6;
+
+		iov.iov_base = &req;
+		iov.iov_len = sizeof(req);
+
+		msg.msg_name = &nladdr;
+		msg.msg_namelen = sizeof(nladdr);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
+		iov_iter_init(&msg.msg_iter, WRITE, &iov, 1, sizeof(req));
+#else
+		msg.msg_iov = &iov;
+		msg.msg_iovlen = 1;
+#endif
+		msg.msg_control = NULL;
+		msg.msg_controllen = 0;
+		msg.msg_flags = MSG_DONTWAIT;
+
+		oldfs = get_fs();
+		set_fs(KERNEL_DS);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
+		err = sock_sendmsg(sock, &msg);
+#else
+		err = sock_sendmsg(sock, &msg, sizeof(req));
+#endif
+		set_fs(oldfs);
+
+		if (err > 0)
+			goto restart;
+	}
+#endif
+
+out_sock_pg:
+	free_page((unsigned long) pg);
+
+out_sock:
+	sock_release(sock);
+	return err;
+}
+
+static int arp_query(unsigned char *haddr, u32 paddr,
+		     struct net_device *dev)
+{
+	struct neighbour *neighbor_entry;
+	int	ret = 0;
+
+	neighbor_entry = neigh_lookup(&arp_tbl, &paddr, dev);
+
+	if (neighbor_entry != NULL) {
+		neighbor_entry->used = jiffies;
+		if (neighbor_entry->nud_state & NUD_VALID) {
+			memcpy(haddr, neighbor_entry->ha, dev->addr_len);
+			ret = 1;
+		}
+		neigh_release(neighbor_entry);
+	}
+	return ret;
+}
+
+static int get_defaultgw(u32 *ip_addr , char mac[])
+{
+	int gw_index = 0; /* oif device index */
+	struct net_device *gw_dev = NULL; /* oif device */
+
+	route_dump(ip_addr, &gw_index);
+
+	if (!(*ip_addr) || !gw_index) {
+		/* RTW_INFO("No default GW\n"); */
+		return -1;
+	}
+
+	gw_dev = dev_get_by_index(&init_net, gw_index);
+
+	if (gw_dev == NULL) {
+		/* RTW_INFO("get Oif Device Fail\n"); */
+		return -1;
+	}
+
+	if (!arp_query(mac, *ip_addr, gw_dev)) {
+		/* RTW_INFO( "arp query failed\n"); */
+		dev_put(gw_dev);
+		return -1;
+
+	}
+	dev_put(gw_dev);
+
+	return 0;
+}
+
+int	rtw_gw_addr_query(_adapter *padapter)
+{
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
+	u32 gw_addr = 0; /* default gw address */
+	unsigned char gw_mac[32] = {0}; /* default gw mac */
+	int i;
+	int res;
+
+	res = get_defaultgw(&gw_addr, gw_mac);
+	if (!res) {
+		pmlmepriv->gw_ip[0] = gw_addr & 0xff;
+		pmlmepriv->gw_ip[1] = (gw_addr & 0xff00) >> 8;
+		pmlmepriv->gw_ip[2] = (gw_addr & 0xff0000) >> 16;
+		pmlmepriv->gw_ip[3] = (gw_addr & 0xff000000) >> 24;
+		memcpy(pmlmepriv->gw_mac_addr, gw_mac, 6);
+		RTW_INFO("%s Gateway Mac:\t" MAC_FMT "\n", __func__, MAC_ARG(pmlmepriv->gw_mac_addr));
+		RTW_INFO("%s Gateway IP:\t" IP_FMT "\n", __func__, IP_ARG(pmlmepriv->gw_ip));
+	} else
+		RTW_INFO("Get Gateway IP/MAC fail!\n");
+
+	return res;
+}
+#endif
+
+void rtw_dev_unload(_adapter *padapter)
+{
+	struct net_device *pnetdev = (struct net_device *)padapter->pnetdev;
+	struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
+	struct dvobj_priv *pobjpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &pobjpriv->drv_dbg;
+	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+	u8 cnt = 0;
+
+
+	if (padapter->bup == true) {
+		RTW_INFO("==> "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+
+		rtw_set_drv_stopped(padapter);
+#ifdef CONFIG_XMIT_ACK
+		if (padapter->xmitpriv.ack_tx)
+			rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_DRV_STOP);
+#endif
+
+		rtw_intf_stop(padapter);
+
+
+		if (!pwrctl->bInternalAutoSuspend)
+			rtw_stop_drv_threads(padapter);
+
+		while (ATOMIC_READ(&(pcmdpriv->cmdthd_running)) == true) {
+			if (cnt > 5) {
+				RTW_INFO("stop cmdthd timeout\n");
+				break;
+			} else {
+				cnt++;
+				RTW_INFO("cmdthd is running(%d)\n", cnt);
+				rtw_msleep_os(10);
+			}
+		}
+
+
+		/* check the status of IPS */
+		if (rtw_hal_check_ips_status(padapter) == true || pwrctl->rf_pwrstate == rf_off) { /* check HW status and SW state */
+			RTW_INFO("%s: driver in IPS-FWLPS\n", __func__);
+			pdbgpriv->dbg_dev_unload_inIPS_cnt++;
+		} else
+			RTW_INFO("%s: driver not in IPS\n", __func__);
+
+		if (!rtw_is_surprise_removed(padapter)) {
+#ifdef CONFIG_BT_COEXIST
+			rtw_btcoex_IpsNotify(padapter, pwrctl->ips_mode_req);
+#endif
+#ifdef CONFIG_WOWLAN
+			if (pwrctl->bSupportRemoteWakeup == true &&
+			    pwrctl->wowlan_mode == true)
+				RTW_INFO("%s bSupportRemoteWakeup==true  do not run rtw_hal_deinit()\n", __func__);
+			else
+#endif
+			{
+				/* amy modify 20120221 for power seq is different between driver open and ips */
+				rtw_hal_deinit(padapter);
+			}
+			rtw_set_surprise_removed(padapter);
+		}
+
+		padapter->bup = false;
+
+		RTW_INFO("<== "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+	} else {
+		RTW_INFO("%s: bup==false\n", __func__);
+	}
+	rtw_cancel_all_timer(padapter);
+}
+
+int rtw_suspend_free_assoc_resource(_adapter *padapter)
+{
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct net_device *pnetdev = padapter->pnetdev;
+#ifdef CONFIG_P2P
+	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_P2P */
+
+	RTW_INFO("==> "FUNC_ADPT_FMT" entry....\n", FUNC_ADPT_ARG(padapter));
+
+	if (rtw_chk_roam_flags(padapter, RTW_ROAM_ON_RESUME)) {
+		if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
+			&& check_fwstate(pmlmepriv, _FW_LINKED)
+			#ifdef CONFIG_P2P
+			&& (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
+				#if defined(CONFIG_IOCTL_CFG80211) && RTW_P2P_GROUP_INTERFACE
+				|| rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)
+				#endif
+				)
+			#endif /* CONFIG_P2P */
+		) {
+			RTW_INFO("%s %s(" MAC_FMT "), length:%d assoc_ssid.length:%d\n", __func__,
+				pmlmepriv->cur_network.network.Ssid.Ssid,
+				MAC_ARG(pmlmepriv->cur_network.network.MacAddress),
+				pmlmepriv->cur_network.network.Ssid.SsidLength,
+				pmlmepriv->assoc_ssid.SsidLength);
+			rtw_set_to_roam(padapter, 1);
+		}
+	}
+
+	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED)) {
+		rtw_disassoc_cmd(padapter, 0, false);
+		/* s2-2.  indicate disconnect to os */
+		rtw_indicate_disconnect(padapter, 0, false);
+	}
+#ifdef CONFIG_AP_MODE
+	else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
+		rtw_sta_flush(padapter, true);
+#endif
+
+	/* s2-3. */
+	rtw_free_assoc_resources(padapter, 1);
+
+	/* s2-4. */
+#ifdef CONFIG_AUTOSUSPEND
+	if (is_primary_adapter(padapter) && (!adapter_to_pwrctl(padapter)->bInternalAutoSuspend))
+#endif
+		rtw_free_network_queue(padapter, true);
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
+		RTW_INFO("%s: fw_under_survey\n", __func__);
+		rtw_indicate_scan_done(padapter, 1);
+		clr_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
+	}
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
+		RTW_INFO("%s: fw_under_linking\n", __func__);
+		rtw_indicate_disconnect(padapter, 0, false);
+	}
+
+	RTW_INFO("<== "FUNC_ADPT_FMT" exit....\n", FUNC_ADPT_ARG(padapter));
+	return _SUCCESS;
+}
+
+#ifdef CONFIG_WOWLAN
+int rtw_suspend_wow(_adapter *padapter)
+{
+	u8 ch, bw, offset;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct net_device *pnetdev = padapter->pnetdev;
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct wowlan_ioctl_param poidparam;
+	int i;
+	_adapter *iface = NULL;
+	u8 ps_mode;
+	int ret = _SUCCESS;
+
+	RTW_INFO("==> "FUNC_ADPT_FMT" entry....\n", FUNC_ADPT_ARG(padapter));
+
+
+	RTW_INFO("wowlan_mode: %d\n", pwrpriv->wowlan_mode);
+	RTW_INFO("wowlan_pno_enable: %d\n", pwrpriv->wowlan_pno_enable);
+#ifdef CONFIG_P2P_WOWLAN
+	RTW_INFO("wowlan_p2p_enable: %d\n", pwrpriv->wowlan_p2p_enable);
+#endif
+
+	if (pwrpriv->wowlan_mode == true) {
+#ifdef CONFIG_BT_COEXIST
+		rtw_btcoex_SuspendNotify(padapter, BTCOEX_SUSPEND_STATE_SUSPEND_KEEP_ANT);
+#endif
+
+		if (pnetdev)
+			rtw_netif_stop_queue(pnetdev);
+		rtw_mi_buddy_netif_stop_queue(padapter, true);
+
+		/* 0. Power off LED */
+		rtw_led_control(padapter, LED_CTL_POWER_OFF);
+		/* 1. stop thread */
+		rtw_set_drv_stopped(padapter);	/*for stop thread*/
+		for (i = 0; i < dvobj->iface_nums; i++) {
+			iface = dvobj->padapters[i];
+			if ((iface) && (iface->bup == true))
+				rtw_stop_drv_threads(iface);
+		}
+		rtw_clr_drv_stopped(padapter);	/*for 32k command*/
+
+		/* #ifdef CONFIG_LPS */
+		/* rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, "WOWLAN"); */
+		/* #endif */
+
+		/* 2.2 free irq */
+		/* sdio_free_irq(adapter_to_dvobj(padapter)); */
+#if !(CONFIG_RTW_SDIO_KEEP_IRQ)
+		if (padapter->intf_free_irq)
+			padapter->intf_free_irq(adapter_to_dvobj(padapter));
+#endif
+
+#ifdef CONFIG_RUNTIME_PORT_SWITCH
+		if (rtw_port_switch_chk(padapter)) {
+			RTW_INFO(" ### PORT SWITCH ###\n");
+			rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
+		}
+#endif
+
+		poidparam.subcode = WOWLAN_ENABLE;
+		rtw_hal_set_hwreg(padapter, HW_VAR_WOWLAN, (u8 *)&poidparam);
+		if (rtw_chk_roam_flags(padapter, RTW_ROAM_ON_RESUME)) {
+			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
+			    && check_fwstate(pmlmepriv, _FW_LINKED)) {
+				RTW_INFO("%s %s(" MAC_FMT "), length:%d assoc_ssid.length:%d\n", __func__,
+					pmlmepriv->cur_network.network.Ssid.Ssid,
+					MAC_ARG(pmlmepriv->cur_network.network.MacAddress),
+					pmlmepriv->cur_network.network.Ssid.SsidLength,
+					 pmlmepriv->assoc_ssid.SsidLength);
+
+				rtw_set_to_roam(padapter, 0);
+			}
+		}
+
+		RTW_INFO("%s: wowmode suspending\n", __func__);
+
+		if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
+			RTW_INFO("%s: fw_under_survey\n", __func__);
+			rtw_indicate_scan_done(padapter, 1);
+			clr_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
+		}
+
+		if (rtw_mi_check_status(padapter, MI_LINKED)) {
+			ch =  rtw_mi_get_union_chan(padapter);
+			bw = rtw_mi_get_union_bw(padapter);
+			offset = rtw_mi_get_union_offset(padapter);
+			RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",
+				 FUNC_ADPT_ARG(padapter), ch, bw, offset);
+			set_channel_bwmode(padapter, ch, offset, bw);
+		}
+
+#ifdef CONFIG_CONCURRENT_MODE
+		rtw_mi_buddy_suspend_free_assoc_resource(padapter);
+#endif
+
+		if (pwrpriv->wowlan_pno_enable) {
+			RTW_INFO("%s: pno: %d\n", __func__,
+				  pwrpriv->wowlan_pno_enable);
+#ifdef CONFIG_FWLPS_IN_IPS
+			rtw_set_fw_in_ips_mode(padapter, true);
+#endif
+		}
+#ifdef CONFIG_LPS
+		else
+			rtw_set_ps_mode(padapter, PS_MODE_MAX, 0, 0, "WOWLAN");
+#endif /* #ifdef CONFIG_LPS */
+
+	} else
+		RTW_INFO("%s: ### ERROR ### wowlan_mode=%d\n", __func__, pwrpriv->wowlan_mode);
+	RTW_INFO("<== "FUNC_ADPT_FMT" exit....\n", FUNC_ADPT_ARG(padapter));
+	return ret;
+}
+#endif /* #ifdef CONFIG_WOWLAN */
+
+#ifdef CONFIG_AP_WOWLAN
+int rtw_suspend_ap_wow(_adapter *padapter)
+{
+	u8 ch, bw, offset;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct wowlan_ioctl_param poidparam;
+	int i;
+	_adapter *iface = NULL;
+	u8 ps_mode;
+	int ret = _SUCCESS;
+
+	RTW_INFO("==> "FUNC_ADPT_FMT" entry....\n", FUNC_ADPT_ARG(padapter));
+
+	pwrpriv->wowlan_ap_mode = true;
+
+	RTW_INFO("wowlan_ap_mode: %d\n", pwrpriv->wowlan_ap_mode);
+
+#ifdef CONFIG_BT_COEXIST
+	rtw_btcoex_SuspendNotify(padapter, BTCOEX_SUSPEND_STATE_SUSPEND_KEEP_ANT);
+#endif
+
+	rtw_mi_netif_stop_queue(padapter, false);
+
+	/* 0. Power off LED */
+	rtw_led_control(padapter, LED_CTL_POWER_OFF);
+	/* 1. stop thread */
+	rtw_set_drv_stopped(padapter);	/*for stop thread*/
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		iface = dvobj->padapters[i];
+		if ((iface) && (iface->bup == true))
+			rtw_stop_drv_threads(iface);
+	}
+	rtw_clr_drv_stopped(padapter);	/*for 32k command*/
+
+	/* 2.2 free irq */
+	if (padapter->intf_free_irq)
+		padapter->intf_free_irq(adapter_to_dvobj(padapter));
+
+#ifdef CONFIG_RUNTIME_PORT_SWITCH
+	if (rtw_port_switch_chk(padapter)) {
+		RTW_INFO(" ### PORT SWITCH ###\n");
+		rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
+	}
+#endif
+
+	poidparam.subcode = WOWLAN_AP_ENABLE;
+	rtw_hal_set_hwreg(padapter, HW_VAR_WOWLAN, (u8 *)&poidparam);
+
+	RTW_INFO("%s: wowmode suspending\n", __func__);
+	if (rtw_mi_check_status(padapter, MI_LINKED)) {
+		ch =  rtw_mi_get_union_chan(padapter);
+		bw = rtw_mi_get_union_bw(padapter);
+		offset = rtw_mi_get_union_offset(padapter);
+		RTW_INFO("back to linked/linking union - ch:%u, bw:%u, offset:%u\n", ch, bw, offset);
+		set_channel_bwmode(padapter, ch, offset, bw);
+	}
+	/*FOR ONE AP - TODO :Multi-AP*/
+	{
+		int i;
+		_adapter *iface;
+		struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+
+		for (i = 0; i < dvobj->iface_nums; i++) {
+			iface = dvobj->padapters[i];
+			if ((iface) && rtw_is_adapter_up(iface)) {
+				if (check_fwstate(&iface->mlmepriv, WIFI_AP_STATE | _FW_LINKED))
+					rtw_mi_buddy_suspend_free_assoc_resource(iface);
+			}
+		}
+
+	}
+
+#ifdef CONFIG_LPS
+	rtw_set_ps_mode(padapter, PS_MODE_MIN, 0, 0, "AP-WOWLAN");
+#endif
+
+	RTW_INFO("<== "FUNC_ADPT_FMT" exit....\n", FUNC_ADPT_ARG(padapter));
+	return ret;
+}
+#endif /* #ifdef CONFIG_AP_WOWLAN */
+
+
+static int rtw_suspend_normal(_adapter *padapter)
+{
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	int ret = _SUCCESS;
+
+	RTW_INFO("==> "FUNC_ADPT_FMT" entry....\n", FUNC_ADPT_ARG(padapter));
+
+#ifdef CONFIG_BT_COEXIST
+	rtw_btcoex_SuspendNotify(padapter, BTCOEX_SUSPEND_STATE_SUSPEND);
+#endif
+
+	rtw_mi_netif_stop_queue(padapter, true);
+
+	rtw_mi_suspend_free_assoc_resource(padapter);
+
+	rtw_led_control(padapter, LED_CTL_POWER_OFF);
+
+	if ((rtw_hal_check_ips_status(padapter) == true)
+	    || (adapter_to_pwrctl(padapter)->rf_pwrstate == rf_off))
+		RTW_INFO("%s: ### ERROR #### driver in IPS ####ERROR###!!!\n", __func__);
+
+
+#ifdef CONFIG_CONCURRENT_MODE
+	rtw_mi_buddy_dev_unload(padapter);
+#endif
+	rtw_dev_unload(padapter);
+
+	/* sdio_deinit(adapter_to_dvobj(padapter)); */
+	if (padapter->intf_deinit)
+		padapter->intf_deinit(adapter_to_dvobj(padapter));
+
+#if !(CONFIG_RTW_SDIO_KEEP_IRQ)
+	if(padapter->intf_free_irq)
+		padapter->intf_free_irq(adapter_to_dvobj(padapter));
+#endif
+
+	RTW_INFO("<== "FUNC_ADPT_FMT" exit....\n", FUNC_ADPT_ARG(padapter));
+	return ret;
+}
+
+int rtw_suspend_common(_adapter *padapter)
+{
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+	struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(psdpriv);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+	int ret = 0;
+	u32 start_time = jiffies;
+
+	RTW_INFO(" suspend start\n");
+	RTW_INFO("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
+
+	pdbgpriv->dbg_suspend_cnt++;
+
+	pwrpriv->bInSuspend = true;
+
+	while (pwrpriv->bips_processing == true)
+		rtw_msleep_os(1);
+
+#ifdef CONFIG_IOL_READ_EFUSE_MAP
+	if (!padapter->bup) {
+		u8 bMacPwrCtrlOn = false;
+		rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
+		if (bMacPwrCtrlOn)
+			rtw_hal_power_off(padapter);
+	}
+#endif
+
+	if ((!padapter->bup) || RTW_CANNOT_RUN(padapter)) {
+		RTW_INFO("%s bup=%d bDriverStopped=%s bSurpriseRemoved = %s\n", __func__
+			 , padapter->bup
+			 , rtw_is_drv_stopped(padapter) ? "True" : "False"
+			, rtw_is_surprise_removed(padapter) ? "True" : "False");
+		pdbgpriv->dbg_suspend_error_cnt++;
+		goto exit;
+	}
+	rtw_ps_deny(padapter, PS_DENY_SUSPEND);
+
+	rtw_mi_cancel_all_timer(padapter);
+	LeaveAllPowerSaveModeDirect(padapter);
+	rtw_stop_cmd_thread(padapter);
+
+	rtw_ps_deny_cancel(padapter, PS_DENY_SUSPEND);
+
+	if (rtw_mi_check_status(padapter, MI_AP_MODE) == false) {
+#ifdef CONFIG_WOWLAN
+		if (check_fwstate(pmlmepriv, _FW_LINKED))
+			pwrpriv->wowlan_mode = true;
+		else if (pwrpriv->wowlan_pno_enable == true)
+			pwrpriv->wowlan_mode |= pwrpriv->wowlan_pno_enable;
+
+#ifdef CONFIG_P2P_WOWLAN
+		if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE) || P2P_ROLE_DISABLE != padapter->wdinfo.role)
+			pwrpriv->wowlan_p2p_mode = true;
+		if (pwrpriv->wowlan_p2p_mode)
+			pwrpriv->wowlan_mode |= pwrpriv->wowlan_p2p_mode;
+#endif /* CONFIG_P2P_WOWLAN */
+
+		if (pwrpriv->wowlan_mode == true)
+			rtw_suspend_wow(padapter);
+		else
+#endif /* CONFIG_WOWLAN */
+			rtw_suspend_normal(padapter);
+	} else if (rtw_mi_check_status(padapter, MI_AP_MODE)) {
+#ifdef CONFIG_AP_WOWLAN
+		rtw_suspend_ap_wow(padapter);
+#else
+		rtw_suspend_normal(padapter);
+#endif /*CONFIG_AP_WOWLAN*/
+	}
+
+
+	RTW_INFO("rtw suspend success in %d ms\n",
+		  rtw_get_passing_time_ms(start_time));
+
+exit:
+	RTW_INFO("<===  %s return %d.............. in %dms\n", __func__
+		 , ret, rtw_get_passing_time_ms(start_time));
+
+	return ret;
+}
+
+#ifdef CONFIG_WOWLAN
+int rtw_resume_process_wow(_adapter *padapter)
+{
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct net_device *pnetdev = padapter->pnetdev;
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+	struct wowlan_ioctl_param poidparam;
+	struct sta_info	*psta = NULL;
+	int ret = _SUCCESS;
+
+	RTW_INFO("==> "FUNC_ADPT_FMT" entry....\n", FUNC_ADPT_ARG(padapter));
+
+	if (padapter) {
+		pnetdev = padapter->pnetdev;
+		pwrpriv = adapter_to_pwrctl(padapter);
+	} else {
+		pdbgpriv->dbg_resume_error_cnt++;
+		ret = -1;
+		goto exit;
+	}
+
+	if (RTW_CANNOT_RUN(padapter)) {
+		RTW_INFO("%s pdapter %p bDriverStopped %s bSurpriseRemoved %s\n"
+			 , __func__, padapter
+			 , rtw_is_drv_stopped(padapter) ? "True" : "False"
+			, rtw_is_surprise_removed(padapter) ? "True" : "False");
+		goto exit;
+	}
+
+	pwrpriv->wowlan_in_resume = true;
+#ifdef CONFIG_PNO_SUPPORT
+#ifdef CONFIG_FWLPS_IN_IPS
+	if (pwrpriv->wowlan_pno_enable)
+		rtw_set_fw_in_ips_mode(padapter, false);
+#endif /* CONFIG_FWLPS_IN_IPS */
+#endif/* CONFIG_PNO_SUPPORT */
+
+	if (pwrpriv->wowlan_mode == true) {
+#ifdef CONFIG_LPS
+		rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, "WOWLAN");
+#endif /* CONFIG_LPS */
+
+		pwrpriv->bFwCurrentInPSMode = false;
+
+#if !(CONFIG_RTW_SDIO_KEEP_IRQ)
+		/* if (sdio_alloc_irq(adapter_to_dvobj(padapter)) != _SUCCESS) {		 */
+		if ((padapter->intf_alloc_irq) && (padapter->intf_alloc_irq(adapter_to_dvobj(padapter)) != _SUCCESS)) {
+			ret = -1;
+			goto exit;
+		}
+#endif
+
+		/* Disable WOW, set H2C command */
+		poidparam.subcode = WOWLAN_DISABLE;
+		rtw_hal_set_hwreg(padapter, HW_VAR_WOWLAN, (u8 *)&poidparam);
+
+#ifdef CONFIG_CONCURRENT_MODE
+		rtw_mi_buddy_reset_drv_sw(padapter);
+#endif
+
+		psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));
+		if (psta)
+			set_sta_rate(padapter, psta);
+
+
+		rtw_clr_drv_stopped(padapter);
+		RTW_INFO("%s: wowmode resuming, DriverStopped:%s\n", __func__, rtw_is_drv_stopped(padapter) ? "True" : "False");
+
+		rtw_mi_start_drv_threads(padapter);
+
+		rtw_mi_intf_start(padapter);
+
+#ifdef CONFIG_CONCURRENT_MODE
+		rtw_mi_buddy_netif_carrier_on(padapter);
+#endif
+
+		/* start netif queue */
+		if (pnetdev)
+			rtw_netif_wake_queue(pnetdev);
+	} else
+
+		RTW_INFO("%s: ### ERROR ### wowlan_mode=%d\n", __func__, pwrpriv->wowlan_mode);
+
+	if (padapter->pid[1] != 0) {
+		RTW_INFO("pid[1]:%d\n", padapter->pid[1]);
+		rtw_signal_process(padapter->pid[1], SIGUSR2);
+	}
+
+	if (rtw_chk_roam_flags(padapter, RTW_ROAM_ON_RESUME)) {
+		if (pwrpriv->wowlan_wake_reason == FW_DECISION_DISCONNECT ||
+		    pwrpriv->wowlan_wake_reason == RX_DISASSOC||
+		    pwrpriv->wowlan_wake_reason == RX_DEAUTH) {
+
+			RTW_INFO("%s: disconnect reason: %02x\n", __func__,
+				 pwrpriv->wowlan_wake_reason);
+			rtw_indicate_disconnect(padapter, 0, false);
+
+			rtw_sta_media_status_rpt(padapter,
+					 rtw_get_stainfo(&padapter->stapriv,
+					 get_bssid(&padapter->mlmepriv)), 0);
+
+			rtw_free_assoc_resources(padapter, 1);
+			pmlmeinfo->state = WIFI_FW_NULL_STATE;
+
+		} else {
+			RTW_INFO("%s: do roaming\n", __func__);
+			rtw_roaming(padapter, NULL);
+		}
+	}
+
+	if (pwrpriv->wowlan_wake_reason == FW_DECISION_DISCONNECT)
+		rtw_lock_ext_suspend_timeout(2000);
+
+	if (pwrpriv->wowlan_wake_reason == RX_GTK ||
+	    pwrpriv->wowlan_wake_reason == RX_DISASSOC||
+	    pwrpriv->wowlan_wake_reason == RX_DEAUTH)
+		rtw_lock_ext_suspend_timeout(8000);
+
+	if (pwrpriv->wowlan_wake_reason == RX_PNO) {
+#ifdef CONFIG_IOCTL_CFG80211
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
+		u8 locally_generated = 1;
+
+		cfg80211_disconnected(padapter->pnetdev, 0, NULL, 0, locally_generated, GFP_ATOMIC);
+#else
+		cfg80211_disconnected(padapter->pnetdev, 0, NULL, 0, GFP_ATOMIC);
+#endif
+#endif /* CONFIG_IOCTL_CFG80211 */
+		rtw_lock_ext_suspend_timeout(10000);
+	}
+
+	if (pwrpriv->wowlan_mode == true) {
+		pwrpriv->bips_processing = false;
+		_set_timer(&adapter_to_dvobj(padapter)->dynamic_chk_timer, 2000);
+#ifndef CONFIG_IPS_CHECK_IN_WD
+		rtw_set_pwr_state_check_timer(pwrpriv);
+#endif
+	} else
+		RTW_INFO("do not reset timer\n");
+
+	pwrpriv->wowlan_mode = false;
+
+	/* Power On LED */
+#ifdef CONFIG_SW_LED
+
+	if (pwrpriv->wowlan_wake_reason == RX_DISASSOC||
+	    pwrpriv->wowlan_wake_reason == RX_DEAUTH||
+	    pwrpriv->wowlan_wake_reason == FW_DECISION_DISCONNECT)
+		rtw_led_control(padapter, LED_CTL_NO_LINK);
+	else
+		rtw_led_control(padapter, LED_CTL_LINK);
+#endif
+	/* clean driver side wake up reason. */
+	pwrpriv->wowlan_last_wake_reason = pwrpriv->wowlan_wake_reason;
+	pwrpriv->wowlan_wake_reason = 0;
+
+#ifdef CONFIG_BT_COEXIST
+	rtw_btcoex_SuspendNotify(padapter, BTCOEX_SUSPEND_STATE_RESUME);
+#endif /* CONFIG_BT_COEXIST */
+
+exit:
+	RTW_INFO("<== "FUNC_ADPT_FMT" exit....\n", FUNC_ADPT_ARG(padapter));
+	return ret;
+}
+#endif /* #ifdef CONFIG_WOWLAN */
+
+#ifdef CONFIG_AP_WOWLAN
+int rtw_resume_process_ap_wow(_adapter *padapter)
+{
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct net_device *pnetdev = padapter->pnetdev;
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+	struct wowlan_ioctl_param poidparam;
+	struct sta_info	*psta = NULL;
+	int ret = _SUCCESS;
+	u8 ch, bw, offset;
+
+	RTW_INFO("==> "FUNC_ADPT_FMT" entry....\n", FUNC_ADPT_ARG(padapter));
+
+	if (padapter) {
+		pnetdev = padapter->pnetdev;
+		pwrpriv = adapter_to_pwrctl(padapter);
+	} else {
+		pdbgpriv->dbg_resume_error_cnt++;
+		ret = -1;
+		goto exit;
+	}
+
+
+#ifdef CONFIG_LPS
+	rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, "AP-WOWLAN");
+#endif /* CONFIG_LPS */
+
+	pwrpriv->bFwCurrentInPSMode = false;
+
+	rtw_hal_disable_interrupt(padapter);
+
+	rtw_hal_clear_interrupt(padapter);
+
+	/* if (sdio_alloc_irq(adapter_to_dvobj(padapter)) != _SUCCESS) {		 */
+	if ((padapter->intf_alloc_irq) && (padapter->intf_alloc_irq(adapter_to_dvobj(padapter)) != _SUCCESS)) {
+		ret = -1;
+		goto exit;
+	}
+
+	/* Disable WOW, set H2C command */
+	poidparam.subcode = WOWLAN_AP_DISABLE;
+	rtw_hal_set_hwreg(padapter, HW_VAR_WOWLAN, (u8 *)&poidparam);
+	pwrpriv->wowlan_ap_mode = false;
+
+	rtw_clr_drv_stopped(padapter);
+	RTW_INFO("%s: wowmode resuming, DriverStopped:%s\n", __func__, rtw_is_drv_stopped(padapter) ? "True" : "False");
+
+	rtw_mi_start_drv_threads(padapter);
+
+	if (rtw_mi_check_status(padapter, MI_LINKED)) {
+		ch =  rtw_mi_get_union_chan(padapter);
+		bw = rtw_mi_get_union_bw(padapter);
+		offset = rtw_mi_get_union_offset(padapter);
+		RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n", FUNC_ADPT_ARG(padapter), ch, bw, offset);
+		set_channel_bwmode(padapter, ch, offset, bw);
+	}
+
+	/*FOR ONE AP - TODO :Multi-AP*/
+	{
+		int i;
+		_adapter *iface;
+		struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+
+		for (i = 0; i < dvobj->iface_nums; i++) {
+			iface = dvobj->padapters[i];
+			if ((iface) && rtw_is_adapter_up(iface)) {
+				if (check_fwstate(&iface->mlmepriv, WIFI_AP_STATE | _FW_LINKED))
+					rtw_mi_buddy_reset_drv_sw(iface);
+			}
+		}
+
+	}
+	rtw_mi_intf_start(padapter);
+	rtw_mi_netif_wake_queue(padapter);
+
+	if (padapter->pid[1] != 0) {
+		RTW_INFO("pid[1]:%d\n", padapter->pid[1]);
+		rtw_signal_process(padapter->pid[1], SIGUSR2);
+	}
+
+#ifdef CONFIG_RESUME_IN_WORKQUEUE
+	/* rtw_unlock_suspend(); */
+#endif /* CONFIG_RESUME_IN_WORKQUEUE */
+
+	if (pwrpriv->wowlan_wake_reason == AP_OFFLOAD_WAKEUP)
+		rtw_lock_ext_suspend_timeout(8000);
+
+	pwrpriv->bips_processing = false;
+	_set_timer(&adapter_to_dvobj(padapter)->dynamic_chk_timer, 2000);
+#ifndef CONFIG_IPS_CHECK_IN_WD
+	rtw_set_pwr_state_check_timer(pwrpriv);
+#endif
+	/* clean driver side wake up reason. */
+	pwrpriv->wowlan_wake_reason = 0;
+
+#ifdef CONFIG_BT_COEXIST
+	rtw_btcoex_SuspendNotify(padapter, BTCOEX_SUSPEND_STATE_RESUME);
+#endif /* CONFIG_BT_COEXIST */
+
+	/* Power On LED */
+#ifdef CONFIG_SW_LED
+
+	rtw_led_control(padapter, LED_CTL_LINK);
+#endif
+exit:
+	RTW_INFO("<== "FUNC_ADPT_FMT" exit....\n", FUNC_ADPT_ARG(padapter));
+	return ret;
+}
+#endif /* #ifdef CONFIG_APWOWLAN */
+
+static void rtw_mi_resume_process_normal(_adapter *padapter)
+{
+	int i;
+	_adapter *iface;
+	struct mlme_priv *pmlmepriv;
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		iface = dvobj->padapters[i];
+		if ((iface) && rtw_is_adapter_up(iface)) {
+			pmlmepriv = &iface->mlmepriv;
+
+			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+				RTW_INFO(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_STATION_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv));
+
+				if (rtw_chk_roam_flags(padapter, RTW_ROAM_ON_RESUME))
+					rtw_roaming(padapter, NULL);
+
+			} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+				RTW_INFO(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_AP_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv));
+				rtw_ap_restore_network(padapter);
+			} else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
+				RTW_INFO(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_ADHOC_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv));
+			else
+				RTW_INFO(FUNC_ADPT_FMT" fwstate:0x%08x - ???\n", FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv));
+		}
+	}
+}
+
+static int rtw_resume_process_normal(_adapter *padapter)
+{
+	struct net_device *pnetdev;
+	struct pwrctrl_priv *pwrpriv;
+	struct dvobj_priv *psdpriv;
+	struct debug_priv *pdbgpriv;
+	int ret = _SUCCESS;
+
+	if (!padapter) {
+		ret = -1;
+		goto exit;
+	}
+
+	pnetdev = padapter->pnetdev;
+	pwrpriv = adapter_to_pwrctl(padapter);
+	psdpriv = padapter->dvobj;
+	pdbgpriv = &psdpriv->drv_dbg;
+
+	RTW_INFO("==> "FUNC_ADPT_FMT" entry....\n", FUNC_ADPT_ARG(padapter));
+	/* interface init */
+	/* if (sdio_init(adapter_to_dvobj(padapter)) != _SUCCESS) */
+	if ((padapter->intf_init) && (padapter->intf_init(adapter_to_dvobj(padapter)) != _SUCCESS)) {
+		ret = -1;
+		goto exit;
+	}
+	rtw_hal_disable_interrupt(padapter);
+#if !(CONFIG_RTW_SDIO_KEEP_IRQ)
+	/* if (sdio_alloc_irq(adapter_to_dvobj(padapter)) != _SUCCESS) */
+	if ((padapter->intf_alloc_irq) && (padapter->intf_alloc_irq(adapter_to_dvobj(padapter)) != _SUCCESS)) {
+		ret = -1;
+		goto exit;
+	}
+#endif
+
+	rtw_mi_reset_drv_sw(padapter);
+
+	pwrpriv->bkeepfwalive = false;
+
+	RTW_INFO("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive);
+	if (pm_netdev_open(pnetdev, true) != 0) {
+		ret = -1;
+		pdbgpriv->dbg_resume_error_cnt++;
+		goto exit;
+	}
+
+	rtw_mi_netif_carrier_on(padapter);
+
+	if (padapter->pid[1] != 0) {
+		RTW_INFO("pid[1]:%d\n", padapter->pid[1]);
+		rtw_signal_process(padapter->pid[1], SIGUSR2);
+	}
+
+#ifdef CONFIG_BT_COEXIST
+	rtw_btcoex_SuspendNotify(padapter, BTCOEX_SUSPEND_STATE_RESUME);
+#endif /* CONFIG_BT_COEXIST */
+
+	rtw_mi_resume_process_normal(padapter);
+
+#ifdef CONFIG_RESUME_IN_WORKQUEUE
+	/* rtw_unlock_suspend(); */
+#endif /* CONFIG_RESUME_IN_WORKQUEUE */
+	RTW_INFO("<== "FUNC_ADPT_FMT" exit....\n", FUNC_ADPT_ARG(padapter));
+
+exit:
+	return ret;
+}
+
+int rtw_resume_common(_adapter *padapter)
+{
+	int ret = 0;
+	u32 start_time = jiffies;
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+
+	if (pwrpriv->bInSuspend == false)
+		return 0;
+
+	RTW_INFO("resume start\n");
+	RTW_INFO("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
+
+	if (rtw_mi_check_status(padapter, WIFI_AP_STATE) == false) {
+#ifdef CONFIG_WOWLAN
+		if (pwrpriv->wowlan_mode == true)
+			rtw_resume_process_wow(padapter);
+		else
+#endif
+			rtw_resume_process_normal(padapter);
+
+	} else if (rtw_mi_check_status(padapter, WIFI_AP_STATE)) {
+#ifdef CONFIG_AP_WOWLAN
+		rtw_resume_process_ap_wow(padapter);
+#else
+		rtw_resume_process_normal(padapter);
+#endif /* CONFIG_AP_WOWLAN */
+	}
+
+	if (pwrpriv) {
+		pwrpriv->bInSuspend = false;
+#ifdef CONFIG_WOWLAN
+		pwrpriv->wowlan_in_resume = false;
+#endif
+	}
+	RTW_INFO("%s:%d in %d ms\n", __func__ , ret,
+		  rtw_get_passing_time_ms(start_time));
+
+
+	return ret;
+}
+
+#ifdef CONFIG_GPIO_API
+u8 rtw_get_gpio(struct net_device *netdev, u8 gpio_num)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(netdev);
+	return rtw_hal_get_gpio(adapter, gpio_num);
+}
+EXPORT_SYMBOL(rtw_get_gpio);
+
+int  rtw_set_gpio_output_value(struct net_device *netdev, u8 gpio_num, bool isHigh)
+{
+	u8 direction = 0;
+	u8 res = -1;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(netdev);
+	return rtw_hal_set_gpio_output_value(adapter, gpio_num, isHigh);
+}
+EXPORT_SYMBOL(rtw_set_gpio_output_value);
+
+int rtw_config_gpio(struct net_device *netdev, u8 gpio_num, bool isOutput)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(netdev);
+	return rtw_hal_config_gpio(adapter, gpio_num, isOutput);
+}
+EXPORT_SYMBOL(rtw_config_gpio);
+int rtw_register_gpio_interrupt(struct net_device *netdev, int gpio_num, void(*callback)(u8 level))
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(netdev);
+	return rtw_hal_register_gpio_interrupt(adapter, gpio_num, callback);
+}
+EXPORT_SYMBOL(rtw_register_gpio_interrupt);
+
+int rtw_disable_gpio_interrupt(struct net_device *netdev, int gpio_num)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(netdev);
+	return rtw_hal_disable_gpio_interrupt(adapter, gpio_num);
+}
+EXPORT_SYMBOL(rtw_disable_gpio_interrupt);
+
+#endif /* #ifdef CONFIG_GPIO_API */
+
+#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
+
+int rtw_vendor_ie_get_api(struct net_device *dev, int ie_num, char *extra, __u16 *length)
+{
+	*length = rtw_vendor_ie_get_data(dev, ie_num, extra);
+	return 0;
+}
+EXPORT_SYMBOL(rtw_vendor_ie_get_api);
+
+int rtw_vendor_ie_set_api(struct net_device *dev, char *extra)
+{
+	return rtw_vendor_ie_set(dev, NULL, NULL, extra);
+}
+EXPORT_SYMBOL(rtw_vendor_ie_set_api);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c
new file mode 100644
index 000000000000..9132038bd135
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c
@@ -0,0 +1,1731 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+
+
+#define _OSDEP_SERVICE_C_
+
+#include <drv_types.h>
+
+#define RT_TAG	'1178'
+
+/*
+* Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE
+* @return: one of RTW_STATUS_CODE
+*/
+inline int RTW_STATUS_CODE(int error_code)
+{
+	if (error_code >= 0)
+		return _SUCCESS;
+
+	switch (error_code) {
+	/* case -ETIMEDOUT: */
+	/*	return RTW_STATUS_TIMEDOUT; */
+	default:
+		return _FAIL;
+	}
+}
+
+u32 rtw_atoi(u8 *s)
+{
+	int num = 0, flag = 0;
+	int i;
+	for (i = 0; i <= strlen(s); i++) {
+		if (s[i] >= '0' && s[i] <= '9')
+			num = num * 10 + s[i] - '0';
+		else if (s[0] == '-' && i == 0)
+			flag = 1;
+		else
+			break;
+	}
+
+	if (flag == 1)
+		num = num * -1;
+
+	return num;
+
+}
+
+inline u8 *_rtw_zvmalloc(u32 sz)
+{
+	u8	*pbuf;
+	pbuf = vmalloc(sz);
+	if (pbuf != NULL)
+		memset(pbuf, 0, sz);
+	return pbuf;
+}
+
+inline void _rtw_vmfree(u8 *pbuf, u32 sz)
+{
+	vfree(pbuf);
+}
+
+u8 *_rtw_malloc(u32 sz)
+{
+	u8	*pbuf = NULL;
+
+#ifdef RTK_DMP_PLATFORM
+	if (sz > 0x4000)
+		pbuf = (u8 *)dvr_malloc(sz);
+	else
+#endif
+		pbuf = kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+
+	return pbuf;
+}
+
+u8 *_rtw_zmalloc(u32 sz)
+{
+	u8	*pbuf = _rtw_malloc(sz);
+
+	if (pbuf != NULL)
+		memset(pbuf, 0, sz);
+	return pbuf;
+}
+
+void	_rtw_mfree(u8 *pbuf, u32 sz)
+{
+#ifdef RTK_DMP_PLATFORM
+	if (sz > 0x4000)
+		dvr_free(pbuf);
+	else
+#endif
+		kfree(pbuf);
+}
+
+inline struct sk_buff *_rtw_skb_alloc(u32 sz)
+{
+	return __dev_alloc_skb(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+}
+
+inline void _rtw_skb_free(struct sk_buff *skb)
+{
+	dev_kfree_skb_any(skb);
+}
+
+inline struct sk_buff *_rtw_skb_copy(const struct sk_buff *skb)
+{
+	return skb_copy(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+}
+
+inline struct sk_buff *_rtw_skb_clone(struct sk_buff *skb)
+{
+	return skb_clone(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+}
+inline struct sk_buff *_rtw_pskb_copy(struct sk_buff *skb)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36))
+	return pskb_copy(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+#else
+	return skb_clone(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+#endif
+}
+
+inline int _rtw_netif_rx(_nic_hdl ndev, struct sk_buff *skb)
+{
+	skb->dev = ndev;
+	return netif_rx(skb);
+}
+
+#ifdef CONFIG_RTW_NAPI
+inline int _rtw_netif_receive_skb(_nic_hdl ndev, struct sk_buff *skb)
+{
+	skb->dev = ndev;
+	return netif_receive_skb(skb);
+}
+
+#ifdef CONFIG_RTW_GRO
+inline gro_result_t _rtw_napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
+{
+	return napi_gro_receive(napi, skb);
+}
+#endif /* CONFIG_RTW_GRO */
+#endif /* CONFIG_RTW_NAPI */
+
+void _rtw_skb_queue_purge(struct sk_buff_head *list)
+{
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(list)) != NULL)
+		_rtw_skb_free(skb);
+}
+
+inline void *_rtw_usb_buffer_alloc(struct usb_device *dev, size_t size, dma_addr_t *dma)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	return usb_alloc_coherent(dev, size, (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL), dma);
+#else
+	return usb_buffer_alloc(dev, size, (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL), dma);
+#endif
+}
+
+inline void _rtw_usb_buffer_free(struct usb_device *dev, size_t size, void *addr, dma_addr_t dma)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	usb_free_coherent(dev, size, addr, dma);
+#else
+	usb_buffer_free(dev, size, addr, dma);
+#endif
+}
+
+#if defined(DBG_MEM_ALLOC)
+
+struct rtw_mem_stat {
+	ATOMIC_T alloc; /* the memory bytes we allocate currently */
+	ATOMIC_T peak; /* the peak memory bytes we allocate */
+	ATOMIC_T alloc_cnt; /* the alloc count for alloc currently */
+	ATOMIC_T alloc_err_cnt; /* the error times we fail to allocate memory */
+};
+
+struct rtw_mem_stat rtw_mem_type_stat[mstat_tf_idx(MSTAT_TYPE_MAX)];
+#ifdef RTW_MEM_FUNC_STAT
+struct rtw_mem_stat rtw_mem_func_stat[mstat_ff_idx(MSTAT_FUNC_MAX)];
+#endif
+
+char *MSTAT_TYPE_str[] = {
+	"VIR",
+	"PHY",
+	"SKB",
+	"USB",
+};
+
+#ifdef RTW_MEM_FUNC_STAT
+char *MSTAT_FUNC_str[] = {
+	"UNSP",
+	"IO",
+	"TXIO",
+	"RXIO",
+	"TX",
+	"RX",
+};
+#endif
+
+void rtw_mstat_dump(void *sel)
+{
+	int i;
+	int value_t[4][mstat_tf_idx(MSTAT_TYPE_MAX)];
+#ifdef RTW_MEM_FUNC_STAT
+	int value_f[4][mstat_ff_idx(MSTAT_FUNC_MAX)];
+#endif
+
+	int vir_alloc, vir_peak, vir_alloc_err, phy_alloc, phy_peak, phy_alloc_err;
+	int tx_alloc, tx_peak, tx_alloc_err, rx_alloc, rx_peak, rx_alloc_err;
+
+	for (i = 0; i < mstat_tf_idx(MSTAT_TYPE_MAX); i++) {
+		value_t[0][i] = ATOMIC_READ(&(rtw_mem_type_stat[i].alloc));
+		value_t[1][i] = ATOMIC_READ(&(rtw_mem_type_stat[i].peak));
+		value_t[2][i] = ATOMIC_READ(&(rtw_mem_type_stat[i].alloc_cnt));
+		value_t[3][i] = ATOMIC_READ(&(rtw_mem_type_stat[i].alloc_err_cnt));
+	}
+
+#ifdef RTW_MEM_FUNC_STAT
+	for (i = 0; i < mstat_ff_idx(MSTAT_FUNC_MAX); i++) {
+		value_f[0][i] = ATOMIC_READ(&(rtw_mem_func_stat[i].alloc));
+		value_f[1][i] = ATOMIC_READ(&(rtw_mem_func_stat[i].peak));
+		value_f[2][i] = ATOMIC_READ(&(rtw_mem_func_stat[i].alloc_cnt));
+		value_f[3][i] = ATOMIC_READ(&(rtw_mem_func_stat[i].alloc_err_cnt));
+	}
+#endif
+
+	RTW_PRINT_SEL(sel, "===================== MSTAT =====================\n");
+	RTW_PRINT_SEL(sel, "%4s %10s %10s %10s %10s\n", "TAG", "alloc", "peak", "aloc_cnt", "err_cnt");
+	RTW_PRINT_SEL(sel, "-------------------------------------------------\n");
+	for (i = 0; i < mstat_tf_idx(MSTAT_TYPE_MAX); i++)
+		RTW_PRINT_SEL(sel, "%4s %10d %10d %10d %10d\n", MSTAT_TYPE_str[i], value_t[0][i], value_t[1][i], value_t[2][i], value_t[3][i]);
+#ifdef RTW_MEM_FUNC_STAT
+	RTW_PRINT_SEL(sel, "-------------------------------------------------\n");
+	for (i = 0; i < mstat_ff_idx(MSTAT_FUNC_MAX); i++)
+		RTW_PRINT_SEL(sel, "%4s %10d %10d %10d %10d\n", MSTAT_FUNC_str[i], value_f[0][i], value_f[1][i], value_f[2][i], value_f[3][i]);
+#endif
+}
+
+void rtw_mstat_update(const enum mstat_f flags, const MSTAT_STATUS status, u32 sz)
+{
+	static u32 update_time = 0;
+	int peak, alloc;
+	int i;
+
+	/* initialization */
+	if (!update_time) {
+		for (i = 0; i < mstat_tf_idx(MSTAT_TYPE_MAX); i++) {
+			ATOMIC_SET(&(rtw_mem_type_stat[i].alloc), 0);
+			ATOMIC_SET(&(rtw_mem_type_stat[i].peak), 0);
+			ATOMIC_SET(&(rtw_mem_type_stat[i].alloc_cnt), 0);
+			ATOMIC_SET(&(rtw_mem_type_stat[i].alloc_err_cnt), 0);
+		}
+		#ifdef RTW_MEM_FUNC_STAT
+		for (i = 0; i < mstat_ff_idx(MSTAT_FUNC_MAX); i++) {
+			ATOMIC_SET(&(rtw_mem_func_stat[i].alloc), 0);
+			ATOMIC_SET(&(rtw_mem_func_stat[i].peak), 0);
+			ATOMIC_SET(&(rtw_mem_func_stat[i].alloc_cnt), 0);
+			ATOMIC_SET(&(rtw_mem_func_stat[i].alloc_err_cnt), 0);
+		}
+		#endif
+	}
+
+	switch (status) {
+	case MSTAT_ALLOC_SUCCESS:
+		ATOMIC_INC(&(rtw_mem_type_stat[mstat_tf_idx(flags)].alloc_cnt));
+		alloc = ATOMIC_ADD_RETURN(&(rtw_mem_type_stat[mstat_tf_idx(flags)].alloc), sz);
+		peak = ATOMIC_READ(&(rtw_mem_type_stat[mstat_tf_idx(flags)].peak));
+		if (peak < alloc)
+			ATOMIC_SET(&(rtw_mem_type_stat[mstat_tf_idx(flags)].peak), alloc);
+
+		#ifdef RTW_MEM_FUNC_STAT
+		ATOMIC_INC(&(rtw_mem_func_stat[mstat_ff_idx(flags)].alloc_cnt));
+		alloc = ATOMIC_ADD_RETURN(&(rtw_mem_func_stat[mstat_ff_idx(flags)].alloc), sz);
+		peak = ATOMIC_READ(&(rtw_mem_func_stat[mstat_ff_idx(flags)].peak));
+		if (peak < alloc)
+			ATOMIC_SET(&(rtw_mem_func_stat[mstat_ff_idx(flags)].peak), alloc);
+		#endif
+		break;
+
+	case MSTAT_ALLOC_FAIL:
+		ATOMIC_INC(&(rtw_mem_type_stat[mstat_tf_idx(flags)].alloc_err_cnt));
+		#ifdef RTW_MEM_FUNC_STAT
+		ATOMIC_INC(&(rtw_mem_func_stat[mstat_ff_idx(flags)].alloc_err_cnt));
+		#endif
+		break;
+
+	case MSTAT_FREE:
+		ATOMIC_DEC(&(rtw_mem_type_stat[mstat_tf_idx(flags)].alloc_cnt));
+		ATOMIC_SUB(&(rtw_mem_type_stat[mstat_tf_idx(flags)].alloc), sz);
+		#ifdef RTW_MEM_FUNC_STAT
+		ATOMIC_DEC(&(rtw_mem_func_stat[mstat_ff_idx(flags)].alloc_cnt));
+		ATOMIC_SUB(&(rtw_mem_func_stat[mstat_ff_idx(flags)].alloc), sz);
+		#endif
+		break;
+	};
+
+	/* if (rtw_get_passing_time_ms(update_time) > 5000) { */
+	/*	rtw_mstat_dump(RTW_DBGDUMP); */
+	update_time = jiffies;
+	/* } */
+}
+
+#ifndef SIZE_MAX
+	#define SIZE_MAX (~(size_t)0)
+#endif
+
+struct mstat_sniff_rule {
+	enum mstat_f flags;
+	size_t lb;
+	size_t hb;
+};
+
+struct mstat_sniff_rule mstat_sniff_rules[] = {
+	{MSTAT_TYPE_PHY, 4097, SIZE_MAX},
+};
+
+int mstat_sniff_rule_num = sizeof(mstat_sniff_rules) / sizeof(struct mstat_sniff_rule);
+
+bool match_mstat_sniff_rules(const enum mstat_f flags, const size_t size)
+{
+	int i;
+	for (i = 0; i < mstat_sniff_rule_num; i++) {
+		if (mstat_sniff_rules[i].flags == flags
+			&& mstat_sniff_rules[i].lb <= size
+			&& mstat_sniff_rules[i].hb >= size)
+			return true;
+	}
+
+	return false;
+}
+
+inline u8 *dbg_rtw_vmalloc(u32 sz, const enum mstat_f flags, const char *func, const int line)
+{
+	u8  *p;
+
+	if (match_mstat_sniff_rules(flags, sz))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d)\n", func, line, __func__, (sz));
+
+	p = vmalloc((sz));
+
+	rtw_mstat_update(
+		flags
+		, p ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
+		, sz
+	);
+
+	return p;
+}
+
+inline u8 *dbg_rtw_zvmalloc(u32 sz, const enum mstat_f flags, const char *func, const int line)
+{
+	u8 *p;
+
+	if (match_mstat_sniff_rules(flags, sz))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d)\n", func, line, __func__, (sz));
+
+	p = _rtw_zvmalloc((sz));
+
+	rtw_mstat_update(
+		flags
+		, p ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
+		, sz
+	);
+
+	return p;
+}
+
+inline void dbg_rtw_vmfree(u8 *pbuf, u32 sz, const enum mstat_f flags, const char *func, const int line)
+{
+
+	if (match_mstat_sniff_rules(flags, sz))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d)\n", func, line, __func__, (sz));
+
+	_rtw_vmfree((pbuf), (sz));
+
+	rtw_mstat_update(
+		flags
+		, MSTAT_FREE
+		, sz
+	);
+}
+
+inline u8 *dbg_rtw_malloc(u32 sz, const enum mstat_f flags, const char *func, const int line)
+{
+	u8 *p;
+
+	if (match_mstat_sniff_rules(flags, sz))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d)\n", func, line, __func__, (sz));
+
+	p = _rtw_malloc((sz));
+
+	rtw_mstat_update(
+		flags
+		, p ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
+		, sz
+	);
+
+	return p;
+}
+
+inline u8 *dbg_rtw_zmalloc(u32 sz, const enum mstat_f flags, const char *func, const int line)
+{
+	u8 *p;
+
+	if (match_mstat_sniff_rules(flags, sz))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d)\n", func, line, __func__, (sz));
+
+	p = _rtw_zmalloc((sz));
+
+	rtw_mstat_update(
+		flags
+		, p ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
+		, sz
+	);
+
+	return p;
+}
+
+inline void dbg_rtw_mfree(u8 *pbuf, u32 sz, const enum mstat_f flags, const char *func, const int line)
+{
+	if (match_mstat_sniff_rules(flags, sz))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d)\n", func, line, __func__, (sz));
+
+	_rtw_mfree((pbuf), (sz));
+
+	rtw_mstat_update(
+		flags
+		, MSTAT_FREE
+		, sz
+	);
+}
+
+inline struct sk_buff *dbg_rtw_skb_alloc(unsigned int size, const enum mstat_f flags, const char *func, int line)
+{
+	struct sk_buff *skb;
+	unsigned int truesize = 0;
+
+	skb = _rtw_skb_alloc(size);
+
+	if (skb)
+		truesize = skb->truesize;
+
+	if (!skb || truesize < size || match_mstat_sniff_rules(flags, truesize))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d), skb:%p, truesize=%u\n", func, line, __func__, size, skb, truesize);
+
+	rtw_mstat_update(
+		flags
+		, skb ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
+		, truesize
+	);
+
+	return skb;
+}
+
+inline void dbg_rtw_skb_free(struct sk_buff *skb, const enum mstat_f flags, const char *func, int line)
+{
+	unsigned int truesize = skb->truesize;
+
+	if (match_mstat_sniff_rules(flags, truesize))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __func__, truesize);
+
+	_rtw_skb_free(skb);
+
+	rtw_mstat_update(
+		flags
+		, MSTAT_FREE
+		, truesize
+	);
+}
+
+inline struct sk_buff *dbg_rtw_skb_copy(const struct sk_buff *skb, const enum mstat_f flags, const char *func, const int line)
+{
+	struct sk_buff *skb_cp;
+	unsigned int truesize = skb->truesize;
+	unsigned int cp_truesize = 0;
+
+	skb_cp = _rtw_skb_copy(skb);
+	if (skb_cp)
+		cp_truesize = skb_cp->truesize;
+
+	if (!skb_cp || cp_truesize < truesize || match_mstat_sniff_rules(flags, cp_truesize))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%u), skb_cp:%p, cp_truesize=%u\n", func, line, __func__, truesize, skb_cp, cp_truesize);
+
+	rtw_mstat_update(
+		flags
+		, skb_cp ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
+		, truesize
+	);
+
+	return skb_cp;
+}
+
+inline struct sk_buff *dbg_rtw_skb_clone(struct sk_buff *skb, const enum mstat_f flags, const char *func, const int line)
+{
+	struct sk_buff *skb_cl;
+	unsigned int truesize = skb->truesize;
+	unsigned int cl_truesize = 0;
+
+	skb_cl = _rtw_skb_clone(skb);
+	if (skb_cl)
+		cl_truesize = skb_cl->truesize;
+
+	if (!skb_cl || cl_truesize < truesize || match_mstat_sniff_rules(flags, cl_truesize))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%u), skb_cl:%p, cl_truesize=%u\n", func, line, __func__, truesize, skb_cl, cl_truesize);
+
+	rtw_mstat_update(
+		flags
+		, skb_cl ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
+		, truesize
+	);
+
+	return skb_cl;
+}
+
+inline int dbg_rtw_netif_rx(_nic_hdl ndev, struct sk_buff *skb, const enum mstat_f flags, const char *func, int line)
+{
+	int ret;
+	unsigned int truesize = skb->truesize;
+
+	if (match_mstat_sniff_rules(flags, truesize))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __func__, truesize);
+
+	ret = _rtw_netif_rx(ndev, skb);
+
+	rtw_mstat_update(
+		flags
+		, MSTAT_FREE
+		, truesize
+	);
+
+	return ret;
+}
+
+#ifdef CONFIG_RTW_NAPI
+inline int dbg_rtw_netif_receive_skb(_nic_hdl ndev, struct sk_buff *skb, const enum mstat_f flags, const char *func, int line)
+{
+	int ret;
+	unsigned int truesize = skb->truesize;
+
+	if (match_mstat_sniff_rules(flags, truesize))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __func__, truesize);
+
+	ret = _rtw_netif_receive_skb(ndev, skb);
+
+	rtw_mstat_update(
+		flags
+		, MSTAT_FREE
+		, truesize
+	);
+
+	return ret;
+}
+
+#ifdef CONFIG_RTW_GRO
+inline gro_result_t dbg_rtw_napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb, const enum mstat_f flags, const char *func, int line)
+{
+	int ret;
+	unsigned int truesize = skb->truesize;
+
+	if (match_mstat_sniff_rules(flags, truesize))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __func__, truesize);
+
+	ret = _rtw_napi_gro_receive(napi, skb);
+
+	rtw_mstat_update(
+		flags
+		, MSTAT_FREE
+		, truesize
+	);
+
+	return ret;
+}
+#endif /* CONFIG_RTW_GRO */
+#endif /* CONFIG_RTW_NAPI */
+
+inline void dbg_rtw_skb_queue_purge(struct sk_buff_head *list, enum mstat_f flags, const char *func, int line)
+{
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(list)) != NULL)
+		dbg_rtw_skb_free(skb, flags, func, line);
+}
+
+inline void *dbg_rtw_usb_buffer_alloc(struct usb_device *dev, size_t size, dma_addr_t *dma, const enum mstat_f flags, const char *func, int line)
+{
+	void *p;
+
+	if (match_mstat_sniff_rules(flags, size))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%zu)\n", func, line, __func__, size);
+
+	p = _rtw_usb_buffer_alloc(dev, size, dma);
+
+	rtw_mstat_update(
+		flags
+		, p ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
+		, size
+	);
+
+	return p;
+}
+
+inline void dbg_rtw_usb_buffer_free(struct usb_device *dev, size_t size, void *addr, dma_addr_t dma, const enum mstat_f flags, const char *func, int line)
+{
+
+	if (match_mstat_sniff_rules(flags, size))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%zu)\n", func, line, __func__, size);
+
+	_rtw_usb_buffer_free(dev, size, addr, dma);
+
+	rtw_mstat_update(
+		flags
+		, MSTAT_FREE
+		, size
+	);
+}
+
+#endif /* defined(DBG_MEM_ALLOC) */
+
+void *rtw_malloc2d(int h, int w, size_t size)
+{
+	int j;
+
+	void **a = (void **) rtw_zmalloc(h * sizeof(void *) + h * w * size);
+	if (a == NULL) {
+		RTW_INFO("%s: alloc memory fail!\n", __func__);
+		return NULL;
+	}
+
+	for (j = 0; j < h; j++)
+		a[j] = ((char *)(a + h)) + j * w * size;
+
+	return a;
+}
+
+void rtw_mfree2d(void *pbuf, int h, int w, int size)
+{
+	rtw_mfree((u8 *)pbuf, h * sizeof(void *) + w * h * size);
+}
+
+u32 _rtw_down_sema(_sema *sema)
+{
+	if (down_interruptible(sema))
+		return _FAIL;
+	return _SUCCESS;
+}
+
+void	_rtw_mutex_init(_mutex *pmutex)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+	mutex_init(pmutex);
+#else
+	init_MUTEX(pmutex);
+#endif
+}
+
+void	_rtw_mutex_free(_mutex *pmutex)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+	mutex_destroy(pmutex);
+#endif
+}
+
+void _rtw_init_queue(_queue *pqueue)
+{
+	INIT_LIST_HEAD(&(pqueue->queue));
+	spin_lock_init(&(pqueue->lock));
+}
+
+u32	  _rtw_queue_empty(_queue	*pqueue)
+{
+	return list_empty(&(pqueue->queue));
+}
+
+
+u32 rtw_end_of_queue_search(_list *head, _list *plist)
+{
+	if (head == plist)
+		return true;
+	else
+		return false;
+}
+
+inline u32 rtw_systime_to_ms(u32 systime)
+{
+	return systime * 1000 / HZ;
+}
+
+inline u32 rtw_ms_to_systime(u32 ms)
+{
+	return ms * HZ / 1000;
+}
+
+/* the input parameter start use the same unit as returned by rtw_get_current_time */
+inline s32 rtw_get_passing_time_ms(u32 start)
+{
+	return rtw_systime_to_ms(jiffies - start);
+}
+
+inline s32 rtw_get_time_interval_ms(u32 start, u32 end)
+{
+	return rtw_systime_to_ms(end - start);
+}
+
+void rtw_sleep_schedulable(int ms)
+{
+	u32 delta;
+
+	delta = (ms * HZ) / 1000; /* (ms) */
+	if (delta == 0) {
+		delta = 1;/* 1 ms */
+	}
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (schedule_timeout(delta) != 0)
+		return ;
+	return;
+}
+
+void rtw_msleep_os(int ms)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36))
+	if (ms < 20) {
+		unsigned long us = ms * 1000UL;
+		usleep_range(us, us + 1000UL);
+	} else
+#endif
+		msleep((unsigned int)ms);
+}
+void rtw_usleep_os(int us)
+{
+	/* msleep((unsigned int)us); */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36))
+	usleep_range(us, us + 1);
+#else
+	if (1 < (us / 1000))
+		msleep(1);
+	else
+		msleep((us / 1000) + 1);
+#endif
+}
+
+#ifdef DBG_DELAY_OS
+void _rtw_mdelay_os(int ms, const char *func, const int line)
+{
+	RTW_INFO("%s:%d %s(%d)\n", func, line, __func__, ms);
+	mdelay((unsigned long)ms);
+}
+
+void _rtw_udelay_os(int us, const char *func, const int line)
+{
+	RTW_INFO("%s:%d %s(%d)\n", func, line, __func__, us);
+
+	udelay((unsigned long)us);
+}
+#else
+void rtw_mdelay_os(int ms)
+{
+	mdelay((unsigned long)ms);
+}
+
+void rtw_udelay_os(int us)
+{
+	udelay((unsigned long)us);
+}
+#endif
+
+void rtw_yield_os(void)
+{
+	yield();
+}
+
+#define RTW_SUSPEND_LOCK_NAME "rtw_wifi"
+#define RTW_SUSPEND_EXT_LOCK_NAME "rtw_wifi_ext"
+#define RTW_SUSPEND_RX_LOCK_NAME "rtw_wifi_rx"
+#define RTW_SUSPEND_TRAFFIC_LOCK_NAME "rtw_wifi_traffic"
+#define RTW_SUSPEND_RESUME_LOCK_NAME "rtw_wifi_resume"
+#define RTW_RESUME_SCAN_LOCK_NAME "rtw_wifi_scan"
+#ifdef CONFIG_WAKELOCK
+static struct wake_lock rtw_suspend_lock;
+static struct wake_lock rtw_suspend_ext_lock;
+static struct wake_lock rtw_suspend_rx_lock;
+static struct wake_lock rtw_suspend_traffic_lock;
+static struct wake_lock rtw_suspend_resume_lock;
+static struct wake_lock rtw_resume_scan_lock;
+#elif defined(CONFIG_ANDROID_POWER)
+static android_suspend_lock_t rtw_suspend_lock = {
+	.name = RTW_SUSPEND_LOCK_NAME
+};
+static android_suspend_lock_t rtw_suspend_ext_lock = {
+	.name = RTW_SUSPEND_EXT_LOCK_NAME
+};
+static android_suspend_lock_t rtw_suspend_rx_lock = {
+	.name = RTW_SUSPEND_RX_LOCK_NAME
+};
+static android_suspend_lock_t rtw_suspend_traffic_lock = {
+	.name = RTW_SUSPEND_TRAFFIC_LOCK_NAME
+};
+static android_suspend_lock_t rtw_suspend_resume_lock = {
+	.name = RTW_SUSPEND_RESUME_LOCK_NAME
+};
+static android_suspend_lock_t rtw_resume_scan_lock = {
+	.name = RTW_RESUME_SCAN_LOCK_NAME
+};
+#endif
+
+inline void rtw_suspend_lock_init(void)
+{
+#ifdef CONFIG_WAKELOCK
+	wake_lock_init(&rtw_suspend_lock, WAKE_LOCK_SUSPEND, RTW_SUSPEND_LOCK_NAME);
+	wake_lock_init(&rtw_suspend_ext_lock, WAKE_LOCK_SUSPEND, RTW_SUSPEND_EXT_LOCK_NAME);
+	wake_lock_init(&rtw_suspend_rx_lock, WAKE_LOCK_SUSPEND, RTW_SUSPEND_RX_LOCK_NAME);
+	wake_lock_init(&rtw_suspend_traffic_lock, WAKE_LOCK_SUSPEND, RTW_SUSPEND_TRAFFIC_LOCK_NAME);
+	wake_lock_init(&rtw_suspend_resume_lock, WAKE_LOCK_SUSPEND, RTW_SUSPEND_RESUME_LOCK_NAME);
+	wake_lock_init(&rtw_resume_scan_lock, WAKE_LOCK_SUSPEND, RTW_RESUME_SCAN_LOCK_NAME);
+#elif defined(CONFIG_ANDROID_POWER)
+	android_init_suspend_lock(&rtw_suspend_lock);
+	android_init_suspend_lock(&rtw_suspend_ext_lock);
+	android_init_suspend_lock(&rtw_suspend_rx_lock);
+	android_init_suspend_lock(&rtw_suspend_traffic_lock);
+	android_init_suspend_lock(&rtw_suspend_resume_lock);
+	android_init_suspend_lock(&rtw_resume_scan_lock);
+#endif
+}
+
+inline void rtw_suspend_lock_uninit(void)
+{
+#ifdef CONFIG_WAKELOCK
+	wake_lock_destroy(&rtw_suspend_lock);
+	wake_lock_destroy(&rtw_suspend_ext_lock);
+	wake_lock_destroy(&rtw_suspend_rx_lock);
+	wake_lock_destroy(&rtw_suspend_traffic_lock);
+	wake_lock_destroy(&rtw_suspend_resume_lock);
+	wake_lock_destroy(&rtw_resume_scan_lock);
+#elif defined(CONFIG_ANDROID_POWER)
+	android_uninit_suspend_lock(&rtw_suspend_lock);
+	android_uninit_suspend_lock(&rtw_suspend_ext_lock);
+	android_uninit_suspend_lock(&rtw_suspend_rx_lock);
+	android_uninit_suspend_lock(&rtw_suspend_traffic_lock);
+	android_uninit_suspend_lock(&rtw_suspend_resume_lock);
+	android_uninit_suspend_lock(&rtw_resume_scan_lock);
+#endif
+}
+
+inline void rtw_lock_suspend(void)
+{
+#ifdef CONFIG_WAKELOCK
+	wake_lock(&rtw_suspend_lock);
+#elif defined(CONFIG_ANDROID_POWER)
+	android_lock_suspend(&rtw_suspend_lock);
+#endif
+
+#if  defined(CONFIG_WAKELOCK) || defined(CONFIG_ANDROID_POWER)
+	/* RTW_INFO("####%s: suspend_lock_count:%d####\n", __func__, rtw_suspend_lock.stat.count); */
+#endif
+}
+
+inline void rtw_unlock_suspend(void)
+{
+#ifdef CONFIG_WAKELOCK
+	wake_unlock(&rtw_suspend_lock);
+#elif defined(CONFIG_ANDROID_POWER)
+	android_unlock_suspend(&rtw_suspend_lock);
+#endif
+
+#if  defined(CONFIG_WAKELOCK) || defined(CONFIG_ANDROID_POWER)
+	/* RTW_INFO("####%s: suspend_lock_count:%d####\n", __func__, rtw_suspend_lock.stat.count); */
+#endif
+}
+
+inline void rtw_resume_lock_suspend(void)
+{
+#ifdef CONFIG_WAKELOCK
+	wake_lock(&rtw_suspend_resume_lock);
+#elif defined(CONFIG_ANDROID_POWER)
+	android_lock_suspend(&rtw_suspend_resume_lock);
+#endif
+
+#if  defined(CONFIG_WAKELOCK) || defined(CONFIG_ANDROID_POWER)
+	/* RTW_INFO("####%s: suspend_lock_count:%d####\n", __func__, rtw_suspend_lock.stat.count); */
+#endif
+}
+
+inline void rtw_resume_unlock_suspend(void)
+{
+#ifdef CONFIG_WAKELOCK
+	wake_unlock(&rtw_suspend_resume_lock);
+#elif defined(CONFIG_ANDROID_POWER)
+	android_unlock_suspend(&rtw_suspend_resume_lock);
+#endif
+
+#if  defined(CONFIG_WAKELOCK) || defined(CONFIG_ANDROID_POWER)
+	/* RTW_INFO("####%s: suspend_lock_count:%d####\n", __func__, rtw_suspend_lock.stat.count); */
+#endif
+}
+
+inline void rtw_lock_suspend_timeout(u32 timeout_ms)
+{
+#ifdef CONFIG_WAKELOCK
+	wake_lock_timeout(&rtw_suspend_lock, rtw_ms_to_systime(timeout_ms));
+#elif defined(CONFIG_ANDROID_POWER)
+	android_lock_suspend_auto_expire(&rtw_suspend_lock, rtw_ms_to_systime(timeout_ms));
+#endif
+}
+
+inline void rtw_lock_ext_suspend_timeout(u32 timeout_ms)
+{
+#ifdef CONFIG_WAKELOCK
+	wake_lock_timeout(&rtw_suspend_ext_lock, rtw_ms_to_systime(timeout_ms));
+#elif defined(CONFIG_ANDROID_POWER)
+	android_lock_suspend_auto_expire(&rtw_suspend_ext_lock, rtw_ms_to_systime(timeout_ms));
+#endif
+	/* RTW_INFO("EXT lock timeout:%d\n", timeout_ms); */
+}
+
+inline void rtw_lock_rx_suspend_timeout(u32 timeout_ms)
+{
+#ifdef CONFIG_WAKELOCK
+	wake_lock_timeout(&rtw_suspend_rx_lock, rtw_ms_to_systime(timeout_ms));
+#elif defined(CONFIG_ANDROID_POWER)
+	android_lock_suspend_auto_expire(&rtw_suspend_rx_lock, rtw_ms_to_systime(timeout_ms));
+#endif
+	/* RTW_INFO("RX lock timeout:%d\n", timeout_ms); */
+}
+
+
+inline void rtw_lock_traffic_suspend_timeout(u32 timeout_ms)
+{
+#ifdef CONFIG_WAKELOCK
+	wake_lock_timeout(&rtw_suspend_traffic_lock, rtw_ms_to_systime(timeout_ms));
+#elif defined(CONFIG_ANDROID_POWER)
+	android_lock_suspend_auto_expire(&rtw_suspend_traffic_lock, rtw_ms_to_systime(timeout_ms));
+#endif
+	/* RTW_INFO("traffic lock timeout:%d\n", timeout_ms); */
+}
+
+inline void rtw_lock_resume_scan_timeout(u32 timeout_ms)
+{
+#ifdef CONFIG_WAKELOCK
+	wake_lock_timeout(&rtw_resume_scan_lock, rtw_ms_to_systime(timeout_ms));
+#elif defined(CONFIG_ANDROID_POWER)
+	android_lock_suspend_auto_expire(&rtw_resume_scan_lock, rtw_ms_to_systime(timeout_ms));
+#endif
+	/* RTW_INFO("resume scan lock:%d\n", timeout_ms); */
+}
+
+inline void ATOMIC_SET(ATOMIC_T *v, int i)
+{
+	atomic_set(v, i);
+}
+
+inline int ATOMIC_READ(ATOMIC_T *v)
+{
+	return atomic_read(v);
+}
+
+inline void ATOMIC_ADD(ATOMIC_T *v, int i)
+{
+	atomic_add(i, v);
+}
+inline void ATOMIC_SUB(ATOMIC_T *v, int i)
+{
+	atomic_sub(i, v);
+}
+
+inline void ATOMIC_INC(ATOMIC_T *v)
+{
+	atomic_inc(v);
+}
+
+inline void ATOMIC_DEC(ATOMIC_T *v)
+{
+	atomic_dec(v);
+}
+
+inline int ATOMIC_ADD_RETURN(ATOMIC_T *v, int i)
+{
+	return atomic_add_return(i, v);
+}
+
+inline int ATOMIC_SUB_RETURN(ATOMIC_T *v, int i)
+{
+	return atomic_sub_return(i, v);
+}
+
+inline int ATOMIC_INC_RETURN(ATOMIC_T *v)
+{
+	return atomic_inc_return(v);
+}
+
+inline int ATOMIC_DEC_RETURN(ATOMIC_T *v)
+{
+	return atomic_dec_return(v);
+}
+
+/*
+* Open a file with the specific @param path, @param flag, @param mode
+* @param fpp the pointer of struct file pointer to get struct file pointer while file opening is success
+* @param path the path of the file to open
+* @param flag file operation flags, please refer to linux document
+* @param mode please refer to linux document
+* @return Linux specific error code
+*/
+static int openFile(struct file **fpp, const char *path, int flag, int mode)
+{
+	struct file *fp;
+
+	fp = filp_open(path, flag, mode);
+	if (IS_ERR(fp)) {
+		*fpp = NULL;
+		return PTR_ERR(fp);
+	} else {
+		*fpp = fp;
+		return 0;
+	}
+}
+
+/*
+* Close the file with the specific @param fp
+* @param fp the pointer of struct file to close
+* @return always 0
+*/
+static int closeFile(struct file *fp)
+{
+	filp_close(fp, NULL);
+	return 0;
+}
+
+static int readFile(struct file *fp, char *buf, int len)
+{
+	int rlen = 0, sum = 0;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
+	if (!(fp->f_mode & FMODE_CAN_READ))
+#else
+	if (!fp->f_op || !fp->f_op->read)
+#endif
+		return -EPERM;
+
+	while (sum < len) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
+		rlen = kernel_read(fp, buf + sum, len - sum, &fp->f_pos);
+#else
+		rlen = __vfs_read(fp, buf + sum, len - sum, &fp->f_pos);
+#endif
+#else
+		rlen = fp->f_op->read(fp, buf + sum, len - sum, &fp->f_pos);
+#endif
+		if (rlen > 0)
+			sum += rlen;
+		else if (0 != rlen)
+			return rlen;
+		else
+			break;
+	}
+
+	return  sum;
+
+}
+
+static int writeFile(struct file *fp, char *buf, int len)
+{
+	int wlen = 0, sum = 0;
+
+	if (!fp->f_op || !fp->f_op->write)
+		return -EPERM;
+
+	while (sum < len) {
+		wlen = fp->f_op->write(fp, (char __user *)buf + sum, len - sum, &fp->f_pos);
+		if (wlen > 0)
+			sum += wlen;
+		else if (0 != wlen)
+			return wlen;
+		else
+			break;
+	}
+
+	return sum;
+
+}
+
+/*
+* Test if the specifi @param path is a file and readable
+* If readable, @param sz is got
+* @param path the path of the file to test
+* @return Linux specific error code
+*/
+static int isFileReadable(const char *path, u32 *sz)
+{
+	struct file *fp;
+	int ret = 0;
+#ifdef set_fs
+	mm_segment_t oldfs;
+#endif
+	char buf;
+
+	fp = filp_open(path, O_RDONLY, 0);
+	if (IS_ERR(fp))
+		ret = PTR_ERR(fp);
+	else {
+#ifdef set_fs
+		oldfs = get_fs();
+		set_fs(KERNEL_DS);
+#endif
+
+		if (1 != readFile(fp, &buf, 1))
+			ret = PTR_ERR(fp);
+
+		if (ret == 0 && sz) {
+			#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
+			*sz = i_size_read(fp->f_path.dentry->d_inode);
+			#else
+			*sz = i_size_read(fp->f_dentry->d_inode);
+			#endif
+		}
+
+#ifdef set_fs
+		set_fs(oldfs);
+#endif
+		filp_close(fp, NULL);
+	}
+	return ret;
+}
+
+/*
+* Open the file with @param path and retrive the file content into memory starting from @param buf for @param sz at most
+* @param path the path of the file to open and read
+* @param buf the starting address of the buffer to store file content
+* @param sz how many bytes to read at most
+* @return the byte we've read, or Linux specific error code
+*/
+static int retriveFromFile(const char *path, u8 *buf, u32 sz)
+{
+	int ret = -1;
+#ifdef set_fs
+	mm_segment_t oldfs;
+#endif
+	struct file *fp;
+
+	if (path && buf) {
+		ret = openFile(&fp, path, O_RDONLY, 0);
+		if (0 == ret) {
+			RTW_INFO("%s openFile path:%s fp=%p\n", __func__, path , fp);
+
+#ifdef set_fs
+			oldfs = get_fs();
+			set_fs(KERNEL_DS);
+#endif
+			ret = readFile(fp, buf, sz);
+#ifdef set_fs
+			set_fs(oldfs);
+#endif
+			closeFile(fp);
+
+			RTW_INFO("%s readFile, ret:%d\n", __func__, ret);
+
+		} else
+			RTW_INFO("%s openFile path:%s Fail, ret:%d\n", __func__, path, ret);
+	} else {
+		RTW_INFO("%s NULL pointer\n", __func__);
+		ret =  -EINVAL;
+	}
+	return ret;
+}
+
+/*
+* Open the file with @param path and wirte @param sz byte of data starting from @param buf into the file
+* @param path the path of the file to open and write
+* @param buf the starting address of the data to write into file
+* @param sz how many bytes to write at most
+* @return the byte we've written, or Linux specific error code
+*/
+static int storeToFile(const char *path, u8 *buf, u32 sz)
+{
+	int ret = 0;
+#ifdef set_fs
+	mm_segment_t oldfs;
+#endif
+	struct file *fp;
+
+	if (path && buf) {
+		ret = openFile(&fp, path, O_CREAT | O_WRONLY, 0666);
+		if (0 == ret) {
+			RTW_INFO("%s openFile path:%s fp=%p\n", __func__, path , fp);
+
+#ifdef set_fs
+			oldfs = get_fs();
+			set_fs(KERNEL_DS);
+#endif
+			ret = writeFile(fp, buf, sz);
+#ifdef set_fs
+			set_fs(oldfs);
+#endif
+			closeFile(fp);
+
+			RTW_INFO("%s writeFile, ret:%d\n", __func__, ret);
+
+		} else
+			RTW_INFO("%s openFile path:%s Fail, ret:%d\n", __func__, path, ret);
+	} else {
+		RTW_INFO("%s NULL pointer\n", __func__);
+		ret =  -EINVAL;
+	}
+	return ret;
+}
+
+/*
+* Test if the specifi @param path is a file and readable
+* @param path the path of the file to test
+* @return true or false
+*/
+int rtw_is_file_readable(const char *path)
+{
+	if (isFileReadable(path, NULL) == 0)
+		return true;
+	else
+		return false;
+}
+
+/*
+* Test if the specifi @param path is a file and readable.
+* If readable, @param sz is got
+* @param path the path of the file to test
+* @return true or false
+*/
+int rtw_is_file_readable_with_size(const char *path, u32 *sz)
+{
+	if (isFileReadable(path, sz) == 0)
+		return true;
+	else
+		return false;
+}
+
+/*
+* Open the file with @param path and retrive the file content into memory starting from @param buf for @param sz at most
+* @param path the path of the file to open and read
+* @param buf the starting address of the buffer to store file content
+* @param sz how many bytes to read at most
+* @return the byte we've read
+*/
+int rtw_retrieve_from_file(const char *path, u8 *buf, u32 sz)
+{
+	int ret = retriveFromFile(path, buf, sz);
+
+	return ret >= 0 ? ret : 0;
+}
+
+/*
+* Open the file with @param path and wirte @param sz byte of data starting from @param buf into the file
+* @param path the path of the file to open and write
+* @param buf the starting address of the data to write into file
+* @param sz how many bytes to write at most
+* @return the byte we've written
+*/
+int rtw_store_to_file(const char *path, u8 *buf, u32 sz)
+{
+	int ret = storeToFile(path, buf, sz);
+	return ret >= 0 ? ret : 0;
+}
+
+struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, void *old_priv)
+{
+	struct net_device *pnetdev;
+	struct rtw_netdev_priv_indicator *pnpi;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
+#else
+	pnetdev = alloc_etherdev(sizeof(struct rtw_netdev_priv_indicator));
+#endif
+	if (!pnetdev)
+		goto RETURN;
+
+	pnpi = netdev_priv(pnetdev);
+	pnpi->priv = old_priv;
+	pnpi->sizeof_priv = sizeof_priv;
+
+RETURN:
+	return pnetdev;
+}
+
+struct net_device *rtw_alloc_etherdev(int sizeof_priv)
+{
+	struct net_device *pnetdev;
+	struct rtw_netdev_priv_indicator *pnpi;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
+#else
+	pnetdev = alloc_etherdev(sizeof(struct rtw_netdev_priv_indicator));
+#endif
+	if (!pnetdev)
+		goto RETURN;
+
+	pnpi = netdev_priv(pnetdev);
+
+	pnpi->priv = rtw_zvmalloc(sizeof_priv);
+	if (!pnpi->priv) {
+		free_netdev(pnetdev);
+		pnetdev = NULL;
+		goto RETURN;
+	}
+
+	pnpi->sizeof_priv = sizeof_priv;
+RETURN:
+	return pnetdev;
+}
+
+void rtw_free_netdev(struct net_device *netdev)
+{
+	struct rtw_netdev_priv_indicator *pnpi;
+
+	if (!netdev)
+		goto RETURN;
+
+	pnpi = netdev_priv(netdev);
+
+	if (!pnpi->priv)
+		goto RETURN;
+
+	free_netdev(netdev);
+
+RETURN:
+	return;
+}
+
+int rtw_change_ifname(_adapter *padapter, const char *ifname)
+{
+	struct dvobj_priv *dvobj;
+	struct net_device *pnetdev;
+	struct net_device *cur_pnetdev;
+	struct rereg_nd_name_data *rereg_priv;
+	int ret;
+	u8 rtnl_lock_needed;
+
+	if (!padapter)
+		goto error;
+
+	dvobj = adapter_to_dvobj(padapter);
+	cur_pnetdev = padapter->pnetdev;
+	rereg_priv = &padapter->rereg_nd_name_priv;
+
+	/* free the old_pnetdev */
+	if (rereg_priv->old_pnetdev) {
+		free_netdev(rereg_priv->old_pnetdev);
+		rereg_priv->old_pnetdev = NULL;
+	}
+
+	rtnl_lock_needed = rtw_rtnl_lock_needed(dvobj);
+
+	if (rtnl_lock_needed)
+		unregister_netdev(cur_pnetdev);
+	else
+		unregister_netdevice(cur_pnetdev);
+
+	rereg_priv->old_pnetdev = cur_pnetdev;
+
+	pnetdev = rtw_init_netdev(padapter);
+	if (!pnetdev)  {
+		ret = -1;
+		goto error;
+	}
+
+	SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter)));
+
+	rtw_init_netdev_name(pnetdev, ifname);
+
+	memcpy(pnetdev->dev_addr, adapter_mac_addr(padapter), ETH_ALEN);
+
+	if (rtnl_lock_needed)
+		ret = register_netdev(pnetdev);
+	else
+		ret = register_netdevice(pnetdev);
+
+	if (ret != 0) {
+		goto error;
+	}
+
+	return 0;
+
+error:
+
+	return -1;
+
+}
+
+#ifdef CONFIG_PLATFORM_SPRD
+	#ifdef do_div
+		#undef do_div
+	#endif
+	#include <asm-generic/div64.h>
+#endif
+
+u64 rtw_modular64(u64 x, u64 y)
+{
+	return do_div(x, y);
+}
+
+u64 rtw_division64(u64 x, u64 y)
+{
+	do_div(x, y);
+	return x;
+}
+
+inline u32 rtw_random32(void)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+	return prandom_u32();
+#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18))
+	u32 random_int;
+	get_random_bytes(&random_int , 4);
+	return random_int;
+#else
+	return random32();
+#endif
+}
+
+void rtw_buf_free(u8 **buf, u32 *buf_len)
+{
+	u32 ori_len;
+
+	if (!buf || !buf_len)
+		return;
+
+	ori_len = *buf_len;
+
+	if (*buf) {
+		u32 tmp_buf_len = *buf_len;
+		*buf_len = 0;
+		rtw_mfree(*buf, tmp_buf_len);
+		*buf = NULL;
+	}
+}
+
+void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
+{
+	u32 ori_len = 0, dup_len = 0;
+	u8 *ori = NULL;
+	u8 *dup = NULL;
+
+	if (!buf || !buf_len)
+		return;
+
+	if (!src || !src_len)
+		goto keep_ori;
+
+	/* duplicate src */
+	dup = rtw_malloc(src_len);
+	if (dup) {
+		dup_len = src_len;
+		memcpy(dup, src, dup_len);
+	}
+
+keep_ori:
+	ori = *buf;
+	ori_len = *buf_len;
+
+	/* replace buf with dup */
+	*buf_len = 0;
+	*buf = dup;
+	*buf_len = dup_len;
+
+	/* free ori */
+	if (ori && ori_len > 0)
+		rtw_mfree(ori, ori_len);
+}
+
+
+/**
+ * rtw_cbuf_full - test if cbuf is full
+ * @cbuf: pointer of struct rtw_cbuf
+ *
+ * Returns: true if cbuf is full
+ */
+inline bool rtw_cbuf_full(struct rtw_cbuf *cbuf)
+{
+	return (cbuf->write == cbuf->read - 1) ? true : false;
+}
+
+/**
+ * rtw_cbuf_empty - test if cbuf is empty
+ * @cbuf: pointer of struct rtw_cbuf
+ *
+ * Returns: true if cbuf is empty
+ */
+inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
+{
+	return (cbuf->write == cbuf->read) ? true : false;
+}
+
+/**
+ * rtw_cbuf_push - push a pointer into cbuf
+ * @cbuf: pointer of struct rtw_cbuf
+ * @buf: pointer to push in
+ *
+ * Lock free operation, be careful of the use scheme
+ * Returns: true push success
+ */
+bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf)
+{
+	if (rtw_cbuf_full(cbuf))
+		return _FAIL;
+
+	if (0)
+		RTW_INFO("%s on %u\n", __func__, cbuf->write);
+	cbuf->bufs[cbuf->write] = buf;
+	cbuf->write = (cbuf->write + 1) % cbuf->size;
+
+	return _SUCCESS;
+}
+
+/**
+ * rtw_cbuf_pop - pop a pointer from cbuf
+ * @cbuf: pointer of struct rtw_cbuf
+ *
+ * Lock free operation, be careful of the use scheme
+ * Returns: pointer popped out
+ */
+void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
+{
+	void *buf;
+	if (rtw_cbuf_empty(cbuf))
+		return NULL;
+
+	if (0)
+		RTW_INFO("%s on %u\n", __func__, cbuf->read);
+	buf = cbuf->bufs[cbuf->read];
+	cbuf->read = (cbuf->read + 1) % cbuf->size;
+
+	return buf;
+}
+
+/**
+ * rtw_cbuf_alloc - allocte a rtw_cbuf with given size and do initialization
+ * @size: size of pointer
+ *
+ * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
+ */
+struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
+{
+	struct rtw_cbuf *cbuf;
+
+	cbuf = (struct rtw_cbuf *)rtw_malloc(sizeof(*cbuf) + sizeof(void *) * size);
+
+	if (cbuf) {
+		cbuf->write = cbuf->read = 0;
+		cbuf->size = size;
+	}
+
+	return cbuf;
+}
+
+/**
+ * rtw_cbuf_free - free the given rtw_cbuf
+ * @cbuf: pointer of struct rtw_cbuf to free
+ */
+void rtw_cbuf_free(struct rtw_cbuf *cbuf)
+{
+	rtw_mfree((u8 *)cbuf, sizeof(*cbuf) + sizeof(void *) * cbuf->size);
+}
+
+/**
+ * map_readN - read a range of map data
+ * @map: map to read
+ * @offset: start address to read
+ * @len: length to read
+ * @buf: pointer of buffer to store data read
+ *
+ * Returns: _SUCCESS or _FAIL
+ */
+int map_readN(const struct map_t *map, u16 offset, u16 len, u8 *buf)
+{
+	const struct map_seg_t *seg;
+	int ret = _FAIL;
+	int i;
+
+	if (len == 0) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	if (offset + len > map->len) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	memset(buf, map->init_value, len);
+
+	for (i = 0; i < map->seg_num; i++) {
+		u8 *c_dst, *c_src;
+		u16 c_len;
+
+		seg = map->segs + i;
+		if (seg->sa + seg->len <= offset || seg->sa >= offset + len)
+			continue;
+
+		if (seg->sa >= offset) {
+			c_dst = buf + (seg->sa - offset);
+			c_src = seg->c;
+			if (seg->sa + seg->len <= offset + len)
+				c_len = seg->len;
+			else
+				c_len = offset + len - seg->sa;
+		} else {
+			c_dst = buf;
+			c_src = seg->c + (offset - seg->sa);
+			if (seg->sa + seg->len >= offset + len)
+				c_len = len;
+			else
+				c_len = seg->sa + seg->len - offset;
+		}
+			
+		memcpy(c_dst, c_src, c_len);
+	}
+
+exit:
+	return ret;
+}
+
+/**
+ * map_read8 - read 1 byte of map data
+ * @map: map to read
+ * @offset: address to read
+ *
+ * Returns: value of data of specified offset. map.init_value if offset is out of range
+ */
+u8 map_read8(const struct map_t *map, u16 offset)
+{
+	const struct map_seg_t *seg;
+	u8 val = map->init_value;
+	int i;
+
+	if (offset + 1 > map->len) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	for (i = 0; i < map->seg_num; i++) {
+		seg = map->segs + i;
+		if (seg->sa + seg->len <= offset || seg->sa >= offset + 1)
+			continue;
+
+		val = *(seg->c + offset - seg->sa);
+		break;
+	}
+
+exit:
+	return val;
+}
+
+/**
+* is_null -
+*
+* Return	true if c is null character
+*		false otherwise.
+*/
+inline bool is_null(char c)
+{
+	if (c == '\0')
+		return true;
+	else
+		return false;
+}
+
+/**
+* is_eol -
+*
+* Return	true if c is represent for EOL (end of line)
+*		false otherwise.
+*/
+inline bool is_eol(char c)
+{
+	if (c == '\r' || c == '\n')
+		return true;
+	else
+		return false;
+}
+
+/**
+* is_space -
+*
+* Return	true if c is represent for space
+*		false otherwise.
+*/
+inline bool is_space(char c)
+{
+	if (c == ' ' || c == '\t')
+		return true;
+	else
+		return false;
+}
+
+/**
+* IsHexDigit -
+*
+* Return	true if chTmp is represent for hex digit
+*		false otherwise.
+*/
+inline bool IsHexDigit(char chTmp)
+{
+	if ((chTmp >= '0' && chTmp <= '9') ||
+		(chTmp >= 'a' && chTmp <= 'f') ||
+		(chTmp >= 'A' && chTmp <= 'F'))
+		return true;
+	else
+		return false;
+}
+
+/**
+* is_alpha -
+*
+* Return	true if chTmp is represent for alphabet
+*		false otherwise.
+*/
+inline bool is_alpha(char chTmp)
+{
+	if ((chTmp >= 'a' && chTmp <= 'z') ||
+		(chTmp >= 'A' && chTmp <= 'Z'))
+		return true;
+	else
+		return false;
+}
+
+inline char alpha_to_upper(char c)
+{
+	if ((c >= 'a' && c <= 'z'))
+		c = 'A' + (c - 'a');
+	return c;
+}
diff --git a/drivers/staging/rtl8188eu/os_dep/recv_linux.c b/drivers/staging/rtl8188eu/os_dep/recv_linux.c
new file mode 100644
index 000000000000..bb5833a0bf41
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/recv_linux.c
@@ -0,0 +1,790 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+#define _RECV_OSDEP_C_
+
+#include <drv_types.h>
+#include <usb_osintf.h>
+
+int rtw_os_recvframe_duplicate_skb(_adapter *padapter, union recv_frame *pcloneframe, _pkt *pskb)
+{
+	int res = _SUCCESS;
+	_pkt	*pkt_copy = NULL;
+	struct rx_pkt_attrib *pattrib = &pcloneframe->u.hdr.attrib;
+
+	if (pskb == NULL) {
+		RTW_INFO("%s [WARN] skb == NULL, drop frag frame\n", __func__);
+		return _FAIL;
+	}
+	pkt_copy = rtw_skb_copy(pskb);
+
+	if (pkt_copy == NULL) {
+		RTW_INFO("%s [WARN] rtw_skb_copy fail , drop frag frame\n", __func__);
+		return _FAIL;
+	}
+	pkt_copy->dev = padapter->pnetdev;
+
+	pcloneframe->u.hdr.pkt = pkt_copy;
+	pcloneframe->u.hdr.rx_head = pkt_copy->head;
+	pcloneframe->u.hdr.rx_data = pkt_copy->data;
+	pcloneframe->u.hdr.rx_end = skb_end_pointer(pkt_copy);
+	pcloneframe->u.hdr.rx_tail = skb_tail_pointer(pkt_copy);
+	pcloneframe->u.hdr.len = pkt_copy->len;
+
+	return res;
+}
+
+int rtw_os_alloc_recvframe(_adapter *padapter, union recv_frame *precvframe, u8 *pdata, _pkt *pskb)
+{
+	int res = _SUCCESS;
+	u8	shift_sz = 0;
+	u32	skb_len, alloc_sz;
+	_pkt	*pkt_copy = NULL;
+	struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;
+
+
+	if (pdata == NULL) {
+		precvframe->u.hdr.pkt = NULL;
+		res = _FAIL;
+		return res;
+	}
+
+
+	/*	Modified by Albert 20101213 */
+	/*	For 8 bytes IP header alignment. */
+	shift_sz = pattrib->qos ? 6 : 0; /*	Qos data, wireless lan header length is 26 */
+
+	skb_len = le16_to_cpu(pattrib->pkt_len);
+
+	/* for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */
+	/* modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */
+	if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
+		/* alloc_sz = 1664;	 */ /* 1664 is 128 alignment. */
+		alloc_sz = (skb_len <= 1650) ? 1664 : (skb_len + 14);
+	} else {
+		alloc_sz = skb_len;
+		/*	6 is for IP header 8 bytes alignment in QoS packet case. */
+		/*	8 is for skb->data 4 bytes alignment. */
+		alloc_sz += 14;
+	}
+
+	pkt_copy = rtw_skb_alloc(alloc_sz);
+
+	if (pkt_copy) {
+		pkt_copy->dev = padapter->pnetdev;
+		pkt_copy->len = skb_len;
+		precvframe->u.hdr.pkt = pkt_copy;
+		precvframe->u.hdr.rx_head = pkt_copy->head;
+		precvframe->u.hdr.rx_end = pkt_copy->data + alloc_sz;
+		skb_reserve(pkt_copy, 8 - ((SIZE_PTR)(pkt_copy->data) & 7));  /* force pkt_copy->data at 8-byte alignment address */
+		skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */
+		memcpy(pkt_copy->data, pdata, skb_len);
+		precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_copy->data;
+	} else {
+#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
+		RTW_INFO("%s:can not allocate memory for skb copy\n", __func__);
+
+		precvframe->u.hdr.pkt = NULL;
+
+		/* rtw_free_recvframe(precvframe, pfree_recv_queue); */
+		/*exit_rtw_os_recv_resource_alloc;*/
+
+		res = _FAIL;
+#else
+		if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
+			RTW_INFO("%s: alloc_skb fail , drop frag frame\n", __func__);
+			/* rtw_free_recvframe(precvframe, pfree_recv_queue); */
+			res = _FAIL;
+			goto exit_rtw_os_recv_resource_alloc;
+		}
+
+		if (pskb == NULL) {
+			res = _FAIL;
+			goto exit_rtw_os_recv_resource_alloc;
+		}
+
+		precvframe->u.hdr.pkt = rtw_skb_clone(pskb);
+		if (precvframe->u.hdr.pkt) {
+			precvframe->u.hdr.pkt->dev = padapter->pnetdev;
+			precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pdata;
+			precvframe->u.hdr.rx_end =  pdata + alloc_sz;
+		} else {
+			RTW_INFO("%s: rtw_skb_clone fail\n", __func__);
+			/* rtw_free_recvframe(precvframe, pfree_recv_queue); */
+			/*exit_rtw_os_recv_resource_alloc;*/
+			res = _FAIL;
+		}
+#endif
+	}
+
+exit_rtw_os_recv_resource_alloc:
+
+	return res;
+
+}
+
+void rtw_os_free_recvframe(union recv_frame *precvframe)
+{
+	if (precvframe->u.hdr.pkt) {
+		rtw_skb_free(precvframe->u.hdr.pkt);/* free skb by driver */
+
+		precvframe->u.hdr.pkt = NULL;
+	}
+}
+
+/* init os related resource in struct recv_priv */
+int rtw_os_recv_resource_init(struct recv_priv *precvpriv, _adapter *padapter)
+{
+	int	res = _SUCCESS;
+
+
+#ifdef CONFIG_RTW_NAPI
+	skb_queue_head_init(&precvpriv->rx_napi_skb_queue);
+#endif /* CONFIG_RTW_NAPI */
+
+	return res;
+}
+
+/* alloc os related resource in union recv_frame */
+int rtw_os_recv_resource_alloc(_adapter *padapter, union recv_frame *precvframe)
+{
+	int	res = _SUCCESS;
+
+	precvframe->u.hdr.pkt_newalloc = precvframe->u.hdr.pkt = NULL;
+
+	return res;
+}
+
+/* free os related resource in union recv_frame */
+void rtw_os_recv_resource_free(struct recv_priv *precvpriv)
+{
+	sint i;
+	union recv_frame *precvframe;
+
+	precvframe = (union recv_frame *) precvpriv->precv_frame_buf;
+
+#ifdef CONFIG_RTW_NAPI
+	if (skb_queue_len(&precvpriv->rx_napi_skb_queue))
+		RTW_WARN("rx_napi_skb_queue not empty\n");
+	rtw_skb_queue_purge(&precvpriv->rx_napi_skb_queue);
+#endif /* CONFIG_RTW_NAPI */
+
+	for (i = 0; i < NR_RECVFRAME; i++) {
+		if (precvframe->u.hdr.pkt) {
+			rtw_skb_free(precvframe->u.hdr.pkt);/* free skb by driver */
+			precvframe->u.hdr.pkt = NULL;
+		}
+		precvframe++;
+	}
+}
+
+/* alloc os related resource in struct recv_buf */
+int rtw_os_recvbuf_resource_alloc(_adapter *padapter, struct recv_buf *precvbuf)
+{
+	int res = _SUCCESS;
+	struct dvobj_priv	*pdvobjpriv = adapter_to_dvobj(padapter);
+	struct usb_device	*pusbd = pdvobjpriv->pusbdev;
+
+	precvbuf->irp_pending = false;
+	precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
+	if (precvbuf->purb == NULL)
+		res = _FAIL;
+
+	precvbuf->pskb = NULL;
+
+	precvbuf->pallocated_buf  = precvbuf->pbuf = NULL;
+
+	precvbuf->pdata = precvbuf->phead = precvbuf->ptail = precvbuf->pend = NULL;
+
+	precvbuf->transfer_len = 0;
+
+	precvbuf->len = 0;
+
+#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
+	precvbuf->pallocated_buf = rtw_usb_buffer_alloc(pusbd, (size_t)precvbuf->alloc_sz, &precvbuf->dma_transfer_addr);
+	precvbuf->pbuf = precvbuf->pallocated_buf;
+	if (precvbuf->pallocated_buf == NULL)
+		return _FAIL;
+#endif /* CONFIG_USE_USB_BUFFER_ALLOC_RX */
+
+	return res;
+}
+
+/* free os related resource in struct recv_buf */
+int rtw_os_recvbuf_resource_free(_adapter *padapter, struct recv_buf *precvbuf)
+{
+	int ret = _SUCCESS;
+
+#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
+
+	struct dvobj_priv	*pdvobjpriv = adapter_to_dvobj(padapter);
+	struct usb_device	*pusbd = pdvobjpriv->pusbdev;
+
+	rtw_usb_buffer_free(pusbd, (size_t)precvbuf->alloc_sz, precvbuf->pallocated_buf, precvbuf->dma_transfer_addr);
+	precvbuf->pallocated_buf =  NULL;
+	precvbuf->dma_transfer_addr = 0;
+
+#endif /* CONFIG_USE_USB_BUFFER_ALLOC_RX */
+
+	if (precvbuf->purb) {
+		/* usb_kill_urb(precvbuf->purb); */
+		usb_free_urb(precvbuf->purb);
+	}
+
+	if (precvbuf->pskb) {
+#ifdef CONFIG_PREALLOC_RX_SKB_BUFFER
+		if (rtw_free_skb_premem(precvbuf->pskb) != 0)
+#endif
+			rtw_skb_free(precvbuf->pskb);
+	}
+	return ret;
+
+}
+
+_pkt *rtw_os_alloc_msdu_pkt(union recv_frame *prframe, u16 nSubframe_Length, u8 *pdata)
+{
+	u16	eth_type;
+	u8	*data_ptr;
+	_pkt *sub_skb;
+	struct rx_pkt_attrib *pattrib;
+
+	pattrib = &prframe->u.hdr.attrib;
+
+#ifdef CONFIG_SKB_COPY
+	sub_skb = rtw_skb_alloc(nSubframe_Length + 12);
+	if (sub_skb) {
+		skb_reserve(sub_skb, 12);
+		data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
+		memcpy(data_ptr, (pdata + ETH_HLEN), nSubframe_Length);
+	} else
+#endif /* CONFIG_SKB_COPY */
+	{
+		sub_skb = rtw_skb_clone(prframe->u.hdr.pkt);
+		if (sub_skb) {
+			sub_skb->data = pdata + ETH_HLEN;
+			sub_skb->len = nSubframe_Length;
+			skb_set_tail_pointer(sub_skb, nSubframe_Length);
+		} else {
+			RTW_INFO("%s(): rtw_skb_clone() Fail!!!\n", __func__);
+			return NULL;
+		}
+	}
+
+	eth_type = RTW_GET_BE16(&sub_skb->data[6]);
+
+	if (sub_skb->len >= 8 &&
+	    ((!memcmp(sub_skb->data, rtw_rfc1042_header, SNAP_SIZE) &&
+	      eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
+	     !memcmp(sub_skb->data, rtw_bridge_tunnel_header, SNAP_SIZE))) {
+		/* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
+		skb_pull(sub_skb, SNAP_SIZE);
+		memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN);
+		memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN);
+	} else {
+		__be16 len;
+		/* Leave Ethernet header part of hdr and full payload */
+		len = htons(sub_skb->len);
+		memcpy(skb_push(sub_skb, 2), &len, 2);
+		memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN);
+		memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN);
+	}
+
+	return sub_skb;
+}
+
+#ifdef CONFIG_RTW_NAPI
+static int napi_recv(_adapter *padapter, int budget)
+{
+	_pkt *pskb;
+	struct recv_priv *precvpriv = &padapter->recvpriv;
+	int work_done = 0;
+	struct registry_priv *pregistrypriv = &padapter->registrypriv;
+	u8 rx_ok;
+
+	while ((work_done < budget) &&
+	       (!skb_queue_empty(&precvpriv->rx_napi_skb_queue))) {
+		pskb = skb_dequeue(&precvpriv->rx_napi_skb_queue);
+		if (!pskb)
+			break;
+
+		rx_ok = false;
+
+#ifdef CONFIG_RTW_GRO
+		if (pregistrypriv->en_gro) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
+			if (rtw_napi_gro_receive(&padapter->napi, pskb) != GRO_DROP)
+				rx_ok = true;
+#else
+			rx_ok = true;
+#endif
+			goto next;
+		}
+#endif /* CONFIG_RTW_GRO */
+
+		if (rtw_netif_receive_skb(padapter->pnetdev, pskb) == NET_RX_SUCCESS)
+			rx_ok = true;
+
+#ifdef CONFIG_RTW_GRO
+next:
+#endif /* CONFIG_RTW_GRO */
+		if (rx_ok) {
+			work_done++;
+			DBG_COUNTER(padapter->rx_logs.os_netif_ok);
+		} else {
+			DBG_COUNTER(padapter->rx_logs.os_netif_err);
+		}
+	}
+	return work_done;
+}
+
+int rtw_recv_napi_poll(struct napi_struct *napi, int budget)
+{
+	_adapter *padapter = container_of(napi, _adapter, napi);
+	int work_done = 0;
+	struct recv_priv *precvpriv = &padapter->recvpriv;
+
+	work_done = napi_recv(padapter, budget);
+	if (work_done < budget) {
+		napi_complete(napi);
+		if (!skb_queue_empty(&precvpriv->rx_napi_skb_queue))
+			napi_schedule(napi);
+	}
+	return work_done;
+}
+#endif /* CONFIG_RTW_NAPI */
+
+#ifdef DBG_UDP_PKT_LOSE_11AC
+	#define PAYLOAD_LEN_LOC_OF_IP_HDR 0x10 /*ethernet payload length location of ip header (DA + SA+eth_type+(version&hdr_len)) */
+#endif
+
+void rtw_os_recv_indicate_pkt(_adapter *padapter, _pkt *pkt, struct rx_pkt_attrib *pattrib)
+{
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct recv_priv *precvpriv = &(padapter->recvpriv);
+	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+#ifdef CONFIG_BR_EXT
+	void *br_port = NULL;
+#endif
+	int ret;
+
+	/* Indicate the packets to upper layer */
+	if (pkt) {
+		if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+			_pkt *pskb2 = NULL;
+			struct sta_info *psta = NULL;
+			struct sta_priv *pstapriv = &padapter->stapriv;
+			int bmcast = IS_MCAST(pattrib->dst);
+
+			if (!memcmp(pattrib->dst, adapter_mac_addr(padapter), ETH_ALEN) == false) {
+				if (bmcast) {
+					psta = rtw_get_bcmc_stainfo(padapter);
+					pskb2 = rtw_skb_clone(pkt);
+				} else
+					psta = rtw_get_stainfo(pstapriv, pattrib->dst);
+
+				if (psta) {
+					struct net_device *pnetdev = (struct net_device *)padapter->pnetdev;
+
+					pkt->dev = pnetdev;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+					skb_set_queue_mapping(pkt, rtw_recv_select_queue(pkt));
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) */
+
+					_rtw_xmit_entry(pkt, pnetdev);
+
+					if (bmcast && (pskb2 != NULL)) {
+						pkt = pskb2;
+						DBG_COUNTER(padapter->rx_logs.os_indicate_ap_mcast);
+					} else {
+						DBG_COUNTER(padapter->rx_logs.os_indicate_ap_forward);
+						return;
+					}
+				}
+			} else { /* to APself */
+				DBG_COUNTER(padapter->rx_logs.os_indicate_ap_self);
+			}
+		}
+
+#ifdef CONFIG_BR_EXT
+		/* Insert NAT2.5 RX here! */
+#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)) */
+
+#endif /* CONFIG_BR_EXT */
+		if (precvpriv->sink_udpport > 0)
+			rtw_sink_rtp_seq_dbg(padapter, pkt);
+#ifdef DBG_UDP_PKT_LOSE_11AC
+		/* After eth_type_trans process , pkt->data pointer will move from ethrnet header to ip header ,
+		 * we have to check ethernet type , so this debug must be print before eth_type_trans
+		 */
+		if (*((unsigned short *)(pkt->data + ETH_ALEN * 2)) == htons(ETH_P_ARP)) {
+			/* ARP Payload length will be 42bytes or 42+18(tailer)=60bytes*/
+			if (pkt->len != 42 && pkt->len != 60)
+				RTW_INFO("Error !!%s,ARP Payload length %u not correct\n",
+					 __func__, pkt->len);
+		} else if (*((unsigned short *)(pkt->data + ETH_ALEN * 2)) == htons(ETH_P_IP)) {
+			if (be16_to_cpu(*((u16 *)(pkt->data + PAYLOAD_LEN_LOC_OF_IP_HDR))) !=
+					(pkt->len) - ETH_HLEN) {
+				RTW_INFO("Error !!%s,Payload length not correct\n", __func__);
+				RTW_INFO("%s, IP header describe Total length=%u\n",
+					 __func__, be16_to_cpu(*((u16 *)(pkt->data +
+							       PAYLOAD_LEN_LOC_OF_IP_HDR))));
+				RTW_INFO("%s, Pkt real length=%u\n", __func__,
+					 (pkt->len) - ETH_HLEN);
+			}
+		}
+#endif
+		/* After eth_type_trans process , pkt->data pointer will move from ethrnet header to ip header */
+		pkt->protocol = eth_type_trans(pkt, padapter->pnetdev);
+		pkt->dev = padapter->pnetdev;
+
+#ifdef CONFIG_TCP_CSUM_OFFLOAD_RX
+		if ((pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1))
+			pkt->ip_summed = CHECKSUM_UNNECESSARY;
+		else
+			pkt->ip_summed = CHECKSUM_NONE;
+#else /* !CONFIG_TCP_CSUM_OFFLOAD_RX */
+		pkt->ip_summed = CHECKSUM_NONE;
+#endif /* CONFIG_TCP_CSUM_OFFLOAD_RX */
+
+#ifdef CONFIG_RTW_NAPI
+		if (pregistrypriv->en_napi) {
+			skb_queue_tail(&precvpriv->rx_napi_skb_queue, pkt);
+			napi_schedule(&padapter->napi);
+			return;
+		}
+#endif /* CONFIG_RTW_NAPI */
+
+		ret = rtw_netif_rx(padapter->pnetdev, pkt);
+		if (ret == NET_RX_SUCCESS)
+			DBG_COUNTER(padapter->rx_logs.os_netif_ok);
+		else
+			DBG_COUNTER(padapter->rx_logs.os_netif_err);
+	}
+}
+
+void rtw_handle_tkip_mic_err(_adapter *padapter, struct sta_info *sta, u8 bgroup)
+{
+#ifdef CONFIG_IOCTL_CFG80211
+	enum nl80211_key_type key_type = 0;
+#endif
+	union iwreq_data wrqu;
+	struct iw_michaelmicfailure    ev;
+	struct mlme_priv              *pmlmepriv  = &padapter->mlmepriv;
+	struct security_priv	*psecuritypriv = &padapter->securitypriv;
+	u32 cur_time = 0;
+
+	if (psecuritypriv->last_mic_err_time == 0) {
+		psecuritypriv->last_mic_err_time = jiffies;
+	} else {
+		cur_time = jiffies;
+
+		if (cur_time - psecuritypriv->last_mic_err_time < 60 * HZ) {
+			psecuritypriv->btkip_countermeasure = true;
+			psecuritypriv->last_mic_err_time = 0;
+			psecuritypriv->btkip_countermeasure_time = cur_time;
+		} else {
+			psecuritypriv->last_mic_err_time = jiffies;
+		}
+	}
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if (bgroup)
+		key_type |= NL80211_KEYTYPE_GROUP;
+	else
+		key_type |= NL80211_KEYTYPE_PAIRWISE;
+
+	cfg80211_michael_mic_failure(padapter->pnetdev, sta->hwaddr, key_type, -1, NULL, GFP_ATOMIC);
+#endif
+
+	memset(&ev, 0x00, sizeof(ev));
+	if (bgroup)
+		ev.flags |= IW_MICFAILURE_GROUP;
+	else
+		ev.flags |= IW_MICFAILURE_PAIRWISE;
+
+	ev.src_addr.sa_family = ARPHRD_ETHER;
+	memcpy(ev.src_addr.sa_data, sta->hwaddr, ETH_ALEN);
+
+	memset(&wrqu, 0x00, sizeof(wrqu));
+	wrqu.data.length = sizeof(ev);
+
+#ifndef CONFIG_IOCTL_CFG80211
+	wireless_send_event(padapter->pnetdev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev);
+#endif
+}
+
+void rtw_hostapd_mlme_rx(_adapter *padapter, union recv_frame *precv_frame)
+{
+#ifdef CONFIG_HOSTAPD_MLME
+	_pkt *skb;
+	struct hostapd_priv *phostapdpriv  = padapter->phostapdpriv;
+	struct net_device *pmgnt_netdev = phostapdpriv->pmgnt_netdev;
+
+	skb = precv_frame->u.hdr.pkt;
+
+	if (!skb)
+		return;
+
+	skb->data = precv_frame->u.hdr.rx_data;
+	skb->tail = precv_frame->u.hdr.rx_tail;
+	skb->len = precv_frame->u.hdr.len;
+
+	skb->dev = pmgnt_netdev;
+	skb->ip_summed = CHECKSUM_NONE;
+	skb->pkt_type = PACKET_OTHERHOST;
+	skb->protocol = htons(0x0003); /*ETH_P_80211_RAW*/
+
+	skb_reset_mac_header(skb);
+
+	memset(skb->cb, 0, sizeof(skb->cb));
+
+	rtw_netif_rx(pmgnt_netdev, skb);
+
+	precv_frame->u.hdr.pkt = NULL; /* set pointer to NULL before rtw_free_recvframe() if call rtw_netif_rx() */
+#endif
+}
+
+#ifdef CONFIG_AUTO_AP_MODE
+static void rtw_os_ksocket_send(_adapter *padapter, union recv_frame *precv_frame)
+{
+	_pkt *skb = precv_frame->u.hdr.pkt;
+	struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+	struct sta_info *psta = precv_frame->u.hdr.psta;
+
+	RTW_INFO("eth rx: got eth_type=0x%x\n", pattrib->eth_type);
+
+	if (psta && psta->isrc && psta->pid > 0) {
+		u16 rx_pid;
+
+		rx_pid = *(u16 *)(skb->data + ETH_HLEN);
+
+		RTW_INFO("eth 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 *)(skb->data + ETH_HLEN + 2);
+
+			RTW_INFO("eth, RC: len=0x%x\n", len);
+
+			for (i = 0; i < len; i++)
+				RTW_INFO("0x%x\n", *(skb->data + ETH_HLEN + 4 + i));
+
+			RTW_INFO("eth, RC-end\n");
+
+		}
+
+	}
+
+}
+#endif /* CONFIG_AUTO_AP_MODE */
+
+int rtw_recv_monitor(_adapter *padapter, union recv_frame *precv_frame)
+{
+	int ret = _FAIL;
+	struct recv_priv *precvpriv;
+	_queue	*pfree_recv_queue;
+	_pkt *skb;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct rx_pkt_attrib *pattrib;
+
+	if (!precv_frame)
+		goto _recv_drop;
+
+	pattrib = &precv_frame->u.hdr.attrib;
+	precvpriv = &(padapter->recvpriv);
+	pfree_recv_queue = &(precvpriv->free_recv_queue);
+
+	skb = precv_frame->u.hdr.pkt;
+	if (!skb) {
+		RTW_INFO("%s :skb==NULL something wrong!!!!\n", __func__);
+		goto _recv_drop;
+	}
+
+	skb->data = precv_frame->u.hdr.rx_data;
+	skb_set_tail_pointer(skb, precv_frame->u.hdr.len);
+	skb->len = precv_frame->u.hdr.len;
+	skb->ip_summed = CHECKSUM_NONE;
+	skb->pkt_type = PACKET_OTHERHOST;
+	skb->protocol = htons(0x0019); /* ETH_P_80211_RAW */
+
+	rtw_netif_rx(padapter->pnetdev, skb);
+
+	/* pointers to NULL before rtw_free_recvframe() */
+	precv_frame->u.hdr.pkt = NULL;
+
+	ret = _SUCCESS;
+
+_recv_drop:
+
+	/* enqueue back to free_recv_queue */
+	if (precv_frame)
+		rtw_free_recvframe(precv_frame, pfree_recv_queue);
+
+	return ret;
+}
+
+static inline void check_reg_rule(struct sta_info *sta, u8 *ip, _adapter *padapter)
+{
+	u8 *tcp = ip + GET_IPV4_IHL(ip) * 4;
+
+	if (rtw_st_ctl_chk_reg_rule(&sta->st_ctl, padapter, IPV4_DST(ip),
+				    TCP_DST(tcp), IPV4_SRC(ip), TCP_SRC(tcp))) {
+		if (GET_TCP_SYN(tcp) && GET_TCP_ACK(tcp)) {
+			session_tracker_add_cmd(padapter, sta, IPV4_DST(ip),
+						TCP_DST(tcp), IPV4_SRC(ip),
+						TCP_SRC(tcp));
+			if (DBG_SESSION_TRACKER)
+				RTW_INFO(FUNC_ADPT_FMT" local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT" SYN-ACK\n",
+					 FUNC_ADPT_ARG(padapter),
+					 IP_ARG(IPV4_DST(ip)), PORT_ARG(TCP_DST(tcp)),
+					 IP_ARG(IPV4_SRC(ip)), PORT_ARG(TCP_SRC(tcp)));
+		}
+		if (GET_TCP_FIN(tcp)) {
+			session_tracker_del_cmd(padapter, sta,
+						IPV4_DST(ip), TCP_DST(tcp),
+						IPV4_SRC(ip), TCP_SRC(tcp));
+			if (DBG_SESSION_TRACKER)
+				RTW_INFO(FUNC_ADPT_FMT" local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT" FIN\n",
+					 FUNC_ADPT_ARG(padapter),
+					 IP_ARG(IPV4_DST(ip)), PORT_ARG(TCP_DST(tcp)),
+					 IP_ARG(IPV4_SRC(ip)), PORT_ARG(TCP_SRC(tcp)));
+		}
+	}
+}
+
+int rtw_recv_indicatepkt(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct recv_priv *precvpriv;
+	_queue	*pfree_recv_queue;
+	_pkt *skb;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct rx_pkt_attrib *pattrib;
+
+	if (!precv_frame)
+		goto _recv_indicatepkt_drop;
+
+	DBG_COUNTER(padapter->rx_logs.os_indicate);
+	pattrib = &precv_frame->u.hdr.attrib;
+	precvpriv = &(padapter->recvpriv);
+	pfree_recv_queue = &(precvpriv->free_recv_queue);
+
+#ifdef CONFIG_DRVEXT_MODULE
+	if (drvext_rx_handler(padapter, precv_frame->u.hdr.rx_data, precv_frame->u.hdr.len) == _SUCCESS)
+		goto _recv_indicatepkt_drop;
+#endif
+
+#ifdef CONFIG_WAPI_SUPPORT
+	if (rtw_wapi_check_for_drop(padapter, precv_frame)) {
+		WAPI_TRACE(WAPI_ERR, "%s(): Rx Reorder Drop case!!\n", __func__);
+		goto _recv_indicatepkt_drop;
+	}
+#endif
+
+	skb = precv_frame->u.hdr.pkt;
+	if (!skb)
+		goto _recv_indicatepkt_drop;
+
+	skb->data = precv_frame->u.hdr.rx_data;
+
+	skb_set_tail_pointer(skb, precv_frame->u.hdr.len);
+
+	skb->len = precv_frame->u.hdr.len;
+
+
+	if (pattrib->eth_type == cpu_to_le16(0x888e))
+		RTW_INFO("recv eapol packet\n");
+
+#ifdef CONFIG_AUTO_AP_MODE
+	if (pattrib->eth_type == 0x8899) {
+		rtw_os_ksocket_send(padapter, precv_frame);
+
+		/* goto _recv_indicatepkt_drop; */
+	}
+#endif /* CONFIG_AUTO_AP_MODE */
+
+	/* TODO: move to core */
+	{
+		_pkt *pkt = skb;
+		struct ethhdr *etherhdr = (struct ethhdr *)pkt->data;
+		struct sta_info *sta = precv_frame->u.hdr.psta;
+
+		if (!sta)
+			goto bypass_session_tracker;
+
+		if (ntohs(etherhdr->h_proto) == ETH_P_IP) {
+			u8 *ip = pkt->data + 14;
+
+			if (GET_IPV4_PROTOCOL(ip) == 0x06  /* TCP */
+			    && rtw_st_ctl_chk_reg_s_proto(&sta->st_ctl, 0x06))
+				check_reg_rule(sta, ip, padapter);
+		}
+bypass_session_tracker:
+		;
+	}
+
+	rtw_os_recv_indicate_pkt(padapter, skb, pattrib);
+
+	precv_frame->u.hdr.pkt = NULL; /* pointers to NULL before rtw_free_recvframe() */
+
+	rtw_free_recvframe(precv_frame, pfree_recv_queue);
+
+	return _SUCCESS;
+
+_recv_indicatepkt_drop:
+
+	/* enqueue back to free_recv_queue */
+	if (precv_frame)
+		rtw_free_recvframe(precv_frame, pfree_recv_queue);
+
+	DBG_COUNTER(padapter->rx_logs.os_indicate_err);
+
+	return _FAIL;
+}
+
+void rtw_os_read_port(_adapter *padapter, struct recv_buf *precvbuf)
+{
+	struct recv_priv *precvpriv = &padapter->recvpriv;
+
+	precvbuf->ref_cnt--;
+
+	/* free skb in recv_buf */
+	rtw_skb_free(precvbuf->pskb);
+
+	precvbuf->pskb = NULL;
+
+	if (precvbuf->irp_pending == false)
+		rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+static void _rtw_reordering_ctrl_timeout_handler(void *FunctionContext)
+#else
+static void _rtw_reordering_ctrl_timeout_handler(struct timer_list *t)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	struct recv_reorder_ctrl *preorder_ctrl = (struct recv_reorder_ctrl *)FunctionContext;
+#else
+	struct recv_reorder_ctrl *preorder_ctrl = from_timer(preorder_ctrl, t, reordering_ctrl_timer);
+#endif
+
+	rtw_reordering_ctrl_timeout_handler(preorder_ctrl);
+}
+
+void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
+{
+	_adapter *padapter = preorder_ctrl->padapter;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
+	_init_timer(&preorder_ctrl->reordering_ctrl_timer, padapter->pnetdev, _rtw_reordering_ctrl_timeout_handler, preorder_ctrl);
+#else
+	timer_setup(&preorder_ctrl->reordering_ctrl_timer, _rtw_reordering_ctrl_timeout_handler, 0);
+#endif
+
+}
diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_android.c b/drivers/staging/rtl8188eu/os_dep/rtw_android.c
new file mode 100644
index 000000000000..5c55717c1b5a
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/rtw_android.c
@@ -0,0 +1,1250 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+
+#ifdef CONFIG_GPIO_WAKEUP
+#include <linux/gpio.h>
+#endif
+
+#include <drv_types.h>
+
+#if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
+#include <linux/platform_device.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	#include <linux/wlan_plat.h>
+#else
+	#include <linux/wifi_tiwlan.h>
+#endif
+#endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
+#define strnicmp	strncasecmp
+#endif /* Linux kernel >= 4.0.0 */
+
+#ifdef CONFIG_GPIO_WAKEUP
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#endif
+
+#include "rtw_version.h"
+
+extern void macstr2num(u8 *dst, u8 *src);
+
+static const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
+	"START",
+	"STOP",
+	"SCAN-ACTIVE",
+	"SCAN-PASSIVE",
+	"RSSI",
+	"LINKSPEED",
+	"RXFILTER-START",
+	"RXFILTER-STOP",
+	"RXFILTER-ADD",
+	"RXFILTER-REMOVE",
+	"BTCOEXSCAN-START",
+	"BTCOEXSCAN-STOP",
+	"BTCOEXMODE",
+	"SETSUSPENDOPT",
+	"P2P_DEV_ADDR",
+	"SETFWPATH",
+	"SETBAND",
+	"GETBAND",
+	"COUNTRY",
+	"P2P_SET_NOA",
+	"P2P_GET_NOA",
+	"P2P_SET_PS",
+	"SET_AP_WPS_P2P_IE",
+
+	"MIRACAST",
+
+#ifdef CONFIG_PNO_SUPPORT
+	"PNOSSIDCLR",
+	"PNOSETUP",
+	"PNOFORCE",
+	"PNODEBUG",
+#endif
+
+	"MACADDR",
+
+	"BLOCK_SCAN",
+	"BLOCK",
+	"WFD-ENABLE",
+	"WFD-DISABLE",
+	"WFD-SET-TCPPORT",
+	"WFD-SET-MAXTPUT",
+	"WFD-SET-DEVTYPE",
+	"SET_DTIM",
+	"HOSTAPD_SET_MACADDR_ACL",
+	"HOSTAPD_ACL_ADD_STA",
+	"HOSTAPD_ACL_REMOVE_STA",
+#if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
+	"GTK_REKEY_OFFLOAD",
+#endif /* CONFIG_GTK_OL */
+/*	Private command for	P2P disable*/
+	"P2P_DISABLE",
+	"DRIVER_VERSION"
+};
+
+#ifdef CONFIG_PNO_SUPPORT
+#define PNO_TLV_PREFIX			'S'
+#define PNO_TLV_VERSION			'1'
+#define PNO_TLV_SUBVERSION		'2'
+#define PNO_TLV_RESERVED		'0'
+#define PNO_TLV_TYPE_SSID_IE	'S'
+#define PNO_TLV_TYPE_TIME		'T'
+#define PNO_TLV_FREQ_REPEAT		'R'
+#define PNO_TLV_FREQ_EXPO_MAX	'M'
+
+typedef struct cmd_tlv {
+	char prefix;
+	char version;
+	char subver;
+	char reserved;
+} cmd_tlv_t;
+
+#ifdef CONFIG_PNO_SET_DEBUG
+char pno_in_example[] = {
+	'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
+	'S', '1', '2', '0',
+	'S',	/* 1 */
+	0x05,
+	'd', 'l', 'i', 'n', 'k',
+	'S',	/* 2 */
+	0x06,
+	'B', 'U', 'F', 'B', 'U', 'F',
+	'S',	/* 3 */
+	0x20,
+	'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '!', '@', '#', '$', '%', '^',
+	'S',	/* 4 */
+	0x0a,
+	'!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
+	'T',
+	'0', '5',
+	'R',
+	'2',
+	'M',
+	'2',
+	0x00
+};
+#endif /* CONFIG_PNO_SET_DEBUG */
+#endif /* PNO_SUPPORT */
+
+typedef struct android_wifi_priv_cmd {
+	char *buf;
+	int used_len;
+	int total_len;
+} android_wifi_priv_cmd;
+
+#ifdef CONFIG_COMPAT
+typedef struct compat_android_wifi_priv_cmd {
+	compat_uptr_t buf;
+	int used_len;
+	int total_len;
+} compat_android_wifi_priv_cmd;
+#endif /* CONFIG_COMPAT */
+
+/**
+ * Local (static) functions and variables
+ */
+
+/* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
+ * time (only) in dhd_open, subsequential wifi on will be handled by
+ * wl_android_wifi_on
+ */
+static int g_wifi_on = true;
+
+static unsigned int oob_irq = 0;
+static unsigned int oob_gpio = 0;
+
+#ifdef CONFIG_PNO_SUPPORT
+/*
+ * rtw_android_pno_setup
+ * Description:
+ * This is used for private command.
+ *
+ * Parameter:
+ * net: net_device
+ * command: parameters from private command
+ * total_len: the length of the command.
+ *
+ * */
+static int rtw_android_pno_setup(struct net_device *net, char *command, int total_len)
+{
+	pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
+	int res = -1;
+	int nssid = 0;
+	cmd_tlv_t *cmd_tlv_temp;
+	char *str_ptr;
+	int tlv_size_left;
+	int pno_time = 0;
+	int pno_repeat = 0;
+	int pno_freq_expo_max = 0;
+	int cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOSETUP_SET]) + 1;
+
+#ifdef CONFIG_PNO_SET_DEBUG
+	int i;
+	char *p;
+	p = pno_in_example;
+
+	total_len = sizeof(pno_in_example);
+	str_ptr = p + cmdlen;
+#else
+	str_ptr = command + cmdlen;
+#endif
+
+	if (total_len < (cmdlen + sizeof(cmd_tlv_t))) {
+		RTW_INFO("%s argument=%d less min size\n", __func__, total_len);
+		goto exit_proc;
+	}
+
+	tlv_size_left = total_len - cmdlen;
+
+	cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
+	memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
+
+	if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
+	    (cmd_tlv_temp->version == PNO_TLV_VERSION) &&
+	    (cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) {
+
+		str_ptr += sizeof(cmd_tlv_t);
+		tlv_size_left -= sizeof(cmd_tlv_t);
+
+		nssid = rtw_parse_ssid_list_tlv(&str_ptr, pno_ssids_local,
+			     MAX_PNO_LIST_COUNT, &tlv_size_left);
+		if (nssid <= 0) {
+			RTW_INFO("SSID is not presented or corrupted ret=%d\n", nssid);
+			goto exit_proc;
+		} else {
+			if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
+				RTW_INFO("%s scan duration corrupted field size %d\n",
+					 __func__, tlv_size_left);
+				goto exit_proc;
+			}
+			str_ptr++;
+			pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
+			RTW_INFO("%s: pno_time=%d\n", __func__, pno_time);
+
+			if (str_ptr[0] != 0) {
+				if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
+					RTW_INFO("%s pno repeat : corrupted field\n",
+						 __func__);
+					goto exit_proc;
+				}
+				str_ptr++;
+				pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
+				RTW_INFO("%s :got pno_repeat=%d\n", __func__, pno_repeat);
+				if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
+					RTW_INFO("%s FREQ_EXPO_MAX corrupted field size\n",
+						 __func__);
+					goto exit_proc;
+				}
+				str_ptr++;
+				pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
+				RTW_INFO("%s: pno_freq_expo_max=%d\n",
+					 __func__, pno_freq_expo_max);
+			}
+		}
+	} else {
+		RTW_INFO("%s get wrong TLV command\n", __func__);
+		goto exit_proc;
+	}
+
+	res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
+
+#ifdef CONFIG_PNO_SET_DEBUG
+	rtw_dev_pno_debug(net);
+#endif
+
+exit_proc:
+	return res;
+}
+
+/*
+ * rtw_android_cfg80211_pno_setup
+ * Description:
+ * This is used for cfg80211 sched_scan.
+ *
+ * Parameter:
+ * net: net_device
+ * request: cfg80211_request
+ * */
+
+int rtw_android_cfg80211_pno_setup(struct net_device *net,
+		   struct cfg80211_ssid *ssids, int n_ssids, int interval)
+{
+	int res = -1;
+	int nssid = 0;
+	int pno_time = 0;
+	int pno_repeat = 0;
+	int pno_freq_expo_max = 0;
+	int index = 0;
+	pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
+
+	if (n_ssids > MAX_PNO_LIST_COUNT || n_ssids < 0) {
+		RTW_INFO("%s: nssids(%d) is invalid.\n", __func__, n_ssids);
+		return -EINVAL;
+	}
+
+	memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
+
+	nssid = n_ssids;
+
+	for (index = 0 ; index < nssid ; index++) {
+		pno_ssids_local[index].SSID_len = ssids[index].ssid_len;
+		memcpy(pno_ssids_local[index].SSID, ssids[index].ssid,
+		       ssids[index].ssid_len);
+	}
+
+	pno_time = (interval / 1000);
+
+	RTW_INFO("%s: nssids: %d, pno_time=%d\n", __func__, nssid, pno_time);
+
+	res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time,
+			      pno_repeat, pno_freq_expo_max);
+
+#ifdef CONFIG_PNO_SET_DEBUG
+	rtw_dev_pno_debug(net);
+#endif
+exit_proc:
+	return res;
+}
+
+int rtw_android_pno_enable(struct net_device *net, int pno_enable)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+	struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
+
+	if (pwrctl) {
+		pwrctl->wowlan_pno_enable = pno_enable;
+		RTW_INFO("%s: wowlan_pno_enable: %d\n", __func__, pwrctl->wowlan_pno_enable);
+		if (pwrctl->wowlan_pno_enable == 0) {
+			if (pwrctl->pnlo_info != NULL) {
+				rtw_mfree((u8 *)pwrctl->pnlo_info, sizeof(pno_nlo_info_t));
+				pwrctl->pnlo_info = NULL;
+			}
+			if (pwrctl->pno_ssid_list != NULL) {
+				rtw_mfree((u8 *)pwrctl->pno_ssid_list, sizeof(pno_ssid_list_t));
+				pwrctl->pno_ssid_list = NULL;
+			}
+			if (pwrctl->pscan_info != NULL) {
+				rtw_mfree((u8 *)pwrctl->pscan_info, sizeof(pno_scan_info_t));
+				pwrctl->pscan_info = NULL;
+			}
+		}
+		return 0;
+	} else
+		return -1;
+}
+#endif /* CONFIG_PNO_SUPPORT */
+
+int rtw_android_cmdstr_to_num(char *cmdstr)
+{
+	int cmd_num;
+	for (cmd_num = 0 ; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
+		if (0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])))
+			break;
+
+	return cmd_num;
+}
+
+static int rtw_android_get_rssi(struct net_device *net, char *command, int total_len)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	struct	wlan_network	*pcur_network = &pmlmepriv->cur_network;
+	int bytes_written = 0;
+
+	if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+		bytes_written += snprintf(&command[bytes_written], total_len, "%s rssi %d",
+			pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
+	}
+
+	return bytes_written;
+}
+
+static int rtw_android_get_link_speed(struct net_device *net, char *command, int total_len)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	struct	wlan_network	*pcur_network = &pmlmepriv->cur_network;
+	int bytes_written = 0;
+	u16 link_speed = 0;
+
+	link_speed = rtw_get_cur_max_rate(padapter) / 10;
+	bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
+
+	return bytes_written;
+}
+
+static int rtw_android_get_macaddr(struct net_device *net, char *command, int total_len)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
+	int bytes_written = 0;
+
+	bytes_written = snprintf(command, total_len, "Macaddr = "MAC_FMT, MAC_ARG(net->dev_addr));
+	return bytes_written;
+}
+
+static int rtw_android_set_country(struct net_device *net, char *command, int total_len)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
+	char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
+	int ret = _FAIL;
+
+	ret = rtw_set_country(adapter, country_code);
+
+	return (ret == _SUCCESS) ? 0 : -1;
+}
+
+static int rtw_android_get_p2p_dev_addr(struct net_device *net, char *command, int total_len)
+{
+	int bytes_written = 0;
+
+	/* We use the same address as our HW MAC address */
+	memcpy(command, net->dev_addr, ETH_ALEN);
+
+	bytes_written = ETH_ALEN;
+	return bytes_written;
+}
+
+static int rtw_android_set_block_scan(struct net_device *net, char *command, int total_len)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
+	char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK_SCAN]) + 1;
+
+#ifdef CONFIG_IOCTL_CFG80211
+	adapter_wdev_data(adapter)->block_scan = (*block_value == '0') ? false : true;
+#endif
+
+	return 0;
+}
+
+static int rtw_android_set_block(struct net_device *net, char *command, int total_len)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
+	char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK]) + 1;
+
+#ifdef CONFIG_IOCTL_CFG80211
+	adapter_wdev_data(adapter)->block = (*block_value == '0') ? false : true;
+#endif
+
+	return 0;
+}
+
+static int rtw_android_setband(struct net_device *net, char *command, int total_len)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
+	char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SETBAND]) + 1;
+	u32 band = WIFI_FREQUENCY_BAND_AUTO;
+	int ret = _FAIL;
+
+	if (sscanf(arg, "%u", &band) >= 1)
+		ret = rtw_set_band(adapter, band);
+
+	return (ret == _SUCCESS) ? 0 : -1;
+}
+
+static int rtw_android_getband(struct net_device *net, char *command, int total_len)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
+	int bytes_written = 0;
+
+	bytes_written = snprintf(command, total_len, "%u", adapter->setband);
+
+	return bytes_written;
+}
+
+#ifdef CONFIG_WFD
+static int rtw_android_set_miracast_mode(struct net_device *net, char *command, int total_len)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
+	struct wifi_display_info *wfd_info = &adapter->wfd_info;
+	char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_MIRACAST]) + 1;
+	u8 mode;
+	int num;
+	int ret = _FAIL;
+
+	num = sscanf(arg, "%hhu", &mode);
+
+	if (num < 1)
+		goto exit;
+
+	switch (mode) {
+	case 1: /* soruce */
+		mode = MIRACAST_SOURCE;
+		break;
+	case 2: /* sink */
+		mode = MIRACAST_SINK;
+		break;
+	case 0: /* disabled */
+	default:
+		mode = MIRACAST_DISABLED;
+		break;
+	}
+	wfd_info->stack_wfd_mode = mode;
+	RTW_INFO("stack miracast mode: %s\n", get_miracast_mode_str(wfd_info->stack_wfd_mode));
+
+	ret = _SUCCESS;
+
+exit:
+	return (ret == _SUCCESS) ? 0 : -1;
+}
+#endif /* CONFIG_WFD */
+
+static int get_int_from_command(char *pcmd)
+{
+	int i = 0;
+
+	for (i = 0; i < strlen(pcmd); i++) {
+		if (pcmd[i] == '=') {
+			/*	Skip the '=' and space characters. */
+			i += 2;
+			break;
+		}
+	}
+	return rtw_atoi(pcmd + i) ;
+}
+
+#if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
+int rtw_gtk_offload(struct net_device *net, u8 *cmd_ptr)
+{
+	int i;
+	/* u8 *cmd_ptr = priv_cmd.buf; */
+	struct sta_info *psta;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct security_priv *psecuritypriv = &(padapter->securitypriv);
+	psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
+
+
+	if (psta == NULL)
+		RTW_INFO("%s, : Obtain Sta_info fail\n", __func__);
+	else {
+		/* string command length of "GTK_REKEY_OFFLOAD" */
+		cmd_ptr += 18;
+
+		memcpy(psta->kek, cmd_ptr, RTW_KEK_LEN);
+		cmd_ptr += RTW_KEK_LEN;
+		/*
+		printk("supplicant KEK: ");
+		for(i=0;i<RTW_KEK_LEN; i++)
+			printk(" %02x ", psta->kek[i]);
+		printk("\n supplicant KCK: ");
+		*/
+		memcpy(psta->kck, cmd_ptr, RTW_KCK_LEN);
+		cmd_ptr += RTW_KCK_LEN;
+		/*
+		for(i=0;i<RTW_KEK_LEN; i++)
+			printk(" %02x ", psta->kck[i]);
+		*/
+		memcpy(psta->replay_ctr, cmd_ptr, RTW_REPLAY_CTR_LEN);
+		psecuritypriv->binstallKCK_KEK = true;
+
+		/* printk("\nREPLAY_CTR: "); */
+		/* for(i=0;i<RTW_REPLAY_CTR_LEN; i++) */
+		/* printk(" %02x ", psta->replay_ctr[i]); */
+	}
+
+	return _SUCCESS;
+}
+#endif /* CONFIG_GTK_OL */
+
+int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
+{
+	int ret = 0;
+	char *command = NULL;
+	int cmd_num;
+	int bytes_written = 0;
+#ifdef CONFIG_PNO_SUPPORT
+	uint cmdlen = 0;
+	uint pno_enable = 0;
+#endif
+	android_wifi_priv_cmd priv_cmd;
+	_adapter	*padapter = (_adapter *) rtw_netdev_priv(net);
+#ifdef CONFIG_WFD
+	struct wifi_display_info		*pwfd_info;
+#endif
+
+	rtw_lock_suspend();
+
+	if (!ifr->ifr_data) {
+		ret = -EINVAL;
+		goto exit;
+	}
+	if (padapter->registrypriv.mp_mode == 1) {
+		ret = -EINVAL;
+		goto exit;
+	}
+#ifdef CONFIG_COMPAT
+#if (KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE)
+	if (is_compat_task()) {
+#else
+	if (in_compat_syscall()) {
+#endif
+		/* User space is 32-bit, use compat ioctl */
+		compat_android_wifi_priv_cmd compat_priv_cmd;
+
+		if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) {
+			ret = -EFAULT;
+			goto exit;
+		}
+		priv_cmd.buf = compat_ptr(compat_priv_cmd.buf);
+		priv_cmd.used_len = compat_priv_cmd.used_len;
+		priv_cmd.total_len = compat_priv_cmd.total_len;
+	} else
+#endif /* CONFIG_COMPAT */
+		if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
+			ret = -EFAULT;
+			goto exit;
+		}
+	if (padapter->registrypriv.mp_mode == 1) {
+		ret = -EFAULT;
+		goto exit;
+	}
+	/*RTW_INFO("%s priv_cmd.buf=%p priv_cmd.total_len=%d  priv_cmd.used_len=%d\n",__func__,priv_cmd.buf,priv_cmd.total_len,priv_cmd.used_len);*/
+	command = rtw_zmalloc(priv_cmd.total_len);
+	if (!command) {
+		RTW_INFO("%s: failed to allocate memory\n", __func__);
+		ret = -ENOMEM;
+		goto exit;
+	}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
+	if (!access_ok(priv_cmd.buf, priv_cmd.total_len)) {
+#else
+	if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)) {
+#endif
+		RTW_DBG("%s: failed to access memory\n", __func__);
+		ret = -EFAULT;
+		goto exit;
+	}
+	if (copy_from_user(command, (void __user *)priv_cmd.buf, priv_cmd.total_len)) {
+		ret = -EFAULT;
+		goto exit;
+	}
+
+	RTW_INFO("%s: Android private cmd \"%s\" on %s\n"
+		 , __func__, command, ifr->ifr_name);
+
+	cmd_num = rtw_android_cmdstr_to_num(command);
+
+	switch (cmd_num) {
+	case ANDROID_WIFI_CMD_START:
+		/* bytes_written = wl_android_wifi_on(net); */
+		goto response;
+	case ANDROID_WIFI_CMD_SETFWPATH:
+		goto response;
+	}
+
+	if (!g_wifi_on) {
+		RTW_INFO("%s: Ignore private cmd \"%s\" - iface %s is down\n"
+			 , __func__, command, ifr->ifr_name);
+		ret = 0;
+		goto exit;
+	}
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
+		switch (cmd_num) {
+		case ANDROID_WIFI_CMD_WFD_ENABLE:
+		case ANDROID_WIFI_CMD_WFD_DISABLE:
+		case ANDROID_WIFI_CMD_WFD_SET_TCPPORT:
+		case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT:
+		case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE:
+			goto response;
+		}
+	}
+
+	switch (cmd_num) {
+
+	case ANDROID_WIFI_CMD_STOP:
+		/* bytes_written = wl_android_wifi_off(net); */
+		break;
+
+	case ANDROID_WIFI_CMD_SCAN_ACTIVE:
+		/* rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_ACTIVE); */
+#ifdef CONFIG_PLATFORM_MSTAR
+#ifdef CONFIG_IOCTL_CFG80211
+		adapter_wdev_data((_adapter *)rtw_netdev_priv(net))->bandroid_scan = true;
+#endif /* CONFIG_IOCTL_CFG80211 */
+#endif /* CONFIG_PLATFORM_MSTAR */
+		break;
+	case ANDROID_WIFI_CMD_SCAN_PASSIVE:
+		/* rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_PASSIVE); */
+		break;
+
+	case ANDROID_WIFI_CMD_RSSI:
+		bytes_written = rtw_android_get_rssi(net, command, priv_cmd.total_len);
+		break;
+	case ANDROID_WIFI_CMD_LINKSPEED:
+		bytes_written = rtw_android_get_link_speed(net, command, priv_cmd.total_len);
+		break;
+
+	case ANDROID_WIFI_CMD_MACADDR:
+		bytes_written = rtw_android_get_macaddr(net, command, priv_cmd.total_len);
+		break;
+
+	case ANDROID_WIFI_CMD_BLOCK_SCAN:
+		bytes_written = rtw_android_set_block_scan(net, command, priv_cmd.total_len);
+		break;
+
+	case ANDROID_WIFI_CMD_BLOCK:
+		bytes_written = rtw_android_set_block(net, command, priv_cmd.total_len);
+		break;
+
+	case ANDROID_WIFI_CMD_RXFILTER_START:
+		/* bytes_written = net_os_set_packet_filter(net, 1); */
+		break;
+	case ANDROID_WIFI_CMD_RXFILTER_STOP:
+		/* bytes_written = net_os_set_packet_filter(net, 0); */
+		break;
+	case ANDROID_WIFI_CMD_RXFILTER_ADD:
+		/* int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0'; */
+		/* bytes_written = net_os_rxfilter_add_remove(net, true, filter_num); */
+		break;
+	case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
+		/* int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0'; */
+		/* bytes_written = net_os_rxfilter_add_remove(net, false, filter_num); */
+		break;
+
+	case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
+		/* TBD: BTCOEXSCAN-START */
+		break;
+	case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
+		/* TBD: BTCOEXSCAN-STOP */
+		break;
+	case ANDROID_WIFI_CMD_BTCOEXMODE:
+		break;
+	case ANDROID_WIFI_CMD_SETSUSPENDOPT:
+		/* bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len); */
+		break;
+
+	case ANDROID_WIFI_CMD_SETBAND:
+		bytes_written = rtw_android_setband(net, command, priv_cmd.total_len);
+		break;
+
+	case ANDROID_WIFI_CMD_GETBAND:
+		bytes_written = rtw_android_getband(net, command, priv_cmd.total_len);
+		break;
+
+	case ANDROID_WIFI_CMD_COUNTRY:
+		bytes_written = rtw_android_set_country(net, command, priv_cmd.total_len);
+		break;
+
+#ifdef CONFIG_PNO_SUPPORT
+	case ANDROID_WIFI_CMD_PNOSSIDCLR_SET:
+		/* bytes_written = dhd_dev_pno_reset(net); */
+		break;
+	case ANDROID_WIFI_CMD_PNOSETUP_SET:
+		bytes_written = rtw_android_pno_setup(net, command, priv_cmd.total_len);
+		break;
+	case ANDROID_WIFI_CMD_PNOENABLE_SET:
+		cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOENABLE_SET]);
+		pno_enable = *(command + cmdlen + 1) - '0';
+		bytes_written = rtw_android_pno_enable(net, pno_enable);
+		break;
+#endif
+
+	case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
+		bytes_written = rtw_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
+		break;
+	case ANDROID_WIFI_CMD_P2P_SET_NOA:
+		/* int skip = strlen(CMD_P2P_SET_NOA) + 1; */
+		/* bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip); */
+		break;
+	case ANDROID_WIFI_CMD_P2P_GET_NOA:
+		/* bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len); */
+		break;
+	case ANDROID_WIFI_CMD_P2P_SET_PS:
+		/* int skip = strlen(CMD_P2P_SET_PS) + 1; */
+		/* bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip); */
+		break;
+
+#ifdef CONFIG_IOCTL_CFG80211
+	case ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE: {
+		int skip = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE]) + 3;
+		bytes_written = rtw_cfg80211_set_mgnt_wpsp2pie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0');
+		break;
+	}
+#endif /* CONFIG_IOCTL_CFG80211 */
+
+#ifdef CONFIG_WFD
+
+	case ANDROID_WIFI_CMD_MIRACAST:
+		bytes_written = rtw_android_set_miracast_mode(net, command, priv_cmd.total_len);
+		break;
+
+	case ANDROID_WIFI_CMD_WFD_ENABLE: {
+		/*	Commented by Albert 2012/07/24 */
+		/*	We can enable the WFD function by using the following command: */
+		/*	wpa_cli driver wfd-enable */
+
+		if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
+			rtw_wfd_enable(padapter, 1);
+		break;
+	}
+
+	case ANDROID_WIFI_CMD_WFD_DISABLE: {
+		/*	Commented by Albert 2012/07/24 */
+		/*	We can disable the WFD function by using the following command: */
+		/*	wpa_cli driver wfd-disable */
+
+		if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
+			rtw_wfd_enable(padapter, 0);
+		break;
+	}
+	case ANDROID_WIFI_CMD_WFD_SET_TCPPORT: {
+		/*	Commented by Albert 2012/07/24 */
+		/*	We can set the tcp port number by using the following command: */
+		/*	wpa_cli driver wfd-set-tcpport = 554 */
+
+		if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
+			rtw_wfd_set_ctrl_port(padapter, (u16)get_int_from_command(priv_cmd.buf));
+		break;
+	}
+	case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT: {
+		break;
+	}
+	case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE: {
+		/*	Commented by Albert 2012/08/28 */
+		/*	Specify the WFD device type ( WFD source/primary sink ) */
+
+		pwfd_info = &padapter->wfd_info;
+		if (padapter->wdinfo.driver_interface == DRIVER_CFG80211) {
+			pwfd_info->wfd_device_type = (u8) get_int_from_command(priv_cmd.buf);
+			pwfd_info->wfd_device_type &= WFD_DEVINFO_DUAL;
+		}
+		break;
+	}
+#endif
+	case ANDROID_WIFI_CMD_CHANGE_DTIM: {
+#ifdef CONFIG_LPS
+		u8 dtim;
+		u8 *ptr = (u8 *) &priv_cmd.buf;
+
+		ptr += 9;/* string command length of  "SET_DTIM"; */
+
+		dtim = rtw_atoi(ptr);
+
+		RTW_INFO("DTIM=%d\n", dtim);
+
+		rtw_lps_change_dtim_cmd(padapter, dtim);
+#endif
+	}
+	break;
+
+#if CONFIG_RTW_MACADDR_ACL
+	case ANDROID_WIFI_CMD_HOSTAPD_SET_MACADDR_ACL: {
+		rtw_set_macaddr_acl(padapter, get_int_from_command(command));
+		break;
+	}
+	case ANDROID_WIFI_CMD_HOSTAPD_ACL_ADD_STA: {
+		u8 addr[ETH_ALEN] = {0x00};
+		macstr2num(addr, command + strlen("HOSTAPD_ACL_ADD_STA") + 3);	/* 3 is space bar + "=" + space bar these 3 chars */
+		rtw_acl_add_sta(padapter, addr);
+		break;
+	}
+	case ANDROID_WIFI_CMD_HOSTAPD_ACL_REMOVE_STA: {
+		u8 addr[ETH_ALEN] = {0x00};
+		macstr2num(addr, command + strlen("HOSTAPD_ACL_REMOVE_STA") + 3);	/* 3 is space bar + "=" + space bar these 3 chars */
+		rtw_acl_remove_sta(padapter, addr);
+		break;
+	}
+#endif /* CONFIG_RTW_MACADDR_ACL */
+#if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
+	case ANDROID_WIFI_CMD_GTK_REKEY_OFFLOAD:
+		rtw_gtk_offload(net, (u8 *)command);
+		break;
+#endif /* CONFIG_GTK_OL		 */
+	case ANDROID_WIFI_CMD_P2P_DISABLE: {
+#ifdef CONFIG_P2P
+		struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+		u8 channel, ch_offset;
+		u16 bwmode;
+
+		rtw_p2p_enable(padapter, P2P_ROLE_DISABLE);
+#endif /* CONFIG_P2P */
+		break;
+	}
+	case ANDROID_WIFI_CMD_DRIVERVERSION: {
+		bytes_written = strlen(DRIVERVERSION);
+		snprintf(command, bytes_written + 1, DRIVERVERSION);
+		break;
+	}
+	default:
+		RTW_INFO("Unknown PRIVATE command %s - ignored\n", command);
+		snprintf(command, 3, "OK");
+		bytes_written = strlen("OK");
+	}
+
+response:
+	if (bytes_written >= 0) {
+		if ((bytes_written == 0) && (priv_cmd.total_len > 0))
+			command[0] = '\0';
+		if (bytes_written >= priv_cmd.total_len) {
+			RTW_INFO("%s: bytes_written = %d\n", __func__, bytes_written);
+			bytes_written = priv_cmd.total_len;
+		} else
+			bytes_written++;
+		priv_cmd.used_len = bytes_written;
+		if (copy_to_user((void __user *)priv_cmd.buf, command, bytes_written)) {
+			RTW_INFO("%s: failed to copy data to user buffer\n", __func__);
+			ret = -EFAULT;
+		}
+	} else
+		ret = bytes_written;
+
+exit:
+	rtw_unlock_suspend();
+	if (command)
+		rtw_mfree(command, priv_cmd.total_len);
+
+	return ret;
+}
+
+
+/**
+ * Functions for Android WiFi card detection
+ */
+#if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
+
+static int g_wifidev_registered = 0;
+static struct semaphore wifi_control_sem;
+static struct wifi_platform_data *wifi_control_data = NULL;
+static struct resource *wifi_irqres = NULL;
+
+static int wifi_add_dev(void);
+static void wifi_del_dev(void);
+
+int rtw_android_wifictrl_func_add(void)
+{
+	int ret = 0;
+	sema_init(&wifi_control_sem, 0);
+
+	ret = wifi_add_dev();
+	if (ret) {
+		RTW_INFO("%s: platform_driver_register failed\n", __func__);
+		return ret;
+	}
+	g_wifidev_registered = 1;
+
+	/* Waiting callback after platform_driver_register is done or exit with error */
+	if (down_timeout(&wifi_control_sem,  msecs_to_jiffies(1000)) != 0) {
+		ret = -EINVAL;
+		RTW_INFO("%s: platform_driver_register timeout\n", __func__);
+	}
+
+	return ret;
+}
+
+void rtw_android_wifictrl_func_del(void)
+{
+	if (g_wifidev_registered) {
+		wifi_del_dev();
+		g_wifidev_registered = 0;
+	}
+}
+
+void *wl_android_prealloc(int section, unsigned long size)
+{
+	void *alloc_ptr = NULL;
+	if (wifi_control_data && wifi_control_data->mem_prealloc) {
+		alloc_ptr = wifi_control_data->mem_prealloc(section, size);
+		if (alloc_ptr) {
+			RTW_INFO("success alloc section %d\n", section);
+			if (size != 0L)
+				memset(alloc_ptr, 0, size);
+			return alloc_ptr;
+		}
+	}
+
+	RTW_INFO("can't alloc section %d\n", section);
+	return NULL;
+}
+
+int wifi_get_irq_number(unsigned long *irq_flags_ptr)
+{
+	if (wifi_irqres) {
+		*irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
+		return (int)wifi_irqres->start;
+	}
+#ifdef CUSTOM_OOB_GPIO_NUM
+	return CUSTOM_OOB_GPIO_NUM;
+#else
+	return -1;
+#endif
+}
+
+int wifi_set_power(int on, unsigned long msec)
+{
+	RTW_INFO("%s = %d\n", __func__, on);
+	if (wifi_control_data && wifi_control_data->set_power)
+		wifi_control_data->set_power(on);
+	if (msec)
+		msleep(msec);
+	return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+int wifi_get_mac_addr(unsigned char *buf)
+{
+	RTW_INFO("%s\n", __func__);
+	if (!buf)
+		return -EINVAL;
+	if (wifi_control_data && wifi_control_data->get_mac_addr)
+		return wifi_control_data->get_mac_addr(buf);
+	return -EOPNOTSUPP;
+}
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) || defined(COMPAT_KERNEL_RELEASE)
+void *wifi_get_country_code(char *ccode)
+{
+	RTW_INFO("%s\n", __func__);
+	if (!ccode)
+		return NULL;
+	if (wifi_control_data && wifi_control_data->get_country_code)
+		return wifi_control_data->get_country_code(ccode);
+	return NULL;
+}
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
+
+static int wifi_set_carddetect(int on)
+{
+	RTW_INFO("%s = %d\n", __func__, on);
+	if (wifi_control_data && wifi_control_data->set_carddetect)
+		wifi_control_data->set_carddetect(on);
+	return 0;
+}
+
+static int wifi_probe(struct platform_device *pdev)
+{
+	struct wifi_platform_data *wifi_ctrl =
+		(struct wifi_platform_data *)(pdev->dev.platform_data);
+	int wifi_wake_gpio = 0;
+
+	RTW_INFO("## %s\n", __func__);
+	wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
+
+	if (wifi_irqres == NULL)
+		wifi_irqres = platform_get_resource_byname(pdev,
+				IORESOURCE_IRQ, "bcm4329_wlan_irq");
+	else
+		wifi_wake_gpio = wifi_irqres->start;
+
+#ifdef CONFIG_GPIO_WAKEUP
+	printk("%s: gpio:%d wifi_wake_gpio:%d\n", __func__,
+	       wifi_irqres->start, wifi_wake_gpio);
+
+	if (wifi_wake_gpio > 0) {
+#ifdef CONFIG_PLATFORM_INTEL_BYT
+		wifi_configure_gpio();
+#else /* CONFIG_PLATFORM_INTEL_BYT */
+		gpio_request(wifi_wake_gpio, "oob_irq");
+		gpio_direction_input(wifi_wake_gpio);
+		oob_irq = gpio_to_irq(wifi_wake_gpio);
+#endif /* CONFIG_PLATFORM_INTEL_BYT */
+		printk("%s oob_irq:%d\n", __func__, oob_irq);
+	} else if (wifi_irqres) {
+		oob_irq = wifi_irqres->start;
+		printk("%s oob_irq:%d\n", __func__, oob_irq);
+	}
+#endif
+	wifi_control_data = wifi_ctrl;
+
+	wifi_set_power(1, 0);	/* Power On */
+	wifi_set_carddetect(1);	/* CardDetect (0->1) */
+
+	up(&wifi_control_sem);
+	return 0;
+}
+
+#ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
+extern PADAPTER g_test_adapter;
+
+static void shutdown_card(void)
+{
+	u32 addr;
+	u8 tmp8, cnt = 0;
+
+	if (NULL == g_test_adapter) {
+		RTW_INFO("%s: padapter==NULL\n", __func__);
+		return;
+	}
+
+#ifdef CONFIG_FWLPS_IN_IPS
+	LeaveAllPowerSaveMode(g_test_adapter);
+#endif /* CONFIG_FWLPS_IN_IPS */
+
+	/* Leave SDIO HCI Suspend */
+	addr = 0x10250086;
+	rtw_write8(g_test_adapter, addr, 0);
+	do {
+		tmp8 = rtw_read8(g_test_adapter, addr);
+		cnt++;
+		RTW_INFO(FUNC_ADPT_FMT ": polling SDIO_HSUS_CTRL(0x%x)=0x%x, cnt=%d\n",
+			 FUNC_ADPT_ARG(g_test_adapter), addr, tmp8, cnt);
+
+		if (tmp8 & BIT(1))
+			break;
+
+		if (cnt >= 100) {
+			RTW_INFO(FUNC_ADPT_FMT ": polling 0x%x[1]==1 FAIL!!\n",
+				 FUNC_ADPT_ARG(g_test_adapter), addr);
+			break;
+		}
+
+		rtw_mdelay_os(10);
+	} while (1);
+
+	/* unlock register I/O */
+	rtw_write8(g_test_adapter, 0x1C, 0);
+
+	/* enable power down function */
+	/* 0x04[4] = 1 */
+	/* 0x05[7] = 1 */
+	addr = 0x04;
+	tmp8 = rtw_read8(g_test_adapter, addr);
+	tmp8 |= BIT(4);
+	rtw_write8(g_test_adapter, addr, tmp8);
+	RTW_INFO(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
+		FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
+
+	addr = 0x05;
+	tmp8 = rtw_read8(g_test_adapter, addr);
+	tmp8 |= BIT(7);
+	rtw_write8(g_test_adapter, addr, tmp8);
+	RTW_INFO(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
+		FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
+
+	/* lock register page0 0x0~0xB read/write */
+	rtw_write8(g_test_adapter, 0x1C, 0x0E);
+
+	rtw_set_surprise_removed(g_test_adapter);
+	RTW_INFO(FUNC_ADPT_FMT ": bSurpriseRemoved=%s\n",
+		FUNC_ADPT_ARG(g_test_adapter), rtw_is_surprise_removed(g_test_adapter) ? "True" : "False");
+}
+#endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
+
+static int wifi_remove(struct platform_device *pdev)
+{
+	struct wifi_platform_data *wifi_ctrl =
+		(struct wifi_platform_data *)(pdev->dev.platform_data);
+
+	RTW_INFO("## %s\n", __func__);
+	wifi_control_data = wifi_ctrl;
+
+	wifi_set_power(0, 0);	/* Power Off */
+	wifi_set_carddetect(0);	/* CardDetect (1->0) */
+
+	up(&wifi_control_sem);
+	return 0;
+}
+
+#ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
+static void wifi_shutdown(struct platform_device *pdev)
+{
+	struct wifi_platform_data *wifi_ctrl =
+		(struct wifi_platform_data *)(pdev->dev.platform_data);
+
+
+	RTW_INFO("## %s\n", __func__);
+
+	wifi_control_data = wifi_ctrl;
+
+	shutdown_card();
+	wifi_set_power(0, 0);	/* Power Off */
+	wifi_set_carddetect(0);	/* CardDetect (1->0) */
+}
+#endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
+
+static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	RTW_INFO("##> %s\n", __func__);
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
+	bcmsdh_oob_intr_set(0);
+#endif
+	return 0;
+}
+
+static int wifi_resume(struct platform_device *pdev)
+{
+	RTW_INFO("##> %s\n", __func__);
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
+	if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
+		bcmsdh_oob_intr_set(1);
+#endif
+	return 0;
+}
+
+/* temporarily use these two */
+static struct platform_driver wifi_device = {
+	.probe          = wifi_probe,
+	.remove         = wifi_remove,
+	.suspend        = wifi_suspend,
+	.resume         = wifi_resume,
+#ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
+	.shutdown       = wifi_shutdown,
+#endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
+	.driver         = {
+		.name   = "bcmdhd_wlan",
+	}
+};
+
+static struct platform_driver wifi_device_legacy = {
+	.probe          = wifi_probe,
+	.remove         = wifi_remove,
+	.suspend        = wifi_suspend,
+	.resume         = wifi_resume,
+	.driver         = {
+		.name   = "bcm4329_wlan",
+	}
+};
+
+static int wifi_add_dev(void)
+{
+	RTW_INFO("## Calling platform_driver_register\n");
+	platform_driver_register(&wifi_device);
+	platform_driver_register(&wifi_device_legacy);
+	return 0;
+}
+
+static void wifi_del_dev(void)
+{
+	RTW_INFO("## Unregister platform_driver_register\n");
+	platform_driver_unregister(&wifi_device);
+	platform_driver_unregister(&wifi_device_legacy);
+}
+#endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
+
+#ifdef CONFIG_GPIO_WAKEUP
+#ifdef CONFIG_PLATFORM_INTEL_BYT
+int wifi_configure_gpio(void)
+{
+	if (gpio_request(oob_gpio, "oob_irq")) {
+		RTW_INFO("## %s Cannot request GPIO\n", __func__);
+		return -1;
+	}
+	gpio_export(oob_gpio, 0);
+	if (gpio_direction_input(oob_gpio)) {
+		RTW_INFO("## %s Cannot set GPIO direction input\n", __func__);
+		return -1;
+	}
+	oob_irq = gpio_to_irq(oob_gpio);
+	if (oob_irq < 0) {
+		RTW_INFO("## %s Cannot convert GPIO to IRQ\n", __func__);
+		return -1;
+	}
+
+	RTW_INFO("## %s OOB_IRQ=%d\n", __func__, oob_irq);
+
+	return 0;
+}
+#endif /* CONFIG_PLATFORM_INTEL_BYT */
+void wifi_free_gpio(unsigned int gpio)
+{
+#ifdef CONFIG_PLATFORM_INTEL_BYT
+	if (gpio)
+		gpio_free(gpio);
+#endif /* CONFIG_PLATFORM_INTEL_BYT */
+}
+#endif /* CONFIG_GPIO_WAKEUP */
diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_cfgvendor.c b/drivers/staging/rtl8188eu/os_dep/rtw_cfgvendor.c
new file mode 100644
index 000000000000..8d18373c728c
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/rtw_cfgvendor.c
@@ -0,0 +1,1330 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+
+#include <drv_types.h>
+
+#ifdef CONFIG_IOCTL_CFG80211
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT)
+
+/*
+#include <linux/kernel.h>
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <linux/wait.h>
+#include <net/cfg80211.h>
+*/
+
+#include <net/rtnetlink.h>
+
+#ifdef DBG_MEM_ALLOC
+extern bool match_mstat_sniff_rules(const enum mstat_f flags, const size_t size);
+struct sk_buff *dbg_rtw_cfg80211_vendor_event_alloc(struct wiphy *wiphy, struct wireless_dev *wdev, int len, int event_id, gfp_t gfp
+		, const enum mstat_f flags, const char *func, const int line)
+{
+	struct sk_buff *skb;
+	unsigned int truesize = 0;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
+	skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, gfp);
+#else
+	skb = cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp);
+#endif
+
+	if (skb)
+		truesize = skb->truesize;
+
+	if (!skb || truesize < len || match_mstat_sniff_rules(flags, truesize))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d), skb:%p, truesize=%u\n", func, line, __func__, len, skb, truesize);
+
+	rtw_mstat_update(
+		flags
+		, skb ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
+		, truesize
+	);
+
+	return skb;
+}
+
+void dbg_rtw_cfg80211_vendor_event(struct sk_buff *skb, gfp_t gfp
+		   , const enum mstat_f flags, const char *func, const int line)
+{
+	unsigned int truesize = skb->truesize;
+
+	if (match_mstat_sniff_rules(flags, truesize))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __func__, truesize);
+
+	cfg80211_vendor_event(skb, gfp);
+
+	rtw_mstat_update(
+		flags
+		, MSTAT_FREE
+		, truesize
+	);
+}
+
+struct sk_buff *dbg_rtw_cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int len
+		, const enum mstat_f flags, const char *func, const int line)
+{
+	struct sk_buff *skb;
+	unsigned int truesize = 0;
+
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
+
+	if (skb)
+		truesize = skb->truesize;
+
+	if (!skb || truesize < len || match_mstat_sniff_rules(flags, truesize))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d), skb:%p, truesize=%u\n", func, line, __func__, len, skb, truesize);
+
+	rtw_mstat_update(
+		flags
+		, skb ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
+		, truesize
+	);
+
+	return skb;
+}
+
+int dbg_rtw_cfg80211_vendor_cmd_reply(struct sk_buff *skb
+	      , const enum mstat_f flags, const char *func, const int line)
+{
+	unsigned int truesize = skb->truesize;
+	int ret;
+
+	if (match_mstat_sniff_rules(flags, truesize))
+		RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __func__, truesize);
+
+	ret = cfg80211_vendor_cmd_reply(skb);
+
+	rtw_mstat_update(
+		flags
+		, MSTAT_FREE
+		, truesize
+	);
+
+	return ret;
+}
+
+#define rtw_cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp) \
+	dbg_rtw_cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __func__, __LINE__)
+
+#define rtw_cfg80211_vendor_event(skb, gfp) \
+	dbg_rtw_cfg80211_vendor_event(skb, gfp, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __func__, __LINE__)
+
+#define rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \
+	dbg_rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __func__, __LINE__)
+
+#define rtw_cfg80211_vendor_cmd_reply(skb) \
+	dbg_rtw_cfg80211_vendor_cmd_reply(skb, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __func__, __LINE__)
+#else
+
+static struct sk_buff *rtw_cfg80211_vendor_event_alloc(
+	struct wiphy *wiphy, struct wireless_dev *wdev, int len, int event_id, gfp_t gfp)
+{
+	struct sk_buff *skb;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
+	skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, gfp);
+#else
+	skb = cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp);
+#endif
+	return skb;
+}
+
+#define rtw_cfg80211_vendor_event(skb, gfp) \
+	cfg80211_vendor_event(skb, gfp)
+
+#define rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \
+	cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len)
+
+#define rtw_cfg80211_vendor_cmd_reply(skb) \
+	cfg80211_vendor_cmd_reply(skb)
+#endif /* DBG_MEM_ALLOC */
+
+/*
+ * This API is to be used for asynchronous vendor events. This
+ * shouldn't be used in response to a vendor command from its
+ * do_it handler context (instead rtw_cfgvendor_send_cmd_reply should
+ * be used).
+ */
+int rtw_cfgvendor_send_async_event(struct wiphy *wiphy,
+	   struct net_device *dev, int event_id, const void  *data, int len)
+{
+	gfp_t kflags;
+	struct sk_buff *skb;
+
+	kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
+
+	/* Alloc the SKB for vendor_event */
+	skb = rtw_cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev), len, event_id, kflags);
+	if (!skb) {
+		RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(dev));
+		return -ENOMEM;
+	}
+
+	/* Push the data to the skb */
+	nla_put_nohdr(skb, len, data);
+
+	rtw_cfg80211_vendor_event(skb, kflags);
+
+	return 0;
+}
+
+static int rtw_cfgvendor_send_cmd_reply(struct wiphy *wiphy,
+			struct net_device *dev, const void  *data, int len)
+{
+	struct sk_buff *skb;
+
+	/* Alloc the SKB for vendor_event */
+	skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
+	if (unlikely(!skb)) {
+		RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(dev));
+		return -ENOMEM;
+	}
+
+	/* Push the data to the skb */
+	nla_put_nohdr(skb, len, data);
+
+	return rtw_cfg80211_vendor_cmd_reply(skb);
+}
+
+#define WIFI_FEATURE_INFRA              0x0001      /* Basic infrastructure mode       */
+#define WIFI_FEATURE_INFRA_5G           0x0002      /* Support for 5 GHz Band          */
+#define WIFI_FEATURE_HOTSPOT            0x0004      /* Support for GAS/ANQP            */
+#define WIFI_FEATURE_P2P                0x0008      /* Wifi-Direct                     */
+#define WIFI_FEATURE_SOFT_AP            0x0010      /* Soft AP                         */
+#define WIFI_FEATURE_GSCAN              0x0020      /* Google-Scan APIs                */
+#define WIFI_FEATURE_NAN                0x0040      /* Neighbor Awareness Networking   */
+#define WIFI_FEATURE_D2D_RTT            0x0080      /* Device-to-device RTT            */
+#define WIFI_FEATURE_D2AP_RTT           0x0100      /* Device-to-AP RTT                */
+#define WIFI_FEATURE_BATCH_SCAN         0x0200      /* Batched Scan (legacy)           */
+#define WIFI_FEATURE_PNO                0x0400      /* Preferred network offload       */
+#define WIFI_FEATURE_ADDITIONAL_STA     0x0800      /* Support for two STAs            */
+#define WIFI_FEATURE_TDLS               0x1000      /* Tunnel directed link setup      */
+#define WIFI_FEATURE_TDLS_OFFCHANNEL    0x2000      /* Support for TDLS off channel    */
+#define WIFI_FEATURE_EPR                0x4000      /* Enhanced power reporting        */
+#define WIFI_FEATURE_AP_STA             0x8000      /* Support for AP STA Concurrency  */
+
+#define MAX_FEATURE_SET_CONCURRRENT_GROUPS  3
+
+#include <hal_data.h>
+static int rtw_dev_get_feature_set(struct net_device *dev)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	HAL_DATA_TYPE *HalData = GET_HAL_DATA(adapter);
+	HAL_VERSION *hal_ver = &HalData->version_id;
+
+	int feature_set = 0;
+
+	feature_set |= WIFI_FEATURE_INFRA;
+
+	if (IS_8814A_SERIES(*hal_ver) || IS_8812_SERIES(*hal_ver) ||
+	    IS_8821_SERIES(*hal_ver))
+		feature_set |= WIFI_FEATURE_INFRA_5G;
+
+	feature_set |= WIFI_FEATURE_P2P;
+	feature_set |= WIFI_FEATURE_SOFT_AP;
+
+	feature_set |= WIFI_FEATURE_ADDITIONAL_STA;
+
+	return feature_set;
+}
+
+static int *rtw_dev_get_feature_set_matrix(struct net_device *dev, int *num)
+{
+	int feature_set_full, mem_needed;
+	int *ret;
+
+	*num = 0;
+	mem_needed = sizeof(int) * MAX_FEATURE_SET_CONCURRRENT_GROUPS;
+	ret = (int *)rtw_malloc(mem_needed);
+
+	if (!ret) {
+		RTW_ERR(FUNC_NDEV_FMT" failed to allocate %d bytes\n"
+			, FUNC_NDEV_ARG(dev), mem_needed);
+		return ret;
+	}
+
+	feature_set_full = rtw_dev_get_feature_set(dev);
+
+	ret[0] = (feature_set_full & WIFI_FEATURE_INFRA) |
+		 (feature_set_full & WIFI_FEATURE_INFRA_5G) |
+		 (feature_set_full & WIFI_FEATURE_NAN) |
+		 (feature_set_full & WIFI_FEATURE_D2D_RTT) |
+		 (feature_set_full & WIFI_FEATURE_D2AP_RTT) |
+		 (feature_set_full & WIFI_FEATURE_PNO) |
+		 (feature_set_full & WIFI_FEATURE_BATCH_SCAN) |
+		 (feature_set_full & WIFI_FEATURE_GSCAN) |
+		 (feature_set_full & WIFI_FEATURE_HOTSPOT) |
+		 (feature_set_full & WIFI_FEATURE_ADDITIONAL_STA) |
+		 (feature_set_full & WIFI_FEATURE_EPR);
+
+	ret[1] = (feature_set_full & WIFI_FEATURE_INFRA) |
+		 (feature_set_full & WIFI_FEATURE_INFRA_5G) |
+		 /* Not yet verified NAN with P2P */
+		 /* (feature_set_full & WIFI_FEATURE_NAN) | */
+		 (feature_set_full & WIFI_FEATURE_P2P) |
+		 (feature_set_full & WIFI_FEATURE_D2AP_RTT) |
+		 (feature_set_full & WIFI_FEATURE_D2D_RTT) |
+		 (feature_set_full & WIFI_FEATURE_EPR);
+
+	ret[2] = (feature_set_full & WIFI_FEATURE_INFRA) |
+		 (feature_set_full & WIFI_FEATURE_INFRA_5G) |
+		 (feature_set_full & WIFI_FEATURE_NAN) |
+		 (feature_set_full & WIFI_FEATURE_D2D_RTT) |
+		 (feature_set_full & WIFI_FEATURE_D2AP_RTT) |
+		 (feature_set_full & WIFI_FEATURE_TDLS) |
+		 (feature_set_full & WIFI_FEATURE_TDLS_OFFCHANNEL) |
+		 (feature_set_full & WIFI_FEATURE_EPR);
+	*num = MAX_FEATURE_SET_CONCURRRENT_GROUPS;
+
+	return ret;
+}
+
+static int rtw_cfgvendor_get_feature_set(struct wiphy *wiphy,
+		struct wireless_dev *wdev, const void  *data, int len)
+{
+	int err = 0;
+	int reply;
+
+	reply = rtw_dev_get_feature_set(wdev_to_ndev(wdev));
+
+	err =  rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev), &reply, sizeof(int));
+
+	if (unlikely(err))
+		RTW_ERR(FUNC_NDEV_FMT" Vendor Command reply failed ret:%d\n"
+			, FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
+
+	return err;
+}
+
+static int rtw_cfgvendor_get_feature_set_matrix(struct wiphy *wiphy,
+		struct wireless_dev *wdev, const void  *data, int len)
+{
+	int err = 0;
+	struct sk_buff *skb;
+	int *reply;
+	int num, mem_needed, i;
+
+	reply = rtw_dev_get_feature_set_matrix(wdev_to_ndev(wdev), &num);
+
+	if (!reply) {
+		RTW_ERR(FUNC_NDEV_FMT" Could not get feature list matrix\n"
+			, FUNC_NDEV_ARG(wdev_to_ndev(wdev)));
+		err = -EINVAL;
+		return err;
+	}
+
+	mem_needed = VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * num) +
+		     ATTRIBUTE_U32_LEN;
+
+	/* Alloc the SKB for vendor_event */
+	skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
+	if (unlikely(!skb)) {
+		RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(wdev_to_ndev(wdev)));
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, num);
+	for (i = 0; i < num; i++)
+		nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_FEATURE_SET, reply[i]);
+
+	err =  rtw_cfg80211_vendor_cmd_reply(skb);
+
+	if (unlikely(err))
+		RTW_ERR(FUNC_NDEV_FMT" Vendor Command reply failed ret:%d\n"
+			, FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
+exit:
+	rtw_mfree((u8 *)reply, sizeof(int) * num);
+	return err;
+}
+
+#if defined(GSCAN_SUPPORT) && 0
+int wl_cfgvendor_send_hotlist_event(struct wiphy *wiphy,
+	struct net_device *dev, void  *data, int len, wl_vendor_event_t event)
+{
+	u16 kflags;
+	const void *ptr;
+	struct sk_buff *skb;
+	int malloc_len, total, iter_cnt_to_send, cnt;
+	gscan_results_cache_t *cache = (gscan_results_cache_t *)data;
+
+	total = len / sizeof(wifi_gscan_result_t);
+	while (total > 0) {
+		malloc_len = (total * sizeof(wifi_gscan_result_t)) + VENDOR_DATA_OVERHEAD;
+		if (malloc_len > NLMSG_DEFAULT_SIZE)
+			malloc_len = NLMSG_DEFAULT_SIZE;
+		iter_cnt_to_send =
+			(malloc_len - VENDOR_DATA_OVERHEAD) / sizeof(wifi_gscan_result_t);
+		total = total - iter_cnt_to_send;
+
+		kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
+
+		/* Alloc the SKB for vendor_event */
+		skb = rtw_cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev), malloc_len, event, kflags);
+		if (!skb) {
+			WL_ERR(("skb alloc failed"));
+			return -ENOMEM;
+		}
+
+		while (cache && iter_cnt_to_send) {
+			ptr = (const void *) &cache->results[cache->tot_consumed];
+
+			if (iter_cnt_to_send < (cache->tot_count - cache->tot_consumed))
+				cnt = iter_cnt_to_send;
+			else
+				cnt = (cache->tot_count - cache->tot_consumed);
+
+			iter_cnt_to_send -= cnt;
+			cache->tot_consumed += cnt;
+			/* Push the data to the skb */
+			nla_append(skb, cnt * sizeof(wifi_gscan_result_t), ptr);
+			if (cache->tot_consumed == cache->tot_count)
+				cache = cache->next;
+
+		}
+
+		rtw_cfg80211_vendor_event(skb, kflags);
+	}
+
+	return 0;
+}
+
+
+static int wl_cfgvendor_gscan_get_capabilities(struct wiphy *wiphy,
+		struct wireless_dev *wdev, const void  *data, int len)
+{
+	int err = 0;
+	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+	dhd_pno_gscan_capabilities_t *reply = NULL;
+	uint32 reply_len = 0;
+
+
+	reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
+			      DHD_PNO_GET_CAPABILITIES, NULL, &reply_len);
+	if (!reply) {
+		WL_ERR(("Could not get capabilities\n"));
+		err = -EINVAL;
+		return err;
+	}
+
+	err =  rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
+					    reply, reply_len);
+
+	if (unlikely(err))
+		WL_ERR(("Vendor Command reply failed ret:%d\n", err));
+
+	kfree(reply);
+	return err;
+}
+
+static int wl_cfgvendor_gscan_get_channel_list(struct wiphy *wiphy,
+		struct wireless_dev *wdev, const void  *data, int len)
+{
+	int err = 0, type, band;
+	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+	uint16 *reply = NULL;
+	uint32 reply_len = 0, num_channels, mem_needed;
+	struct sk_buff *skb;
+
+	type = nla_type(data);
+
+	if (type == GSCAN_ATTRIBUTE_BAND)
+		band = nla_get_u32(data);
+	else
+		return -1;
+
+	reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
+			      DHD_PNO_GET_CHANNEL_LIST, &band, &reply_len);
+
+	if (!reply) {
+		WL_ERR(("Could not get channel list\n"));
+		err = -EINVAL;
+		return err;
+	}
+	num_channels =  reply_len / sizeof(uint32);
+	mem_needed = reply_len + VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * 2);
+
+	/* Alloc the SKB for vendor_event */
+	skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
+	if (unlikely(!skb)) {
+		WL_ERR(("skb alloc failed"));
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels);
+	nla_put(skb, GSCAN_ATTRIBUTE_CHANNEL_LIST, reply_len, reply);
+
+	err =  rtw_cfg80211_vendor_cmd_reply(skb);
+
+	if (unlikely(err))
+		WL_ERR(("Vendor Command reply failed ret:%d\n", err));
+exit:
+	kfree(reply);
+	return err;
+}
+
+static int wl_cfgvendor_gscan_get_batch_results(struct wiphy *wiphy,
+		struct wireless_dev *wdev, const void  *data, int len)
+{
+	int err = 0;
+	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+	gscan_results_cache_t *results, *iter;
+	uint32 reply_len, complete = 0, num_results_iter;
+	int32 mem_needed;
+	wifi_gscan_result_t *ptr;
+	uint16 num_scan_ids, num_results;
+	struct sk_buff *skb;
+	struct nlattr *scan_hdr;
+
+	dhd_dev_wait_batch_results_complete(bcmcfg_to_prmry_ndev(cfg));
+	dhd_dev_pno_lock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
+	results = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
+				DHD_PNO_GET_BATCH_RESULTS, NULL, &reply_len);
+
+	if (!results) {
+		WL_ERR(("No results to send %d\n", err));
+		err =  rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
+						    results, 0);
+
+		if (unlikely(err))
+			WL_ERR(("Vendor Command reply failed ret:%d\n", err));
+		dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
+		return err;
+	}
+	num_scan_ids = reply_len & 0xFFFF;
+	num_results = (reply_len & 0xFFFF0000) >> 16;
+	mem_needed = (num_results * sizeof(wifi_gscan_result_t)) +
+		     (num_scan_ids * GSCAN_BATCH_RESULT_HDR_LEN) +
+		     VENDOR_REPLY_OVERHEAD + SCAN_RESULTS_COMPLETE_FLAG_LEN;
+
+	if (mem_needed > (int32)NLMSG_DEFAULT_SIZE) {
+		mem_needed = (int32)NLMSG_DEFAULT_SIZE;
+		complete = 0;
+	} else
+		complete = 1;
+
+	WL_TRACE(("complete %d mem_needed %d max_mem %d\n", complete, mem_needed,
+		  (int)NLMSG_DEFAULT_SIZE));
+	/* Alloc the SKB for vendor_event */
+	skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
+	if (unlikely(!skb)) {
+		WL_ERR(("skb alloc failed"));
+		dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
+		return -ENOMEM;
+	}
+	iter = results;
+
+	nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, complete);
+
+	mem_needed = mem_needed - (SCAN_RESULTS_COMPLETE_FLAG_LEN + VENDOR_REPLY_OVERHEAD);
+
+	while (iter && ((mem_needed - GSCAN_BATCH_RESULT_HDR_LEN)  > 0)) {
+		scan_hdr = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS);
+		nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_ID, iter->scan_id);
+		nla_put_u8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, iter->flag);
+		num_results_iter =
+			(mem_needed - GSCAN_BATCH_RESULT_HDR_LEN) / sizeof(wifi_gscan_result_t);
+
+		if ((iter->tot_count - iter->tot_consumed) < num_results_iter)
+			num_results_iter = iter->tot_count - iter->tot_consumed;
+
+		nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num_results_iter);
+		if (num_results_iter) {
+			ptr = &iter->results[iter->tot_consumed];
+			iter->tot_consumed += num_results_iter;
+			nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS,
+				num_results_iter * sizeof(wifi_gscan_result_t), ptr);
+		}
+		nla_nest_end(skb, scan_hdr);
+		mem_needed -= GSCAN_BATCH_RESULT_HDR_LEN +
+			      (num_results_iter * sizeof(wifi_gscan_result_t));
+		iter = iter->next;
+	}
+
+	dhd_dev_gscan_batch_cache_cleanup(bcmcfg_to_prmry_ndev(cfg));
+	dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
+
+	return rtw_cfg80211_vendor_cmd_reply(skb);
+}
+
+static int wl_cfgvendor_initiate_gscan(struct wiphy *wiphy,
+		       struct wireless_dev *wdev, const void  *data, int len)
+{
+	int err = 0;
+	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+	int type, tmp = len;
+	int run = 0xFF;
+	int flush = 0;
+	const struct nlattr *iter;
+
+	nla_for_each_attr(iter, data, len, tmp) {
+		type = nla_type(iter);
+		if (type == GSCAN_ATTRIBUTE_ENABLE_FEATURE)
+			run = nla_get_u32(iter);
+		else if (type == GSCAN_ATTRIBUTE_FLUSH_FEATURE)
+			flush = nla_get_u32(iter);
+	}
+
+	if (run != 0xFF) {
+		err = dhd_dev_pno_run_gscan(bcmcfg_to_prmry_ndev(cfg), run, flush);
+
+		if (unlikely(err))
+			WL_ERR(("Could not run gscan:%d\n", err));
+		return err;
+	} else
+		return -1;
+
+
+}
+
+static int wl_cfgvendor_enable_full_scan_result(struct wiphy *wiphy,
+		struct wireless_dev *wdev, const void  *data, int len)
+{
+	int err = 0;
+	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+	int type;
+	bool real_time = false;
+
+	type = nla_type(data);
+
+	if (type == GSCAN_ATTRIBUTE_ENABLE_FULL_SCAN_RESULTS) {
+		real_time = nla_get_u32(data);
+
+		err = dhd_dev_pno_enable_full_scan_result(bcmcfg_to_prmry_ndev(cfg), real_time);
+
+		if (unlikely(err))
+			WL_ERR(("Could not run gscan:%d\n", err));
+
+	} else
+		err = -1;
+
+	return err;
+}
+
+static int wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy,
+		     struct wireless_dev *wdev, const void  *data, int len)
+{
+	int err = 0;
+	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+	gscan_scan_params_t *scan_param;
+	int j = 0;
+	int type, tmp, tmp1, tmp2, k = 0;
+	const struct nlattr *iter, *iter1, *iter2;
+	struct dhd_pno_gscan_channel_bucket  *ch_bucket;
+
+	scan_param = kzalloc(sizeof(gscan_scan_params_t), GFP_KERNEL);
+	if (!scan_param) {
+		WL_ERR(("Could not set GSCAN scan cfg, mem alloc failure\n"));
+		err = -EINVAL;
+		return err;
+
+	}
+
+	scan_param->scan_fr = PNO_SCAN_MIN_FW_SEC;
+	nla_for_each_attr(iter, data, len, tmp) {
+		type = nla_type(iter);
+
+		if (j >= GSCAN_MAX_CH_BUCKETS)
+			break;
+
+		switch (type) {
+		case GSCAN_ATTRIBUTE_BASE_PERIOD:
+			scan_param->scan_fr = nla_get_u32(iter) / 1000;
+			break;
+		case GSCAN_ATTRIBUTE_NUM_BUCKETS:
+			scan_param->nchannel_buckets = nla_get_u32(iter);
+			break;
+		case GSCAN_ATTRIBUTE_CH_BUCKET_1:
+		case GSCAN_ATTRIBUTE_CH_BUCKET_2:
+		case GSCAN_ATTRIBUTE_CH_BUCKET_3:
+		case GSCAN_ATTRIBUTE_CH_BUCKET_4:
+		case GSCAN_ATTRIBUTE_CH_BUCKET_5:
+		case GSCAN_ATTRIBUTE_CH_BUCKET_6:
+		case GSCAN_ATTRIBUTE_CH_BUCKET_7:
+			nla_for_each_nested(iter1, iter, tmp1) {
+				type = nla_type(iter1);
+				ch_bucket =
+					scan_param->channel_bucket;
+
+				switch (type) {
+				case GSCAN_ATTRIBUTE_BUCKET_ID:
+					break;
+				case GSCAN_ATTRIBUTE_BUCKET_PERIOD:
+					ch_bucket[j].bucket_freq_multiple =
+						nla_get_u32(iter1) / 1000;
+					break;
+				case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS:
+					ch_bucket[j].num_channels =
+						nla_get_u32(iter1);
+					break;
+				case GSCAN_ATTRIBUTE_BUCKET_CHANNELS:
+					nla_for_each_nested(iter2, iter1, tmp2) {
+						if (k >= PFN_SWC_RSSI_WINDOW_MAX)
+							break;
+						ch_bucket[j].chan_list[k] =
+							nla_get_u32(iter2);
+						k++;
+					}
+					k = 0;
+					break;
+				case GSCAN_ATTRIBUTE_BUCKETS_BAND:
+					ch_bucket[j].band = (uint16)
+							    nla_get_u32(iter1);
+					break;
+				case GSCAN_ATTRIBUTE_REPORT_EVENTS:
+					ch_bucket[j].report_flag = (uint8)
+							   nla_get_u32(iter1);
+					break;
+				}
+			}
+			j++;
+			break;
+		}
+	}
+
+	if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
+				      DHD_PNO_SCAN_CFG_ID, scan_param, 0) < 0) {
+		WL_ERR(("Could not set GSCAN scan cfg\n"));
+		err = -EINVAL;
+	}
+
+	kfree(scan_param);
+	return err;
+
+}
+
+static int wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy,
+		    struct wireless_dev *wdev, const void  *data, int len)
+{
+	int err = 0;
+	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+	gscan_hotlist_scan_params_t *hotlist_params;
+	int tmp, tmp1, tmp2, type, j = 0, dummy;
+	const struct nlattr *outer, *inner, *iter;
+	uint8 flush = 0;
+	struct bssid_t *pbssid;
+
+	hotlist_params = (gscan_hotlist_scan_params_t *)kzalloc(len, GFP_KERNEL);
+	if (!hotlist_params) {
+		WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes\n", len));
+		return -1;
+	}
+
+	hotlist_params->lost_ap_window = GSCAN_LOST_AP_WINDOW_DEFAULT;
+
+	nla_for_each_attr(iter, data, len, tmp2) {
+		type = nla_type(iter);
+		switch (type) {
+		case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS:
+			pbssid = hotlist_params->bssid;
+			nla_for_each_nested(outer, iter, tmp) {
+				nla_for_each_nested(inner, outer, tmp1) {
+					type = nla_type(inner);
+
+					switch (type) {
+					case GSCAN_ATTRIBUTE_BSSID:
+						memcpy(&(pbssid[j].macaddr),
+						       nla_data(inner), ETHER_ADDR_LEN);
+						break;
+					case GSCAN_ATTRIBUTE_RSSI_LOW:
+						pbssid[j].rssi_reporting_threshold =
+							(int8) nla_get_u8(inner);
+						break;
+					case GSCAN_ATTRIBUTE_RSSI_HIGH:
+						dummy = (int8) nla_get_u8(inner);
+						break;
+					}
+				}
+				j++;
+			}
+			hotlist_params->nbssid = j;
+			break;
+		case GSCAN_ATTRIBUTE_HOTLIST_FLUSH:
+			flush = nla_get_u8(iter);
+			break;
+		case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
+			hotlist_params->lost_ap_window = nla_get_u32(iter);
+			break;
+		}
+
+	}
+
+	if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
+		DHD_PNO_GEOFENCE_SCAN_CFG_ID, hotlist_params, flush) < 0) {
+		WL_ERR(("Could not set GSCAN HOTLIST cfg\n"));
+		err = -EINVAL;
+		goto exit;
+	}
+exit:
+	kfree(hotlist_params);
+	return err;
+}
+static int wl_cfgvendor_set_batch_scan_cfg(struct wiphy *wiphy,
+		struct wireless_dev *wdev, const void  *data, int len)
+{
+	int err = 0, tmp, type;
+	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+	gscan_batch_params_t batch_param;
+	const struct nlattr *iter;
+
+	batch_param.mscan = batch_param.bestn = 0;
+	batch_param.buffer_threshold = GSCAN_BATCH_NO_THR_SET;
+
+	nla_for_each_attr(iter, data, len, tmp) {
+		type = nla_type(iter);
+
+		switch (type) {
+		case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN:
+			batch_param.bestn = nla_get_u32(iter);
+			break;
+		case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE:
+			batch_param.mscan = nla_get_u32(iter);
+			break;
+		case GSCAN_ATTRIBUTE_REPORT_THRESHOLD:
+			batch_param.buffer_threshold = nla_get_u32(iter);
+			break;
+		}
+	}
+
+	if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
+			      DHD_PNO_BATCH_SCAN_CFG_ID, &batch_param, 0) < 0) {
+		WL_ERR(("Could not set batch cfg\n"));
+		err = -EINVAL;
+		return err;
+	}
+
+	return err;
+}
+
+static int wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy,
+		struct wireless_dev *wdev, const void  *data, int len)
+{
+	int err = 0;
+	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+	gscan_swc_params_t *significant_params;
+	int tmp, tmp1, tmp2, type, j = 0;
+	const struct nlattr *outer, *inner, *iter;
+	uint8 flush = 0;
+	wl_pfn_significant_bssid_t *pbssid;
+
+	significant_params = (gscan_swc_params_t *) kzalloc(len, GFP_KERNEL);
+	if (!significant_params) {
+		WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes\n", len));
+		return -1;
+	}
+
+
+	nla_for_each_attr(iter, data, len, tmp2) {
+		type = nla_type(iter);
+
+		switch (type) {
+		case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH:
+			flush = nla_get_u8(iter);
+			break;
+		case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE:
+			significant_params->rssi_window = nla_get_u16(iter);
+			break;
+		case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
+			significant_params->lost_ap_window = nla_get_u16(iter);
+			break;
+		case GSCAN_ATTRIBUTE_MIN_BREACHING:
+			significant_params->swc_threshold = nla_get_u16(iter);
+			break;
+		case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS:
+			pbssid = significant_params->bssid_elem_list;
+			nla_for_each_nested(outer, iter, tmp) {
+				nla_for_each_nested(inner, outer, tmp1) {
+					switch (nla_type(inner)) {
+					case GSCAN_ATTRIBUTE_BSSID:
+						memcpy(&(pbssid[j].macaddr),
+						       nla_data(inner),
+						       ETHER_ADDR_LEN);
+						break;
+					case GSCAN_ATTRIBUTE_RSSI_HIGH:
+						pbssid[j].rssi_high_threshold =
+							(int8) nla_get_u8(inner);
+						break;
+					case GSCAN_ATTRIBUTE_RSSI_LOW:
+						pbssid[j].rssi_low_threshold =
+							(int8) nla_get_u8(inner);
+						break;
+					}
+				}
+				j++;
+			}
+			break;
+		}
+	}
+	significant_params->nbssid = j;
+
+	if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
+		DHD_PNO_SIGNIFICANT_SCAN_CFG_ID, significant_params, flush) < 0) {
+		WL_ERR(("Could not set GSCAN significant cfg\n"));
+		err = -EINVAL;
+		goto exit;
+	}
+exit:
+	kfree(significant_params);
+	return err;
+}
+#endif /* GSCAN_SUPPORT */
+
+#if defined(RTT_SUPPORT) && 0
+void wl_cfgvendor_rtt_evt(void *ctx, void *rtt_data)
+{
+	struct wireless_dev *wdev = (struct wireless_dev *)ctx;
+	struct wiphy *wiphy;
+	struct sk_buff *skb;
+	uint32 tot_len = NLMSG_DEFAULT_SIZE, entry_len = 0;
+	gfp_t kflags;
+	rtt_report_t *rtt_report = NULL;
+	rtt_result_t *rtt_result = NULL;
+	struct list_head *rtt_list;
+	wiphy = wdev->wiphy;
+
+	WL_DBG(("In\n"));
+	/* Push the data to the skb */
+	if (!rtt_data) {
+		WL_ERR(("rtt_data is NULL\n"));
+		goto exit;
+	}
+	rtt_list = (struct list_head *)rtt_data;
+	kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
+	/* Alloc the SKB for vendor_event */
+	skb = rtw_cfg80211_vendor_event_alloc(wiphy, wdev, tot_len, GOOGLE_RTT_COMPLETE_EVENT, kflags);
+	if (!skb) {
+		WL_ERR(("skb alloc failed"));
+		goto exit;
+	}
+	/* fill in the rtt results on each entry */
+	list_for_each_entry(rtt_result, rtt_list, list) {
+		entry_len = 0;
+		if (rtt_result->TOF_type == TOF_TYPE_ONE_WAY) {
+			entry_len = sizeof(rtt_report_t);
+			rtt_report = kzalloc(entry_len, kflags);
+			if (!rtt_report) {
+				WL_ERR(("rtt_report alloc failed"));
+				goto exit;
+			}
+			rtt_report->addr = rtt_result->peer_mac;
+			rtt_report->num_measurement = 1; /* ONE SHOT */
+			rtt_report->status = rtt_result->err_code;
+			rtt_report->type = (rtt_result->TOF_type == TOF_TYPE_ONE_WAY) ? RTT_ONE_WAY : RTT_TWO_WAY;
+			rtt_report->peer = rtt_result->target_info->peer;
+			rtt_report->channel = rtt_result->target_info->channel;
+			rtt_report->rssi = rtt_result->avg_rssi;
+			/* tx_rate */
+			rtt_report->tx_rate = rtt_result->tx_rate;
+			/* RTT */
+			rtt_report->rtt = rtt_result->meanrtt;
+			rtt_report->rtt_sd = rtt_result->sdrtt;
+			/* convert to centi meter */
+			if (rtt_result->distance != 0xffffffff)
+				rtt_report->distance = (rtt_result->distance >> 2) * 25;
+			else /* invalid distance */
+				rtt_report->distance = -1;
+
+			rtt_report->ts = rtt_result->ts;
+			nla_append(skb, entry_len, rtt_report);
+			kfree(rtt_report);
+		}
+	}
+	rtw_cfg80211_vendor_event(skb, kflags);
+exit:
+	return;
+}
+
+static int wl_cfgvendor_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev,
+				       const void *data, int len)
+{
+	int err = 0, rem, rem1, rem2, type;
+	rtt_config_params_t rtt_param;
+	rtt_target_info_t *rtt_target = NULL;
+	const struct nlattr *iter, *iter1, *iter2;
+	int8 eabuf[ETHER_ADDR_STR_LEN];
+	int8 chanbuf[CHANSPEC_STR_LEN];
+	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+
+	WL_DBG(("In\n"));
+	err = dhd_dev_rtt_register_noti_callback(wdev->netdev, wdev, wl_cfgvendor_rtt_evt);
+	if (err < 0) {
+		WL_ERR(("failed to register rtt_noti_callback\n"));
+		goto exit;
+	}
+	memset(&rtt_param, 0, sizeof(rtt_param));
+	nla_for_each_attr(iter, data, len, rem) {
+		type = nla_type(iter);
+		switch (type) {
+		case RTT_ATTRIBUTE_TARGET_CNT:
+			rtt_param.rtt_target_cnt = nla_get_u8(iter);
+			if (rtt_param.rtt_target_cnt > RTT_MAX_TARGET_CNT) {
+				WL_ERR(("exceed max target count : %d\n",
+					rtt_param.rtt_target_cnt));
+				err = BCME_RANGE;
+			}
+			break;
+		case RTT_ATTRIBUTE_TARGET_INFO:
+			rtt_target = rtt_param.target_info;
+			nla_for_each_nested(iter1, iter, rem1) {
+				nla_for_each_nested(iter2, iter1, rem2) {
+					type = nla_type(iter2);
+					switch (type) {
+					case RTT_ATTRIBUTE_TARGET_MAC:
+						memcpy(&rtt_target->addr, nla_data(iter2), ETHER_ADDR_LEN);
+						break;
+					case RTT_ATTRIBUTE_TARGET_TYPE:
+						rtt_target->type = nla_get_u8(iter2);
+						break;
+					case RTT_ATTRIBUTE_TARGET_PEER:
+						rtt_target->peer = nla_get_u8(iter2);
+						break;
+					case RTT_ATTRIBUTE_TARGET_CHAN:
+						memcpy(&rtt_target->channel, nla_data(iter2),
+						       sizeof(rtt_target->channel));
+						break;
+					case RTT_ATTRIBUTE_TARGET_MODE:
+						rtt_target->continuous = nla_get_u8(iter2);
+						break;
+					case RTT_ATTRIBUTE_TARGET_INTERVAL:
+						rtt_target->interval = nla_get_u32(iter2);
+						break;
+					case RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT:
+						rtt_target->measure_cnt = nla_get_u32(iter2);
+						break;
+					case RTT_ATTRIBUTE_TARGET_NUM_PKT:
+						rtt_target->ftm_cnt = nla_get_u32(iter2);
+						break;
+					case RTT_ATTRIBUTE_TARGET_NUM_RETRY:
+						rtt_target->retry_cnt = nla_get_u32(iter2);
+					}
+				}
+				/* convert to chanspec value */
+				rtt_target->chanspec = dhd_rtt_convert_to_chspec(rtt_target->channel);
+				if (rtt_target->chanspec == 0) {
+					WL_ERR(("Channel is not valid\n"));
+					goto exit;
+				}
+				WL_INFORM(("Target addr %s, Channel : %s for RTT\n",
+					bcm_ether_ntoa((const struct ether_addr *)&rtt_target->addr, eabuf),
+					wf_chspec_ntoa(rtt_target->chanspec, chanbuf)));
+				rtt_target++;
+			}
+			break;
+		}
+	}
+	WL_DBG(("leave :target_cnt : %d\n", rtt_param.rtt_target_cnt));
+	if (dhd_dev_rtt_set_cfg(bcmcfg_to_prmry_ndev(cfg), &rtt_param) < 0) {
+		WL_ERR(("Could not set RTT configuration\n"));
+		err = -EINVAL;
+	}
+exit:
+	return err;
+}
+
+static int wl_cfgvendor_rtt_cancel_config(struct wiphy *wiphy, struct wireless_dev *wdev,
+		const void *data, int len)
+{
+	int err = 0, rem, type, target_cnt = 0;
+	const struct nlattr *iter;
+	struct ether_addr *mac_list = NULL, *mac_addr = NULL;
+	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+
+	nla_for_each_attr(iter, data, len, rem) {
+		type = nla_type(iter);
+		switch (type) {
+		case RTT_ATTRIBUTE_TARGET_CNT:
+			target_cnt = nla_get_u8(iter);
+			mac_list = (struct ether_addr *)kzalloc(target_cnt * ETHER_ADDR_LEN , GFP_KERNEL);
+			if (mac_list == NULL) {
+				WL_ERR(("failed to allocate mem for mac list\n"));
+				goto exit;
+			}
+			mac_addr = &mac_list[0];
+			break;
+		case RTT_ATTRIBUTE_TARGET_MAC:
+			if (mac_addr)
+				memcpy(mac_addr++, nla_data(iter), ETHER_ADDR_LEN);
+			else {
+				WL_ERR(("mac_list is NULL\n"));
+				goto exit;
+			}
+			break;
+		}
+		if (dhd_dev_rtt_cancel_cfg(bcmcfg_to_prmry_ndev(cfg), mac_list, target_cnt) < 0) {
+			WL_ERR(("Could not cancel RTT configuration\n"));
+			err = -EINVAL;
+			goto exit;
+		}
+	}
+exit:
+	if (mac_list)
+		kfree(mac_list);
+	return err;
+}
+static int wl_cfgvendor_rtt_get_capability(struct wiphy *wiphy, struct wireless_dev *wdev,
+		const void *data, int len)
+{
+	int err = 0;
+	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+	rtt_capabilities_t capability;
+
+	err = dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg), &capability);
+	if (unlikely(err)) {
+		WL_ERR(("Vendor Command reply failed ret:%d\n", err));
+		goto exit;
+	}
+	err =  rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
+					    &capability, sizeof(capability));
+
+	if (unlikely(err))
+		WL_ERR(("Vendor Command reply failed ret:%d\n", err));
+exit:
+	return err;
+}
+
+#endif /* RTT_SUPPORT */
+static int wl_cfgvendor_priv_string_handler(struct wiphy *wiphy,
+		struct wireless_dev *wdev, const void  *data, int len)
+{
+	int err = 0;
+	u8 resp[1] = {'\0'};
+
+	RTW_INFO(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char *)data);
+	err =  rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev), resp, 1);
+	if (unlikely(err))
+		RTW_ERR(FUNC_NDEV_FMT"Vendor Command reply failed ret:%d\n"
+			, FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
+
+	return err;
+}
+
+static const struct wiphy_vendor_command rtw_vendor_cmds[] = {
+	{
+		{
+			.vendor_id = OUI_BRCM,
+			.subcmd = BRCM_VENDOR_SCMD_PRIV_STR
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = wl_cfgvendor_priv_string_handler
+	},
+#if defined(GSCAN_SUPPORT) && 0
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = GSCAN_SUBCMD_GET_CAPABILITIES
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = wl_cfgvendor_gscan_get_capabilities
+	},
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = GSCAN_SUBCMD_SET_CONFIG
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = wl_cfgvendor_set_scan_cfg
+	},
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = wl_cfgvendor_set_batch_scan_cfg
+	},
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = GSCAN_SUBCMD_ENABLE_GSCAN
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = wl_cfgvendor_initiate_gscan
+	},
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = wl_cfgvendor_enable_full_scan_result
+	},
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = GSCAN_SUBCMD_SET_HOTLIST
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = wl_cfgvendor_hotlist_cfg
+	},
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = wl_cfgvendor_significant_change_cfg
+	},
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = wl_cfgvendor_gscan_get_batch_results
+	},
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = wl_cfgvendor_gscan_get_channel_list
+	},
+#endif /* GSCAN_SUPPORT */
+#if defined(RTT_SUPPORT) && 0
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = RTT_SUBCMD_SET_CONFIG
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = wl_cfgvendor_rtt_set_config
+	},
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = RTT_SUBCMD_CANCEL_CONFIG
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = wl_cfgvendor_rtt_cancel_config
+	},
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = RTT_SUBCMD_GETCAPABILITY
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = wl_cfgvendor_rtt_get_capability
+	},
+#endif /* RTT_SUPPORT */
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = rtw_cfgvendor_get_feature_set
+	},
+	{
+		{
+			.vendor_id = OUI_GOOGLE,
+			.subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+		.doit = rtw_cfgvendor_get_feature_set_matrix
+	}
+};
+
+static const struct  nl80211_vendor_cmd_info rtw_vendor_events[] = {
+	{ OUI_BRCM, BRCM_VENDOR_EVENT_UNSPEC },
+	{ OUI_BRCM, BRCM_VENDOR_EVENT_PRIV_STR },
+#if defined(GSCAN_SUPPORT) && 0
+	{ OUI_GOOGLE, GOOGLE_GSCAN_SIGNIFICANT_EVENT },
+	{ OUI_GOOGLE, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT },
+	{ OUI_GOOGLE, GOOGLE_GSCAN_BATCH_SCAN_EVENT },
+	{ OUI_GOOGLE, GOOGLE_SCAN_FULL_RESULTS_EVENT },
+#endif /* GSCAN_SUPPORT */
+#if defined(RTT_SUPPORT) && 0
+	{ OUI_GOOGLE, GOOGLE_RTT_COMPLETE_EVENT },
+#endif /* RTT_SUPPORT */
+#if defined(GSCAN_SUPPORT) && 0
+	{ OUI_GOOGLE, GOOGLE_SCAN_COMPLETE_EVENT },
+	{ OUI_GOOGLE, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT }
+#endif /* GSCAN_SUPPORT */
+};
+
+int rtw_cfgvendor_attach(struct wiphy *wiphy)
+{
+
+	RTW_INFO("Register RTW cfg80211 vendor cmd(0x%x) interface\n", NL80211_CMD_VENDOR);
+
+	wiphy->vendor_commands	= rtw_vendor_cmds;
+	wiphy->n_vendor_commands = ARRAY_SIZE(rtw_vendor_cmds);
+	wiphy->vendor_events	= rtw_vendor_events;
+	wiphy->n_vendor_events	= ARRAY_SIZE(rtw_vendor_events);
+
+	return 0;
+}
+
+int rtw_cfgvendor_detach(struct wiphy *wiphy)
+{
+	RTW_INFO("Vendor: Unregister RTW cfg80211 vendor interface\n");
+
+	wiphy->vendor_commands  = NULL;
+	wiphy->vendor_events    = NULL;
+	wiphy->n_vendor_commands = 0;
+	wiphy->n_vendor_events  = 0;
+
+	return 0;
+}
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT) */
+
+#endif /* CONFIG_IOCTL_CFG80211 */
diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_cfgvendor.h b/drivers/staging/rtl8188eu/os_dep/rtw_cfgvendor.h
new file mode 100644
index 000000000000..8caacca8bee0
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/rtw_cfgvendor.h
@@ -0,0 +1,229 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+
+#ifndef _RTW_CFGVENDOR_H_
+#define _RTW_CFGVENDOR_H_
+
+#define OUI_BRCM    0x001018
+#define OUI_GOOGLE  0x001A11
+#define BRCM_VENDOR_SUBCMD_PRIV_STR	1
+#define ATTRIBUTE_U32_LEN                  (NLA_HDRLEN  + 4)
+#define VENDOR_ID_OVERHEAD                 ATTRIBUTE_U32_LEN
+#define VENDOR_SUBCMD_OVERHEAD             ATTRIBUTE_U32_LEN
+#define VENDOR_DATA_OVERHEAD               (NLA_HDRLEN)
+
+#define SCAN_RESULTS_COMPLETE_FLAG_LEN       ATTRIBUTE_U32_LEN
+#define SCAN_INDEX_HDR_LEN                   (NLA_HDRLEN)
+#define SCAN_ID_HDR_LEN                      ATTRIBUTE_U32_LEN
+#define SCAN_FLAGS_HDR_LEN                   ATTRIBUTE_U32_LEN
+#define GSCAN_NUM_RESULTS_HDR_LEN            ATTRIBUTE_U32_LEN
+#define GSCAN_RESULTS_HDR_LEN                (NLA_HDRLEN)
+#define GSCAN_BATCH_RESULT_HDR_LEN  (SCAN_INDEX_HDR_LEN + SCAN_ID_HDR_LEN + \
+				     SCAN_FLAGS_HDR_LEN + \
+				     GSCAN_NUM_RESULTS_HDR_LEN + \
+				     GSCAN_RESULTS_HDR_LEN)
+
+#define VENDOR_REPLY_OVERHEAD       (VENDOR_ID_OVERHEAD + \
+				     VENDOR_SUBCMD_OVERHEAD + \
+				     VENDOR_DATA_OVERHEAD)
+typedef enum {
+	/* don't use 0 as a valid subcommand */
+	VENDOR_NL80211_SUBCMD_UNSPECIFIED,
+
+	/* define all vendor startup commands between 0x0 and 0x0FFF */
+	VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001,
+	VENDOR_NL80211_SUBCMD_RANGE_END   = 0x0FFF,
+
+	/* define all GScan related commands between 0x1000 and 0x10FF */
+	ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000,
+	ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END   = 0x10FF,
+
+	/* define all NearbyDiscovery related commands between 0x1100 and 0x11FF */
+	ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1100,
+	ANDROID_NL80211_SUBCMD_NBD_RANGE_END   = 0x11FF,
+
+	/* define all RTT related commands between 0x1100 and 0x11FF */
+	ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100,
+	ANDROID_NL80211_SUBCMD_RTT_RANGE_END   = 0x11FF,
+
+	ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200,
+	ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END   = 0x12FF,
+
+	ANDROID_NL80211_SUBCMD_TDLS_RANGE_START = 0x1300,
+	ANDROID_NL80211_SUBCMD_TDLS_RANGE_END	= 0x13FF,
+	/* This is reserved for future usage */
+
+} ANDROID_VENDOR_SUB_COMMAND;
+
+enum wl_vendor_subcmd {
+	BRCM_VENDOR_SCMD_UNSPEC,
+	BRCM_VENDOR_SCMD_PRIV_STR,
+	GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START,
+	GSCAN_SUBCMD_SET_CONFIG,
+	GSCAN_SUBCMD_SET_SCAN_CONFIG,
+	GSCAN_SUBCMD_ENABLE_GSCAN,
+	GSCAN_SUBCMD_GET_SCAN_RESULTS,
+	GSCAN_SUBCMD_SCAN_RESULTS,
+	GSCAN_SUBCMD_SET_HOTLIST,
+	GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG,
+	GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS,
+	GSCAN_SUBCMD_GET_CHANNEL_LIST,
+	ANDR_WIFI_SUBCMD_GET_FEATURE_SET,
+	ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX,
+	RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START,
+	RTT_SUBCMD_CANCEL_CONFIG,
+	RTT_SUBCMD_GETCAPABILITY,
+	/* Add more sub commands here */
+	VENDOR_SUBCMD_MAX
+};
+
+enum gscan_attributes {
+	GSCAN_ATTRIBUTE_NUM_BUCKETS = 10,
+	GSCAN_ATTRIBUTE_BASE_PERIOD,
+	GSCAN_ATTRIBUTE_BUCKETS_BAND,
+	GSCAN_ATTRIBUTE_BUCKET_ID,
+	GSCAN_ATTRIBUTE_BUCKET_PERIOD,
+	GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
+	GSCAN_ATTRIBUTE_BUCKET_CHANNELS,
+	GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN,
+	GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
+	GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
+	GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND,
+
+	GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20,
+	GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE,
+	GSCAN_ATTRIBUTE_FLUSH_FEATURE,
+	GSCAN_ATTRIBUTE_ENABLE_FULL_SCAN_RESULTS,
+	GSCAN_ATTRIBUTE_REPORT_EVENTS,
+	/* remaining reserved for additional attributes */
+	GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30,
+	GSCAN_ATTRIBUTE_FLUSH_RESULTS,
+	GSCAN_ATTRIBUTE_SCAN_RESULTS,                       /* flat array of wifi_scan_result */
+	GSCAN_ATTRIBUTE_SCAN_ID,                            /* indicates scan number */
+	GSCAN_ATTRIBUTE_SCAN_FLAGS,                         /* indicates if scan was aborted */
+	GSCAN_ATTRIBUTE_AP_FLAGS,                           /* flags on significant change event */
+	GSCAN_ATTRIBUTE_NUM_CHANNELS,
+	GSCAN_ATTRIBUTE_CHANNEL_LIST,
+
+	/* remaining reserved for additional attributes */
+
+	GSCAN_ATTRIBUTE_SSID = 40,
+	GSCAN_ATTRIBUTE_BSSID,
+	GSCAN_ATTRIBUTE_CHANNEL,
+	GSCAN_ATTRIBUTE_RSSI,
+	GSCAN_ATTRIBUTE_TIMESTAMP,
+	GSCAN_ATTRIBUTE_RTT,
+	GSCAN_ATTRIBUTE_RTTSD,
+
+	/* remaining reserved for additional attributes */
+
+	GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50,
+	GSCAN_ATTRIBUTE_RSSI_LOW,
+	GSCAN_ATTRIBUTE_RSSI_HIGH,
+	GSCAN_ATTRIBUTE_HOSTLIST_BSSID_ELEM,
+	GSCAN_ATTRIBUTE_HOTLIST_FLUSH,
+
+	/* remaining reserved for additional attributes */
+	GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60,
+	GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE,
+	GSCAN_ATTRIBUTE_MIN_BREACHING,
+	GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS,
+	GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH,
+	GSCAN_ATTRIBUTE_MAX
+};
+
+enum gscan_bucket_attributes {
+	GSCAN_ATTRIBUTE_CH_BUCKET_1,
+	GSCAN_ATTRIBUTE_CH_BUCKET_2,
+	GSCAN_ATTRIBUTE_CH_BUCKET_3,
+	GSCAN_ATTRIBUTE_CH_BUCKET_4,
+	GSCAN_ATTRIBUTE_CH_BUCKET_5,
+	GSCAN_ATTRIBUTE_CH_BUCKET_6,
+	GSCAN_ATTRIBUTE_CH_BUCKET_7
+};
+
+enum gscan_ch_attributes {
+	GSCAN_ATTRIBUTE_CH_ID_1,
+	GSCAN_ATTRIBUTE_CH_ID_2,
+	GSCAN_ATTRIBUTE_CH_ID_3,
+	GSCAN_ATTRIBUTE_CH_ID_4,
+	GSCAN_ATTRIBUTE_CH_ID_5,
+	GSCAN_ATTRIBUTE_CH_ID_6,
+	GSCAN_ATTRIBUTE_CH_ID_7
+};
+
+enum rtt_attributes {
+	RTT_ATTRIBUTE_TARGET_CNT,
+	RTT_ATTRIBUTE_TARGET_INFO,
+	RTT_ATTRIBUTE_TARGET_MAC,
+	RTT_ATTRIBUTE_TARGET_TYPE,
+	RTT_ATTRIBUTE_TARGET_PEER,
+	RTT_ATTRIBUTE_TARGET_CHAN,
+	RTT_ATTRIBUTE_TARGET_MODE,
+	RTT_ATTRIBUTE_TARGET_INTERVAL,
+	RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT,
+	RTT_ATTRIBUTE_TARGET_NUM_PKT,
+	RTT_ATTRIBUTE_TARGET_NUM_RETRY
+};
+
+typedef enum wl_vendor_event {
+	BRCM_VENDOR_EVENT_UNSPEC,
+	BRCM_VENDOR_EVENT_PRIV_STR,
+	GOOGLE_GSCAN_SIGNIFICANT_EVENT,
+	GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT,
+	GOOGLE_GSCAN_BATCH_SCAN_EVENT,
+	GOOGLE_SCAN_FULL_RESULTS_EVENT,
+	GOOGLE_RTT_COMPLETE_EVENT,
+	GOOGLE_SCAN_COMPLETE_EVENT,
+	GOOGLE_GSCAN_GEOFENCE_LOST_EVENT
+} wl_vendor_event_t;
+
+enum andr_wifi_feature_set_attr {
+	ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
+	ANDR_WIFI_ATTRIBUTE_FEATURE_SET
+};
+
+typedef enum wl_vendor_gscan_attribute {
+	ATTR_START_GSCAN,
+	ATTR_STOP_GSCAN,
+	ATTR_SET_SCAN_BATCH_CFG_ID, /* set batch scan params */
+	ATTR_SET_SCAN_GEOFENCE_CFG_ID, /* set list of bssids to track */
+	ATTR_SET_SCAN_SIGNIFICANT_CFG_ID, /* set list of bssids, rssi threshold etc.. */
+	ATTR_SET_SCAN_CFG_ID, /* set common scan config params here */
+	ATTR_GET_GSCAN_CAPABILITIES_ID,
+	/* Add more sub commands here */
+	ATTR_GSCAN_MAX
+} wl_vendor_gscan_attribute_t;
+
+typedef enum gscan_batch_attribute {
+	ATTR_GSCAN_BATCH_BESTN,
+	ATTR_GSCAN_BATCH_MSCAN,
+	ATTR_GSCAN_BATCH_BUFFER_THRESHOLD
+} gscan_batch_attribute_t;
+
+typedef enum gscan_geofence_attribute {
+	ATTR_GSCAN_NUM_HOTLIST_BSSID,
+	ATTR_GSCAN_HOTLIST_BSSID
+} gscan_geofence_attribute_t;
+
+typedef enum gscan_complete_event {
+	WIFI_SCAN_BUFFER_FULL,
+	WIFI_SCAN_COMPLETE
+} gscan_complete_event_t;
+
+/* Capture the BRCM_VENDOR_SUBCMD_PRIV_STRINGS* here */
+#define BRCM_VENDOR_SCMD_CAPA	"cap"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT)
+extern int rtw_cfgvendor_attach(struct wiphy *wiphy);
+extern int rtw_cfgvendor_detach(struct wiphy *wiphy);
+extern int rtw_cfgvendor_send_async_event(struct wiphy *wiphy,
+	struct net_device *dev, int event_id, const void  *data, int len);
+#if defined(GSCAN_SUPPORT) && 0
+extern int wl_cfgvendor_send_hotlist_event(struct wiphy *wiphy,
+	struct net_device *dev, void  *data, int len, wl_vendor_event_t event);
+#endif
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT) */
+
+#endif /* _RTW_CFGVENDOR_H_ */
diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_proc.c b/drivers/staging/rtl8188eu/os_dep/rtw_proc.c
new file mode 100644
index 000000000000..cdf24a2859d1
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/rtw_proc.c
@@ -0,0 +1,3216 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+
+#include <linux/ctype.h>	/* tolower() */
+#include <drv_types.h>
+#include <hal_data.h>
+#include "rtw_proc.h"
+#ifdef CONFIG_BT_COEXIST
+#include <rtw_btcoex.h>
+#endif
+
+#ifdef CONFIG_PROC_DEBUG
+
+static struct proc_dir_entry *rtw_proc = NULL;
+
+inline struct proc_dir_entry *get_rtw_drv_proc(void)
+{
+	return rtw_proc;
+}
+
+#define RTW_PROC_NAME DRV_NAME
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
+#define file_inode(file) ((file)->f_dentry->d_inode)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#define PDE_DATA(inode) PDE((inode))->data
+#define proc_get_parent_data(inode) PDE((inode))->parent->data
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+#define get_proc_net proc_net
+#else
+#define get_proc_net init_net.proc_net
+#endif
+
+inline struct proc_dir_entry *rtw_proc_create_dir(const char *name, struct proc_dir_entry *parent, void *data)
+{
+	struct proc_dir_entry *entry;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
+	entry = proc_mkdir_data(name, S_IRUGO | S_IXUGO, parent, data);
+#else
+	/* entry = proc_mkdir_mode(name, S_IRUGO|S_IXUGO, parent); */
+	entry = proc_mkdir(name, parent);
+	if (entry)
+		entry->data = data;
+#endif
+
+	return entry;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+inline struct proc_dir_entry *rtw_proc_create_entry(const char *name, struct proc_dir_entry *parent,
+	const struct proc_ops *fops, void * data)
+#else
+inline struct proc_dir_entry *rtw_proc_create_entry(const char *name, struct proc_dir_entry *parent,
+	const struct file_operations *fops, void * data)
+#endif
+{
+	struct proc_dir_entry *entry;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+	entry = proc_create_data(name,  S_IFREG | S_IRUGO | S_IWUGO, parent, fops, data);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26))
+	entry = proc_create_data(name,  S_IFREG | S_IRUGO | S_IWUGO, parent, fops, data);
+#else
+	entry = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUGO, parent);
+	if (entry) {
+		entry->data = data;
+		entry->proc_fops = fops;
+	}
+#endif
+
+	return entry;
+}
+
+static int proc_get_dummy(struct seq_file *m, void *v)
+{
+	return 0;
+}
+
+static int proc_get_drv_version(struct seq_file *m, void *v)
+{
+	dump_drv_version(m);
+	return 0;
+}
+
+static int proc_get_log_level(struct seq_file *m, void *v)
+{
+	dump_log_level(m);
+	return 0;
+}
+
+static int proc_get_drv_cfg(struct seq_file *m, void *v)
+{
+	dump_drv_cfg(m);
+	return 0;
+}
+
+static ssize_t proc_set_log_level(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	char tmp[32];
+	int log_level;
+
+	if (count < 1)
+		return -EINVAL;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+#ifdef CONFIG_RTW_DEBUG
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%d ", &log_level);
+
+		if (log_level >= _DRV_NONE_ && log_level <= _DRV_MAX_) {
+			rtw_drv_log_level = log_level;
+			printk("rtw_drv_log_level:%d\n", rtw_drv_log_level);
+		}
+	} else
+		return -EFAULT;
+#else
+	printk("CONFIG_RTW_DEBUG is disabled\n");
+#endif
+
+	return count;
+}
+
+#ifdef DBG_MEM_ALLOC
+static int proc_get_mstat(struct seq_file *m, void *v)
+{
+	rtw_mstat_dump(m);
+	return 0;
+}
+#endif /* DBG_MEM_ALLOC */
+
+static int proc_get_country_chplan_map(struct seq_file *m, void *v)
+{
+	dump_country_chplan_map(m);
+	return 0;
+}
+
+static int proc_get_chplan_id_list(struct seq_file *m, void *v)
+{
+	dump_chplan_id_list(m);
+	return 0;
+}
+
+static int proc_get_chplan_test(struct seq_file *m, void *v)
+{
+	dump_chplan_test(m);
+	return 0;
+}
+
+/*
+* rtw_drv_proc:
+* init/deinit when register/unregister driver
+*/
+static const struct rtw_proc_hdl drv_proc_hdls[] = {
+	RTW_PROC_HDL_SSEQ("ver_info", proc_get_drv_version, NULL),
+	RTW_PROC_HDL_SSEQ("log_level", proc_get_log_level, proc_set_log_level),
+	RTW_PROC_HDL_SSEQ("drv_cfg", proc_get_drv_cfg, NULL),
+#ifdef DBG_MEM_ALLOC
+	RTW_PROC_HDL_SSEQ("mstat", proc_get_mstat, NULL),
+#endif /* DBG_MEM_ALLOC */
+	RTW_PROC_HDL_SSEQ("country_chplan_map", proc_get_country_chplan_map, NULL),
+	RTW_PROC_HDL_SSEQ("chplan_id_list", proc_get_chplan_id_list, NULL),
+	RTW_PROC_HDL_SSEQ("chplan_test", proc_get_chplan_test, NULL),
+};
+
+static const int drv_proc_hdls_num = sizeof(drv_proc_hdls) / sizeof(struct rtw_proc_hdl);
+
+static int rtw_drv_proc_open(struct inode *inode, struct file *file)
+{
+	/* struct net_device *dev = proc_get_parent_data(inode); */
+	ssize_t index = (ssize_t)PDE_DATA(inode);
+	const struct rtw_proc_hdl *hdl = drv_proc_hdls + index;
+	void *private = NULL;
+
+	if (hdl->type == RTW_PROC_HDL_TYPE_SEQ) {
+		int res = seq_open(file, hdl->u.seq_op);
+
+		if (res == 0)
+			((struct seq_file *)file->private_data)->private = private;
+
+		return res;
+	} else if (hdl->type == RTW_PROC_HDL_TYPE_SSEQ) {
+		int (*show)(struct seq_file *, void *) = hdl->u.show ? hdl->u.show : proc_get_dummy;
+
+		return single_open(file, show, private);
+	} else {
+		return -EROFS;
+	}
+}
+
+static ssize_t rtw_drv_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos)
+{
+	ssize_t index = (ssize_t)PDE_DATA(file_inode(file));
+	const struct rtw_proc_hdl *hdl = drv_proc_hdls + index;
+	ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *, void *) = hdl->write;
+
+	if (write)
+		return write(file, buffer, count, pos, NULL);
+
+	return -EROFS;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+static const struct proc_ops rtw_drv_proc_seq_fops = {
+	.proc_open	= rtw_drv_proc_open,
+	.proc_read	= seq_read,
+	.proc_lseek	= seq_lseek,
+	.proc_release	= seq_release,
+	.proc_write	= rtw_drv_proc_write,
+};
+#else
+static const struct file_operations rtw_drv_proc_seq_fops = {
+	.owner = THIS_MODULE,
+	.open = rtw_drv_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+	.write = rtw_drv_proc_write,
+};
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+static const struct proc_ops rtw_drv_proc_sseq_fops = {
+	.proc_open = rtw_drv_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+	.proc_write = rtw_drv_proc_write,
+};
+#else
+static const struct file_operations rtw_drv_proc_sseq_fops = {
+	.owner = THIS_MODULE,
+	.open = rtw_drv_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = rtw_drv_proc_write,
+};
+#endif
+
+int rtw_drv_proc_init(void)
+{
+	int ret = _FAIL;
+	ssize_t i;
+	struct proc_dir_entry *entry = NULL;
+
+	if (rtw_proc != NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	rtw_proc = rtw_proc_create_dir(RTW_PROC_NAME, get_proc_net, NULL);
+
+	if (rtw_proc == NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	for (i = 0; i < drv_proc_hdls_num; i++) {
+		if (drv_proc_hdls[i].type == RTW_PROC_HDL_TYPE_SEQ)
+			entry = rtw_proc_create_entry(drv_proc_hdls[i].name, rtw_proc, &rtw_drv_proc_seq_fops, (void *)i);
+		else if (drv_proc_hdls[i].type == RTW_PROC_HDL_TYPE_SSEQ)
+			entry = rtw_proc_create_entry(drv_proc_hdls[i].name, rtw_proc, &rtw_drv_proc_sseq_fops, (void *)i);
+		else
+			entry = NULL;
+
+		if (!entry) {
+			rtw_warn_on(1);
+			goto exit;
+		}
+	}
+
+	ret = _SUCCESS;
+
+exit:
+	return ret;
+}
+
+void rtw_drv_proc_deinit(void)
+{
+	int i;
+
+	if (rtw_proc == NULL)
+		return;
+
+	for (i = 0; i < drv_proc_hdls_num; i++)
+		remove_proc_entry(drv_proc_hdls[i].name, rtw_proc);
+
+	remove_proc_entry(RTW_PROC_NAME, get_proc_net);
+	rtw_proc = NULL;
+}
+
+#ifndef RTW_SEQ_FILE_TEST
+#define RTW_SEQ_FILE_TEST 0
+#endif
+
+#if RTW_SEQ_FILE_TEST
+#define RTW_SEQ_FILE_TEST_SHOW_LIMIT 300
+static void *proc_start_seq_file_test(struct seq_file *m, loff_t *pos)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
+	if (*pos >= RTW_SEQ_FILE_TEST_SHOW_LIMIT) {
+		RTW_INFO(FUNC_ADPT_FMT" pos:%llu, out of range return\n", FUNC_ADPT_ARG(adapter), *pos);
+		return NULL;
+	}
+
+	RTW_INFO(FUNC_ADPT_FMT" return pos:%lld\n", FUNC_ADPT_ARG(adapter), *pos);
+	return pos;
+}
+void proc_stop_seq_file_test(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
+}
+
+void *proc_next_seq_file_test(struct seq_file *m, void *v, loff_t *pos)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	(*pos)++;
+	if (*pos >= RTW_SEQ_FILE_TEST_SHOW_LIMIT) {
+		RTW_INFO(FUNC_ADPT_FMT" pos:%lld, out of range return\n", FUNC_ADPT_ARG(adapter), *pos);
+		return NULL;
+	}
+
+	RTW_INFO(FUNC_ADPT_FMT" return pos:%lld\n", FUNC_ADPT_ARG(adapter), *pos);
+	return pos;
+}
+
+static int proc_get_seq_file_test(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	u32 pos = *((loff_t *)(v));
+	RTW_INFO(FUNC_ADPT_FMT" pos:%d\n", FUNC_ADPT_ARG(adapter), pos);
+	RTW_PRINT_SEL(m, FUNC_ADPT_FMT" pos:%d\n", FUNC_ADPT_ARG(adapter), pos);
+	return 0;
+}
+
+struct seq_operations seq_file_test = {
+	.start = proc_start_seq_file_test,
+	.stop  = proc_stop_seq_file_test,
+	.next  = proc_next_seq_file_test,
+	.show  = proc_get_seq_file_test,
+};
+#endif /* RTW_SEQ_FILE_TEST */
+
+#ifdef CONFIG_SDIO_HCI
+static int proc_get_sd_f0_reg_dump(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	sd_f0_reg_dump(m, adapter);
+
+	return 0;
+}
+
+static int proc_get_sdio_local_reg_dump(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	sdio_local_reg_dump(m, adapter);
+
+	return 0;
+}
+#endif /* CONFIG_SDIO_HCI */
+
+#ifdef RTW_HALMAC
+#include "../../hal/hal_halmac.h"
+static int proc_get_halmac_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	rtw_dump_halmac_info(m);
+	return 0;
+}
+#endif
+static int proc_get_fw_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	rtw_dump_fw_info(m, adapter);
+	return 0;
+}
+static int proc_get_mac_reg_dump(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	mac_reg_dump(m, adapter);
+
+	return 0;
+}
+
+static int proc_get_bb_reg_dump(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	bb_reg_dump(m, adapter);
+
+	return 0;
+}
+
+static int proc_get_bb_reg_dump_ex(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	bb_reg_dump_ex(m, adapter);
+
+	return 0;
+}
+
+static int proc_get_rf_reg_dump(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	rf_reg_dump(m, adapter);
+
+	return 0;
+}
+
+static int proc_get_dump_tx_rate_bmp(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	dump_tx_rate_bmp(m, adapter_to_dvobj(adapter));
+
+	return 0;
+}
+
+static int proc_get_dump_adapters_status(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	dump_adapters_status(m, adapter_to_dvobj(adapter));
+
+	return 0;
+}
+
+#ifdef CONFIG_RTW_CUSTOMER_STR
+static int proc_get_customer_str(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 cstr[RTW_CUSTOMER_STR_LEN];
+
+	if (rtw_hal_customer_str_read(adapter, cstr) != _SUCCESS)
+		goto exit;
+
+	RTW_PRINT_SEL(m, RTW_CUSTOMER_STR_FMT"\n", RTW_CUSTOMER_STR_ARG(cstr));
+
+exit:
+	return 0;
+}
+#endif /* CONFIG_RTW_CUSTOMER_STR */
+
+/* gpio setting */
+#ifdef CONFIG_GPIO_API
+static ssize_t proc_set_config_gpio(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] = {0};
+	int num = 0, gpio_pin = 0, gpio_mode = 0; /* gpio_mode:0 input  1:output; */
+
+	if (count < 2)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+		num	= sscanf(tmp, "%d %d", &gpio_pin, &gpio_mode);
+		RTW_INFO("num=%d gpio_pin=%d mode=%d\n", num, gpio_pin, gpio_mode);
+		padapter->pre_gpio_pin = gpio_pin;
+
+		if (gpio_mode == 0 || gpio_mode == 1)
+			rtw_hal_config_gpio(padapter, gpio_pin, gpio_mode);
+	}
+	return count;
+
+}
+static ssize_t proc_set_gpio_output_value(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] = {0};
+	int num = 0, gpio_pin = 0, pin_mode = 0; /* pin_mode: 1 high         0:low */
+
+	if (count < 2)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+		num	= sscanf(tmp, "%d %d", &gpio_pin, &pin_mode);
+		RTW_INFO("num=%d gpio_pin=%d pin_high=%d\n", num, gpio_pin, pin_mode);
+		padapter->pre_gpio_pin = gpio_pin;
+
+		if (pin_mode == 0 || pin_mode == 1)
+			rtw_hal_set_gpio_output_value(padapter, gpio_pin, pin_mode);
+	}
+	return count;
+}
+static int proc_get_gpio(struct seq_file *m, void *v)
+{
+	u8 gpioreturnvalue = 0;
+	struct net_device *dev = m->private;
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	if (!padapter)
+		return -EFAULT;
+	gpioreturnvalue = rtw_hal_get_gpio(padapter, padapter->pre_gpio_pin);
+	RTW_PRINT_SEL(m, "get_gpio %d:%d\n", padapter->pre_gpio_pin, gpioreturnvalue);
+
+	return 0;
+
+}
+static ssize_t proc_set_gpio(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] = {0};
+	int num = 0, gpio_pin = 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, "%d", &gpio_pin);
+		RTW_INFO("num=%d gpio_pin=%d\n", num, gpio_pin);
+		padapter->pre_gpio_pin = gpio_pin;
+
+	}
+	return count;
+}
+#endif
+static ssize_t proc_set_rx_info_msg(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 recv_priv *precvpriv = &(padapter->recvpriv);
+	char tmp[32] = {0};
+	int phy_info_flag = 0;
+
+	if (!padapter)
+		return -EFAULT;
+
+	if (count < 1) {
+		RTW_INFO("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, "%d", &phy_info_flag);
+
+		precvpriv->store_law_data_flag = (bool) phy_info_flag;
+
+		/*RTW_INFO("precvpriv->store_law_data_flag = %d\n",( bool )(precvpriv->store_law_data_flag));*/
+	}
+	return count;
+}
+static int proc_get_rx_info_msg(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	rtw_hal_set_odm_var(padapter, HAL_ODM_RX_Dframe_INFO, m, false);
+	return 0;
+}
+static int proc_get_tx_info_msg(struct seq_file *m, void *v)
+{
+	unsigned long irqL;
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
+	struct sta_info *psta;
+	u8 bc_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	u8 null_addr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	int i;
+	_list	*plist, *phead;
+	u8 current_rate_id = 0, current_sgi = 0;
+
+	char *BW, *status;
+
+	_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+
+	if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE))
+		status = "station mode";
+	else if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE))
+		status = "AP mode";
+	else
+		status = " ";
+	_RTW_PRINT_SEL(m, "status=%s\n", status);
+	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 ((memcmp(psta->hwaddr, bc_addr, 6))
+				&& (memcmp(psta->hwaddr, null_addr, 6))
+				&& (memcmp(psta->hwaddr, adapter_mac_addr(padapter), 6))) {
+
+				switch (psta->bw_mode) {
+
+				case CHANNEL_WIDTH_20:
+					BW = "20M";
+					break;
+
+				case CHANNEL_WIDTH_40:
+					BW = "40M";
+					break;
+
+				case CHANNEL_WIDTH_80:
+					BW = "80M";
+					break;
+
+				case CHANNEL_WIDTH_160:
+					BW = "160M";
+					break;
+
+				default:
+					BW = "";
+					break;
+				}
+				current_rate_id = rtw_get_current_tx_rate(adapter, psta->mac_id);
+				current_sgi = rtw_get_current_tx_sgi(adapter, psta->mac_id);
+
+				RTW_PRINT_SEL(m, "==============================\n");
+				_RTW_PRINT_SEL(m, "macaddr=" MAC_FMT"\n", MAC_ARG(psta->hwaddr));
+				_RTW_PRINT_SEL(m, "Tx_Data_Rate=%s\n", HDATA_RATE(current_rate_id));
+				_RTW_PRINT_SEL(m, "BW=%s,sgi=%u\n", BW, current_sgi);
+
+			}
+		}
+	}
+
+	_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+
+	return 0;
+
+}
+
+
+static int proc_get_linked_info_dump(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	if (padapter)
+		RTW_PRINT_SEL(m, "linked_info_dump :%s\n", (padapter->bLinkInfoDump) ? "enable" : "disable");
+
+	return 0;
+}
+
+
+static ssize_t proc_set_linked_info_dump(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] = {0};
+	int mode = 0, pre_mode = 0;
+	int num = 0;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	pre_mode = padapter->bLinkInfoDump;
+	RTW_INFO("pre_mode=%d\n", pre_mode);
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		num	= sscanf(tmp, "%d ", &mode);
+		RTW_INFO("num=%d mode=%d\n", num, mode);
+
+		if (num != 1) {
+			RTW_INFO("argument number is wrong\n");
+			return -EFAULT;
+		}
+
+		if (mode == 1 || (mode == 0 && pre_mode == 1)) /* not consider pwr_saving 0: */
+			padapter->bLinkInfoDump = mode;
+
+		else if ((mode == 2) || (mode == 0 && pre_mode == 2)) { /* consider power_saving */
+			/* RTW_INFO("linked_info_dump =%s\n", (padapter->bLinkInfoDump)?"enable":"disable") */
+			linked_info_dump(padapter, mode);
+		}
+	}
+	return count;
+}
+
+static int proc_get_mac_qinfo(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	rtw_hal_get_hwreg(adapter, HW_VAR_DUMP_MAC_QUEUE_INFO, (u8 *)m);
+
+	return 0;
+}
+
+int proc_get_wifi_spec(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;
+
+	RTW_PRINT_SEL(m, "wifi_spec=%d\n", pregpriv->wifi_spec);
+	return 0;
+}
+
+static int proc_get_chan_plan(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	dump_cur_chset(m, adapter);
+
+	return 0;
+}
+
+static ssize_t proc_set_chan_plan(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];
+	u8 chan_plan = RTW_CHPLAN_MAX;
+
+	if (!padapter)
+		return -EFAULT;
+
+	if (count < 1) {
+		RTW_INFO("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, "%hhx", &chan_plan);
+		if (num !=  1)
+			return count;
+	}
+
+	rtw_set_channel_plan(padapter, chan_plan);
+
+	return count;
+}
+
+static int proc_get_country_code(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	if (adapter->mlmepriv.country_ent)
+		dump_country_chplan(m, adapter->mlmepriv.country_ent);
+	else
+		RTW_PRINT_SEL(m, "unspecified\n");
+
+	return 0;
+}
+
+static ssize_t proc_set_country_code(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];
+	char alpha2[2];
+	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))
+		goto exit;
+
+	num = sscanf(tmp, "%c%c", &alpha2[0], &alpha2[1]);
+	if (num !=	2)
+		return count;
+
+	rtw_set_country(padapter, alpha2);
+
+exit:
+	return count;
+}
+
+#if CONFIG_RTW_MACADDR_ACL
+static int proc_get_macaddr_acl(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	dump_macaddr_acl(m, adapter);
+	return 0;
+}
+
+static ssize_t proc_set_macaddr_acl(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;
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+	char tmp[17 * NUM_ACL + 32] = {0};
+	u8 mode;
+	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)) {
+		/* mode [<macaddr>] */
+		char *c, *next;
+
+		next = tmp;
+		c = strsep(&next, " \t");
+
+		if (sscanf(c, "%hhu", &mode) != 1)
+			return count;
+
+		if (mode >= RTW_ACL_MODE_MAX)
+			mode = RTW_ACL_MODE_DISABLED;
+
+		rtw_set_macaddr_acl(adapter, RTW_ACL_MODE_DISABLED); /* deinit first */
+		if (mode == RTW_ACL_MODE_DISABLED)
+			return count;
+
+		rtw_set_macaddr_acl(adapter, mode);
+
+		/* macaddr list */
+		c = strsep(&next, " \t");
+		while (c != NULL) {
+			if (sscanf(c, MAC_SFMT, MAC_SARG(addr)) != 6)
+				break;
+
+			if (rtw_check_invalid_mac_address(addr, 0) == false)
+				rtw_acl_add_sta(adapter, addr);
+
+			c = strsep(&next, " \t");
+		}
+
+	}
+
+exit:
+	return count;
+}
+#endif /* CONFIG_RTW_MACADDR_ACL */
+
+#if CONFIG_RTW_PRE_LINK_STA
+static int proc_get_pre_link_sta(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	dump_pre_link_sta_ctl(m, &adapter->stapriv);
+	return 0;
+}
+
+ssize_t proc_set_pre_link_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_priv *mlme = &adapter->mlmepriv;
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+	char tmp[17 * RTW_PRE_LINK_STA_NUM + 32] = {0};
+	char arg0[16] = {0};
+	u8 addr[ETH_ALEN];
+
+#define PRE_LINK_STA_CMD_RESET	0
+#define PRE_LINK_STA_CMD_ADD	1
+#define PRE_LINK_STA_CMD_DEL	2
+#define PRE_LINK_STA_CMD_NUM	3
+
+	static const char * const pre_link_sta_cmd_str[] = {
+		"reset",
+		"add",
+		"del"
+	};
+	u8 cmd_id = PRE_LINK_STA_CMD_NUM;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+		/* cmd [<macaddr>] */
+		char *c, *next;
+		int i;
+
+		next = tmp;
+		c = strsep(&next, " \t");
+
+		if (sscanf(c, "%s", arg0) != 1)
+			goto exit;
+
+		for (i = 0; i < PRE_LINK_STA_CMD_NUM; i++)
+			if (strcmp(pre_link_sta_cmd_str[i], arg0) == 0)
+				cmd_id = i;
+
+		switch (cmd_id) {
+		case PRE_LINK_STA_CMD_RESET:
+			rtw_pre_link_sta_ctl_reset(&adapter->stapriv);
+			goto exit;
+		case PRE_LINK_STA_CMD_ADD:
+		case PRE_LINK_STA_CMD_DEL:
+			break;
+		default:
+			goto exit;
+		}
+
+		/* macaddr list */
+		c = strsep(&next, " \t");
+		while (c != NULL) {
+			if (sscanf(c, MAC_SFMT, MAC_SARG(addr)) != 6)
+				break;
+
+			if (rtw_check_invalid_mac_address(addr, 0) == false) {
+				if (cmd_id == PRE_LINK_STA_CMD_ADD)
+					rtw_pre_link_sta_add(&adapter->stapriv, addr);
+				else
+					rtw_pre_link_sta_del(&adapter->stapriv, addr);
+			}
+
+			c = strsep(&next, " \t");
+		}
+	}
+
+exit:
+	return count;
+}
+#endif /* CONFIG_RTW_PRE_LINK_STA */
+
+#ifdef CONFIG_DFS_MASTER
+ssize_t proc_set_update_non_ocp(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;
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+	char tmp[32];
+	u8 ch, bw = CHANNEL_WIDTH_20, offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	int ms = -1;
+
+	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 %hhu %d", &ch, &bw, &offset, &ms);
+
+		if (num < 1 || (bw != CHANNEL_WIDTH_20 && num < 3))
+			goto exit;
+
+		if (bw == CHANNEL_WIDTH_20)
+			rtw_chset_update_non_ocp_ms(mlmeext->channel_set
+				, ch, bw, HAL_PRIME_CHNL_OFFSET_DONT_CARE, ms);
+		else
+			rtw_chset_update_non_ocp_ms(mlmeext->channel_set
+				, ch, bw, offset, ms);
+	}
+
+exit:
+	return count;
+}
+
+ssize_t proc_set_radar_detect(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 fake_radar_detect_cnt = 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, "%hhu", &fake_radar_detect_cnt);
+
+		if (num < 1)
+			goto exit;
+
+		rfctl->dbg_dfs_master_fake_radar_detect_cnt = fake_radar_detect_cnt;
+	}
+
+exit:
+	return count;
+}
+
+static int proc_get_dfs_ch_sel_d_flags(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);
+
+	RTW_PRINT_SEL(m, "0x%02x\n", rfctl->dfs_ch_sel_d_flags);
+
+	return 0;
+}
+
+static ssize_t proc_set_dfs_ch_sel_d_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);
+	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
+	char tmp[32];
+	u8 d_flags;
+	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))
+		goto exit;
+
+	num = sscanf(tmp, "%hhx", &d_flags);
+	if (num !=	1)
+		goto exit;
+
+	rfctl->dfs_ch_sel_d_flags = d_flags;
+
+exit:
+	return count;
+}
+#endif /* CONFIG_DFS_MASTER */
+
+static int proc_get_udpport(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);
+
+	RTW_PRINT_SEL(m, "%d\n", precvpriv->sink_udpport);
+	return 0;
+}
+static ssize_t proc_set_udpport(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 recv_priv *precvpriv = &(padapter->recvpriv);
+	int sink_udpport = 0;
+	char tmp[32];
+
+
+	if (!padapter)
+		return -EFAULT;
+
+	if (count < 1) {
+		RTW_INFO("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, "%d", &sink_udpport);
+
+		if (num !=  1) {
+			RTW_INFO("invalid input parameter number!\n");
+			return count;
+		}
+
+	}
+	precvpriv->sink_udpport = sink_udpport;
+
+	return count;
+
+}
+
+static int proc_get_mi_ap_bc_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
+	u8 i;
+
+	for (i = 0; i < dvobj->iface_nums; i++)
+		RTW_PRINT_SEL(m, "iface_id:%d, mac_id && sec_cam_id = %d\n", i, macid_ctl->iface_bmc[i]);
+
+	return 0;
+}
+static int proc_get_macid_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
+	u8 chip_type = rtw_get_chip_type(adapter);
+	u8 i;
+	u8 null_addr[ETH_ALEN] = {0};
+	u8 *macaddr;
+
+	RTW_PRINT_SEL(m, "max_num:%u\n", macid_ctl->num);
+	RTW_PRINT_SEL(m, "\n");
+
+	RTW_PRINT_SEL(m, "used:\n");
+	dump_macid_map(m, &macid_ctl->used, macid_ctl->num);
+	RTW_PRINT_SEL(m, "\n");
+
+	RTW_PRINT_SEL(m, "%-3s %-3s %-4s %-4s %-17s %-6s %-3s"
+		, "id", "bmc", "if_g", "ch_g", "macaddr", "bw", "vht");
+
+	if (chip_type == RTL8814A)
+		_RTW_PRINT_SEL(m, " %-10s", "rate_bmp1");
+
+	_RTW_PRINT_SEL(m, " %-10s %s\n", "rate_bmp0", "status");
+
+	for (i = 0; i < macid_ctl->num; i++) {
+		if (rtw_macid_is_used(macid_ctl, i)
+			|| macid_ctl->h2c_msr[i]
+		) {
+			if (macid_ctl->sta[i])
+				macaddr = macid_ctl->sta[i]->hwaddr;
+			else
+				macaddr = null_addr;
+
+			RTW_PRINT_SEL(m, "%3u %3u %4d %4d "MAC_FMT" %6s %3u"
+				, i
+				, rtw_macid_is_bmc(macid_ctl, i)
+				, rtw_macid_get_if_g(macid_ctl, i)
+				, rtw_macid_get_ch_g(macid_ctl, i)
+				, MAC_ARG(macaddr)
+				, ch_width_str(macid_ctl->bw[i])
+				, macid_ctl->vht_en[i]
+			);
+
+			if (chip_type == RTL8814A)
+				_RTW_PRINT_SEL(m, " 0x%08X", macid_ctl->rate_bmp1[i]);
+
+			_RTW_PRINT_SEL(m, " 0x%08X "H2C_MSR_FMT" %s\n"
+				, macid_ctl->rate_bmp0[i]
+				, H2C_MSR_ARG(&macid_ctl->h2c_msr[i])
+				, rtw_macid_is_used(macid_ctl, i) ? "" : "[unused]"
+			);
+		}
+	}
+
+	return 0;
+}
+
+static int proc_get_sec_cam(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+
+	RTW_PRINT_SEL(m, "sec_cap:0x%02x\n", cam_ctl->sec_cap);
+	RTW_PRINT_SEL(m, "flags:0x%08x\n", cam_ctl->flags);
+	RTW_PRINT_SEL(m, "\n");
+
+	RTW_PRINT_SEL(m, "max_num:%u\n", cam_ctl->num);
+	RTW_PRINT_SEL(m, "used:\n");
+	dump_sec_cam_map(m, &cam_ctl->used, cam_ctl->num);
+	RTW_PRINT_SEL(m, "\n");
+
+	RTW_PRINT_SEL(m, "reg_scr:0x%04x\n", rtw_read16(adapter, 0x680));
+	RTW_PRINT_SEL(m, "\n");
+
+	dump_sec_cam(m, adapter);
+
+	return 0;
+}
+
+static ssize_t proc_set_sec_cam(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 dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	char tmp[32] = {0};
+	char cmd[4];
+	u8 id_1 = 0, id_2 = 0;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		/* c <id_1>: clear specific cam entry */
+		/* wfc <id_1>: write specific cam entry from cam cache */
+		/* sw <id_1> <id_2>: sec_cam 1/2 swap */
+
+		int num = sscanf(tmp, "%s %hhu %hhu", cmd, &id_1, &id_2);
+
+		if (num < 2)
+			return count;
+
+		if ((id_1 >= cam_ctl->num) || (id_2 >= cam_ctl->num)) {
+			RTW_ERR(FUNC_ADPT_FMT" invalid id_1:%u id_2:%u\n", FUNC_ADPT_ARG(adapter), id_1, id_2);
+			return count;
+		}
+
+		if (strcmp("c", cmd) == 0) {
+			_clear_cam_entry(adapter, id_1);
+			adapter->securitypriv.hw_decrypted = false; /* temporarily set this for TX path to use SW enc */
+		} else if (strcmp("wfc", cmd) == 0)
+			write_cam_from_cache(adapter, id_1);
+		else if (strcmp("sw", cmd) == 0)
+			rtw_sec_cam_swap(adapter, id_1, id_2);
+		else if (strcmp("cdk", cmd) == 0)
+			rtw_clean_dk_section(adapter);
+#ifdef DBG_SEC_CAM_MOVE
+		else if (strcmp("sgd", cmd) == 0)
+			rtw_hal_move_sta_gk_to_dk(adapter);
+		else if (strcmp("rsd", cmd) == 0)
+			rtw_hal_read_sta_dk_key(adapter, id_1);
+#endif
+	}
+
+	return count;
+}
+
+static int proc_get_sec_cam_cache(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	dump_sec_cam_cache(m, adapter);
+	return 0;
+}
+
+static ssize_t proc_set_change_bss_chbw(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);
+	struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
+	char tmp[32];
+	s16 ch;
+	s8 bw = -1, offset = -1;
+
+	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, "%hd %hhd %hhd", &ch, &bw, &offset);
+
+		if (num < 1 || (bw != CHANNEL_WIDTH_20 && num < 3))
+			goto exit;
+
+		if (check_fwstate(mlme, WIFI_AP_STATE) && check_fwstate(mlme, WIFI_ASOC_STATE))
+			rtw_change_bss_chbw_cmd(adapter, RTW_CMDF_WAIT_ACK, ch, bw, offset);
+	}
+
+exit:
+	return count;
+}
+
+static int proc_get_tx_bw_mode(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	RTW_PRINT_SEL(m, "0x%02x\n", adapter->driver_tx_bw_mode);
+	RTW_PRINT_SEL(m, "2.4G:%s\n", ch_width_str(ADAPTER_TX_BW_2G(adapter)));
+	RTW_PRINT_SEL(m, "5G:%s\n", ch_width_str(ADAPTER_TX_BW_5G(adapter)));
+
+	return 0;
+}
+
+static ssize_t proc_set_tx_bw_mode(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 macid_ctl_t *macid_ctl = &adapter->dvobj->macid_ctl;
+	struct mlme_priv *mlme = &(adapter->mlmepriv);
+	struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
+	char tmp[32];
+	u8 bw_mode;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		u8 update = false;
+		int num = sscanf(tmp, "%hhx", &bw_mode);
+
+		if (num < 1 || bw_mode == adapter->driver_tx_bw_mode)
+			goto exit;
+
+		if ((MLME_STATE(adapter) & WIFI_ASOC_STATE)
+			&& ((mlmeext->cur_channel <= 14 && BW_MODE_2G(bw_mode) != ADAPTER_TX_BW_2G(adapter))
+				|| (mlmeext->cur_channel >= 36 && BW_MODE_5G(bw_mode) != ADAPTER_TX_BW_5G(adapter)))
+		) {
+			/* RA mask update needed */
+			update = true;
+		}
+		adapter->driver_tx_bw_mode = bw_mode;
+
+		if (update == true) {
+			struct sta_info *sta;
+			int i;
+
+			for (i = 0; i < MACID_NUM_SW_LIMIT; i++) {
+				sta = macid_ctl->sta[i];
+				if (sta && !is_broadcast_mac_addr(sta->hwaddr))
+					rtw_dm_ra_mask_wk_cmd(adapter, (u8 *)sta);
+			}
+		}
+	}
+
+exit:
+	return count;
+}
+
+static int proc_get_hal_txpwr_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
+
+	if (hal_is_band_support(adapter, BAND_ON_2_4G))
+		dump_hal_txpwr_info_2g(m, adapter, hal_spec->rfpath_num_2g, hal_spec->max_tx_cnt);
+
+#ifdef CONFIG_IEEE80211_BAND_5GHZ
+	if (hal_is_band_support(adapter, BAND_ON_5G))
+		dump_hal_txpwr_info_5g(m, adapter, hal_spec->rfpath_num_5g, hal_spec->max_tx_cnt);
+#endif
+
+	return 0;
+}
+
+static int proc_get_target_tx_power(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	dump_target_tx_power(m, adapter);
+
+	return 0;
+}
+
+static int proc_get_tx_power_by_rate(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	dump_tx_power_by_rate(m, adapter);
+
+	return 0;
+}
+
+static int proc_get_tx_power_limit(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	dump_tx_power_limit(m, adapter);
+
+	return 0;
+}
+
+static int proc_get_tx_power_ext_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	dump_tx_power_ext_info(m, adapter);
+
+	return 0;
+}
+
+static ssize_t proc_set_tx_power_ext_info(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] = {0};
+	char cmd[16] = {0};
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%s", cmd);
+
+		if (num < 1)
+			return count;
+
+		#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE
+		phy_free_filebuf_mask(adapter, LOAD_BB_PG_PARA_FILE | LOAD_RF_TXPWR_LMT_PARA_FILE);
+		#endif
+
+		rtw_ps_deny(adapter, PS_DENY_IOCTL);
+		LeaveAllPowerSaveModeDirect(adapter);
+
+		if (strcmp("default", cmd) == 0)
+			rtw_run_in_thread_cmd(adapter, ((void *)(phy_reload_default_tx_power_ext_info)), adapter);
+		else
+			rtw_run_in_thread_cmd(adapter, ((void *)(phy_reload_tx_power_ext_info)), adapter);
+
+		rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);
+	}
+
+	return count;
+}
+
+static void *proc_start_tx_power_idx(struct seq_file *m, loff_t *pos)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 path = ((*pos) & 0xFF00) >> 8;
+	u8 rs = *pos & 0xFF;
+
+	if (path >= RF_PATH_MAX)
+		return NULL;
+
+	return pos;
+}
+static void proc_stop_tx_power_idx(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+}
+
+static void *proc_next_tx_power_idx(struct seq_file *m, void *v, loff_t *pos)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 path = ((*pos) & 0xFF00) >> 8;
+	u8 rs = *pos & 0xFF;
+
+	rs++;
+	if (rs >= RATE_SECTION_NUM) {
+		rs = 0;
+		path++;
+	}
+
+	if (path >= RF_PATH_MAX)
+		return NULL;
+
+	*pos = (path << 8) | rs;
+
+	return pos;
+}
+
+static int proc_get_tx_power_idx(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	u32 pos = *((loff_t *)(v));
+	u8 path = (pos & 0xFF00) >> 8;
+	u8 rs = pos & 0xFF;
+
+	if (0)
+		RTW_INFO("%s path=%u, rs=%u\n", __func__, path, rs);
+
+	if (path == RF_PATH_A && rs == CCK)
+		dump_tx_power_idx_title(m, adapter);
+	dump_tx_power_idx_by_path_rs(m, adapter, path, rs);
+
+	return 0;
+}
+
+static struct seq_operations seq_ops_tx_power_idx = {
+	.start = proc_start_tx_power_idx,
+	.stop  = proc_stop_tx_power_idx,
+	.next  = proc_next_tx_power_idx,
+	.show  = proc_get_tx_power_idx,
+};
+
+#ifdef CONFIG_RF_POWER_TRIM
+static int proc_get_kfree_flag(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct kfree_data_t *kfree_data = GET_KFREE_DATA(adapter);
+
+	RTW_PRINT_SEL(m, "0x%02x\n", kfree_data->flag);
+
+	return 0;
+}
+
+static ssize_t proc_set_kfree_flag(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 kfree_data_t *kfree_data = GET_KFREE_DATA(adapter);
+	char tmp[32] = {0};
+	u8 flag;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%hhx", &flag);
+
+		if (num < 1)
+			return count;
+
+		kfree_data->flag = flag;
+	}
+
+	return count;
+}
+
+static int proc_get_kfree_bb_gain(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
+	struct kfree_data_t *kfree_data = GET_KFREE_DATA(adapter);
+	u8 i, j;
+
+	for (i = 0; i < BB_GAIN_NUM; i++) {
+		if (i == 0)
+			_RTW_PRINT_SEL(m, "2G: ");
+		else if (i == 1)
+			_RTW_PRINT_SEL(m, "5GLB1: ");
+		else if (i == 2)
+			_RTW_PRINT_SEL(m, "5GLB2: ");
+		else if (i == 3)
+			_RTW_PRINT_SEL(m, "5GMB1: ");
+		else if (i == 4)
+			_RTW_PRINT_SEL(m, "5GMB2: ");
+		else if (i == 5)
+			_RTW_PRINT_SEL(m, "5GHB: ");
+
+		for (j = 0; j < hal_data->NumTotalRFPath; j++)
+			_RTW_PRINT_SEL(m, "%d ", kfree_data->bb_gain[i][j]);
+		_RTW_PRINT_SEL(m, "\n");
+	}
+
+	return 0;
+}
+
+static ssize_t proc_set_kfree_bb_gain(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);
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
+	struct kfree_data_t *kfree_data = GET_KFREE_DATA(adapter);
+	char tmp[BB_GAIN_NUM * RF_PATH_MAX] = {0};
+	u8 path, chidx;
+	s8 bb_gain[BB_GAIN_NUM];
+	char ch_band_Group[6];
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+		char *c, *next;
+		int i = 0;
+
+		next = tmp;
+		c = strsep(&next, " \t");
+
+		if (sscanf(c, "%s", ch_band_Group) != 1) {
+			RTW_INFO("Error Head Format, channel Group select\n,Please input:\t 2G , 5GLB1 , 5GLB2 , 5GMB1 , 5GMB2 , 5GHB\n");
+			return count;
+		}
+		if (strcmp("2G", ch_band_Group) == 0)
+			chidx = BB_GAIN_2G;
+#ifdef CONFIG_IEEE80211_BAND_5GHZ
+		else if (strcmp("5GLB1", ch_band_Group) == 0)
+			chidx = BB_GAIN_5GLB1;
+		else if (strcmp("5GLB2", ch_band_Group) == 0)
+			chidx = BB_GAIN_5GLB2;
+		else if (strcmp("5GMB1", ch_band_Group) == 0)
+			chidx = BB_GAIN_5GMB1;
+		else if (strcmp("5GMB2", ch_band_Group) == 0)
+			chidx = BB_GAIN_5GMB2;
+		else if (strcmp("5GHB", ch_band_Group) == 0)
+			chidx = BB_GAIN_5GHB;
+#endif /*CONFIG_IEEE80211_BAND_5GHZ*/
+		else {
+			RTW_INFO("Error Head Format, channel Group select\n,Please input:\t 2G , 5GLB1 , 5GLB2 , 5GMB1 , 5GMB2 , 5GHB\n");
+			return count;
+		}
+		c = strsep(&next, " \t");
+
+		while (c != NULL) {
+			if (sscanf(c, "%hhx", &bb_gain[i]) != 1)
+				break;
+
+			kfree_data->bb_gain[chidx][i] = bb_gain[i];
+			RTW_INFO("%s,kfree_data->bb_gain[%d][%d]=%x\n", __func__, chidx, i, kfree_data->bb_gain[chidx][i]);
+
+			c = strsep(&next, " \t");
+			i++;
+		}
+
+	}
+
+	return count;
+
+}
+
+static int proc_get_kfree_thermal(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct kfree_data_t *kfree_data = GET_KFREE_DATA(adapter);
+
+	_RTW_PRINT_SEL(m, "%d\n", kfree_data->thermal);
+
+	return 0;
+}
+
+static ssize_t proc_set_kfree_thermal(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 kfree_data_t *kfree_data = GET_KFREE_DATA(adapter);
+	char tmp[32] = {0};
+	s8 thermal;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%hhd", &thermal);
+
+		if (num < 1)
+			return count;
+
+		kfree_data->thermal = thermal;
+	}
+
+	return count;
+}
+
+static ssize_t proc_set_tx_gain_offset(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *adapter;
+	char tmp[32] = {0};
+	u8 rf_path;
+	s8 offset;
+
+	adapter = (_adapter *)rtw_netdev_priv(dev);
+	if (!adapter)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+		u8 write_value;
+		int num = sscanf(tmp, "%hhu %hhd", &rf_path, &offset);
+
+		if (num < 2)
+			return count;
+
+		RTW_INFO("write rf_path:%u tx gain offset:%d\n", rf_path, offset);
+		rtw_rf_set_tx_gain_offset(adapter, rf_path, offset);
+	}
+
+	return count;
+}
+#endif /* CONFIG_RF_POWER_TRIM */
+
+#ifdef CONFIG_BT_COEXIST
+ssize_t proc_set_btinfo_evt(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];
+	u8 btinfo[8];
+
+	if (count < 6)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+		int num = 0;
+
+		memset(btinfo, 0, 8);
+
+		num = sscanf(tmp, "%hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx"
+			, &btinfo[0], &btinfo[1], &btinfo[2], &btinfo[3]
+			, &btinfo[4], &btinfo[5], &btinfo[6], &btinfo[7]);
+
+		if (num < 6)
+			return -EINVAL;
+
+		btinfo[1] = num - 2;
+
+		rtw_btinfo_cmd(padapter, btinfo, btinfo[1] + 2);
+	}
+
+	return count;
+}
+
+static u8 btreg_read_type = 0;
+static u16 btreg_read_addr = 0;
+static int btreg_read_error = 0;
+static u8 btreg_write_type = 0;
+static u16 btreg_write_addr = 0;
+static int btreg_write_error = 0;
+
+static u8 *btreg_type[] = {
+	"rf",
+	"modem",
+	"bluewize",
+	"vendor",
+	"le"
+};
+
+static int btreg_parse_str(char const *input, u8 *type, u16 *addr, u16 *val)
+{
+	u32 num;
+	u8 str[80] = {0};
+	u8 t = 0;
+	u32 a, v;
+	u8 i, n;
+	u8 *p;
+
+
+	num = sscanf(input, "%s %x %x", str, &a, &v);
+	if (num < 2) {
+		RTW_INFO("%s: INVALID input!(%s)\n", __func__, input);
+		return -EINVAL;
+	}
+	if ((num < 3) && val) {
+		RTW_INFO("%s: INVALID input!(%s)\n", __func__, input);
+		return -EINVAL;
+	}
+
+	/* convert to lower case for following type compare */
+	p = str;
+	for (; *p; ++p)
+		*p = tolower(*p);
+	n = sizeof(btreg_type) / sizeof(btreg_type[0]);
+	for (i = 0; i < n; i++) {
+		if (!strcmp(str, btreg_type[i])) {
+			t = i;
+			break;
+		}
+	}
+	if (i == n) {
+		RTW_INFO("%s: unknown type(%s)!\n", __func__, str);
+		return -EINVAL;
+	}
+
+	switch (t) {
+	case 0:
+		/* RF */
+		if (a & 0xFFFFFF80) {
+			RTW_INFO("%s: INVALID address(0x%X) for type %s(%d)!\n",
+				 __func__, a, btreg_type[t], t);
+			return -EINVAL;
+		}
+		break;
+	case 1:
+		/* Modem */
+		if (a & 0xFFFFFE00) {
+			RTW_INFO("%s: INVALID address(0x%X) for type %s(%d)!\n",
+				 __func__, a, btreg_type[t], t);
+			return -EINVAL;
+		}
+		break;
+	default:
+		/* Others(Bluewize, Vendor, LE) */
+		if (a & 0xFFFFF000) {
+			RTW_INFO("%s: INVALID address(0x%X) for type %s(%d)!\n",
+				 __func__, a, btreg_type[t], t);
+			return -EINVAL;
+		}
+		break;
+	}
+
+	if (val) {
+		if (v & 0xFFFF0000) {
+			RTW_INFO("%s: INVALID value(0x%x)!\n", __func__, v);
+			return -EINVAL;
+		}
+		*val = (u16)v;
+	}
+
+	*type = (u8)t;
+	*addr = (u16)a;
+
+	return 0;
+}
+
+int proc_get_btreg_read(struct seq_file *m, void *v)
+{
+	struct net_device *dev;
+	PADAPTER padapter;
+	u16 ret;
+	u32 data;
+
+
+	if (btreg_read_error)
+		return btreg_read_error;
+
+	dev = m->private;
+	padapter = (PADAPTER)rtw_netdev_priv(dev);
+
+	ret = rtw_btcoex_btreg_read(padapter, btreg_read_type, btreg_read_addr, &data);
+	if (CHECK_STATUS_CODE_FROM_BT_MP_OPER_RET(ret, BT_STATUS_BT_OP_SUCCESS))
+		RTW_PRINT_SEL(m, "BTREG read: (%s)0x%04X = 0x%08x\n", btreg_type[btreg_read_type], btreg_read_addr, data);
+	else
+		RTW_PRINT_SEL(m, "BTREG read: (%s)0x%04X read fail. error code = 0x%04x.\n", btreg_type[btreg_read_type], btreg_read_addr, ret);
+
+	return 0;
+}
+
+ssize_t proc_set_btreg_read(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 num;
+	int err;
+
+
+	padapter = (PADAPTER)rtw_netdev_priv(dev);
+
+	if (NULL == buffer) {
+		RTW_INFO(FUNC_ADPT_FMT ": input buffer is NULL!\n",
+			 FUNC_ADPT_ARG(padapter));
+		err = -EFAULT;
+		goto exit;
+	}
+
+	if (count < 1) {
+		RTW_INFO(FUNC_ADPT_FMT ": input length is 0!\n",
+			 FUNC_ADPT_ARG(padapter));
+		err = -EFAULT;
+		goto exit;
+	}
+
+	num = count;
+	if (num > (sizeof(tmp) - 1))
+		num = (sizeof(tmp) - 1);
+
+	if (copy_from_user(tmp, buffer, num)) {
+		RTW_INFO(FUNC_ADPT_FMT ": copy buffer from user space FAIL!\n",
+			 FUNC_ADPT_ARG(padapter));
+		err = -EFAULT;
+		goto exit;
+	}
+	/* [Coverity] sure tmp end with '\0'(string terminal) */
+	tmp[sizeof(tmp) - 1] = 0;
+
+	err = btreg_parse_str(tmp, &btreg_read_type, &btreg_read_addr, NULL);
+	if (err)
+		goto exit;
+
+	RTW_INFO(FUNC_ADPT_FMT ": addr=(%s)0x%X\n",
+		FUNC_ADPT_ARG(padapter), btreg_type[btreg_read_type], btreg_read_addr);
+
+exit:
+	btreg_read_error = err;
+
+	return count;
+}
+
+int proc_get_btreg_write(struct seq_file *m, void *v)
+{
+	struct net_device *dev;
+	PADAPTER padapter;
+	u16 ret;
+	u32 data;
+
+
+	if (btreg_write_error < 0)
+		return btreg_write_error;
+	else if (btreg_write_error > 0) {
+		RTW_PRINT_SEL(m, "BTREG write: (%s)0x%04X write fail. error code = 0x%04x.\n", btreg_type[btreg_write_type], btreg_write_addr, btreg_write_error);
+		return 0;
+	}
+
+	dev = m->private;
+	padapter = (PADAPTER)rtw_netdev_priv(dev);
+
+	ret = rtw_btcoex_btreg_read(padapter, btreg_write_type, btreg_write_addr, &data);
+	if (CHECK_STATUS_CODE_FROM_BT_MP_OPER_RET(ret, BT_STATUS_BT_OP_SUCCESS))
+		RTW_PRINT_SEL(m, "BTREG read: (%s)0x%04X = 0x%08x\n", btreg_type[btreg_write_type], btreg_write_addr, data);
+	else
+		RTW_PRINT_SEL(m, "BTREG read: (%s)0x%04X read fail. error code = 0x%04x.\n", btreg_type[btreg_write_type], btreg_write_addr, ret);
+
+	return 0;
+}
+
+ssize_t proc_set_btreg_write(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 num;
+	u16 val;
+	u16 ret;
+	int err;
+
+
+	padapter = (PADAPTER)rtw_netdev_priv(dev);
+
+	if (NULL == buffer) {
+		RTW_INFO(FUNC_ADPT_FMT ": input buffer is NULL!\n",
+			 FUNC_ADPT_ARG(padapter));
+		err = -EFAULT;
+		goto exit;
+	}
+
+	if (count < 1) {
+		RTW_INFO(FUNC_ADPT_FMT ": input length is 0!\n",
+			 FUNC_ADPT_ARG(padapter));
+		err = -EFAULT;
+		goto exit;
+	}
+
+	num = count;
+	if (num > (sizeof(tmp) - 1))
+		num = (sizeof(tmp) - 1);
+
+	if (copy_from_user(tmp, buffer, num)) {
+		RTW_INFO(FUNC_ADPT_FMT ": copy buffer from user space FAIL!\n",
+			 FUNC_ADPT_ARG(padapter));
+		err = -EFAULT;
+		goto exit;
+	}
+
+	err = btreg_parse_str(tmp, &btreg_write_type, &btreg_write_addr, &val);
+	if (err)
+		goto exit;
+
+	RTW_INFO(FUNC_ADPT_FMT ": Set (%s)0x%X = 0x%x\n",
+		FUNC_ADPT_ARG(padapter), btreg_type[btreg_write_type], btreg_write_addr, val);
+
+	ret = rtw_btcoex_btreg_write(padapter, btreg_write_type, btreg_write_addr, val);
+	if (!CHECK_STATUS_CODE_FROM_BT_MP_OPER_RET(ret, BT_STATUS_BT_OP_SUCCESS))
+		err = ret;
+
+exit:
+	btreg_write_error = err;
+
+	return count;
+}
+#endif /* CONFIG_BT_COEXIST */
+
+#ifdef CONFIG_MBSSID_CAM
+int proc_get_mbid_cam_cache(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	rtw_mbid_cam_cache_dump(m, __func__, adapter);
+	rtw_mbid_cam_dump(m, __func__, adapter);
+	return 0;
+}
+#endif /* CONFIG_MBSSID_CAM */
+
+static int proc_get_mac_addr(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	rtw_hal_dump_macaddr(m, adapter);
+	return 0;
+}
+
+static int proc_get_skip_band(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	int bandskip;
+
+	bandskip = RTW_GET_SCAN_BAND_SKIP(adapter);
+	RTW_PRINT_SEL(m, "bandskip:0x%02x\n", bandskip);
+	return 0;
+}
+
+static ssize_t proc_set_skip_band(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[6];
+	u8 skip_band;
+
+	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", &skip_band);
+
+		if (num < 1)
+			return -EINVAL;
+
+		if (1 == skip_band)
+			RTW_SET_SCAN_BAND_SKIP(padapter, BAND_24G);
+		else if (2 == skip_band)
+			RTW_SET_SCAN_BAND_SKIP(padapter, BAND_5G);
+		else if (3 == skip_band)
+			RTW_CLR_SCAN_BAND_SKIP(padapter, BAND_24G);
+		else if (4 == skip_band)
+			RTW_CLR_SCAN_BAND_SKIP(padapter, BAND_5G);
+	}
+	return count;
+
+}
+
+#ifdef CONFIG_AUTO_CHNL_SEL_NHM
+static int proc_get_best_chan(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 best_24g_ch = 0, best_5g_ch = 0;
+
+	rtw_hal_get_odm_var(adapter, HAL_ODM_AUTO_CHNL_SEL, &(best_24g_ch), &(best_5g_ch));
+
+	RTW_PRINT_SEL(m, "Best 2.4G CH:%u\n", best_24g_ch);
+	RTW_PRINT_SEL(m, "Best 5G CH:%u\n", best_5g_ch);
+	return 0;
+}
+
+static ssize_t proc_set_acs(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];
+	u8 acs_satae = 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, "%hhu", &acs_satae);
+
+		if (num < 1)
+			return -EINVAL;
+
+		if (1 == acs_satae)
+			rtw_acs_start(padapter, true);
+		else
+			rtw_acs_start(padapter, false);
+
+	}
+	return count;
+}
+#endif
+
+static int proc_get_hal_spec(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	dump_hal_spec(m, adapter);
+	return 0;
+}
+
+static int proc_get_phy_cap(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	rtw_dump_phy_cap(m, adapter);
+	rtw_dump_drv_phy_cap(m, adapter);
+	rtw_get_dft_phy_cap(m, adapter);
+	return 0;
+}
+
+#ifdef CONFIG_SUPPORT_TRX_SHARED
+#include "../../hal/hal_halmac.h"
+static int proc_get_trx_share_mode(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	dump_trx_share_mode(m, adapter);
+	return 0;
+}
+#endif
+
+static int proc_dump_rsvd_page(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	rtw_dump_rsvd_page(m, adapter, adapter->rsvd_page_offset, adapter->rsvd_page_num);
+	return 0;
+}
+static ssize_t proc_set_rsvd_page_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);
+	char tmp[32];
+	u8 page_offset, page_num;
+
+	if (count < 2)
+		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", &page_offset, &page_num);
+
+		if (num < 2)
+			return -EINVAL;
+		padapter->rsvd_page_offset = page_offset;
+		padapter->rsvd_page_num = page_num;
+	}
+	return count;
+}
+
+#ifdef CONFIG_WOW_PATTERN_HW_CAM
+int proc_dump_pattern_cam(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);
+	int i;
+	struct  rtl_wow_pattern context;
+
+	for (i = 0 ; i < pwrpriv->wowlan_pattern_idx; i++) {
+		rtw_wow_pattern_read_cam_ent(padapter, i, &context);
+		rtw_dump_wow_pattern(m, &context, i);
+	}
+
+	return 0;
+}
+#endif
+
+static int proc_get_napi_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct registry_priv *pregistrypriv = &adapter->registrypriv;
+	u8 napi = 0, gro = 0;
+	u32 weight = 0;
+
+
+#ifdef CONFIG_RTW_NAPI
+	if (pregistrypriv->en_napi) {
+		napi = 1;
+		weight = RTL_NAPI_WEIGHT;
+	}
+
+#ifdef CONFIG_RTW_GRO
+	if (pregistrypriv->en_gro)
+		gro = 1;
+#endif /* CONFIG_RTW_GRO */
+#endif /* CONFIG_RTW_NAPI */
+
+	if (napi)
+		RTW_PRINT_SEL(m, "NAPI enable, weight=%d\n", weight);
+	else
+		RTW_PRINT_SEL(m, "NAPI disable\n");
+	RTW_PRINT_SEL(m, "GRO %s\n", gro?"enable":"disable");
+
+	return 0;
+}
+
+/*
+* rtw_adapter_proc:
+* init/deinit when register/unregister net_device
+*/
+static const struct rtw_proc_hdl adapter_proc_hdls[] = {
+#if RTW_SEQ_FILE_TEST
+	RTW_PROC_HDL_SEQ("seq_file_test", &seq_file_test, NULL),
+#endif
+	RTW_PROC_HDL_SSEQ("write_reg", NULL, proc_set_write_reg),
+	RTW_PROC_HDL_SSEQ("read_reg", proc_get_read_reg, proc_set_read_reg),
+	RTW_PROC_HDL_SSEQ("tx_rate_bmp", proc_get_dump_tx_rate_bmp, NULL),
+	RTW_PROC_HDL_SSEQ("adapters_status", proc_get_dump_adapters_status, NULL),
+#ifdef CONFIG_RTW_CUSTOMER_STR
+	RTW_PROC_HDL_SSEQ("customer_str", proc_get_customer_str, NULL),
+#endif
+	RTW_PROC_HDL_SSEQ("fwstate", proc_get_fwstate, NULL),
+	RTW_PROC_HDL_SSEQ("sec_info", proc_get_sec_info, NULL),
+	RTW_PROC_HDL_SSEQ("mlmext_state", proc_get_mlmext_state, NULL),
+	RTW_PROC_HDL_SSEQ("qos_option", proc_get_qos_option, NULL),
+	RTW_PROC_HDL_SSEQ("ht_option", proc_get_ht_option, NULL),
+	RTW_PROC_HDL_SSEQ("rf_info", proc_get_rf_info, NULL),
+	RTW_PROC_HDL_SSEQ("scan_param", proc_get_scan_param, proc_set_scan_param),
+	RTW_PROC_HDL_SSEQ("scan_abort", proc_get_scan_abort, NULL),
+#ifdef CONFIG_SCAN_BACKOP
+	RTW_PROC_HDL_SSEQ("backop_flags_sta", proc_get_backop_flags_sta, proc_set_backop_flags_sta),
+	RTW_PROC_HDL_SSEQ("backop_flags_ap", proc_get_backop_flags_ap, proc_set_backop_flags_ap),
+#endif
+	RTW_PROC_HDL_SSEQ("survey_info", proc_get_survey_info, proc_set_survey_info),
+	RTW_PROC_HDL_SSEQ("ap_info", proc_get_ap_info, NULL),
+	RTW_PROC_HDL_SSEQ("trx_info", proc_get_trx_info, proc_reset_trx_info),
+	RTW_PROC_HDL_SSEQ("tx_power_offset", proc_get_tx_power_offset, proc_set_tx_power_offset),
+	RTW_PROC_HDL_SSEQ("rate_ctl", proc_get_rate_ctl, proc_set_rate_ctl),
+	RTW_PROC_HDL_SSEQ("bw_ctl", proc_get_bw_ctl, proc_set_bw_ctl),
+	RTW_PROC_HDL_SSEQ("dis_pwt_ctl", proc_get_dis_pwt, proc_set_dis_pwt),
+	RTW_PROC_HDL_SSEQ("mac_qinfo", proc_get_mac_qinfo, NULL),
+	RTW_PROC_HDL_SSEQ("macid_info", proc_get_macid_info, NULL),
+	RTW_PROC_HDL_SSEQ("bcmc_info", proc_get_mi_ap_bc_info, NULL),
+	RTW_PROC_HDL_SSEQ("sec_cam", proc_get_sec_cam, proc_set_sec_cam),
+	RTW_PROC_HDL_SSEQ("sec_cam_cache", proc_get_sec_cam_cache, NULL),
+	RTW_PROC_HDL_SSEQ("suspend_info", proc_get_suspend_resume_info, NULL),
+	RTW_PROC_HDL_SSEQ("wifi_spec", proc_get_wifi_spec, NULL),
+#ifdef CONFIG_LAYER2_ROAMING
+	RTW_PROC_HDL_SSEQ("roam_flags", proc_get_roam_flags, proc_set_roam_flags),
+	RTW_PROC_HDL_SSEQ("roam_param", proc_get_roam_param, proc_set_roam_param),
+	RTW_PROC_HDL_SSEQ("roam_tgt_addr", NULL, proc_set_roam_tgt_addr),
+#endif /* CONFIG_LAYER2_ROAMING */
+
+#ifdef CONFIG_RTW_80211R
+	RTW_PROC_HDL_SSEQ("ft_flags", proc_get_ft_flags, proc_set_ft_flags),
+#endif
+
+#ifdef CONFIG_SDIO_HCI
+	RTW_PROC_HDL_SSEQ("sd_f0_reg_dump", proc_get_sd_f0_reg_dump, NULL),
+	RTW_PROC_HDL_SSEQ("sdio_local_reg_dump", proc_get_sdio_local_reg_dump, NULL),
+#endif /* CONFIG_SDIO_HCI */
+
+	RTW_PROC_HDL_SSEQ("fwdl_test_case", NULL, proc_set_fwdl_test_case),
+	RTW_PROC_HDL_SSEQ("del_rx_ampdu_test_case", NULL, proc_set_del_rx_ampdu_test_case),
+	RTW_PROC_HDL_SSEQ("wait_hiq_empty", NULL, proc_set_wait_hiq_empty),
+
+	RTW_PROC_HDL_SSEQ("mac_reg_dump", proc_get_mac_reg_dump, NULL),
+	RTW_PROC_HDL_SSEQ("bb_reg_dump", proc_get_bb_reg_dump, NULL),
+	RTW_PROC_HDL_SSEQ("bb_reg_dump_ex", proc_get_bb_reg_dump_ex, NULL),
+	RTW_PROC_HDL_SSEQ("rf_reg_dump", proc_get_rf_reg_dump, NULL),
+
+#ifdef CONFIG_AP_MODE
+	RTW_PROC_HDL_SSEQ("all_sta_info", proc_get_all_sta_info, NULL),
+#endif /* CONFIG_AP_MODE */
+
+#ifdef CONFIG_FIND_BEST_CHANNEL
+	RTW_PROC_HDL_SSEQ("best_channel", proc_get_best_channel, proc_set_best_channel),
+#endif
+
+	RTW_PROC_HDL_SSEQ("rx_signal", proc_get_rx_signal, proc_set_rx_signal),
+	RTW_PROC_HDL_SSEQ("hw_info", proc_get_hw_status, proc_set_hw_status),
+
+	RTW_PROC_HDL_SSEQ("ht_enable", proc_get_ht_enable, proc_set_ht_enable),
+	RTW_PROC_HDL_SSEQ("bw_mode", proc_get_bw_mode, proc_set_bw_mode),
+	RTW_PROC_HDL_SSEQ("ampdu_enable", proc_get_ampdu_enable, proc_set_ampdu_enable),
+	RTW_PROC_HDL_SSEQ("rx_ampdu", proc_get_rx_ampdu, proc_set_rx_ampdu),
+	RTW_PROC_HDL_SSEQ("rx_ampdu_factor", proc_get_rx_ampdu_factor, proc_set_rx_ampdu_factor),
+	RTW_PROC_HDL_SSEQ("rx_ampdu_density", proc_get_rx_ampdu_density, proc_set_rx_ampdu_density),
+	RTW_PROC_HDL_SSEQ("tx_ampdu_density", proc_get_tx_ampdu_density, proc_set_tx_ampdu_density),
+#ifdef CONFIG_TX_AMSDU
+	RTW_PROC_HDL_SSEQ("tx_amsdu", proc_get_tx_amsdu, proc_set_tx_amsdu),
+	RTW_PROC_HDL_SSEQ("tx_amsdu_rate", proc_get_tx_amsdu_rate, proc_set_tx_amsdu_rate),
+#endif
+
+	RTW_PROC_HDL_SSEQ("en_fwps", proc_get_en_fwps, proc_set_en_fwps),
+	RTW_PROC_HDL_SSEQ("mac_rptbuf", proc_get_mac_rptbuf, NULL),
+
+	/* RTW_PROC_HDL_SSEQ("path_rssi", proc_get_two_path_rssi, NULL),
+	* 	RTW_PROC_HDL_SSEQ("rssi_disp",proc_get_rssi_disp, proc_set_rssi_disp), */
+
+#ifdef CONFIG_BT_COEXIST
+	RTW_PROC_HDL_SSEQ("btcoex_dbg", proc_get_btcoex_dbg, proc_set_btcoex_dbg),
+	RTW_PROC_HDL_SSEQ("btcoex", proc_get_btcoex_info, NULL),
+	RTW_PROC_HDL_SSEQ("btinfo_evt", NULL, proc_set_btinfo_evt),
+	RTW_PROC_HDL_SSEQ("btreg_read", proc_get_btreg_read, proc_set_btreg_read),
+	RTW_PROC_HDL_SSEQ("btreg_write", proc_get_btreg_write, proc_set_btreg_write),
+#endif /* CONFIG_BT_COEXIST */
+
+#if defined(DBG_CONFIG_ERROR_DETECT)
+	RTW_PROC_HDL_SSEQ("sreset", proc_get_sreset, proc_set_sreset),
+#endif /* DBG_CONFIG_ERROR_DETECT */
+	RTW_PROC_HDL_SSEQ("trx_info_debug", proc_get_trx_info_debug, NULL),
+	RTW_PROC_HDL_SSEQ("linked_info_dump", proc_get_linked_info_dump, proc_set_linked_info_dump),
+	RTW_PROC_HDL_SSEQ("tx_info_msg", proc_get_tx_info_msg, NULL),
+	RTW_PROC_HDL_SSEQ("rx_info_msg", proc_get_rx_info_msg, proc_set_rx_info_msg),
+#ifdef CONFIG_GPIO_API
+	RTW_PROC_HDL_SSEQ("gpio_info", proc_get_gpio, proc_set_gpio),
+	RTW_PROC_HDL_SSEQ("gpio_set_output_value", NULL, proc_set_gpio_output_value),
+	RTW_PROC_HDL_SSEQ("gpio_set_direction", NULL, proc_set_config_gpio),
+#endif
+
+#ifdef CONFIG_DBG_COUNTER
+	RTW_PROC_HDL_SSEQ("rx_logs", proc_get_rx_logs, NULL),
+	RTW_PROC_HDL_SSEQ("tx_logs", proc_get_tx_logs, NULL),
+	RTW_PROC_HDL_SSEQ("int_logs", proc_get_int_logs, NULL),
+#endif
+
+#ifdef CONFIG_PCI_HCI
+	RTW_PROC_HDL_SSEQ("rx_ring", proc_get_rx_ring, NULL),
+	RTW_PROC_HDL_SSEQ("tx_ring", proc_get_tx_ring, NULL),
+#endif
+
+#ifdef CONFIG_WOWLAN
+	RTW_PROC_HDL_SSEQ("wow_pattern_info", proc_get_pattern_info, proc_set_pattern_info),
+	RTW_PROC_HDL_SSEQ("wowlan_last_wake_reason", proc_get_wakeup_reason, NULL),
+#ifdef CONFIG_WOW_PATTERN_HW_CAM
+	RTW_PROC_HDL_SSEQ("wow_pattern_cam", proc_dump_pattern_cam, NULL),
+#endif
+#endif
+
+#ifdef CONFIG_GPIO_WAKEUP
+	RTW_PROC_HDL_SSEQ("wowlan_gpio_info", proc_get_wowlan_gpio_info, proc_set_wowlan_gpio_info),
+#endif
+#ifdef CONFIG_P2P_WOWLAN
+	RTW_PROC_HDL_SSEQ("p2p_wowlan_info", proc_get_p2p_wowlan_info, NULL),
+#endif
+	RTW_PROC_HDL_SSEQ("country_code", proc_get_country_code, proc_set_country_code),
+	RTW_PROC_HDL_SSEQ("chan_plan", proc_get_chan_plan, proc_set_chan_plan),
+#if CONFIG_RTW_MACADDR_ACL
+	RTW_PROC_HDL_SSEQ("macaddr_acl", proc_get_macaddr_acl, proc_set_macaddr_acl),
+#endif
+#if CONFIG_RTW_PRE_LINK_STA
+	RTW_PROC_HDL_SSEQ("pre_link_sta", proc_get_pre_link_sta, proc_set_pre_link_sta),
+#endif
+#ifdef CONFIG_DFS_MASTER
+	RTW_PROC_HDL_SSEQ("dfs_master_test_case", proc_get_dfs_master_test_case, proc_set_dfs_master_test_case),
+	RTW_PROC_HDL_SSEQ("update_non_ocp", NULL, proc_set_update_non_ocp),
+	RTW_PROC_HDL_SSEQ("radar_detect", NULL, proc_set_radar_detect),
+	RTW_PROC_HDL_SSEQ("dfs_ch_sel_d_flags", proc_get_dfs_ch_sel_d_flags, proc_set_dfs_ch_sel_d_flags),
+#endif
+	RTW_PROC_HDL_SSEQ("new_bcn_max", proc_get_new_bcn_max, proc_set_new_bcn_max),
+	RTW_PROC_HDL_SSEQ("sink_udpport", proc_get_udpport, proc_set_udpport),
+#ifdef DBG_RX_COUNTER_DUMP
+	RTW_PROC_HDL_SSEQ("dump_rx_cnt_mode", proc_get_rx_cnt_dump, proc_set_rx_cnt_dump),
+#endif
+	RTW_PROC_HDL_SSEQ("change_bss_chbw", NULL, proc_set_change_bss_chbw),
+	RTW_PROC_HDL_SSEQ("tx_bw_mode", proc_get_tx_bw_mode, proc_set_tx_bw_mode),
+	RTW_PROC_HDL_SSEQ("hal_txpwr_info", proc_get_hal_txpwr_info, NULL),
+	RTW_PROC_HDL_SSEQ("target_tx_power", proc_get_target_tx_power, NULL),
+	RTW_PROC_HDL_SSEQ("tx_power_by_rate", proc_get_tx_power_by_rate, NULL),
+	RTW_PROC_HDL_SSEQ("tx_power_limit", proc_get_tx_power_limit, NULL),
+	RTW_PROC_HDL_SSEQ("tx_power_ext_info", proc_get_tx_power_ext_info, proc_set_tx_power_ext_info),
+	RTW_PROC_HDL_SEQ("tx_power_idx", &seq_ops_tx_power_idx, NULL),
+#ifdef CONFIG_RF_POWER_TRIM
+	RTW_PROC_HDL_SSEQ("tx_gain_offset", NULL, proc_set_tx_gain_offset),
+	RTW_PROC_HDL_SSEQ("kfree_flag", proc_get_kfree_flag, proc_set_kfree_flag),
+	RTW_PROC_HDL_SSEQ("kfree_bb_gain", proc_get_kfree_bb_gain, proc_set_kfree_bb_gain),
+	RTW_PROC_HDL_SSEQ("kfree_thermal", proc_get_kfree_thermal, proc_set_kfree_thermal),
+#endif
+#ifdef CONFIG_POWER_SAVING
+	RTW_PROC_HDL_SSEQ("ps_info", proc_get_ps_info, NULL),
+#endif
+#ifdef CONFIG_TDLS
+	RTW_PROC_HDL_SSEQ("tdls_info", proc_get_tdls_info, NULL),
+#endif
+	RTW_PROC_HDL_SSEQ("monitor", proc_get_monitor, proc_set_monitor),
+
+#ifdef CONFIG_AUTO_CHNL_SEL_NHM
+	RTW_PROC_HDL_SSEQ("acs", proc_get_best_chan, proc_set_acs),
+#endif
+#ifdef CONFIG_PREALLOC_RX_SKB_BUFFER
+	RTW_PROC_HDL_SSEQ("rtkm_info", proc_get_rtkm_info, NULL),
+#endif
+	RTW_PROC_HDL_SSEQ("efuse_map", proc_get_efuse_map, NULL),
+#ifdef CONFIG_IEEE80211W
+	RTW_PROC_HDL_SSEQ("11w_tx_sa_query", proc_get_tx_sa_query, proc_set_tx_sa_query),
+	RTW_PROC_HDL_SSEQ("11w_tx_deauth", proc_get_tx_deauth, proc_set_tx_deauth),
+	RTW_PROC_HDL_SSEQ("11w_tx_auth", proc_get_tx_auth, proc_set_tx_auth),
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef CONFIG_MBSSID_CAM
+	RTW_PROC_HDL_SSEQ("mbid_cam", proc_get_mbid_cam_cache, NULL),
+#endif
+	RTW_PROC_HDL_SSEQ("mac_addr", proc_get_mac_addr, NULL),
+	RTW_PROC_HDL_SSEQ("skip_band", proc_get_skip_band, proc_set_skip_band),
+	RTW_PROC_HDL_SSEQ("hal_spec", proc_get_hal_spec, NULL),
+
+	RTW_PROC_HDL_SSEQ("rx_stat", proc_get_rx_stat, NULL),
+
+	RTW_PROC_HDL_SSEQ("tx_stat", proc_get_tx_stat, NULL),
+	/**** PHY Capability ****/
+	RTW_PROC_HDL_SSEQ("phy_cap", proc_get_phy_cap, NULL),
+
+	RTW_PROC_HDL_SSEQ("rx_stbc", proc_get_rx_stbc, proc_set_rx_stbc),
+	RTW_PROC_HDL_SSEQ("stbc_cap", proc_get_stbc_cap, proc_set_stbc_cap),
+	RTW_PROC_HDL_SSEQ("ldpc_cap", proc_get_ldpc_cap, proc_set_ldpc_cap),
+#ifdef CONFIG_BEAMFORMING
+	RTW_PROC_HDL_SSEQ("txbf_cap", proc_get_txbf_cap, proc_set_txbf_cap),
+#endif
+
+#ifdef CONFIG_SUPPORT_TRX_SHARED
+	RTW_PROC_HDL_SSEQ("trx_share_mode", proc_get_trx_share_mode, NULL),
+#endif
+	RTW_PROC_HDL_SSEQ("napi_info", proc_get_napi_info, NULL),
+	RTW_PROC_HDL_SSEQ("rsvd_page", proc_dump_rsvd_page, proc_set_rsvd_page_info),
+
+	RTW_PROC_HDL_SSEQ("fw_info", proc_get_fw_info, NULL),
+#ifdef RTW_HALMAC
+	RTW_PROC_HDL_SSEQ("halmac_info", proc_get_halmac_info, NULL),
+#endif
+	RTW_PROC_HDL_SSEQ("ack_timeout", proc_get_ack_timeout, proc_set_ack_timeout),
+};
+
+static const int adapter_proc_hdls_num = sizeof(adapter_proc_hdls) / sizeof(struct rtw_proc_hdl);
+
+static int rtw_adapter_proc_open(struct inode *inode, struct file *file)
+{
+	ssize_t index = (ssize_t)PDE_DATA(inode);
+	const struct rtw_proc_hdl *hdl = adapter_proc_hdls + index;
+	void *private = proc_get_parent_data(inode);
+
+	if (hdl->type == RTW_PROC_HDL_TYPE_SEQ) {
+		int res = seq_open(file, hdl->u.seq_op);
+
+		if (res == 0)
+			((struct seq_file *)file->private_data)->private = private;
+
+		return res;
+	} else if (hdl->type == RTW_PROC_HDL_TYPE_SSEQ) {
+		int (*show)(struct seq_file *, void *) = hdl->u.show ? hdl->u.show : proc_get_dummy;
+
+		return single_open(file, show, private);
+	} else {
+		return -EROFS;
+	}
+}
+
+static ssize_t rtw_adapter_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos)
+{
+	ssize_t index = (ssize_t)PDE_DATA(file_inode(file));
+	const struct rtw_proc_hdl *hdl = adapter_proc_hdls + index;
+	ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *, void *) = hdl->write;
+
+	if (write)
+		return write(file, buffer, count, pos, ((struct seq_file *)file->private_data)->private);
+
+	return -EROFS;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+static const struct proc_ops rtw_adapter_proc_seq_fops = {
+	.proc_open = rtw_adapter_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = seq_release,
+	.proc_write = rtw_adapter_proc_write,
+};
+#else
+static const struct file_operations rtw_adapter_proc_seq_fops = {
+	.owner = THIS_MODULE,
+	.open = rtw_adapter_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+	.write = rtw_adapter_proc_write,
+};
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+static const struct proc_ops rtw_adapter_proc_sseq_fops = {
+	.proc_open = rtw_adapter_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+	.proc_write = rtw_adapter_proc_write,
+};
+#else
+static const struct file_operations rtw_adapter_proc_sseq_fops = {
+	.owner = THIS_MODULE,
+	.open = rtw_adapter_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = rtw_adapter_proc_write,
+};
+#endif
+
+static int proc_get_odm_force_igi_lb(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	RTW_PRINT_SEL(m, "force_igi_lb:0x%02x\n", rtw_odm_get_force_igi_lb(padapter));
+
+	return 0;
+}
+
+static ssize_t proc_set_odm_force_igi_lb(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];
+	u8 force_igi_lb;
+
+	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", &force_igi_lb);
+
+		if (num != 1)
+			return count;
+
+		rtw_odm_set_force_igi_lb(padapter, force_igi_lb);
+	}
+
+	return count;
+}
+
+int proc_get_odm_adaptivity(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	rtw_odm_adaptivity_parm_msg(m, padapter);
+
+	return 0;
+}
+
+ssize_t proc_set_odm_adaptivity(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 th_l2h_ini;
+	u32 th_l2h_ini_mode2;
+	s8 th_edcca_hl_diff;
+	s8 th_edcca_hl_diff_mode2;
+	u8 edcca_enable;
+
+	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, "%x %hhd %x %hhd %hhu", &th_l2h_ini, &th_edcca_hl_diff, &th_l2h_ini_mode2, &th_edcca_hl_diff_mode2, &edcca_enable);
+
+		if (num != 5)
+			return count;
+
+		rtw_odm_adaptivity_parm_set(padapter, (s8)th_l2h_ini, th_edcca_hl_diff, (s8)th_l2h_ini_mode2, th_edcca_hl_diff_mode2, edcca_enable);
+	}
+
+	return count;
+}
+
+static char *phydm_msg = NULL;
+#define PHYDM_MSG_LEN	80*24
+
+static int proc_get_phydm_cmd(struct seq_file *m, void *v)
+{
+	struct net_device *netdev;
+	PADAPTER padapter;
+	PHAL_DATA_TYPE pHalData;
+	struct PHY_DM_STRUCT *phydm;
+
+
+	netdev = m->private;
+	padapter = (PADAPTER)rtw_netdev_priv(netdev);
+	pHalData = GET_HAL_DATA(padapter);
+	phydm = &pHalData->odmpriv;
+
+	if (NULL == phydm_msg) {
+		phydm_msg = rtw_zmalloc(PHYDM_MSG_LEN);
+		if (NULL == phydm_msg)
+			return -ENOMEM;
+
+		phydm_cmd(phydm, NULL, 0, 0, phydm_msg, PHYDM_MSG_LEN);
+	}
+
+	_RTW_PRINT_SEL(m, "%s\n", phydm_msg);
+
+	rtw_mfree(phydm_msg, PHYDM_MSG_LEN);
+	phydm_msg = NULL;
+
+	return 0;
+}
+
+static ssize_t proc_set_phydm_cmd(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *netdev;
+	PADAPTER padapter;
+	PHAL_DATA_TYPE pHalData;
+	struct PHY_DM_STRUCT *phydm;
+	char tmp[64] = {0};
+
+
+	netdev = (struct net_device *)data;
+	padapter = (PADAPTER)rtw_netdev_priv(netdev);
+	pHalData = GET_HAL_DATA(padapter);
+	phydm = &pHalData->odmpriv;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp))
+		return -EFAULT;
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+		if (NULL == phydm_msg) {
+			phydm_msg = rtw_zmalloc(PHYDM_MSG_LEN);
+			if (NULL == phydm_msg)
+				return -ENOMEM;
+		} else
+			memset(phydm_msg, 0, PHYDM_MSG_LEN);
+
+		phydm_cmd(phydm, tmp, count, 1, phydm_msg, PHYDM_MSG_LEN);
+
+		if (strlen(phydm_msg) == 0) {
+			rtw_mfree(phydm_msg, PHYDM_MSG_LEN);
+			phydm_msg = NULL;
+		}
+	}
+
+	return count;
+}
+
+#ifdef CONFIG_LAMODE
+static void *proc_start_lamode_dump(struct seq_file *m, loff_t *pos)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(m->private);
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(adapter);
+	struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv;
+	PRT_ADCSMP AdcSmp = &(pDM_Odm->adcsmp);
+	static unsigned long index;
+	static unsigned long max;
+
+
+	if (*pos == 0) {
+		rtw_pm_set_ips(adapter, IPS_NONE);
+		rtw_pm_set_lps(adapter, PS_MODE_ACTIVE);
+		ADCSmp_Start(pDM_Odm, AdcSmp);
+		index = 0;
+		*pos = max = ADCSmp_Get_SampleCounts(pDM_Odm);
+		if (max == 0)
+			return NULL;
+	} else  if (index >= max) {
+		return NULL;
+	}
+
+	return &index;
+}
+
+static void proc_stop_lamode_dump(struct seq_file *m, void *v)
+{
+	/* v is a NULL in kernel 3.19.0-25 */
+}
+
+static void *proc_next_lamode_dump(struct seq_file *m, void *v, loff_t *pos)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(m->private);
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(adapter);
+	struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv;
+	unsigned long *index = v;
+
+
+	*index += 2;
+	if (*index >= *pos) {
+		ADCSmp_DeInit(pDM_Odm);
+		if (phydm_msg) {
+			_RTW_PRINT_SEL(m, "%s", phydm_msg);
+			rtw_mfree(phydm_msg, PHYDM_MSG_LEN);
+			phydm_msg = NULL;
+		}
+		return NULL;
+	}
+	return index;
+}
+
+static int proc_show_lamode_data(struct seq_file *m, void *v)
+{
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(m->private);
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(adapter);
+	struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv;
+	unsigned long *index = v;
+	char line[32];
+	int rtn;
+
+
+	memset(line, 0, sizeof(line));
+	rtn = ADCSmp_Query_SingleData(pDM_Odm, line, sizeof(line), *index);
+	_RTW_PRINT_SEL(m, "%s", line);
+
+	if (rtn<0)
+		return -1;
+
+	return 0;
+}
+
+static struct seq_operations seq_ops_lamode = {
+	.start = proc_start_lamode_dump,
+	.stop  = proc_stop_lamode_dump,
+	.next  = proc_next_lamode_dump,
+	.show  = proc_show_lamode_data,
+};
+#endif /* CONFIG_LAMODE */
+
+/*
+* rtw_odm_proc:
+* init/deinit when register/unregister net_device, along with rtw_adapter_proc
+*/
+static const struct rtw_proc_hdl odm_proc_hdls[] = {
+	RTW_PROC_HDL_SSEQ("adaptivity", proc_get_odm_adaptivity, proc_set_odm_adaptivity),
+	RTW_PROC_HDL_SSEQ("force_igi_lb", proc_get_odm_force_igi_lb, proc_set_odm_force_igi_lb),
+	RTW_PROC_HDL_SSEQ("cmd", proc_get_phydm_cmd, proc_set_phydm_cmd),
+#ifdef CONFIG_LAMODE
+	RTW_PROC_HDL_SEQ("lamode", &seq_ops_lamode, proc_set_phydm_cmd)
+#endif /* CONFIG_LAMODE */
+};
+
+static const int odm_proc_hdls_num = sizeof(odm_proc_hdls) / sizeof(struct rtw_proc_hdl);
+
+static int rtw_odm_proc_open(struct inode *inode, struct file *file)
+{
+	ssize_t index = (ssize_t)PDE_DATA(inode);
+	const struct rtw_proc_hdl *hdl = odm_proc_hdls + index;
+	void *private = proc_get_parent_data(inode);
+
+	if (hdl->type == RTW_PROC_HDL_TYPE_SEQ) {
+		int res = seq_open(file, hdl->u.seq_op);
+
+		if (res == 0)
+			((struct seq_file *)file->private_data)->private = private;
+
+		return res;
+	} else if (hdl->type == RTW_PROC_HDL_TYPE_SSEQ) {
+		int (*show)(struct seq_file *, void *) = hdl->u.show ? hdl->u.show : proc_get_dummy;
+
+		return single_open(file, show, private);
+	} else {
+		return -EROFS;
+	}
+}
+
+static ssize_t rtw_odm_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos)
+{
+	ssize_t index = (ssize_t)PDE_DATA(file_inode(file));
+	const struct rtw_proc_hdl *hdl = odm_proc_hdls + index;
+	ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *, void *) = hdl->write;
+
+	if (write)
+		return write(file, buffer, count, pos, ((struct seq_file *)file->private_data)->private);
+
+	return -EROFS;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+static const struct proc_ops rtw_odm_proc_seq_fops = {
+	.proc_open = rtw_odm_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = seq_release,
+	.proc_write = rtw_odm_proc_write,
+};
+#else
+static const struct file_operations rtw_odm_proc_seq_fops = {
+	.owner = THIS_MODULE,
+	.open = rtw_odm_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+	.write = rtw_odm_proc_write,
+};
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+static const struct proc_ops rtw_odm_proc_sseq_fops = {
+	.proc_open = rtw_odm_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+	.proc_write = rtw_odm_proc_write,
+};
+#else
+static const struct file_operations rtw_odm_proc_sseq_fops = {
+	.owner = THIS_MODULE,
+	.open = rtw_odm_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = rtw_odm_proc_write,
+};
+#endif
+
+static struct proc_dir_entry *rtw_odm_proc_init(struct net_device *dev)
+{
+	struct proc_dir_entry *dir_odm = NULL;
+	struct proc_dir_entry *entry = NULL;
+	_adapter	*adapter = rtw_netdev_priv(dev);
+	ssize_t i;
+
+	if (adapter->dir_dev == NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	if (adapter->dir_odm != NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	dir_odm = rtw_proc_create_dir("odm", adapter->dir_dev, dev);
+	if (dir_odm == NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	adapter->dir_odm = dir_odm;
+
+	for (i = 0; i < odm_proc_hdls_num; i++) {
+		if (odm_proc_hdls[i].type == RTW_PROC_HDL_TYPE_SEQ)
+			entry = rtw_proc_create_entry(odm_proc_hdls[i].name, dir_odm, &rtw_odm_proc_seq_fops, (void *)i);
+		else if (odm_proc_hdls[i].type == RTW_PROC_HDL_TYPE_SSEQ)
+			entry = rtw_proc_create_entry(odm_proc_hdls[i].name, dir_odm, &rtw_odm_proc_sseq_fops, (void *)i);
+		else
+			entry = NULL;
+
+		if (!entry) {
+			rtw_warn_on(1);
+			goto exit;
+		}
+	}
+
+exit:
+	return dir_odm;
+}
+
+static void rtw_odm_proc_deinit(_adapter	*adapter)
+{
+	struct proc_dir_entry *dir_odm = NULL;
+	int i;
+
+	dir_odm = adapter->dir_odm;
+
+	if (dir_odm == NULL) {
+		rtw_warn_on(1);
+		return;
+	}
+
+	for (i = 0; i < odm_proc_hdls_num; i++)
+		remove_proc_entry(odm_proc_hdls[i].name, dir_odm);
+
+	remove_proc_entry("odm", adapter->dir_dev);
+
+	adapter->dir_odm = NULL;
+
+	if (phydm_msg) {
+		rtw_mfree(phydm_msg, PHYDM_MSG_LEN);
+		phydm_msg = NULL;
+	}
+}
+
+#ifdef CONFIG_MCC_MODE
+/*
+* rtw_mcc_proc:
+* init/deinit when register/unregister net_device, along with rtw_adapter_proc
+*/
+const struct rtw_proc_hdl mcc_proc_hdls[] = {
+	RTW_PROC_HDL_SSEQ("mcc_info", proc_get_mcc_info, NULL),
+	RTW_PROC_HDL_SSEQ("mcc_enable", proc_get_mcc_info, proc_set_mcc_enable),
+	RTW_PROC_HDL_SSEQ("mcc_single_tx_criteria", proc_get_mcc_info, proc_set_mcc_single_tx_criteria),
+	RTW_PROC_HDL_SSEQ("mcc_ap_bw20_target_tp", proc_get_mcc_info, proc_set_mcc_ap_bw20_target_tp),
+	RTW_PROC_HDL_SSEQ("mcc_ap_bw40_target_tp", proc_get_mcc_info, proc_set_mcc_ap_bw40_target_tp),
+	RTW_PROC_HDL_SSEQ("mcc_ap_bw80_target_tp", proc_get_mcc_info, proc_set_mcc_ap_bw80_target_tp),
+	RTW_PROC_HDL_SSEQ("mcc_sta_bw20_target_tp", proc_get_mcc_info, proc_set_mcc_sta_bw20_target_tp),
+	RTW_PROC_HDL_SSEQ("mcc_sta_bw40_target_tp", proc_get_mcc_info, proc_set_mcc_sta_bw40_target_tp),
+	RTW_PROC_HDL_SSEQ("mcc_sta_bw80_target_tp", proc_get_mcc_info, proc_set_mcc_sta_bw80_target_tp),
+	RTW_PROC_HDL_SSEQ("mcc_policy_table", proc_get_mcc_policy_table, proc_set_mcc_policy_table),
+};
+
+const int mcc_proc_hdls_num = sizeof(mcc_proc_hdls) / sizeof(struct rtw_proc_hdl);
+
+static int rtw_mcc_proc_open(struct inode *inode, struct file *file)
+{
+	ssize_t index = (ssize_t)PDE_DATA(inode);
+	const struct rtw_proc_hdl *hdl = mcc_proc_hdls + index;
+	void *private = proc_get_parent_data(inode);
+
+	if (hdl->type == RTW_PROC_HDL_TYPE_SEQ) {
+		int res = seq_open(file, hdl->u.seq_op);
+
+		if (res == 0)
+			((struct seq_file *)file->private_data)->private = private;
+
+		return res;
+	} else if (hdl->type == RTW_PROC_HDL_TYPE_SSEQ) {
+		int (*show)(struct seq_file *, void *) = hdl->u.show ? hdl->u.show : proc_get_dummy;
+
+		return single_open(file, show, private);
+	} else {
+		return -EROFS;
+	}
+}
+
+static ssize_t rtw_mcc_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos)
+{
+	ssize_t index = (ssize_t)PDE_DATA(file_inode(file));
+	const struct rtw_proc_hdl *hdl = mcc_proc_hdls + index;
+	ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *, void *) = hdl->write;
+
+	if (write)
+		return write(file, buffer, count, pos, ((struct seq_file *)file->private_data)->private);
+
+	return -EROFS;
+}
+
+static const struct file_operations rtw_mcc_proc_seq_fops = {
+	.owner = THIS_MODULE,
+	.open = rtw_mcc_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+	.write = rtw_mcc_proc_write,
+};
+
+static const struct file_operations rtw_mcc_proc_sseq_fops = {
+	.owner = THIS_MODULE,
+	.open = rtw_mcc_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = rtw_mcc_proc_write,
+};
+
+struct proc_dir_entry *rtw_mcc_proc_init(struct net_device *dev)
+{
+	struct proc_dir_entry *dir_mcc = NULL;
+	struct proc_dir_entry *entry = NULL;
+	_adapter	*adapter = rtw_netdev_priv(dev);
+	ssize_t i;
+
+	if (adapter->dir_dev == NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	if (adapter->dir_mcc != NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	dir_mcc = rtw_proc_create_dir("mcc", adapter->dir_dev, dev);
+	if (dir_mcc == NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	adapter->dir_mcc = dir_mcc;
+
+	for (i = 0; i < mcc_proc_hdls_num; i++) {
+		if (mcc_proc_hdls[i].type == RTW_PROC_HDL_TYPE_SEQ)
+			entry = rtw_proc_create_entry(mcc_proc_hdls[i].name, dir_mcc, &rtw_mcc_proc_seq_fops, (void *)i);
+		else if (mcc_proc_hdls[i].type == RTW_PROC_HDL_TYPE_SSEQ)
+			entry = rtw_proc_create_entry(mcc_proc_hdls[i].name, dir_mcc, &rtw_mcc_proc_sseq_fops, (void *)i);
+		else
+			entry = NULL;
+
+		if (!entry) {
+			rtw_warn_on(1);
+			goto exit;
+		}
+	}
+
+exit:
+	return dir_mcc;
+}
+
+void rtw_mcc_proc_deinit(_adapter	*adapter)
+{
+	struct proc_dir_entry *dir_mcc = NULL;
+	int i;
+
+	dir_mcc = adapter->dir_mcc;
+
+	if (dir_mcc == NULL) {
+		rtw_warn_on(1);
+		return;
+	}
+
+	for (i = 0; i < mcc_proc_hdls_num; i++)
+		remove_proc_entry(mcc_proc_hdls[i].name, dir_mcc);
+
+	remove_proc_entry("mcc", adapter->dir_dev);
+
+	adapter->dir_mcc = NULL;
+}
+#endif /* CONFIG_MCC_MODE */
+
+struct proc_dir_entry *rtw_adapter_proc_init(struct net_device *dev)
+{
+	struct proc_dir_entry *drv_proc = get_rtw_drv_proc();
+	struct proc_dir_entry *dir_dev = NULL;
+	struct proc_dir_entry *entry = NULL;
+	_adapter *adapter = rtw_netdev_priv(dev);
+	u8 rf_type;
+	ssize_t i;
+
+	if (drv_proc == NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	if (adapter->dir_dev != NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	dir_dev = rtw_proc_create_dir(dev->name, drv_proc, dev);
+	if (dir_dev == NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	adapter->dir_dev = dir_dev;
+
+	for (i = 0; i < adapter_proc_hdls_num; i++) {
+		if (adapter_proc_hdls[i].type == RTW_PROC_HDL_TYPE_SEQ)
+			entry = rtw_proc_create_entry(adapter_proc_hdls[i].name, dir_dev, &rtw_adapter_proc_seq_fops, (void *)i);
+		else if (adapter_proc_hdls[i].type == RTW_PROC_HDL_TYPE_SSEQ)
+			entry = rtw_proc_create_entry(adapter_proc_hdls[i].name, dir_dev, &rtw_adapter_proc_sseq_fops, (void *)i);
+		else
+			entry = NULL;
+
+		if (!entry) {
+			rtw_warn_on(1);
+			goto exit;
+		}
+	}
+
+	rtw_odm_proc_init(dev);
+
+#ifdef CONFIG_MCC_MODE
+	rtw_mcc_proc_init(dev);
+#endif /* CONFIG_MCC_MODE */
+
+exit:
+	return dir_dev;
+}
+
+void rtw_adapter_proc_deinit(struct net_device *dev)
+{
+	struct proc_dir_entry *drv_proc = get_rtw_drv_proc();
+	struct proc_dir_entry *dir_dev = NULL;
+	_adapter *adapter = rtw_netdev_priv(dev);
+	int i;
+
+	dir_dev = adapter->dir_dev;
+
+	if (dir_dev == NULL) {
+		rtw_warn_on(1);
+		return;
+	}
+
+	for (i = 0; i < adapter_proc_hdls_num; i++)
+		remove_proc_entry(adapter_proc_hdls[i].name, dir_dev);
+
+	rtw_odm_proc_deinit(adapter);
+
+#ifdef CONFIG_MCC_MODE
+	rtw_mcc_proc_deinit(adapter);
+#endif /* CONFIG_MCC_MODE */
+
+	remove_proc_entry(dev->name, drv_proc);
+
+	adapter->dir_dev = NULL;
+}
+
+void rtw_adapter_proc_replace(struct net_device *dev)
+{
+	struct proc_dir_entry *drv_proc = get_rtw_drv_proc();
+	struct proc_dir_entry *dir_dev = NULL;
+	_adapter *adapter = rtw_netdev_priv(dev);
+	int i;
+
+	dir_dev = adapter->dir_dev;
+
+	if (dir_dev == NULL) {
+		rtw_warn_on(1);
+		return;
+	}
+
+	for (i = 0; i < adapter_proc_hdls_num; i++)
+		remove_proc_entry(adapter_proc_hdls[i].name, dir_dev);
+
+	rtw_odm_proc_deinit(adapter);
+
+#ifdef CONFIG_MCC_MODE
+	rtw_mcc_proc_deinit(adapter);
+#endif /* CONIG_MCC_MODE */
+
+	remove_proc_entry(adapter->old_ifname, drv_proc);
+
+	adapter->dir_dev = NULL;
+
+	rtw_adapter_proc_init(dev);
+
+}
+
+#endif /* CONFIG_PROC_DEBUG */
diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_proc.h b/drivers/staging/rtl8188eu/os_dep/rtw_proc.h
new file mode 100644
index 000000000000..daba6f283b2f
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/rtw_proc.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+#ifndef __RTW_PROC_H__
+#define __RTW_PROC_H__
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#define RTW_PROC_HDL_TYPE_SEQ	0
+#define RTW_PROC_HDL_TYPE_SSEQ	1
+
+struct rtw_proc_hdl {
+	char *name;
+	u8 type;
+	union {
+		int (*show)(struct seq_file *, void *);
+		struct seq_operations *seq_op;
+	} u;
+	ssize_t (*write)(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data);
+};
+
+#define RTW_PROC_HDL_SEQ(_name, _seq_op, _write) \
+	{ .name = _name, .type = RTW_PROC_HDL_TYPE_SEQ, .u.seq_op = _seq_op, .write = _write}
+
+#define RTW_PROC_HDL_SSEQ(_name, _show, _write) \
+	{ .name = _name, .type = RTW_PROC_HDL_TYPE_SSEQ, .u.show = _show, .write = _write}
+
+#ifdef CONFIG_PROC_DEBUG
+
+struct proc_dir_entry *get_rtw_drv_proc(void);
+int rtw_drv_proc_init(void);
+void rtw_drv_proc_deinit(void);
+struct proc_dir_entry *rtw_adapter_proc_init(struct net_device *dev);
+void rtw_adapter_proc_deinit(struct net_device *dev);
+void rtw_adapter_proc_replace(struct net_device *dev);
+
+#else /* !CONFIG_PROC_DEBUG */
+
+#define get_rtw_drv_proc() NULL
+#define rtw_drv_proc_init() 0
+#define rtw_drv_proc_deinit() do {} while (0)
+#define rtw_adapter_proc_init(dev) NULL
+#define rtw_adapter_proc_deinit(dev) do {} while (0)
+#define rtw_adapter_proc_replace(dev) do {} while (0)
+
+#endif /* !CONFIG_PROC_DEBUG */
+
+#endif /* __RTW_PROC_H__ */
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
new file mode 100644
index 000000000000..f3ea5a3332e9
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -0,0 +1,1345 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+#define _HCI_INTF_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+
+#ifdef CONFIG_GLOBAL_UI_PID
+int ui_pid[3] = {0, 0, 0};
+#endif
+
+static int rtw_suspend(struct usb_interface *intf, pm_message_t message);
+static int rtw_resume(struct usb_interface *intf);
+
+
+static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid);
+static void rtw_dev_remove(struct usb_interface *pusb_intf);
+
+static void rtw_dev_shutdown(struct device *dev)
+{
+	struct usb_interface *usb_intf = container_of(dev, struct usb_interface, dev);
+	struct dvobj_priv *dvobj = NULL;
+	_adapter *adapter = NULL;
+	int i;
+
+	RTW_INFO("%s\n", __func__);
+
+	if (usb_intf) {
+		dvobj = usb_get_intfdata(usb_intf);
+		if (dvobj) {
+			adapter = dvobj_get_primary_adapter(dvobj);
+			if (adapter) {
+				if (!rtw_is_surprise_removed(adapter)) {
+					struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
+					#ifdef CONFIG_WOWLAN
+					if (pwrctl->wowlan_mode == true)
+						RTW_INFO("%s wowlan_mode ==true do not run rtw_hal_deinit()\n", __func__);
+					else
+					#endif
+					{
+						rtw_hal_deinit(adapter);
+						rtw_set_surprise_removed(adapter);
+					}
+				}
+			}
+			ATOMIC_SET(&dvobj->continual_io_error, MAX_CONTINUAL_IO_ERR + 1);
+		}
+	}
+}
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23))
+/* Some useful macros to use to create struct usb_device_id */
+#define USB_DEVICE_ID_MATCH_VENDOR			 0x0001
+#define USB_DEVICE_ID_MATCH_PRODUCT			 0x0002
+#define USB_DEVICE_ID_MATCH_DEV_LO			 0x0004
+#define USB_DEVICE_ID_MATCH_DEV_HI			 0x0008
+#define USB_DEVICE_ID_MATCH_DEV_CLASS			 0x0010
+#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS		 0x0020
+#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL		 0x0040
+#define USB_DEVICE_ID_MATCH_INT_CLASS			 0x0080
+#define USB_DEVICE_ID_MATCH_INT_SUBCLASS		 0x0100
+#define USB_DEVICE_ID_MATCH_INT_PROTOCOL		 0x0200
+#define USB_DEVICE_ID_MATCH_INT_NUMBER		 0x0400
+
+
+#define USB_DEVICE_ID_MATCH_INT_INFO \
+	(USB_DEVICE_ID_MATCH_INT_CLASS | \
+	 USB_DEVICE_ID_MATCH_INT_SUBCLASS | \
+	 USB_DEVICE_ID_MATCH_INT_PROTOCOL)
+
+
+#define USB_DEVICE_AND_INTERFACE_INFO(vend, prod, cl, sc, pr) \
+	.match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
+		       | USB_DEVICE_ID_MATCH_DEVICE, \
+		       .idVendor = (vend), \
+				   .idProduct = (prod), \
+						.bInterfaceClass = (cl), \
+						.bInterfaceSubClass = (sc), \
+						.bInterfaceProtocol = (pr)
+
+/**
+ * USB_VENDOR_AND_INTERFACE_INFO - describe a specific usb vendor with a class of usb interfaces
+ * @vend: the 16 bit USB Vendor ID
+ * @cl: bInterfaceClass value
+ * @sc: bInterfaceSubClass value
+ * @pr: bInterfaceProtocol value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific vendor with a specific class of interfaces.
+ *
+ * This is especially useful when explicitly matching devices that have
+ * vendor specific bDeviceClass values, but standards-compliant interfaces.
+ */
+#define USB_VENDOR_AND_INTERFACE_INFO(vend, cl, sc, pr) \
+	.match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
+		       | USB_DEVICE_ID_MATCH_VENDOR, \
+		       .idVendor = (vend), \
+				   .bInterfaceClass = (cl), \
+						   .bInterfaceSubClass = (sc), \
+						   .bInterfaceProtocol = (pr)
+
+/* ----------------------------------------------------------------------- */
+#endif
+
+
+#define USB_VENDER_ID_REALTEK		0x0BDA
+
+
+/* DID_USB_v916_20130116 */
+static struct usb_device_id rtw_usb_id_tbl[] = {
+	/*=== Realtek demoboard ===*/
+	{USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8179), .driver_info = RTL8188E}, /* 8188EUS */
+	{USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179), .driver_info = RTL8188E}, /* 8188ETV */
+	{USB_DEVICE(USB_VENDER_ID_REALTEK, 0xf179), .driver_info = RTL8188F}, /* 8188FU */
+	/*=== Customer ID ===*/
+	/****** 8188EUS ********/
+	{USB_DEVICE(0x07B8, 0x8179), .driver_info = RTL8188E}, /* Abocom - Abocom */
+	{USB_DEVICE(0x0DF6, 0x0076), .driver_info = RTL8188E}, /* Sitecom N150 v2 */
+	{USB_DEVICE(0x2001, 0x330F), .driver_info = RTL8188E}, /* DLink DWA-125 REV D1 */
+        {USB_DEVICE(0x2001, 0x3310), .driver_info = RTL8188E}, /* Dlink DWA-123 REV D1 */
+	{USB_DEVICE(0x2001, 0x3311), .driver_info = RTL8188E}, /* DLink GO-USB-N150 REV B1 */
+	{USB_DEVICE(0x2001, 0x331B), .driver_info = RTL8188E}, /* D-Link DWA-121 rev B1 */
+	{USB_DEVICE(0x056E, 0x4008), .driver_info = RTL8188E}, /* Elecom WDC-150SU2M */
+	{USB_DEVICE(0x2357, 0x010c), .driver_info = RTL8188E}, /* TP-Link TL-WN722N v2 */
+	{USB_DEVICE(0x2357, 0x0111), .driver_info = RTL8188E}, /* TP-Link TL-WN727N v5.21 */
+	{USB_DEVICE(0x2C4E, 0x0102), .driver_info = RTL8188E}, /* MERCUSYS MW150US v2 */
+	{USB_DEVICE(0x0B05, 0x18F0), .driver_info = RTL8188E}, /* ASUS USB-N10 Nano B1 */
+	{USB_DEVICE(0x7392, 0xb811), .driver_info = RTL8188E}, /* Edimax EW-7811Un V2 */
+	{}	/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, rtw_usb_id_tbl);
+
+static int const rtw_usb_id_len = sizeof(rtw_usb_id_tbl) / sizeof(struct usb_device_id);
+
+static struct specific_device_id specific_device_id_tbl[] = {
+	{.idVendor = USB_VENDER_ID_REALTEK, .idProduct = 0x8177, .flags = SPEC_DEV_ID_DISABLE_HT}, /* 8188cu 1*1 dongole, (b/g mode only) */
+	{.idVendor = USB_VENDER_ID_REALTEK, .idProduct = 0x817E, .flags = SPEC_DEV_ID_DISABLE_HT}, /* 8188CE-VAU USB minCard (b/g mode only) */
+	{.idVendor = 0x0b05, .idProduct = 0x1791, .flags = SPEC_DEV_ID_DISABLE_HT},
+	{.idVendor = 0x13D3, .idProduct = 0x3311, .flags = SPEC_DEV_ID_DISABLE_HT},
+	{.idVendor = 0x13D3, .idProduct = 0x3359, .flags = SPEC_DEV_ID_DISABLE_HT}, /* Russian customer -Azwave (8188CE-VAU  g mode) */
+#ifdef RTK_DMP_PLATFORM
+	{.idVendor = USB_VENDER_ID_REALTEK, .idProduct = 0x8111, .flags = SPEC_DEV_ID_ASSIGN_IFNAME}, /* Realtek 5G dongle for WiFi Display */
+	{.idVendor = 0x2019, .idProduct = 0xAB2D, .flags = SPEC_DEV_ID_ASSIGN_IFNAME}, /* PCI-Abocom 5G dongle for WiFi Display */
+#endif /* RTK_DMP_PLATFORM */
+	{}
+};
+
+struct rtw_usb_drv {
+	struct usb_driver usbdrv;
+	int drv_registered;
+	u8 hw_type;
+};
+
+static struct rtw_usb_drv usb_drv = {
+	.usbdrv.name = (char *)DRV_NAME,
+	.usbdrv.probe = rtw_drv_init,
+	.usbdrv.disconnect = rtw_dev_remove,
+	.usbdrv.id_table = rtw_usb_id_tbl,
+	.usbdrv.suspend =  rtw_suspend,
+	.usbdrv.resume = rtw_resume,
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
+	.usbdrv.reset_resume   = rtw_resume,
+#endif
+#ifdef CONFIG_AUTOSUSPEND
+	.usbdrv.supports_autosuspend = 1,
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
+	.usbdrv.drvwrap.driver.shutdown = rtw_dev_shutdown,
+#else
+	.usbdrv.driver.shutdown = rtw_dev_shutdown,
+#endif
+};
+
+static inline int RT_usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
+{
+	return (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN;
+}
+
+static inline int RT_usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
+{
+	return (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
+}
+
+static inline int RT_usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
+{
+	return (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT;
+}
+
+static inline int RT_usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
+{
+	return (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK;
+}
+
+static inline int RT_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
+{
+	return RT_usb_endpoint_xfer_bulk(epd) && RT_usb_endpoint_dir_in(epd);
+}
+
+static inline int RT_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
+{
+	return RT_usb_endpoint_xfer_bulk(epd) && RT_usb_endpoint_dir_out(epd);
+}
+
+static inline int RT_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
+{
+	return RT_usb_endpoint_xfer_int(epd) && RT_usb_endpoint_dir_in(epd);
+}
+
+static inline int RT_usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
+{
+	return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+}
+
+static u8 rtw_init_intf_priv(struct dvobj_priv *dvobj)
+{
+	u8 rst = _SUCCESS;
+
+#ifdef CONFIG_USB_VENDOR_REQ_MUTEX
+	_rtw_mutex_init(&dvobj->usb_vendor_req_mutex);
+#endif
+
+
+#ifdef CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC
+	dvobj->usb_alloc_vendor_req_buf = rtw_zmalloc(MAX_USB_IO_CTL_SIZE);
+	if (dvobj->usb_alloc_vendor_req_buf == NULL) {
+		RTW_INFO("alloc usb_vendor_req_buf failed... /n");
+		rst = _FAIL;
+		goto exit;
+	}
+	dvobj->usb_vendor_req_buf  =
+		(u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(dvobj->usb_alloc_vendor_req_buf), ALIGNMENT_UNIT);
+exit:
+#endif
+
+	return rst;
+
+}
+
+static u8 rtw_deinit_intf_priv(struct dvobj_priv *dvobj)
+{
+	u8 rst = _SUCCESS;
+
+#ifdef CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC
+	if (dvobj->usb_vendor_req_buf)
+		rtw_mfree(dvobj->usb_alloc_vendor_req_buf, MAX_USB_IO_CTL_SIZE);
+#endif
+
+#ifdef CONFIG_USB_VENDOR_REQ_MUTEX
+	_rtw_mutex_free(&dvobj->usb_vendor_req_mutex);
+#endif
+
+	return rst;
+}
+static void rtw_decide_chip_type_by_usb_info(struct dvobj_priv *pdvobjpriv, const struct usb_device_id *pdid)
+{
+	pdvobjpriv->chip_type = pdid->driver_info;
+
+	if (pdvobjpriv->chip_type == RTL8188E)
+		rtl8188eu_set_hw_type(pdvobjpriv);
+}
+
+static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf, const struct usb_device_id *pdid)
+{
+	int	i;
+	u8	val8;
+	int	status = _FAIL;
+	struct dvobj_priv *pdvobjpriv;
+	struct usb_device_descriptor	*pdev_desc;
+	struct usb_host_config			*phost_conf;
+	struct usb_config_descriptor		*pconf_desc;
+	struct usb_host_interface		*phost_iface;
+	struct usb_interface_descriptor	*piface_desc;
+	struct usb_host_endpoint		*phost_endp;
+	struct usb_endpoint_descriptor	*pendp_desc;
+	struct usb_device				*pusbd;
+
+
+
+	pdvobjpriv = devobj_init();
+	if (pdvobjpriv == NULL)
+		goto exit;
+
+
+	pdvobjpriv->pusbintf = usb_intf ;
+	pusbd = pdvobjpriv->pusbdev = interface_to_usbdev(usb_intf);
+	usb_set_intfdata(usb_intf, pdvobjpriv);
+
+	pdvobjpriv->RtNumInPipes = 0;
+	pdvobjpriv->RtNumOutPipes = 0;
+
+	pdev_desc = &pusbd->descriptor;
+
+	phost_conf = pusbd->actconfig;
+	pconf_desc = &phost_conf->desc;
+
+	phost_iface = &usb_intf->altsetting[0];
+	piface_desc = &phost_iface->desc;
+
+	pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
+	pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber;
+	pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
+
+	for (i = 0; i < pdvobjpriv->nr_endpoint; i++) {
+		phost_endp = phost_iface->endpoint + i;
+		if (phost_endp) {
+			pendp_desc = &phost_endp->desc;
+
+			RTW_INFO("\nusb_endpoint_descriptor(%d):\n", i);
+			RTW_INFO("bLength=%x\n", pendp_desc->bLength);
+			RTW_INFO("bDescriptorType=%x\n", pendp_desc->bDescriptorType);
+			RTW_INFO("bEndpointAddress=%x\n", pendp_desc->bEndpointAddress);
+			RTW_INFO("wMaxPacketSize=%d\n", le16_to_cpu(pendp_desc->wMaxPacketSize));
+			RTW_INFO("bInterval=%x\n", pendp_desc->bInterval);
+
+			if (RT_usb_endpoint_is_bulk_in(pendp_desc)) {
+				RTW_INFO("RT_usb_endpoint_is_bulk_in = %x\n", RT_usb_endpoint_num(pendp_desc));
+				pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = RT_usb_endpoint_num(pendp_desc);
+				pdvobjpriv->RtNumInPipes++;
+			} else if (RT_usb_endpoint_is_int_in(pendp_desc)) {
+				RTW_INFO("RT_usb_endpoint_is_int_in = %x, Interval = %x\n", RT_usb_endpoint_num(pendp_desc), pendp_desc->bInterval);
+				pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = RT_usb_endpoint_num(pendp_desc);
+				pdvobjpriv->RtNumInPipes++;
+			} else if (RT_usb_endpoint_is_bulk_out(pendp_desc)) {
+				RTW_INFO("RT_usb_endpoint_is_bulk_out = %x\n", RT_usb_endpoint_num(pendp_desc));
+				pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] = RT_usb_endpoint_num(pendp_desc);
+				pdvobjpriv->RtNumOutPipes++;
+			}
+			pdvobjpriv->ep_num[i] = RT_usb_endpoint_num(pendp_desc);
+		}
+	}
+
+	RTW_INFO("nr_endpoint=%d, in_num=%d, out_num=%d\n\n", pdvobjpriv->nr_endpoint, pdvobjpriv->RtNumInPipes, pdvobjpriv->RtNumOutPipes);
+
+	switch (pusbd->speed) {
+	case USB_SPEED_LOW:
+		RTW_INFO("USB_SPEED_LOW\n");
+		pdvobjpriv->usb_speed = RTW_USB_SPEED_1_1;
+		break;
+	case USB_SPEED_FULL:
+		RTW_INFO("USB_SPEED_FULL\n");
+		pdvobjpriv->usb_speed = RTW_USB_SPEED_1_1;
+		break;
+	case USB_SPEED_HIGH:
+		RTW_INFO("USB_SPEED_HIGH\n");
+		pdvobjpriv->usb_speed = RTW_USB_SPEED_2;
+		break;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+	case USB_SPEED_SUPER:
+		RTW_INFO("USB_SPEED_SUPER\n");
+		pdvobjpriv->usb_speed = RTW_USB_SPEED_3;
+		break;
+#endif
+	default:
+		RTW_INFO("USB_SPEED_UNKNOWN(%x)\n", pusbd->speed);
+		pdvobjpriv->usb_speed = RTW_USB_SPEED_UNKNOWN;
+		break;
+	}
+
+	if (pdvobjpriv->usb_speed == RTW_USB_SPEED_UNKNOWN) {
+		RTW_INFO("UNKNOWN USB SPEED MODE, ERROR !!!\n");
+		goto free_dvobj;
+	}
+
+	if (rtw_init_intf_priv(pdvobjpriv) == _FAIL) {
+		goto free_dvobj;
+	}
+
+	/*step 1-1., decide the chip_type via driver_info*/
+	pdvobjpriv->interface_type = RTW_USB;
+	rtw_decide_chip_type_by_usb_info(pdvobjpriv, pdid);
+
+	/* .3 misc */
+	sema_init(&(pdvobjpriv->usb_suspend_sema), 0);
+	rtw_reset_continual_io_error(pdvobjpriv);
+
+	usb_get_dev(pusbd);
+
+	status = _SUCCESS;
+
+free_dvobj:
+	if (status != _SUCCESS && pdvobjpriv) {
+		usb_set_intfdata(usb_intf, NULL);
+
+		devobj_deinit(pdvobjpriv);
+
+		pdvobjpriv = NULL;
+	}
+exit:
+	return pdvobjpriv;
+}
+
+static void usb_dvobj_deinit(struct usb_interface *usb_intf)
+{
+	struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf);
+
+
+	usb_set_intfdata(usb_intf, NULL);
+	if (dvobj) {
+		/* Modify condition for 92DU DMDP 2010.11.18, by Thomas */
+		if ((dvobj->NumInterfaces != 2 && dvobj->NumInterfaces != 3)
+		    || (dvobj->InterfaceNumber == 1)) {
+			if (interface_to_usbdev(usb_intf)->state != USB_STATE_NOTATTACHED) {
+				/* If we didn't unplug usb dongle and remove/insert modlue, driver fails on sitesurvey for the first time when device is up . */
+				/* Reset usb port for sitesurvey fail issue. 2009.8.13, by Thomas */
+				RTW_INFO("usb attached..., try to reset usb device\n");
+				usb_reset_device(interface_to_usbdev(usb_intf));
+			}
+		}
+
+		rtw_deinit_intf_priv(dvobj);
+
+		devobj_deinit(dvobj);
+	}
+
+	/* RTW_INFO("%s %d\n", __func__, ATOMIC_READ(&usb_intf->dev.kobj.kref.refcount)); */
+	usb_put_dev(interface_to_usbdev(usb_intf));
+
+}
+
+static int usb_reprobe_switch_usb_mode(PADAPTER Adapter)
+{
+	struct registry_priv *registry_par = &Adapter->registrypriv;
+	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
+	u8 ret = false;
+
+	/* efuse not allow driver to switch usb mode */
+	if (pHalData->EEPROMUsbSwitch == false)
+		goto exit;
+
+	/* registry not allow driver to switch usb mode */
+	if (registry_par->switch_usb_mode == 0)
+		goto exit;
+
+	rtw_hal_set_hwreg(Adapter, HW_VAR_USB_MODE, &ret);
+
+exit:
+	return ret;
+}
+
+u8 rtw_set_hal_ops(_adapter *padapter)
+{
+	/* alloc memory for HAL DATA */
+	if (rtw_hal_data_init(padapter) == _FAIL)
+		return _FAIL;
+
+	if (rtw_get_chip_type(padapter) == RTL8188E)
+		rtl8188eu_set_hal_ops(padapter);
+
+	if (_FAIL == rtw_hal_ops_check(padapter))
+		return _FAIL;
+
+	if (hal_spec_init(padapter) == _FAIL)
+		return _FAIL;
+
+	return _SUCCESS;
+}
+
+static void usb_intf_start(_adapter *padapter)
+{
+	PHAL_DATA_TYPE hal = GET_HAL_DATA(padapter);
+
+	rtw_hal_inirp_init(padapter);
+	hal->usb_intf_start = true;
+
+
+}
+
+static void usb_intf_stop(_adapter *padapter)
+{
+	PHAL_DATA_TYPE hal = GET_HAL_DATA(padapter);
+
+	/* disabel_hw_interrupt */
+	if (!rtw_is_surprise_removed(padapter)) {
+		/* device still exists, so driver can do i/o operation */
+		/* TODO: */
+	}
+
+	/* cancel in irp */
+	rtw_hal_inirp_deinit(padapter);
+
+	/* cancel out irp */
+	rtw_write_port_cancel(padapter);
+
+	/* todo:cancel other irps */
+
+	hal->usb_intf_start = false;
+
+}
+
+static void process_spec_devid(const struct usb_device_id *pdid)
+{
+	u16 vid, pid;
+	u32 flags;
+	int i;
+	int num = sizeof(specific_device_id_tbl) / sizeof(struct specific_device_id);
+
+	for (i = 0; i < num; i++) {
+		vid = specific_device_id_tbl[i].idVendor;
+		pid = specific_device_id_tbl[i].idProduct;
+		flags = specific_device_id_tbl[i].flags;
+
+		if ((pdid->idVendor == vid) && (pdid->idProduct == pid) && (flags & SPEC_DEV_ID_DISABLE_HT)) {
+			rtw_ht_enable = 0;
+			rtw_bw_mode = 0;
+			rtw_ampdu_enable = 0;
+		}
+#ifdef RTK_DMP_PLATFORM
+		/* Change the ifname to wlan10 when PC side WFD dongle plugin on DMP platform. */
+		/* It is used to distinguish between normal and PC-side wifi dongle/module. */
+		if ((pdid->idVendor == vid) && (pdid->idProduct == pid) && (flags & SPEC_DEV_ID_ASSIGN_IFNAME)) {
+			extern char *ifname;
+			strncpy(ifname, "wlan10", 6);
+			/* RTW_INFO("%s()-%d: ifname=%s, vid=%04X, pid=%04X\n", __func__, __LINE__, ifname, vid, pid); */
+		}
+#endif /* RTK_DMP_PLATFORM */
+
+	}
+}
+
+#ifdef SUPPORT_HW_RFOFF_DETECTED
+int rtw_hw_suspend(_adapter *padapter)
+{
+	struct pwrctrl_priv *pwrpriv;
+	struct usb_interface *pusb_intf;
+	struct net_device *pnetdev;
+
+	if (NULL == padapter)
+		goto error_exit;
+
+	if ((false == padapter->bup) || RTW_CANNOT_RUN(padapter)) {
+		RTW_INFO("padapter->bup=%d bDriverStopped=%s bSurpriseRemoved = %s\n"
+			 , padapter->bup
+			 , rtw_is_drv_stopped(padapter) ? "True" : "False"
+			, rtw_is_surprise_removed(padapter) ? "True" : "False");
+		goto error_exit;
+	}
+
+	pwrpriv = adapter_to_pwrctl(padapter);
+	pusb_intf = adapter_to_dvobj(padapter)->pusbintf;
+	pnetdev = padapter->pnetdev;
+
+	LeaveAllPowerSaveMode(padapter);
+
+	RTW_INFO("==> rtw_hw_suspend\n");
+	_enter_pwrlock(&pwrpriv->lock);
+	pwrpriv->bips_processing = true;
+	/* padapter->net_closed = true; */
+	/* s1. */
+	if (pnetdev) {
+		netif_carrier_off(pnetdev);
+		rtw_netif_stop_queue(pnetdev);
+	}
+
+	/* s2. */
+	rtw_disassoc_cmd(padapter, 500, false);
+
+	/* s2-2.  indicate disconnect to os */
+	/* rtw_indicate_disconnect(padapter); */
+	{
+		struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
+		if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+			_clr_fwstate_(pmlmepriv, _FW_LINKED);
+			rtw_led_control(padapter, LED_CTL_NO_LINK);
+
+			rtw_os_indicate_disconnect(padapter, 0, false);
+
+#ifdef CONFIG_LPS
+			/* donnot enqueue cmd */
+			rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 0);
+#endif
+		}
+	}
+	/* s2-3. */
+	rtw_free_assoc_resources(padapter, 1);
+
+	/* s2-4. */
+	rtw_free_network_queue(padapter, true);
+#ifdef CONFIG_IPS
+	rtw_ips_dev_unload(padapter);
+#endif
+	pwrpriv->rf_pwrstate = rf_off;
+	pwrpriv->bips_processing = false;
+	_exit_pwrlock(&pwrpriv->lock);
+
+	return 0;
+
+error_exit:
+	RTW_INFO("%s, failed\n", __func__);
+	return -1;
+
+}
+
+int rtw_hw_resume(_adapter *padapter)
+{
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct usb_interface *pusb_intf = adapter_to_dvobj(padapter)->pusbintf;
+	struct net_device *pnetdev = padapter->pnetdev;
+
+	RTW_INFO("==> rtw_hw_resume\n");
+	_enter_pwrlock(&pwrpriv->lock);
+	pwrpriv->bips_processing = true;
+	rtw_reset_drv_sw(padapter);
+
+	if (pm_netdev_open(pnetdev, false) != 0) {
+		_exit_pwrlock(&pwrpriv->lock);
+		goto error_exit;
+	}
+
+	rtw_netif_carrier_on(pnetdev);
+
+	rtw_netif_wake_queue(pnetdev);
+
+	pwrpriv->bkeepfwalive = false;
+	pwrpriv->brfoffbyhw = false;
+
+	pwrpriv->rf_pwrstate = rf_on;
+	pwrpriv->bips_processing = false;
+	_exit_pwrlock(&pwrpriv->lock);
+
+
+	return 0;
+error_exit:
+	RTW_INFO("%s, Open net dev failed\n", __func__);
+	return -1;
+}
+#endif
+
+static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
+{
+	struct dvobj_priv *dvobj;
+	struct pwrctrl_priv *pwrpriv;
+	struct debug_priv *pdbgpriv;
+	PADAPTER padapter;
+	int ret = 0;
+
+
+	dvobj = usb_get_intfdata(pusb_intf);
+	pwrpriv = dvobj_to_pwrctl(dvobj);
+	pdbgpriv = &dvobj->drv_dbg;
+	padapter = dvobj_get_primary_adapter(dvobj);
+
+	if (pwrpriv->bInSuspend == true) {
+		RTW_INFO("%s bInSuspend = %d\n", __func__, pwrpriv->bInSuspend);
+		pdbgpriv->dbg_suspend_error_cnt++;
+		goto exit;
+	}
+
+	if ((padapter->bup) || !rtw_is_drv_stopped(padapter) || !rtw_is_surprise_removed(padapter)) {
+#ifdef CONFIG_AUTOSUSPEND
+		if (pwrpriv->bInternalAutoSuspend) {
+
+#ifdef SUPPORT_HW_RFOFF_DETECTED
+			/* The FW command register update must after MAC and FW init ready. */
+			if ((padapter->bFWReady) && (pwrpriv->bHWPwrPindetect) && (padapter->registrypriv.usbss_enable)) {
+				u8 bOpen = true;
+				rtw_interface_ps_func(padapter, HAL_USB_SELECT_SUSPEND, &bOpen);
+			}
+#endif/* SUPPORT_HW_RFOFF_DETECTED */
+		}
+#endif/* CONFIG_AUTOSUSPEND */
+	}
+
+	ret =  rtw_suspend_common(padapter);
+
+exit:
+	return ret;
+}
+
+static int rtw_resume_process(_adapter *padapter)
+{
+	int ret, pm_cnt = 0;
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct dvobj_priv *pdvobj = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &pdvobj->drv_dbg;
+
+
+	if (pwrpriv->bInSuspend == false) {
+		pdbgpriv->dbg_resume_error_cnt++;
+		RTW_INFO("%s bInSuspend = %d\n", __func__, pwrpriv->bInSuspend);
+		return -1;
+	}
+
+#if defined(CONFIG_BT_COEXIST) && defined(CONFIG_AUTOSUSPEND) /* add by amy for 8723as-vau */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+	RTW_INFO("%s...pm_usage_cnt(%d)  pwrpriv->bAutoResume=%x.  ....\n", __func__, atomic_read(&(adapter_to_dvobj(padapter)->pusbintf->pm_usage_cnt)), pwrpriv->bAutoResume);
+	pm_cnt = atomic_read(&(adapter_to_dvobj(padapter)->pusbintf->pm_usage_cnt));
+#else /* kernel < 2.6.32 */
+	RTW_INFO("...pm_usage_cnt(%d).....\n", adapter_to_dvobj(padapter)->pusbintf->pm_usage_cnt);
+	pm_cnt = adapter_to_dvobj(padapter)->pusbintf->pm_usage_cnt;
+#endif /* kernel < 2.6.32 */
+
+	RTW_INFO("pwrpriv->bAutoResume (%x)\n", pwrpriv->bAutoResume);
+	if (pwrpriv->bAutoResume) {
+		pwrpriv->bInternalAutoSuspend = false;
+		pwrpriv->bAutoResume = false;
+		RTW_INFO("pwrpriv->bAutoResume (%x)  pwrpriv->bInternalAutoSuspend(%x)\n", pwrpriv->bAutoResume, pwrpriv->bInternalAutoSuspend);
+
+	}
+#endif /* #ifdef CONFIG_BT_COEXIST &CONFIG_AUTOSUSPEND& */
+
+	/*
+	 * Due to usb wow suspend flow will cancel read/write port via intf_stop and
+	 * bReadPortCancel and bWritePortCancel are set true in intf_stop.
+	 * But they will not be clear in intf_start during wow resume flow.
+	 * It should move to os_intf in the feature.
+	 */
+	RTW_ENABLE_FUNC(padapter, DF_RX_BIT);
+	RTW_ENABLE_FUNC(padapter, DF_TX_BIT);
+
+	ret =  rtw_resume_common(padapter);
+
+#ifdef CONFIG_AUTOSUSPEND
+	if (pwrpriv->bInternalAutoSuspend) {
+#ifdef SUPPORT_HW_RFOFF_DETECTED
+		/* The FW command register update must after MAC and FW init ready. */
+		if ((padapter->bFWReady) && (pwrpriv->bHWPwrPindetect) && (padapter->registrypriv.usbss_enable)) {
+			u8 bOpen = false;
+			rtw_interface_ps_func(padapter, HAL_USB_SELECT_SUSPEND, &bOpen);
+		}
+#endif
+#ifdef CONFIG_BT_COEXIST /* for 8723as-vau */
+		RTW_INFO("pwrpriv->bAutoResume (%x)\n", pwrpriv->bAutoResume);
+		if (pwrpriv->bAutoResume) {
+			pwrpriv->bInternalAutoSuspend = false;
+			pwrpriv->bAutoResume = false;
+			RTW_INFO("pwrpriv->bAutoResume (%x)  pwrpriv->bInternalAutoSuspend(%x)\n", pwrpriv->bAutoResume, pwrpriv->bInternalAutoSuspend);
+		}
+
+#else	/* #ifdef CONFIG_BT_COEXIST */
+		pwrpriv->bInternalAutoSuspend = false;
+#endif	/* #ifdef CONFIG_BT_COEXIST */
+		pwrpriv->brfoffbyhw = false;
+	}
+#endif/* CONFIG_AUTOSUSPEND */
+
+
+	return ret;
+}
+
+static int rtw_resume(struct usb_interface *pusb_intf)
+{
+	struct dvobj_priv *dvobj;
+	struct pwrctrl_priv *pwrpriv;
+	struct debug_priv *pdbgpriv;
+	PADAPTER padapter;
+	struct mlme_ext_priv *pmlmeext;
+	int ret = 0;
+
+
+	dvobj = usb_get_intfdata(pusb_intf);
+	pwrpriv = dvobj_to_pwrctl(dvobj);
+	pdbgpriv = &dvobj->drv_dbg;
+	padapter = dvobj_get_primary_adapter(dvobj);
+	pmlmeext = &padapter->mlmeextpriv;
+
+	RTW_INFO("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
+	pdbgpriv->dbg_resume_cnt++;
+
+	if (pwrpriv->bInternalAutoSuspend)
+		ret = rtw_resume_process(padapter);
+	else {
+		if (pwrpriv->wowlan_mode || pwrpriv->wowlan_ap_mode) {
+			rtw_resume_lock_suspend();
+			ret = rtw_resume_process(padapter);
+			rtw_resume_unlock_suspend();
+		} else {
+#ifdef CONFIG_RESUME_IN_WORKQUEUE
+			rtw_resume_in_workqueue(pwrpriv);
+#else
+			if (rtw_is_earlysuspend_registered(pwrpriv)) {
+				/* jeff: bypass resume here, do in late_resume */
+				rtw_set_do_late_resume(pwrpriv, true);
+			} else {
+				rtw_resume_lock_suspend();
+				ret = rtw_resume_process(padapter);
+				rtw_resume_unlock_suspend();
+			}
+#endif
+		}
+	}
+
+	pmlmeext->last_scan_time = jiffies;
+	RTW_INFO("<========  %s return %d\n", __func__, ret);
+
+	return ret;
+}
+
+
+
+#ifdef CONFIG_AUTOSUSPEND
+void autosuspend_enter(_adapter *padapter)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
+
+	RTW_INFO("==>autosuspend_enter...........\n");
+
+	pwrpriv->bInternalAutoSuspend = true;
+	pwrpriv->bips_processing = true;
+
+	if (rf_off == pwrpriv->change_rfpwrstate) {
+#ifndef	CONFIG_BT_COEXIST
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+		usb_enable_autosuspend(dvobj->pusbdev);
+#else
+		dvobj->pusbdev->autosuspend_disabled = 0;/* autosuspend disabled by the user */
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
+		usb_autopm_put_interface(dvobj->pusbintf);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20))
+		usb_autopm_enable(dvobj->pusbintf);
+#else
+		usb_autosuspend_device(dvobj->pusbdev, 1);
+#endif
+#else	/* #ifndef	CONFIG_BT_COEXIST */
+		if (1 == pwrpriv->autopm_cnt) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+			usb_enable_autosuspend(dvobj->pusbdev);
+#else
+			dvobj->pusbdev->autosuspend_disabled = 0;/* autosuspend disabled by the user */
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
+			usb_autopm_put_interface(dvobj->pusbintf);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20))
+			usb_autopm_enable(dvobj->pusbintf);
+#else
+			usb_autosuspend_device(dvobj->pusbdev, 1);
+#endif
+			pwrpriv->autopm_cnt--;
+		} else
+			RTW_INFO("0!=pwrpriv->autopm_cnt[%d]   didn't usb_autopm_put_interface\n", pwrpriv->autopm_cnt);
+
+#endif	/* #ifndef	CONFIG_BT_COEXIST */
+	}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+	RTW_INFO("...pm_usage_cnt(%d).....\n", atomic_read(&(dvobj->pusbintf->pm_usage_cnt)));
+#else
+	RTW_INFO("...pm_usage_cnt(%d).....\n", dvobj->pusbintf->pm_usage_cnt);
+#endif
+
+}
+
+int autoresume_enter(_adapter *padapter)
+{
+	int result = _SUCCESS;
+	struct security_priv *psecuritypriv = &(padapter->securitypriv);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
+
+	RTW_INFO("====> autoresume_enter\n");
+
+	if (rf_off == pwrpriv->rf_pwrstate) {
+		pwrpriv->ps_flag = false;
+#ifndef	CONFIG_BT_COEXIST
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
+		if (usb_autopm_get_interface(dvobj->pusbintf) < 0) {
+			RTW_INFO("can't get autopm: %d\n", result);
+			result = _FAIL;
+			goto error_exit;
+		}
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20))
+		usb_autopm_disable(dvobj->pusbintf);
+#else
+		usb_autoresume_device(dvobj->pusbdev, 1);
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+		RTW_INFO("...pm_usage_cnt(%d).....\n", atomic_read(&(dvobj->pusbintf->pm_usage_cnt)));
+#else
+		RTW_INFO("...pm_usage_cnt(%d).....\n", dvobj->pusbintf->pm_usage_cnt);
+#endif
+#else	/* #ifndef	CONFIG_BT_COEXIST */
+		pwrpriv->bAutoResume = true;
+		if (0 == pwrpriv->autopm_cnt) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
+			if (usb_autopm_get_interface(dvobj->pusbintf) < 0) {
+				RTW_INFO("can't get autopm: %d\n", result);
+				result = _FAIL;
+				goto error_exit;
+			}
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20))
+			usb_autopm_disable(dvobj->pusbintf);
+#else
+			usb_autoresume_device(dvobj->pusbdev, 1);
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+			RTW_INFO("...pm_usage_cnt(%d).....\n", atomic_read(&(dvobj->pusbintf->pm_usage_cnt)));
+#else
+			RTW_INFO("...pm_usage_cnt(%d).....\n", dvobj->pusbintf->pm_usage_cnt);
+#endif
+			pwrpriv->autopm_cnt++;
+		} else
+			RTW_INFO("0!=pwrpriv->autopm_cnt[%d]   didn't usb_autopm_get_interface\n", pwrpriv->autopm_cnt);
+#endif /* #ifndef	CONFIG_BT_COEXIST */
+	}
+	RTW_INFO("<==== autoresume_enter\n");
+error_exit:
+
+	return result;
+}
+#endif
+
+#ifdef CONFIG_PLATFORM_RTD2880B
+extern void rtd2885_wlan_netlink_sendMsg(char *action_string, char *name);
+#endif
+
+/*
+ * drv_init() - a device potentially for us
+ *
+ * notes: drv_init() is called when the bus driver has located a card for us to support.
+ *        We accept the new device by returning 0.
+*/
+
+static _adapter  *rtw_sw_export = NULL;
+
+static _adapter *rtw_usb_primary_adapter_init(struct dvobj_priv *dvobj,
+	struct usb_interface *pusb_intf)
+{
+	_adapter *padapter = NULL;
+	int status = _FAIL;
+
+	padapter = (_adapter *)rtw_zvmalloc(sizeof(*padapter));
+	if (padapter == NULL)
+		goto exit;
+
+	if (loadparam(padapter) != _SUCCESS)
+		goto free_adapter;
+
+	padapter->dvobj = dvobj;
+
+
+	rtw_set_drv_stopped(padapter);/*init*/
+
+	dvobj->padapters[dvobj->iface_nums++] = padapter;
+	padapter->iface_id = IFACE_ID0;
+
+	/* set adapter_type/iface type for primary padapter */
+	padapter->isprimary = true;
+	padapter->adapter_type = PRIMARY_ADAPTER;
+#ifdef CONFIG_MI_WITH_MBSSID_CAM/*Configure all IFACE to PORT0-MBSSID*/
+	padapter->hw_port = HW_PORT0;
+#else
+	padapter->hw_port = HW_PORT0;
+#endif
+
+	/* step init_io_priv */
+	if (rtw_init_io_priv(padapter, usb_set_intf_ops) == _FAIL)
+		goto free_adapter;
+
+	/* step 2. hook HalFunc, allocate HalData */
+	if (rtw_set_hal_ops(padapter) == _FAIL)
+		goto free_hal_data;
+
+
+	padapter->intf_start = &usb_intf_start;
+	padapter->intf_stop = &usb_intf_stop;
+
+	/* step read_chip_version */
+	rtw_hal_read_chip_version(padapter);
+
+	/* step usb endpoint mapping */
+	rtw_hal_chip_configure(padapter);
+
+	/* step read efuse/eeprom data and get mac_addr */
+	if (rtw_hal_read_chip_info(padapter) == _FAIL)
+		goto free_hal_data;
+
+	/* step 5. */
+	if (rtw_init_drv_sw(padapter) == _FAIL) {
+		goto free_hal_data;
+	}
+
+#ifdef CONFIG_BT_COEXIST
+	if (GET_HAL_DATA(padapter)->EEPROMBluetoothCoexist)
+		rtw_btcoex_Initialize(padapter);
+	else
+		rtw_btcoex_wifionly_initialize(padapter);
+#else /* !CONFIG_BT_COEXIST */
+	rtw_btcoex_wifionly_initialize(padapter);
+#endif /* CONFIG_BT_COEXIST */
+
+#ifdef CONFIG_PM
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
+	if (dvobj_to_pwrctl(dvobj)->bSupportRemoteWakeup) {
+		dvobj->pusbdev->do_remote_wakeup = 1;
+		pusb_intf->needs_remote_wakeup = 1;
+		device_init_wakeup(&pusb_intf->dev, 1);
+		RTW_INFO("pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n");
+		RTW_INFO("pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n", device_may_wakeup(&pusb_intf->dev));
+	}
+#endif
+#endif
+
+#ifdef CONFIG_AUTOSUSPEND
+	if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE) {
+		if (padapter->registrypriv.usbss_enable) {	/* autosuspend (2s delay) */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
+			dvobj->pusbdev->dev.power.autosuspend_delay = 0 * HZ;/* 15 * HZ; idle-delay time */
+#else
+			dvobj->pusbdev->autosuspend_delay = 0 * HZ;/* 15 * HZ; idle-delay time */
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+			usb_enable_autosuspend(dvobj->pusbdev);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34))
+			padapter->bDisableAutosuspend = dvobj->pusbdev->autosuspend_disabled ;
+			dvobj->pusbdev->autosuspend_disabled = 0;/* autosuspend disabled by the user */
+#endif
+
+			/* usb_autopm_get_interface(adapter_to_dvobj(padapter)->pusbintf ); */ /* init pm_usage_cnt ,let it start from 1 */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+			RTW_INFO("%s...pm_usage_cnt(%d).....\n", __func__, atomic_read(&(dvobj->pusbintf->pm_usage_cnt)));
+#else
+			RTW_INFO("%s...pm_usage_cnt(%d).....\n", __func__, dvobj->pusbintf->pm_usage_cnt);
+#endif
+		}
+	}
+#endif
+	/* 2012-07-11 Move here to prevent the 8723AS-VAU BT auto suspend influence */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
+	if (usb_autopm_get_interface(pusb_intf) < 0)
+		RTW_INFO("can't get autopm:\n");
+#endif
+#ifdef CONFIG_BT_COEXIST
+	dvobj_to_pwrctl(dvobj)->autopm_cnt = 1;
+#endif
+
+	/* set mac addr */
+	rtw_macaddr_cfg(adapter_mac_addr(padapter), get_hal_mac_addr(padapter));
+#ifdef CONFIG_MI_WITH_MBSSID_CAM
+	rtw_mbid_camid_alloc(padapter, adapter_mac_addr(padapter));
+#endif
+
+#ifdef CONFIG_P2P
+	rtw_init_wifidirect_addrs(padapter, adapter_mac_addr(padapter), adapter_mac_addr(padapter));
+#endif /* CONFIG_P2P */
+	RTW_INFO("bDriverStopped:%s, bSurpriseRemoved:%s, bup:%d, hw_init_completed:%d\n"
+		 , rtw_is_drv_stopped(padapter) ? "True" : "False"
+		 , rtw_is_surprise_removed(padapter) ? "True" : "False"
+		 , padapter->bup
+		 , rtw_get_hw_init_completed(padapter)
+		);
+
+	status = _SUCCESS;
+
+free_hal_data:
+	if (status != _SUCCESS && padapter->HalData)
+		rtw_hal_free_data(padapter);
+free_adapter:
+	if (status != _SUCCESS && padapter) {
+		rtw_vmfree((u8 *)padapter, sizeof(*padapter));
+		padapter = NULL;
+	}
+exit:
+	return padapter;
+}
+
+static void rtw_usb_primary_adapter_deinit(_adapter *padapter)
+{
+	struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+	RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+
+	if (check_fwstate(pmlmepriv, _FW_LINKED))
+		rtw_disassoc_cmd(padapter, 0, false);
+
+#ifdef CONFIG_AP_MODE
+	if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true) {
+		free_mlme_ap_info(padapter);
+		#ifdef CONFIG_HOSTAPD_MLME
+		hostapd_mode_unload(padapter);
+		#endif
+	}
+#endif
+
+	/*rtw_cancel_all_timer(if1);*/
+
+#ifdef CONFIG_WOWLAN
+	pwrctl->wowlan_mode = false;
+#endif /* CONFIG_WOWLAN */
+
+	rtw_dev_unload(padapter);
+
+	RTW_INFO("+r871xu_dev_remove, hw_init_completed=%d\n", rtw_get_hw_init_completed(padapter));
+
+#ifdef CONFIG_BT_COEXIST
+	if (1 == pwrctl->autopm_cnt) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
+		usb_autopm_put_interface(adapter_to_dvobj(padapter)->pusbintf);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20))
+		usb_autopm_enable(adapter_to_dvobj(padapter)->pusbintf);
+#else
+		usb_autosuspend_device(adapter_to_dvobj(padapter)->pusbdev, 1);
+#endif
+		pwrctl->autopm_cnt--;
+	}
+#endif
+
+	rtw_free_drv_sw(padapter);
+
+	/* TODO: use rtw_os_ndevs_deinit instead at the first stage of driver's dev deinit function */
+	rtw_os_ndev_free(padapter);
+
+#ifdef RTW_HALMAC
+	rtw_halmac_deinit_adapter(adapter_to_dvobj(padapter));
+#endif /* RTW_HALMAC */
+
+	rtw_vmfree((u8 *)padapter, sizeof(_adapter));
+
+#ifdef CONFIG_PLATFORM_RTD2880B
+	RTW_INFO("wlan link down\n");
+	rtd2885_wlan_netlink_sendMsg("linkdown", "8712");
+#endif
+
+}
+
+static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid)
+{
+	_adapter *padapter = NULL;
+	int status = _FAIL;
+	struct dvobj_priv *dvobj;
+#ifdef CONFIG_CONCURRENT_MODE
+	int i;
+#endif
+
+	/* RTW_INFO("+rtw_drv_init\n"); */
+
+	/* step 0. */
+	process_spec_devid(pdid);
+
+	/* Initialize dvobj_priv */
+	dvobj = usb_dvobj_init(pusb_intf, pdid);
+	if (dvobj == NULL) {
+		goto exit;
+	}
+
+	padapter = rtw_usb_primary_adapter_init(dvobj, pusb_intf);
+	if (padapter == NULL) {
+		RTW_INFO("rtw_usb_primary_adapter_init Failed!\n");
+		goto free_dvobj;
+	}
+
+	if (usb_reprobe_switch_usb_mode(padapter) == true)
+		goto free_if_prim;
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (padapter->registrypriv.virtual_iface_num > (CONFIG_IFACE_NUMBER - 1))
+		padapter->registrypriv.virtual_iface_num = (CONFIG_IFACE_NUMBER - 1);
+
+	for (i = 0; i < padapter->registrypriv.virtual_iface_num; i++) {
+		if (rtw_drv_add_vir_if(padapter, usb_set_intf_ops) == NULL) {
+			RTW_INFO("rtw_drv_add_iface failed! (%d)\n", i);
+			goto free_if_vir;
+		}
+	}
+#endif
+
+#ifdef CONFIG_INTEL_PROXIM
+	rtw_sw_export = padapter;
+#endif
+
+#ifdef CONFIG_GLOBAL_UI_PID
+	if (ui_pid[1] != 0) {
+		RTW_INFO("ui_pid[1]:%d\n", ui_pid[1]);
+		rtw_signal_process(ui_pid[1], SIGUSR2);
+	}
+#endif
+
+	/* dev_alloc_name && register_netdev */
+	if (rtw_os_ndevs_init(dvobj) != _SUCCESS)
+		goto free_if_vir;
+
+#ifdef CONFIG_HOSTAPD_MLME
+	hostapd_mode_init(padapter);
+#endif
+
+#ifdef CONFIG_PLATFORM_RTD2880B
+	RTW_INFO("wlan link up\n");
+	rtd2885_wlan_netlink_sendMsg("linkup", "8712");
+#endif
+	status = _SUCCESS;
+free_if_vir:
+	if (status != _SUCCESS) {
+		#ifdef CONFIG_CONCURRENT_MODE
+		rtw_drv_stop_vir_ifaces(dvobj);
+		rtw_drv_free_vir_ifaces(dvobj);
+		#endif
+	}
+
+free_if_prim:
+	if (status != _SUCCESS && padapter)
+		rtw_usb_primary_adapter_deinit(padapter);
+
+free_dvobj:
+	if (status != _SUCCESS)
+		usb_dvobj_deinit(pusb_intf);
+exit:
+	return status == _SUCCESS ? 0 : -ENODEV;
+}
+
+/*
+ * dev_remove() - our device is being removed
+*/
+/* rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove() => how to recognize both */
+static void rtw_dev_remove(struct usb_interface *pusb_intf)
+{
+	struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
+	struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(dvobj);
+	_adapter *padapter = dvobj_get_primary_adapter(dvobj);
+	struct net_device *pnetdev = padapter->pnetdev;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+
+	RTW_INFO("+rtw_dev_remove\n");
+
+	dvobj->processing_dev_remove = true;
+
+	/* TODO: use rtw_os_ndevs_deinit instead at the first stage of driver's dev deinit function */
+	rtw_os_ndevs_unregister(dvobj);
+
+	if (usb_drv.drv_registered == true) {
+		/* RTW_INFO("r871xu_dev_remove():padapter->bSurpriseRemoved == true\n"); */
+		rtw_set_surprise_removed(padapter);
+	}
+	/*else
+	{
+
+		padapter->HalData->hw_init_completed = false;
+	}*/
+
+
+#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
+	rtw_unregister_early_suspend(pwrctl);
+#endif
+
+	if (padapter->bFWReady == true) {
+		rtw_pm_set_ips(padapter, IPS_NONE);
+		rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
+
+		LeaveAllPowerSaveMode(padapter);
+	}
+	rtw_set_drv_stopped(padapter);	/*for stop thread*/
+	rtw_stop_cmd_thread(padapter);
+#ifdef CONFIG_CONCURRENT_MODE
+	rtw_drv_stop_vir_ifaces(dvobj);
+#endif /* CONFIG_CONCURRENT_MODE */
+
+#ifdef CONFIG_BT_COEXIST
+#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
+	if (GET_HAL_DATA(padapter)->EEPROMBluetoothCoexist)
+		rtw_btcoex_close_socket(padapter);
+#endif
+	rtw_btcoex_HaltNotify(padapter);
+#endif
+
+	rtw_usb_primary_adapter_deinit(padapter);
+
+#ifdef CONFIG_CONCURRENT_MODE
+	rtw_drv_free_vir_ifaces(dvobj);
+#endif /* CONFIG_CONCURRENT_MODE */
+
+	usb_dvobj_deinit(pusb_intf);
+
+	RTW_INFO("-r871xu_dev_remove, done\n");
+
+
+#ifdef CONFIG_INTEL_PROXIM
+	rtw_sw_export = NULL;
+#endif
+
+
+	return;
+
+}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24))
+extern int console_suspend_enabled;
+#endif
+
+static int __init rtw_drv_entry(void)
+{
+	int ret = 0;
+
+	RTW_INFO("module init start\n");
+	dump_drv_version(RTW_DBGDUMP);
+#ifdef BTCOEXVERSION
+	RTW_INFO(DRV_NAME" BT-Coex version = %s\n", BTCOEXVERSION);
+#endif /* BTCOEXVERSION */
+
+	usb_drv.drv_registered = true;
+	rtw_suspend_lock_init();
+	rtw_drv_proc_init();
+	rtw_ndev_notifier_register();
+
+	ret = usb_register(&usb_drv.usbdrv);
+
+	if (ret != 0) {
+		usb_drv.drv_registered = false;
+		rtw_suspend_lock_uninit();
+		rtw_drv_proc_deinit();
+		rtw_ndev_notifier_unregister();
+		goto exit;
+	}
+
+exit:
+	RTW_INFO("module init ret=%d\n", ret);
+	return ret;
+}
+
+static void __exit rtw_drv_halt(void)
+{
+	RTW_INFO("module exit start\n");
+
+	usb_drv.drv_registered = false;
+
+	usb_deregister(&usb_drv.usbdrv);
+
+	rtw_suspend_lock_uninit();
+	rtw_drv_proc_deinit();
+	rtw_ndev_notifier_unregister();
+
+	RTW_INFO("module exit success\n");
+
+	rtw_mstat_dump(RTW_DBGDUMP);
+}
+
+
+module_init(rtw_drv_entry);
+module_exit(rtw_drv_halt);
+
+#ifdef CONFIG_INTEL_PROXIM
+_adapter  *rtw_usb_get_sw_pointer(void)
+{
+	return rtw_sw_export;
+}
+EXPORT_SYMBOL(rtw_usb_get_sw_pointer);
+#endif /* CONFIG_INTEL_PROXIM */
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
new file mode 100644
index 000000000000..10705b33e737
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
@@ -0,0 +1,1082 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+#define _USB_OPS_LINUX_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+#include <rtw_sreset.h>
+
+struct rtw_async_write_data {
+	u8 data[VENDOR_CMD_MAX_DATA_LEN];
+	struct usb_ctrlrequest dr;
+};
+
+int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u8 request, u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
+{
+	_adapter	*padapter = pintfhdl->padapter;
+	struct dvobj_priv  *pdvobjpriv = adapter_to_dvobj(padapter);
+	struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(pdvobjpriv);
+	struct usb_device *udev = pdvobjpriv->pusbdev;
+
+	unsigned int pipe;
+	int status = 0;
+	u32 tmp_buflen = 0;
+	u8 reqtype;
+	u8 *pIo_buf;
+	int vendorreq_times = 0;
+
+#ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE
+	u8 *tmp_buf;
+#else /* use stack memory */
+	u8 tmp_buf[MAX_USB_IO_CTL_SIZE];
+#endif
+
+	/* RTW_INFO("%s %s:%d\n",__func__, current->comm, current->pid); */
+
+	if (RTW_CANNOT_IO(padapter)) {
+		status = -EPERM;
+		goto exit;
+	}
+
+	if (len > MAX_VENDOR_REQ_CMD_SIZE) {
+		RTW_INFO("[%s] Buffer len error ,vendor request failed\n", __func__);
+		status = -EINVAL;
+		goto exit;
+	}
+
+#ifdef CONFIG_USB_VENDOR_REQ_MUTEX
+	_enter_critical_mutex(&pdvobjpriv->usb_vendor_req_mutex, NULL);
+#endif
+
+
+	/* Acquire IO memory for vendorreq */
+#ifdef CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC
+	pIo_buf = pdvobjpriv->usb_vendor_req_buf;
+#else
+	#ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE
+	tmp_buf = rtw_malloc((u32) len + ALIGNMENT_UNIT);
+	tmp_buflen = (u32)len + ALIGNMENT_UNIT;
+	#else /* use stack memory */
+	tmp_buflen = MAX_USB_IO_CTL_SIZE;
+	#endif
+
+	/* Added by Albert 2010/02/09 */
+	/* For mstar platform, mstar suggests the address for USB IO should be 16 bytes alignment. */
+	/* Trying to fix it here. */
+	pIo_buf = (tmp_buf == NULL) ? NULL : tmp_buf + ALIGNMENT_UNIT - ((SIZE_PTR)(tmp_buf) & 0x0f);
+#endif
+
+	if (pIo_buf == NULL) {
+		RTW_INFO("[%s] pIo_buf == NULL\n", __func__);
+		status = -ENOMEM;
+		goto release_mutex;
+	}
+
+	while (++vendorreq_times <= MAX_USBCTRL_VENDORREQ_TIMES) {
+		memset(pIo_buf, 0, len);
+
+		if (requesttype == 0x01) {
+			pipe = usb_rcvctrlpipe(udev, 0);/* read_in */
+			reqtype =  REALTEK_USB_VENQT_READ;
+		} else {
+			pipe = usb_sndctrlpipe(udev, 0);/* write_out */
+			reqtype =  REALTEK_USB_VENQT_WRITE;
+			memcpy(pIo_buf, pdata, len);
+		}
+
+		status = rtw_usb_control_msg(udev, pipe, request, reqtype, value, index, pIo_buf, len, RTW_USB_CONTROL_MSG_TIMEOUT);
+
+		if (status == len) {  /* Success this control transfer. */
+			rtw_reset_continual_io_error(pdvobjpriv);
+			if (requesttype == 0x01) {
+				/* For Control read transfer, we have to copy the read data from pIo_buf to pdata. */
+				memcpy(pdata, pIo_buf,  len);
+			}
+		} else { /* error cases */
+			RTW_INFO("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n"
+				, value, (requesttype == 0x01) ? "read" : "write" , len, status, *(u32 *)pdata, vendorreq_times);
+
+			if (status < 0) {
+				if (status == (-ESHUTDOWN)	|| status == -ENODEV)
+					rtw_set_surprise_removed(padapter);
+				else {
+					#ifdef DBG_CONFIG_ERROR_DETECT
+					{
+						HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+						pHalData->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL;
+					}
+					#endif
+				}
+			} else { /* status != len && status >= 0 */
+				if (status > 0) {
+					if (requesttype == 0x01) {
+						/* For Control read transfer, we have to copy the read data from pIo_buf to pdata. */
+						memcpy(pdata, pIo_buf,  len);
+					}
+				}
+			}
+
+			if (rtw_inc_and_chk_continual_io_error(pdvobjpriv) == true) {
+				rtw_set_surprise_removed(padapter);
+				break;
+			}
+
+		}
+
+		/* firmware download is checksumed, don't retry */
+		if ((value >= FW_START_ADDRESS) || status == len)
+			break;
+
+	}
+
+	/* release IO memory used by vendorreq */
+#ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE
+	rtw_mfree(tmp_buf, tmp_buflen);
+#endif
+
+release_mutex:
+#ifdef CONFIG_USB_VENDOR_REQ_MUTEX
+	_exit_critical_mutex(&pdvobjpriv->usb_vendor_req_mutex, NULL);
+#endif
+exit:
+	return status;
+
+}
+
+#ifdef CONFIG_USB_SUPPORT_ASYNC_VDN_REQ
+static void _usbctrl_vendorreq_async_callback(struct urb *urb, struct pt_regs *regs)
+{
+	if (urb) {
+		if (urb->context)
+			rtw_mfree(urb->context, sizeof(struct rtw_async_write_data));
+		usb_free_urb(urb);
+	}
+}
+
+int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request,
+	u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
+{
+	int rc;
+	unsigned int pipe;
+	u8 reqtype;
+	struct usb_ctrlrequest *dr;
+	struct urb *urb;
+	struct rtw_async_write_data *buf;
+
+
+	if (requesttype == VENDOR_READ) {
+		pipe = usb_rcvctrlpipe(udev, 0);/* read_in */
+		reqtype =  REALTEK_USB_VENQT_READ;
+	} else {
+		pipe = usb_sndctrlpipe(udev, 0);/* write_out */
+		reqtype =  REALTEK_USB_VENQT_WRITE;
+	}
+
+	buf = (struct rtl819x_async_write_data *)rtw_zmalloc(sizeof(*buf));
+	if (!buf) {
+		rc = -ENOMEM;
+		goto exit;
+	}
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		rtw_mfree((u8 *)buf, sizeof(*buf));
+		rc = -ENOMEM;
+		goto exit;
+	}
+
+	dr = &buf->dr;
+
+	dr->bRequestType = reqtype;
+	dr->bRequest = request;
+	dr->wValue = cpu_to_le16(value);
+	dr->wIndex = cpu_to_le16(index);
+	dr->wLength = cpu_to_le16(len);
+
+	memcpy(buf, pdata, len);
+
+	usb_fill_control_urb(urb, udev, pipe, (unsigned char *)dr, buf, len,
+		_usbctrl_vendorreq_async_callback, buf);
+
+	rc = usb_submit_urb(urb, GFP_ATOMIC);
+	if (rc < 0) {
+		rtw_mfree((u8 *)buf, sizeof(*buf));
+		usb_free_urb(urb);
+	}
+
+exit:
+	return rc;
+}
+
+
+#endif /* CONFIG_USB_SUPPORT_ASYNC_VDN_REQ */
+
+unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
+{
+	unsigned int pipe = 0, ep_num = 0;
+	struct usb_device *pusbd = pdvobj->pusbdev;
+
+	if (addr == RECV_BULK_IN_ADDR)
+		pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);
+
+	else if (addr == RECV_INT_IN_ADDR)
+		pipe = usb_rcvintpipe(pusbd, pdvobj->RtInPipe[1]);
+
+	else if (addr < HW_QUEUE_ENTRY) {
+#ifdef RTW_HALMAC
+		/* halmac already translate queue id to bulk out id */
+		ep_num = pdvobj->RtOutPipe[addr];
+#else
+		ep_num = pdvobj->Queue2Pipe[addr];
+#endif
+		pipe = usb_sndbulkpipe(pusbd, ep_num);
+	}
+
+	return pipe;
+}
+
+struct zero_bulkout_context {
+	void *pbuf;
+	void *purb;
+	void *pirp;
+	void *padapter;
+};
+
+static void usb_bulkout_zero_complete(struct urb *purb, struct pt_regs *regs)
+{
+	struct zero_bulkout_context *pcontext = (struct zero_bulkout_context *)purb->context;
+
+	/* RTW_INFO("+usb_bulkout_zero_complete\n"); */
+
+	if (pcontext) {
+		if (pcontext->pbuf)
+			rtw_mfree(pcontext->pbuf, sizeof(int));
+
+		if (pcontext->purb && (pcontext->purb == purb))
+			usb_free_urb(pcontext->purb);
+
+
+		rtw_mfree((u8 *)pcontext, sizeof(struct zero_bulkout_context));
+	}
+
+
+}
+
+static u32 usb_bulkout_zero(struct intf_hdl *pintfhdl, u32 addr)
+{
+	int pipe, status, len;
+	u32 ret;
+	unsigned char *pbuf;
+	struct zero_bulkout_context *pcontext;
+	PURB	purb = NULL;
+	_adapter *padapter = (_adapter *)pintfhdl->padapter;
+	struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
+	struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(pdvobj);
+	struct usb_device *pusbd = pdvobj->pusbdev;
+
+	/* RTW_INFO("%s\n", __func__); */
+
+
+	if (RTW_CANNOT_TX(padapter))
+		return _FAIL;
+
+
+	pcontext = (struct zero_bulkout_context *)rtw_zmalloc(sizeof(struct zero_bulkout_context));
+	if (pcontext == NULL)
+		return _FAIL;
+
+	pbuf = (unsigned char *)rtw_zmalloc(sizeof(int));
+	purb = usb_alloc_urb(0, GFP_ATOMIC);
+
+	/* translate DMA FIFO addr to pipehandle */
+	pipe = ffaddr2pipehdl(pdvobj, addr);
+
+	len = 0;
+	pcontext->pbuf = pbuf;
+	pcontext->purb = purb;
+	pcontext->pirp = NULL;
+	pcontext->padapter = padapter;
+
+
+	/* translate DMA FIFO addr to pipehandle */
+	/* pipe = ffaddr2pipehdl(pdvobj, addr);	 */
+
+	usb_fill_bulk_urb(purb, pusbd, pipe,
+			  pbuf,
+			  len,
+			  usb_bulkout_zero_complete,
+			  pcontext);/* context is pcontext */
+
+	status = usb_submit_urb(purb, GFP_ATOMIC);
+
+	if (!status)
+		ret = _SUCCESS;
+	else
+		ret = _FAIL;
+
+
+	return _SUCCESS;
+
+}
+
+void usb_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
+{
+
+}
+
+void usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
+{
+
+}
+
+
+void usb_read_port_cancel(struct intf_hdl *pintfhdl)
+{
+	int i;
+	struct recv_buf *precvbuf;
+	_adapter	*padapter = pintfhdl->padapter;
+	precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
+
+	RTW_INFO("%s\n", __func__);
+
+	for (i = 0; i < NR_RECVBUFF ; i++) {
+
+		if (precvbuf->purb)	 {
+			/* RTW_INFO("usb_read_port_cancel : usb_kill_urb\n"); */
+			usb_kill_urb(precvbuf->purb);
+		}
+		precvbuf++;
+	}
+
+#ifdef CONFIG_USB_INTERRUPT_IN_PIPE
+	usb_kill_urb(padapter->recvpriv.int_in_urb);
+#endif
+}
+
+static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
+{
+	unsigned long irqL;
+	int i;
+	struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
+	/* struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data; */
+	/* _adapter			*padapter = pxmitframe->padapter; */
+	_adapter	*padapter = pxmitbuf->padapter;
+	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
+	/* struct pkt_attrib *pattrib = &pxmitframe->attrib; */
+
+
+	switch (pxmitbuf->flags) {
+	case VO_QUEUE_INX:
+		pxmitpriv->voq_cnt--;
+		break;
+	case VI_QUEUE_INX:
+		pxmitpriv->viq_cnt--;
+		break;
+	case BE_QUEUE_INX:
+		pxmitpriv->beq_cnt--;
+		break;
+	case BK_QUEUE_INX:
+		pxmitpriv->bkq_cnt--;
+		break;
+	default:
+		break;
+	}
+
+
+	/*
+		_enter_critical(&pxmitpriv->lock, &irqL);
+
+		pxmitpriv->txirp_cnt--;
+
+		switch(pattrib->priority)
+		{
+			case 1:
+			case 2:
+				pxmitpriv->bkq_cnt--;
+
+				break;
+			case 4:
+			case 5:
+				pxmitpriv->viq_cnt--;
+
+				break;
+			case 6:
+			case 7:
+				pxmitpriv->voq_cnt--;
+
+				break;
+			case 0:
+			case 3:
+			default:
+				pxmitpriv->beq_cnt--;
+
+				break;
+
+		}
+
+		_exit_critical(&pxmitpriv->lock, &irqL);
+
+
+		if(pxmitpriv->txirp_cnt==0)
+		{
+			up(&(pxmitpriv->tx_retevt));
+		}
+	*/
+	/* rtw_free_xmitframe(pxmitpriv, pxmitframe); */
+
+	if (RTW_CANNOT_TX(padapter)) {
+		RTW_INFO("%s(): TX Warning! bDriverStopped(%s) OR bSurpriseRemoved(%s) pxmitbuf->buf_tag(%x)\n"
+			 , __func__
+			 , rtw_is_drv_stopped(padapter) ? "True" : "False"
+			 , rtw_is_surprise_removed(padapter) ? "True" : "False"
+			 , pxmitbuf->buf_tag);
+
+		goto check_completion;
+	}
+
+
+	if (purb->status == 0) {
+
+	} else {
+		RTW_INFO("###=> urb_write_port_complete status(%d)\n", purb->status);
+		if ((purb->status == -EPIPE) || (purb->status == -EPROTO)) {
+			/* usb_clear_halt(pusbdev, purb->pipe);	 */
+			/* msleep(10); */
+			sreset_set_wifi_error_status(padapter, USB_WRITE_PORT_FAIL);
+		} else if (purb->status == -EINPROGRESS) {
+			goto check_completion;
+
+		} else if (purb->status == -ENOENT) {
+			RTW_INFO("%s: -ENOENT\n", __func__);
+			goto check_completion;
+
+		} else if (purb->status == -ECONNRESET) {
+			RTW_INFO("%s: -ECONNRESET\n", __func__);
+			goto check_completion;
+
+		} else if (purb->status == -ESHUTDOWN) {
+			rtw_set_drv_stopped(padapter);
+
+			goto check_completion;
+		} else {
+			rtw_set_surprise_removed(padapter);
+			RTW_INFO("bSurpriseRemoved=true\n");
+
+			goto check_completion;
+		}
+	}
+
+	#ifdef DBG_CONFIG_ERROR_DETECT
+	{
+		HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+		pHalData->srestpriv.last_tx_complete_time = jiffies;
+	}
+	#endif
+
+check_completion:
+	_enter_critical(&pxmitpriv->lock_sctx, &irqL);
+	rtw_sctx_done_err(&pxmitbuf->sctx,
+		purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS);
+	_exit_critical(&pxmitpriv->lock_sctx, &irqL);
+
+	rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+
+	/* if(rtw_txframes_pending(padapter))	 */
+	{
+		tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
+	}
+
+
+}
+
+u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
+{
+	unsigned long irqL;
+	unsigned int pipe;
+	int status;
+	u32 ret = _FAIL, bwritezero = false;
+	PURB	purb = NULL;
+	_adapter *padapter = (_adapter *)pintfhdl->padapter;
+	struct dvobj_priv	*pdvobj = adapter_to_dvobj(padapter);
+	struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(pdvobj);
+	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
+	struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem;
+	struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
+	struct usb_device *pusbd = pdvobj->pusbdev;
+	struct pkt_attrib *pattrib = &pxmitframe->attrib;
+
+
+
+	if (RTW_CANNOT_TX(padapter)) {
+#ifdef DBG_TX
+		RTW_INFO(" DBG_TX %s:%d bDriverStopped%s, bSurpriseRemoved:%s\n", __func__, __LINE__
+			 , rtw_is_drv_stopped(padapter) ? "True" : "False"
+			, rtw_is_surprise_removed(padapter) ? "True" : "False");
+#endif
+		rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
+		goto exit;
+	}
+
+	_enter_critical(&pxmitpriv->lock, &irqL);
+
+	switch (addr) {
+	case VO_QUEUE_INX:
+		pxmitpriv->voq_cnt++;
+		pxmitbuf->flags = VO_QUEUE_INX;
+		break;
+	case VI_QUEUE_INX:
+		pxmitpriv->viq_cnt++;
+		pxmitbuf->flags = VI_QUEUE_INX;
+		break;
+	case BE_QUEUE_INX:
+		pxmitpriv->beq_cnt++;
+		pxmitbuf->flags = BE_QUEUE_INX;
+		break;
+	case BK_QUEUE_INX:
+		pxmitpriv->bkq_cnt++;
+		pxmitbuf->flags = BK_QUEUE_INX;
+		break;
+	case HIGH_QUEUE_INX:
+		pxmitbuf->flags = HIGH_QUEUE_INX;
+		break;
+	default:
+		pxmitbuf->flags = MGT_QUEUE_INX;
+		break;
+	}
+
+	_exit_critical(&pxmitpriv->lock, &irqL);
+
+	purb	= pxmitbuf->pxmit_urb[0];
+
+	/* translate DMA FIFO addr to pipehandle */
+#ifdef RTW_HALMAC
+	pipe = ffaddr2pipehdl(pdvobj, pxmitbuf->bulkout_id);
+#else
+	pipe = ffaddr2pipehdl(pdvobj, addr);
+#endif
+
+#ifdef CONFIG_REDUCE_USB_TX_INT
+	if ((pxmitpriv->free_xmitbuf_cnt % NR_XMITBUFF == 0)
+	    || (pxmitbuf->buf_tag > XMITBUF_DATA))
+		purb->transfer_flags  &= (~URB_NO_INTERRUPT);
+	else {
+		purb->transfer_flags  |=  URB_NO_INTERRUPT;
+		/* RTW_INFO("URB_NO_INTERRUPT "); */
+	}
+#endif
+
+
+	usb_fill_bulk_urb(purb, pusbd, pipe,
+			  pxmitframe->buf_addr, /* = pxmitbuf->pbuf */
+			  cnt,
+			  usb_write_port_complete,
+			  pxmitbuf);/* context is pxmitbuf */
+
+#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX
+	purb->transfer_dma = pxmitbuf->dma_transfer_addr;
+	purb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	purb->transfer_flags |= URB_ZERO_PACKET;
+#endif /* CONFIG_USE_USB_BUFFER_ALLOC_TX */
+
+#ifdef USB_PACKET_OFFSET_SZ
+#if (USB_PACKET_OFFSET_SZ == 0)
+	purb->transfer_flags |= URB_ZERO_PACKET;
+#endif
+#endif
+	status = usb_submit_urb(purb, GFP_ATOMIC);
+	if (!status) {
+		#ifdef DBG_CONFIG_ERROR_DETECT
+		{
+			HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+			pHalData->srestpriv.last_tx_time = jiffies;
+		}
+		#endif
+	} else {
+		rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
+		RTW_INFO("usb_write_port, status=%d\n", status);
+
+		switch (status) {
+		case -ENODEV:
+			rtw_set_drv_stopped(padapter);
+			break;
+		default:
+			break;
+		}
+		goto exit;
+	}
+
+	ret = _SUCCESS;
+
+	/* Commented by Albert 2009/10/13
+	 * We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically. */
+	/*
+		if(bwritezero == true)
+		{
+			usb_bulkout_zero(pintfhdl, addr);
+		}
+	*/
+
+
+exit:
+	if (ret != _SUCCESS)
+		rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+	return ret;
+
+}
+
+void usb_write_port_cancel(struct intf_hdl *pintfhdl)
+{
+	int i, j;
+	_adapter	*padapter = pintfhdl->padapter;
+	struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
+
+	RTW_INFO("%s\n", __func__);
+
+	for (i = 0; i < NR_XMITBUFF; i++) {
+		for (j = 0; j < 8; j++) {
+			if (pxmitbuf->pxmit_urb[j])
+				usb_kill_urb(pxmitbuf->pxmit_urb[j]);
+		}
+		pxmitbuf++;
+	}
+
+	pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmit_extbuf;
+	for (i = 0; i < NR_XMIT_EXTBUFF ; i++) {
+		for (j = 0; j < 8; j++) {
+			if (pxmitbuf->pxmit_urb[j])
+				usb_kill_urb(pxmitbuf->pxmit_urb[j]);
+		}
+		pxmitbuf++;
+	}
+}
+
+static void usb_init_recvbuf(_adapter *padapter, struct recv_buf *precvbuf)
+{
+
+	precvbuf->transfer_len = 0;
+
+	precvbuf->len = 0;
+
+	precvbuf->ref_cnt = 0;
+
+	if (precvbuf->pbuf) {
+		precvbuf->pdata = precvbuf->phead = precvbuf->ptail = precvbuf->pbuf;
+		precvbuf->pend = precvbuf->pdata + MAX_RECVBUF_SZ;
+	}
+
+}
+
+#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
+void usb_recv_tasklet(void *priv)
+{
+	struct recv_buf *precvbuf = NULL;
+	_adapter	*padapter = (_adapter *)priv;
+	struct recv_priv	*precvpriv = &padapter->recvpriv;
+
+	while (NULL != (precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue))) {
+		if (RTW_CANNOT_RUN(padapter)) {
+			RTW_INFO("recv_tasklet => bDriverStopped(%s) OR bSurpriseRemoved(%s)\n"
+				, rtw_is_drv_stopped(padapter)? "True" : "False"
+				, rtw_is_surprise_removed(padapter)? "True" : "False");
+			break;
+		}
+
+		recvbuf2recvframe(padapter, precvbuf);
+
+		rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+	}
+}
+
+void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
+{
+	struct recv_buf	*precvbuf = (struct recv_buf *)purb->context;
+	_adapter			*padapter = (_adapter *)precvbuf->adapter;
+	struct recv_priv	*precvpriv = &padapter->recvpriv;
+
+	ATOMIC_DEC(&(precvpriv->rx_pending_cnt));
+
+	if (RTW_CANNOT_RX(padapter)) {
+		RTW_INFO("%s() RX Warning! bDriverStopped(%s) OR bSurpriseRemoved(%s)\n"
+			 , __func__
+			 , rtw_is_drv_stopped(padapter) ? "True" : "False"
+			, rtw_is_surprise_removed(padapter) ? "True" : "False");
+		goto exit;
+	}
+
+	if (purb->status == 0) {
+
+		if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) {
+			RTW_INFO("%s()-%d: urb->actual_length:%u, MAX_RECVBUF_SZ:%u, RXDESC_SIZE:%u\n"
+				, __func__, __LINE__, purb->actual_length, MAX_RECVBUF_SZ, RXDESC_SIZE);
+			rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+		} else {
+			rtw_reset_continual_io_error(adapter_to_dvobj(padapter));
+
+			precvbuf->transfer_len = purb->actual_length;
+
+			rtw_enqueue_recvbuf(precvbuf, &precvpriv->recv_buf_pending_queue);
+
+			tasklet_schedule(&precvpriv->recv_tasklet);
+		}
+	} else {
+
+		RTW_INFO("###=> usb_read_port_complete => urb.status(%d)\n", purb->status);
+
+		if (rtw_inc_and_chk_continual_io_error(adapter_to_dvobj(padapter)) == true)
+			rtw_set_surprise_removed(padapter);
+
+		switch (purb->status) {
+		case -EINVAL:
+		case -EPIPE:
+		case -ENODEV:
+		case -ESHUTDOWN:
+		case -ENOENT:
+			rtw_set_drv_stopped(padapter);
+			break;
+		case -EPROTO:
+		case -EILSEQ:
+		case -ETIME:
+		case -ECOMM:
+		case -EOVERFLOW:
+			#ifdef DBG_CONFIG_ERROR_DETECT
+			{
+				HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+				pHalData->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL;
+			}
+			#endif
+			rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+			break;
+		case -EINPROGRESS:
+			RTW_INFO("ERROR: URB IS IN PROGRESS!/n");
+			break;
+		default:
+			break;
+		}
+	}
+
+exit:
+
+}
+
+u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
+{
+	int err;
+	unsigned int pipe;
+	u32 ret = _SUCCESS;
+	PURB purb = NULL;
+	struct recv_buf	*precvbuf = (struct recv_buf *)rmem;
+	_adapter		*adapter = pintfhdl->padapter;
+	struct dvobj_priv	*pdvobj = adapter_to_dvobj(adapter);
+	struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(pdvobj);
+	struct recv_priv	*precvpriv = &adapter->recvpriv;
+	struct usb_device	*pusbd = pdvobj->pusbdev;
+
+
+	if (RTW_CANNOT_RX(adapter) || (precvbuf == NULL)) {
+		return _FAIL;
+	}
+
+	usb_init_recvbuf(adapter, precvbuf);
+
+	if (precvbuf->pbuf) {
+		ATOMIC_INC(&(precvpriv->rx_pending_cnt));
+		purb = precvbuf->purb;
+
+		/* translate DMA FIFO addr to pipehandle */
+		pipe = ffaddr2pipehdl(pdvobj, addr);
+
+		usb_fill_bulk_urb(purb, pusbd, pipe,
+			precvbuf->pbuf,
+			MAX_RECVBUF_SZ,
+			usb_read_port_complete,
+			precvbuf);/* context is precvbuf */
+
+		purb->transfer_dma = precvbuf->dma_transfer_addr;
+		purb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+		err = usb_submit_urb(purb, GFP_ATOMIC);
+		if ((err) && (err != (-EPERM))) {
+			RTW_INFO("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n", err, purb->status);
+			ret = _FAIL;
+		}
+
+	}
+
+
+	return ret;
+}
+#else	/* CONFIG_USE_USB_BUFFER_ALLOC_RX */
+
+void usb_recv_tasklet(void *priv)
+{
+	_pkt			*pskb;
+	_adapter		*padapter = (_adapter *)priv;
+	struct recv_priv	*precvpriv = &padapter->recvpriv;
+	struct recv_buf	*precvbuf = NULL;
+
+	while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
+
+		if (RTW_CANNOT_RUN(padapter)) {
+			RTW_INFO("recv_tasklet => bDriverStopped(%s) OR bSurpriseRemoved(%s)\n"
+				, rtw_is_drv_stopped(padapter) ? "True" : "False"
+				, rtw_is_surprise_removed(padapter) ? "True" : "False");
+			#ifdef CONFIG_PREALLOC_RX_SKB_BUFFER
+			if (rtw_free_skb_premem(pskb) != 0)
+			#endif /* CONFIG_PREALLOC_RX_SKB_BUFFER */
+				rtw_skb_free(pskb);
+			break;
+		}
+
+		recvbuf2recvframe(padapter, pskb);
+
+		skb_reset_tail_pointer(pskb);
+		pskb->len = 0;
+
+		skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
+
+		precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
+		if (NULL != precvbuf) {
+			precvbuf->pskb = NULL;
+			rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+		}
+	}
+}
+
+static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
+{
+	struct recv_buf	*precvbuf = (struct recv_buf *)purb->context;
+	_adapter			*padapter = (_adapter *)precvbuf->adapter;
+	struct recv_priv	*precvpriv = &padapter->recvpriv;
+
+	ATOMIC_DEC(&(precvpriv->rx_pending_cnt));
+
+	if (RTW_CANNOT_RX(padapter)) {
+		RTW_INFO("%s() RX Warning! bDriverStopped(%s) OR bSurpriseRemoved(%s)\n"
+			, __func__
+			, rtw_is_drv_stopped(padapter) ? "True" : "False"
+			, rtw_is_surprise_removed(padapter) ? "True" : "False");
+		goto exit;
+	}
+
+	if (purb->status == 0) {
+
+		if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) {
+			RTW_INFO("%s()-%d: urb->actual_length:%u, MAX_RECVBUF_SZ:%u, RXDESC_SIZE:%u\n"
+				, __func__, __LINE__, purb->actual_length, MAX_RECVBUF_SZ, RXDESC_SIZE);
+			rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+		} else {
+			rtw_reset_continual_io_error(adapter_to_dvobj(padapter));
+
+			precvbuf->transfer_len = purb->actual_length;
+			skb_put(precvbuf->pskb, purb->actual_length);
+			skb_queue_tail(&precvpriv->rx_skb_queue, precvbuf->pskb);
+
+			#ifndef CONFIG_FIX_NR_BULKIN_BUFFER
+			if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1)
+			#endif
+				tasklet_schedule(&precvpriv->recv_tasklet);
+
+			precvbuf->pskb = NULL;
+			rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+		}
+	} else {
+
+		RTW_INFO("###=> usb_read_port_complete => urb.status(%d)\n", purb->status);
+
+		if (rtw_inc_and_chk_continual_io_error(adapter_to_dvobj(padapter)) == true)
+			rtw_set_surprise_removed(padapter);
+
+		switch (purb->status) {
+		case -EINVAL:
+		case -EPIPE:
+		case -ENODEV:
+		case -ESHUTDOWN:
+		case -ENOENT:
+			rtw_set_drv_stopped(padapter);
+			break;
+		case -EPROTO:
+		case -EILSEQ:
+		case -ETIME:
+		case -ECOMM:
+		case -EOVERFLOW:
+			#ifdef DBG_CONFIG_ERROR_DETECT
+			{
+				HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+				pHalData->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL;
+			}
+			#endif
+			rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+			break;
+		case -EINPROGRESS:
+			RTW_INFO("ERROR: URB IS IN PROGRESS!/n");
+			break;
+		default:
+			break;
+		}
+	}
+
+exit:
+	return;
+}
+
+u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
+{
+	int err;
+	unsigned int pipe;
+	u32 ret = _FAIL;
+	PURB purb = NULL;
+	struct recv_buf	*precvbuf = (struct recv_buf *)rmem;
+	_adapter		*adapter = pintfhdl->padapter;
+	struct dvobj_priv	*pdvobj = adapter_to_dvobj(adapter);
+	struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(pdvobj);
+	struct recv_priv	*precvpriv = &adapter->recvpriv;
+	struct usb_device	*pusbd = pdvobj->pusbdev;
+
+
+	if (RTW_CANNOT_RX(adapter) || (precvbuf == NULL)) {
+		goto exit;
+	}
+
+	usb_init_recvbuf(adapter, precvbuf);
+
+	if (precvbuf->pskb == NULL) {
+		SIZE_PTR tmpaddr = 0;
+		SIZE_PTR alignment = 0;
+
+		precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
+		if (NULL != precvbuf->pskb)
+			goto recv_buf_hook;
+
+		#ifndef CONFIG_FIX_NR_BULKIN_BUFFER
+		precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
+		#endif
+
+		if (precvbuf->pskb == NULL) {
+			if (0)
+				RTW_INFO("usb_read_port() enqueue precvbuf=%p\n", precvbuf);
+			/* enqueue precvbuf and wait for free skb */
+			rtw_enqueue_recvbuf(precvbuf, &precvpriv->recv_buf_pending_queue);
+			goto exit;
+		}
+
+		tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
+		alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
+		skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
+	}
+
+recv_buf_hook:
+	precvbuf->phead = precvbuf->pskb->head;
+	precvbuf->pdata = precvbuf->pskb->data;
+	precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
+	precvbuf->pend = skb_end_pointer(precvbuf->pskb);
+	precvbuf->pbuf = precvbuf->pskb->data;
+
+	purb = precvbuf->purb;
+
+	/* translate DMA FIFO addr to pipehandle */
+	pipe = ffaddr2pipehdl(pdvobj, addr);
+
+	usb_fill_bulk_urb(purb, pusbd, pipe,
+		precvbuf->pbuf,
+		MAX_RECVBUF_SZ,
+		usb_read_port_complete,
+		precvbuf);
+
+	err = usb_submit_urb(purb, GFP_ATOMIC);
+	if (err && err != (-EPERM)) {
+		RTW_INFO("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n"
+			, err, purb->status);
+		goto exit;
+	}
+
+	ATOMIC_INC(&(precvpriv->rx_pending_cnt));
+	ret = _SUCCESS;
+
+exit:
+
+
+	return ret;
+}
+#endif /* CONFIG_USE_USB_BUFFER_ALLOC_RX */
+
+#ifdef CONFIG_USB_INTERRUPT_IN_PIPE
+void usb_read_interrupt_complete(struct urb *purb, struct pt_regs *regs)
+{
+	int	err;
+	_adapter	*padapter = (_adapter *)purb->context;
+
+	if (RTW_CANNOT_RX(padapter)) {
+		RTW_INFO("%s() RX Warning! bDriverStopped(%s) OR bSurpriseRemoved(%s)\n"
+			, __func__
+			, rtw_is_drv_stopped(padapter) ? "True" : "False"
+			, rtw_is_surprise_removed(padapter) ? "True" : "False");
+
+		return;
+	}
+
+	if (purb->status == 0) {/*SUCCESS*/
+		if (purb->actual_length > INTERRUPT_MSG_FORMAT_LEN)
+			RTW_INFO("usb_read_interrupt_complete: purb->actual_length > INTERRUPT_MSG_FORMAT_LEN(%d)\n", INTERRUPT_MSG_FORMAT_LEN);
+
+		rtw_hal_interrupt_handler(padapter, purb->actual_length, purb->transfer_buffer);
+
+		err = usb_submit_urb(purb, GFP_ATOMIC);
+		if ((err) && (err != (-EPERM)))
+			RTW_INFO("cannot submit interrupt in-token(err = 0x%08x),urb_status = %d\n", err, purb->status);
+	} else {
+		RTW_INFO("###=> usb_read_interrupt_complete => urb status(%d)\n", purb->status);
+
+		switch (purb->status) {
+		case -EINVAL:
+		case -EPIPE:
+		case -ENODEV:
+		case -ESHUTDOWN:
+		case -ENOENT:
+			rtw_set_drv_stopped(padapter);
+			break;
+		case -EPROTO:
+			break;
+		case -EINPROGRESS:
+			RTW_INFO("ERROR: URB IS IN PROGRESS!/n");
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+u32 usb_read_interrupt(struct intf_hdl *pintfhdl, u32 addr)
+{
+	int	err;
+	unsigned int pipe;
+	u32	ret = _SUCCESS;
+	_adapter			*adapter = pintfhdl->padapter;
+	struct dvobj_priv	*pdvobj = adapter_to_dvobj(adapter);
+	struct recv_priv	*precvpriv = &adapter->recvpriv;
+	struct usb_device	*pusbd = pdvobj->pusbdev;
+
+
+	if (RTW_CANNOT_RX(adapter)) {
+		return _FAIL;
+	}
+
+	/*translate DMA FIFO addr to pipehandle*/
+	pipe = ffaddr2pipehdl(pdvobj, addr);
+
+	usb_fill_int_urb(precvpriv->int_in_urb, pusbd, pipe,
+			precvpriv->int_in_buf,
+			INTERRUPT_MSG_FORMAT_LEN,
+			usb_read_interrupt_complete,
+			adapter,
+			1);
+
+	err = usb_submit_urb(precvpriv->int_in_urb, GFP_ATOMIC);
+	if ((err) && (err != (-EPERM))) {
+		RTW_INFO("cannot submit interrupt in-token(err = 0x%08x), urb_status = %d\n", err, precvpriv->int_in_urb->status);
+		ret = _FAIL;
+	}
+
+	return ret;
+}
+#endif /* CONFIG_USB_INTERRUPT_IN_PIPE */
diff --git a/drivers/staging/rtl8188eu/os_dep/wifi_regd.c b/drivers/staging/rtl8188eu/os_dep/wifi_regd.c
new file mode 100644
index 000000000000..24b6799cd1d6
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/wifi_regd.c
@@ -0,0 +1,354 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ *****************************************************************************/
+
+#include <drv_types.h>
+
+#ifdef CONFIG_IOCTL_CFG80211
+
+#include <rtw_wifi_regd.h>
+
+static struct country_code_to_enum_rd allCountries[] = {
+	{COUNTRY_CODE_USER, "RD"},
+};
+
+/*
+ * REG_RULE(freq start, freq end, bandwidth, max gain, eirp, reg_flags)
+ */
+
+/*
+ *Only these channels all allow active
+ *scan on all world regulatory domains
+ */
+
+/* 2G chan 01 - chan 11 */
+#define RTW_2GHZ_CH01_11	\
+	REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
+
+/*
+ *We enable active scan on these a case
+ *by case basis by regulatory domain
+ */
+
+/* 2G chan 12 - chan 13, PASSIV SCAN */
+#define RTW_2GHZ_CH12_13	\
+	REG_RULE(2467-10, 2472+10, 40, 0, 20,	\
+		 NL80211_RRF_PASSIVE_SCAN)
+
+/* 2G chan 14, PASSIVS SCAN, NO OFDM (B only) */
+#define RTW_2GHZ_CH14	\
+	REG_RULE(2484-10, 2484+10, 40, 0, 20,	\
+		 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
+
+/* 5G chan 36 - chan 64 */
+#define RTW_5GHZ_5150_5350	\
+	REG_RULE(5150-10, 5350+10, 40, 0, 30,	\
+		 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+
+/* 5G chan 100 - chan 165 */
+#define RTW_5GHZ_5470_5850	\
+	REG_RULE(5470-10, 5850+10, 40, 0, 30, \
+		 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+
+/* 5G chan 149 - chan 165 */
+#define RTW_5GHZ_5725_5850	\
+	REG_RULE(5725-10, 5850+10, 40, 0, 30, \
+		 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+
+/* 5G chan 36 - chan 165 */
+#define RTW_5GHZ_5150_5850	\
+	REG_RULE(5150-10, 5850+10, 40, 0, 30,	\
+		 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+
+static const struct ieee80211_regdomain rtw_regdom_rd = {
+	.n_reg_rules = 3,
+	.alpha2 = "99",
+	.reg_rules = {
+		RTW_2GHZ_CH01_11,
+		RTW_2GHZ_CH12_13,
+		RTW_5GHZ_5150_5850,
+	}
+};
+
+static const struct ieee80211_regdomain rtw_regdom_11 = {
+	.n_reg_rules = 1,
+	.alpha2 = "99",
+	.reg_rules = {
+		RTW_2GHZ_CH01_11,
+	}
+};
+
+static const struct ieee80211_regdomain rtw_regdom_12_13 = {
+	.n_reg_rules = 2,
+	.alpha2 = "99",
+	.reg_rules = {
+		RTW_2GHZ_CH01_11,
+		RTW_2GHZ_CH12_13,
+	}
+};
+
+static const struct ieee80211_regdomain rtw_regdom_no_midband = {
+	.n_reg_rules = 3,
+	.alpha2 = "99",
+	.reg_rules = {
+		RTW_2GHZ_CH01_11,
+		RTW_5GHZ_5150_5350,
+		RTW_5GHZ_5725_5850,
+	}
+};
+
+static const struct ieee80211_regdomain rtw_regdom_60_64 = {
+	.n_reg_rules = 3,
+	.alpha2 = "99",
+	.reg_rules = {
+		RTW_2GHZ_CH01_11,
+		RTW_2GHZ_CH12_13,
+		RTW_5GHZ_5725_5850,
+	}
+};
+
+static const struct ieee80211_regdomain rtw_regdom_14_60_64 = {
+	.n_reg_rules = 4,
+	.alpha2 = "99",
+	.reg_rules = {
+		RTW_2GHZ_CH01_11,
+		RTW_2GHZ_CH12_13,
+		RTW_2GHZ_CH14,
+		RTW_5GHZ_5725_5850,
+	}
+};
+
+static const struct ieee80211_regdomain rtw_regdom_14 = {
+	.n_reg_rules = 3,
+	.alpha2 = "99",
+	.reg_rules = {
+		RTW_2GHZ_CH01_11,
+		RTW_2GHZ_CH12_13,
+		RTW_2GHZ_CH14,
+	}
+};
+
+static bool _rtw_is_radar_freq(u16 center_freq)
+{
+	return center_freq >= 5260 && center_freq <= 5700;
+}
+
+/*
+ * Always apply Radar/DFS rules on
+ * freq range 5260 MHz - 5700 MHz
+ */
+static void _rtw_reg_apply_radar_flags(struct wiphy *wiphy)
+{
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	unsigned int i;
+
+	if (!wiphy->bands[NL80211_BAND_5GHZ])
+		return;
+
+	sband = wiphy->bands[NL80211_BAND_5GHZ];
+
+	for (i = 0; i < sband->n_channels; i++) {
+		ch = &sband->channels[i];
+		if (!_rtw_is_radar_freq(ch->center_freq))
+			continue;
+#ifdef CONFIG_DFS
+		if (!(ch->flags & IEEE80211_CHAN_DISABLED)
+			#if defined(CONFIG_DFS_MASTER)
+			&& rtw_odm_dfs_domain_unknown(wiphy_to_adapter(wiphy))
+			#endif
+		) {
+			ch->flags |= IEEE80211_CHAN_RADAR;
+			#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
+			ch->flags |= (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN);
+			#else
+			ch->flags |= IEEE80211_CHAN_NO_IR;
+			#endif
+		}
+#endif /* CONFIG_DFS */
+	}
+}
+
+static void _rtw_reg_apply_flags(struct wiphy *wiphy)
+{
+	_adapter *padapter = wiphy_to_adapter(wiphy);
+	u8 channel_plan = padapter->mlmepriv.ChannelPlan;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	RT_CHANNEL_INFO *channel_set = pmlmeext->channel_set;
+	u8 max_chan_nums = pmlmeext->max_chan_nums;
+
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	unsigned int i, j;
+	u16 channel;
+	u32 freq;
+
+	/* all channels disable */
+	for (i = 0; i < NUM_NL80211_BANDS; i++) {
+		sband = wiphy->bands[i];
+
+		if (sband) {
+			for (j = 0; j < sband->n_channels; j++) {
+				ch = &sband->channels[j];
+
+				if (ch)
+					ch->flags = IEEE80211_CHAN_DISABLED;
+			}
+		}
+	}
+
+	/* channels apply by channel plans. */
+	for (i = 0; i < max_chan_nums; i++) {
+		channel = channel_set[i].ChannelNum;
+		freq = rtw_ch2freq(channel);
+
+		ch = ieee80211_get_channel(wiphy, freq);
+		if (ch) {
+			if (channel_set[i].ScanType == SCAN_PASSIVE
+				#if defined(CONFIG_DFS_MASTER)
+				&& rtw_odm_dfs_domain_unknown(wiphy_to_adapter(wiphy))
+				#endif
+			) {
+				#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
+				ch->flags = (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN);
+				#else
+				ch->flags = IEEE80211_CHAN_NO_IR;
+				#endif
+			} else
+				ch->flags = 0;
+		}
+	}
+}
+
+static void _rtw_reg_apply_world_flags(struct wiphy *wiphy,
+				       enum nl80211_reg_initiator initiator,
+				       struct rtw_regulatory *reg)
+{
+	/* _rtw_reg_apply_beaconing_flags(wiphy, initiator); */
+	/* _rtw_reg_apply_active_scan_flags(wiphy, initiator); */
+	return;
+}
+
+static int _rtw_reg_notifier_apply(struct wiphy *wiphy,
+				   struct regulatory_request *request,
+				   struct rtw_regulatory *reg)
+{
+
+	/* Hard code flags */
+	_rtw_reg_apply_flags(wiphy);
+
+	/* We always apply this */
+	_rtw_reg_apply_radar_flags(wiphy);
+
+	switch (request->initiator) {
+	case NL80211_REGDOM_SET_BY_DRIVER:
+		RTW_INFO("%s: %s\n", __func__, "NL80211_REGDOM_SET_BY_DRIVER");
+		_rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
+					   reg);
+		break;
+	case NL80211_REGDOM_SET_BY_CORE:
+		RTW_INFO("%s: %s\n", __func__,
+			 "NL80211_REGDOM_SET_BY_CORE to DRV");
+		_rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
+					   reg);
+		break;
+	case NL80211_REGDOM_SET_BY_USER:
+		RTW_INFO("%s: %s\n", __func__,
+			 "NL80211_REGDOM_SET_BY_USER to DRV");
+		_rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER,
+					   reg);
+		break;
+	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+		RTW_INFO("%s: %s\n", __func__,
+			 "NL80211_REGDOM_SET_BY_COUNTRY_IE");
+		_rtw_reg_apply_world_flags(wiphy, request->initiator, reg);
+		break;
+	}
+
+	return 0;
+}
+
+static const struct ieee80211_regdomain *_rtw_regdomain_select(struct
+		rtw_regulatory
+		*reg)
+{
+	return &rtw_regdom_rd;
+}
+
+static void _rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
+{
+	struct rtw_regulatory *reg = NULL;
+
+	RTW_INFO("%s\n", __func__);
+
+	_rtw_reg_notifier_apply(wiphy, request, reg);
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
+static int rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
+#else
+static void rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
+#endif
+{
+	_rtw_reg_notifier(wiphy, request);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
+	return 0;
+#endif
+}
+
+void rtw_reg_notify_by_driver(_adapter *adapter)
+{
+	if ((adapter->rtw_wdev != NULL) && (adapter->rtw_wdev->wiphy)) {
+		struct regulatory_request request;
+		request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
+		rtw_reg_notifier(adapter->rtw_wdev->wiphy, &request);
+	}
+}
+
+static void _rtw_regd_init_wiphy(struct rtw_regulatory *reg, struct wiphy *wiphy)
+{
+	const struct ieee80211_regdomain *regd;
+
+	wiphy->reg_notifier = rtw_reg_notifier;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
+	wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+	wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY;
+	wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS;
+#else
+	wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
+	wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
+	wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
+#endif
+
+	regd = _rtw_regdomain_select(reg);
+	wiphy_apply_custom_regulatory(wiphy, regd);
+
+	/* Hard code flags */
+	_rtw_reg_apply_flags(wiphy);
+	_rtw_reg_apply_radar_flags(wiphy);
+	_rtw_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
+}
+
+static struct country_code_to_enum_rd *_rtw_regd_find_country(u16 countrycode)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
+		if (allCountries[i].countrycode == countrycode)
+			return &allCountries[i];
+	}
+	return NULL;
+}
+
+int rtw_regd_init(_adapter *padapter)
+{
+	struct wiphy *wiphy = padapter->rtw_wdev->wiphy;
+
+	_rtw_regd_init_wiphy(NULL, wiphy);
+
+	return 0;
+}
+#endif /* CONFIG_IOCTL_CFG80211 */
diff --git a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c
new file mode 100644
index 000000000000..d7690a39f0f4
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c
@@ -0,0 +1,489 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */
+
+#define _XMIT_OSDEP_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+
+#define DBG_DUMP_OS_QUEUE_CTL 0
+
+uint rtw_remainder_len(struct pkt_file *pfile)
+{
+	return pfile->buf_len - ((SIZE_PTR)(pfile->cur_addr) - (SIZE_PTR)(pfile->buf_start));
+}
+
+void _rtw_open_pktfile(_pkt *pktptr, struct pkt_file *pfile)
+{
+
+	pfile->pkt = pktptr;
+	pfile->cur_addr = pfile->buf_start = pktptr->data;
+	pfile->pkt_len = pfile->buf_len = pktptr->len;
+
+	pfile->cur_buffer = pfile->buf_start ;
+
+}
+
+uint _rtw_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen)
+{
+	uint	len = 0;
+
+
+	len =  rtw_remainder_len(pfile);
+	len = (rlen > len) ? len : rlen;
+
+	if (rmem)
+		skb_copy_bits(pfile->pkt, pfile->buf_len - pfile->pkt_len, rmem, len);
+
+	pfile->cur_addr += len;
+	pfile->pkt_len -= len;
+
+
+	return len;
+}
+
+sint rtw_endofpktfile(struct pkt_file *pfile)
+{
+
+	if (pfile->pkt_len == 0) {
+		return true;
+	}
+
+
+	return false;
+}
+
+void rtw_set_tx_chksum_offload(_pkt *pkt, struct pkt_attrib *pattrib)
+{
+
+#ifdef CONFIG_TCP_CSUM_OFFLOAD_TX
+	struct sk_buff *skb = (struct sk_buff *)pkt;
+	pattrib->hw_tcp_csum = 0;
+
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		if (skb_shinfo(skb)->nr_frags == 0) {
+			const struct iphdr *ip = ip_hdr(skb);
+			if (ip->protocol == IPPROTO_TCP) {
+				/* TCP checksum offload by HW */
+				RTW_INFO("CHECKSUM_PARTIAL TCP\n");
+				pattrib->hw_tcp_csum = 1;
+				/* skb_checksum_help(skb); */
+			} else if (ip->protocol == IPPROTO_UDP) {
+				/* RTW_INFO("CHECKSUM_PARTIAL UDP\n"); */
+				skb_checksum_help(skb);
+			} else {
+				RTW_INFO("%s-%d TCP CSUM offload Error!!\n", __func__, __LINE__);
+				WARN_ON(1);     /* we need a WARN() */
+			}
+		} else { /* IP fragmentation case */
+			RTW_INFO("%s-%d nr_frags != 0, using skb_checksum_help(skb);!!\n", __func__, __LINE__);
+			skb_checksum_help(skb);
+		}
+	}
+#endif
+
+}
+
+int rtw_os_xmit_resource_alloc(_adapter *padapter, struct xmit_buf *pxmitbuf, u32 alloc_sz, u8 flag)
+{
+	if (alloc_sz > 0) {
+#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX
+		struct dvobj_priv	*pdvobjpriv = adapter_to_dvobj(padapter);
+		struct usb_device	*pusbd = pdvobjpriv->pusbdev;
+
+		pxmitbuf->pallocated_buf = rtw_usb_buffer_alloc(pusbd, (size_t)alloc_sz, &pxmitbuf->dma_transfer_addr);
+		pxmitbuf->pbuf = pxmitbuf->pallocated_buf;
+		if (pxmitbuf->pallocated_buf == NULL)
+			return _FAIL;
+#else /* CONFIG_USE_USB_BUFFER_ALLOC_TX */
+
+		pxmitbuf->pallocated_buf = rtw_zmalloc(alloc_sz);
+		if (pxmitbuf->pallocated_buf == NULL)
+			return _FAIL;
+
+		pxmitbuf->pbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ);
+
+#endif /* CONFIG_USE_USB_BUFFER_ALLOC_TX */
+	}
+
+	if (flag) {
+		int i;
+		for (i = 0; i < 8; i++) {
+			pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
+			if (pxmitbuf->pxmit_urb[i] == NULL) {
+				RTW_INFO("pxmitbuf->pxmit_urb[i]==NULL");
+				return _FAIL;
+			}
+		}
+	}
+	return _SUCCESS;
+}
+
+void rtw_os_xmit_resource_free(_adapter *padapter, struct xmit_buf *pxmitbuf, u32 free_sz, u8 flag)
+{
+	if (flag) {
+		int i;
+
+		for (i = 0; i < 8; i++) {
+			if (pxmitbuf->pxmit_urb[i]) {
+				/* usb_kill_urb(pxmitbuf->pxmit_urb[i]); */
+				usb_free_urb(pxmitbuf->pxmit_urb[i]);
+			}
+		}
+	}
+
+	if (free_sz > 0) {
+#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX
+		struct dvobj_priv	*pdvobjpriv = adapter_to_dvobj(padapter);
+		struct usb_device	*pusbd = pdvobjpriv->pusbdev;
+
+		rtw_usb_buffer_free(pusbd, (size_t)free_sz, pxmitbuf->pallocated_buf, pxmitbuf->dma_transfer_addr);
+		pxmitbuf->pallocated_buf =  NULL;
+		pxmitbuf->dma_transfer_addr = 0;
+#else	/* CONFIG_USE_USB_BUFFER_ALLOC_TX */
+		if (pxmitbuf->pallocated_buf)
+			rtw_mfree(pxmitbuf->pallocated_buf, free_sz);
+#endif /* CONFIG_USE_USB_BUFFER_ALLOC_TX */
+	}
+}
+
+void dump_os_queue(void *sel, _adapter *padapter)
+{
+	struct net_device *ndev = padapter->pnetdev;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		RTW_PRINT_SEL(sel, "os_queue[%d]:%s\n"
+			, i, __netif_subqueue_stopped(ndev, i) ? "stopped" : "waked");
+	}
+#else
+	RTW_PRINT_SEL(sel, "os_queue:%s\n"
+		      , netif_queue_stopped(ndev) ? "stopped" : "waked");
+#endif
+}
+
+#define WMM_XMIT_THRESHOLD	(NR_XMITFRAME*2/5)
+
+static inline bool rtw_os_need_wake_queue(_adapter *padapter, u16 qidx)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+	if (padapter->registrypriv.wifi_spec) {
+		if (pxmitpriv->hwxmits[qidx].accnt < WMM_XMIT_THRESHOLD)
+			return true;
+	} else {
+#ifdef CONFIG_MCC_MODE
+		if (MCC_EN(padapter)) {
+			if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)
+			    && MCC_STOP(padapter))
+				return false;
+		}
+#endif /* CONFIG_MCC_MODE */
+		return true;
+	}
+	return false;
+#else
+#ifdef CONFIG_MCC_MODE
+	if (MCC_EN(padapter)) {
+		if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)
+		    && MCC_STOP(padapter))
+			return false;
+	}
+#endif /* CONFIG_MCC_MODE */
+	return true;
+#endif
+}
+
+static inline bool rtw_os_need_stop_queue(_adapter *padapter, u16 qidx)
+{
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	if (padapter->registrypriv.wifi_spec) {
+		/* No free space for Tx, tx_worker is too slow */
+		if (pxmitpriv->hwxmits[qidx].accnt > WMM_XMIT_THRESHOLD)
+			return true;
+	} else {
+		if (pxmitpriv->free_xmitframe_cnt <= 4)
+			return true;
+	}
+#else
+	if (pxmitpriv->free_xmitframe_cnt <= 4)
+		return true;
+#endif
+	return false;
+}
+
+void rtw_os_pkt_complete(_adapter *padapter, _pkt *pkt)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	u16	qidx;
+
+	qidx = skb_get_queue_mapping(pkt);
+	if (rtw_os_need_wake_queue(padapter, qidx)) {
+		if (DBG_DUMP_OS_QUEUE_CTL)
+			RTW_INFO(FUNC_ADPT_FMT": netif_wake_subqueue[%d]\n", FUNC_ADPT_ARG(padapter), qidx);
+		netif_wake_subqueue(padapter->pnetdev, qidx);
+	}
+#else
+	if (rtw_os_need_wake_queue(padapter, 0)) {
+		if (DBG_DUMP_OS_QUEUE_CTL)
+			RTW_INFO(FUNC_ADPT_FMT": netif_wake_queue\n", FUNC_ADPT_ARG(padapter));
+		netif_wake_queue(padapter->pnetdev);
+	}
+#endif
+
+	rtw_skb_free(pkt);
+}
+
+void rtw_os_xmit_complete(_adapter *padapter, struct xmit_frame *pxframe)
+{
+	if (pxframe->pkt)
+		rtw_os_pkt_complete(padapter, pxframe->pkt);
+
+	pxframe->pkt = NULL;
+}
+
+void rtw_os_xmit_schedule(_adapter *padapter)
+{
+	unsigned long  irqL;
+	struct xmit_priv *pxmitpriv;
+
+	if (!padapter)
+		return;
+
+	pxmitpriv = &padapter->xmitpriv;
+
+	_enter_critical_bh(&pxmitpriv->lock, &irqL);
+
+	if (rtw_txframes_pending(padapter))
+		tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
+
+	_exit_critical_bh(&pxmitpriv->lock, &irqL);
+}
+
+static bool rtw_check_xmit_resource(_adapter *padapter, _pkt *pkt)
+{
+	bool busy = false;
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	u16	qidx;
+
+	qidx = skb_get_queue_mapping(pkt);
+	if (rtw_os_need_stop_queue(padapter, qidx)) {
+		if (DBG_DUMP_OS_QUEUE_CTL)
+			RTW_INFO(FUNC_ADPT_FMT": netif_stop_subqueue[%d]\n", FUNC_ADPT_ARG(padapter), qidx);
+		netif_stop_subqueue(padapter->pnetdev, qidx);
+		busy = true;
+	}
+#else
+	if (rtw_os_need_stop_queue(padapter, 0)) {
+		if (DBG_DUMP_OS_QUEUE_CTL)
+			RTW_INFO(FUNC_ADPT_FMT": netif_stop_queue\n", FUNC_ADPT_ARG(padapter));
+		rtw_netif_stop_queue(padapter->pnetdev);
+		busy = true;
+	}
+#endif
+	return busy;
+}
+
+void rtw_os_wake_queue_at_free_stainfo(_adapter *padapter, int *qcnt_freed)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		if (qcnt_freed[i] == 0)
+			continue;
+
+		if (rtw_os_need_wake_queue(padapter, i)) {
+			if (DBG_DUMP_OS_QUEUE_CTL)
+				RTW_INFO(FUNC_ADPT_FMT": netif_wake_subqueue[%d]\n", FUNC_ADPT_ARG(padapter), i);
+			netif_wake_subqueue(padapter->pnetdev, i);
+		}
+	}
+#else
+	if (qcnt_freed[0] || qcnt_freed[1] || qcnt_freed[2] || qcnt_freed[3]) {
+		if (rtw_os_need_wake_queue(padapter, 0)) {
+			if (DBG_DUMP_OS_QUEUE_CTL)
+				RTW_INFO(FUNC_ADPT_FMT": netif_wake_queue\n", FUNC_ADPT_ARG(padapter));
+			netif_wake_queue(padapter->pnetdev);
+		}
+	}
+#endif
+}
+
+#ifdef CONFIG_TX_MCAST2UNI
+static int rtw_mlcst2unicst(_adapter *padapter, struct sk_buff *skb)
+{
+	struct	sta_priv *pstapriv = &padapter->stapriv;
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+	unsigned long	irqL;
+	_list	*phead, *plist;
+	struct sk_buff *newskb;
+	struct sta_info *psta = NULL;
+	u8 chk_alive_num = 0;
+	char chk_alive_list[NUM_STA];
+	u8 bc_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	u8 null_addr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+	int i;
+	s32	res;
+
+	DBG_COUNTER(padapter->tx_logs.os_tx_m2u);
+
+	_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+	phead = &pstapriv->asoc_list;
+	plist = get_next(phead);
+
+	/* free sta asoc_queue */
+	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->state & _FW_LINKED)) {
+			DBG_COUNTER(padapter->tx_logs.os_tx_m2u_ignore_fw_linked);
+			continue;
+		}
+
+		/* avoid come from STA1 and send back STA1 */
+		if (!memcmp(psta->hwaddr, &skb->data[6], 6)
+			|| !memcmp(psta->hwaddr, null_addr, 6)
+			|| !memcmp(psta->hwaddr, bc_addr, 6)
+		) {
+			DBG_COUNTER(padapter->tx_logs.os_tx_m2u_ignore_self);
+			continue;
+		}
+
+		DBG_COUNTER(padapter->tx_logs.os_tx_m2u_entry);
+
+		newskb = rtw_skb_copy(skb);
+
+		if (newskb) {
+			memcpy(newskb->data, psta->hwaddr, 6);
+			res = rtw_xmit(padapter, &newskb);
+			if (res < 0) {
+				DBG_COUNTER(padapter->tx_logs.os_tx_m2u_entry_err_xmit);
+				RTW_INFO("%s()-%d: rtw_xmit() return error! res=%d\n", __func__, __LINE__, res);
+				pxmitpriv->tx_drop++;
+				rtw_skb_free(newskb);
+			}
+		} else {
+			DBG_COUNTER(padapter->tx_logs.os_tx_m2u_entry_err_skb);
+			RTW_INFO("%s-%d: rtw_skb_copy() failed!\n", __func__, __LINE__);
+			pxmitpriv->tx_drop++;
+			/* rtw_skb_free(skb); */
+			return false;	/* Caller shall tx this multicast frame via normal way. */
+		}
+	}
+
+	rtw_skb_free(skb);
+	return true;
+}
+#endif /* CONFIG_TX_MCAST2UNI */
+
+
+int _rtw_xmit_entry(_pkt *pkt, _nic_hdl pnetdev)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+#ifdef CONFIG_TX_MCAST2UNI
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+#endif /* CONFIG_TX_MCAST2UNI	 */
+	s32 res = 0;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+	u16 queue;
+#endif
+
+
+	if (padapter->registrypriv.mp_mode) {
+		RTW_INFO("MP_TX_DROP_OS_FRAME\n");
+		goto drop_packet;
+	}
+	DBG_COUNTER(padapter->tx_logs.os_tx);
+
+	if (rtw_if_up(padapter) == false) {
+		DBG_COUNTER(padapter->tx_logs.os_tx_err_up);
+		#ifdef DBG_TX_DROP_FRAME
+		RTW_INFO("DBG_TX_DROP_FRAME %s if_up fail\n", __func__);
+		#endif
+		goto drop_packet;
+	}
+
+	rtw_check_xmit_resource(padapter, pkt);
+
+#ifdef CONFIG_TX_MCAST2UNI
+	if (!rtw_mc2u_disable
+		&& check_fwstate(pmlmepriv, WIFI_AP_STATE)
+		&& (IP_MCAST_MAC(pkt->data)
+			|| ICMPV6_MCAST_MAC(pkt->data)
+			#ifdef CONFIG_TX_BCAST2UNI
+			|| is_broadcast_mac_addr(pkt->data)
+			#endif
+			)
+		&& (padapter->registrypriv.wifi_spec == 0)
+	) {
+		if (pxmitpriv->free_xmitframe_cnt > (NR_XMITFRAME / 4)) {
+			res = rtw_mlcst2unicst(padapter, pkt);
+			if (res)
+				goto exit;
+		} else {
+			/* RTW_INFO("Stop M2U(%d, %d)! ", pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmitbuf_cnt); */
+			/* RTW_INFO("!m2u ); */
+			DBG_COUNTER(padapter->tx_logs.os_tx_m2u_stop);
+		}
+	}
+#endif /* CONFIG_TX_MCAST2UNI	 */
+
+	res = rtw_xmit(padapter, &pkt);
+	if (res < 0) {
+		#ifdef DBG_TX_DROP_FRAME
+		RTW_INFO("DBG_TX_DROP_FRAME %s rtw_xmit fail\n", __func__);
+		#endif
+		goto drop_packet;
+	}
+
+	goto exit;
+
+drop_packet:
+	pxmitpriv->tx_drop++;
+	rtw_os_pkt_complete(padapter, pkt);
+
+exit:
+
+
+	return 0;
+}
+
+int rtw_xmit_entry(_pkt *pkt, _nic_hdl pnetdev)
+{
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	int ret = 0;
+
+	if (pkt) {
+		if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE)) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24))
+			rtw_monitor_xmit_entry((struct sk_buff *)pkt, pnetdev);
+#endif
+		}
+		else {
+			rtw_mstat_update(MSTAT_TYPE_SKB, MSTAT_ALLOC_SUCCESS, pkt->truesize);
+			ret = _rtw_xmit_entry(pkt, pnetdev);
+		}
+
+	}
+
+	return ret;
+}
-- 
2.31.1


  parent reply	other threads:[~2021-07-23  0:43 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-23  0:42 [PATCH 0/7] staging: rtl8188eu: replace driver with better version Phillip Potter
2021-07-23  0:42 ` [PATCH 1/7] staging: rtl8188eu: remove existing staging driver Phillip Potter
2021-07-23  0:42 ` [PATCH 2/7] staging: rtl8188eu: introduce new core dir for RTL8188eu driver Phillip Potter
2021-07-23  0:42 ` [PATCH 3/7] staging: rtl8188eu: introduce new hal " Phillip Potter
2021-07-23  0:42 ` Phillip Potter [this message]
2021-07-23 17:33   ` [PATCH 4/7] staging: rtl8188eu: introduce new os_dep " kernel test robot
2021-07-23 17:33   ` [RFC PATCH] staging: rtl8188eu: fix duplicated inclusion kernel test robot
2021-07-23  0:42 ` [PATCH 5/7] staging: rtl8188eu: introduce new include dir for RTL8188eu driver Phillip Potter
2021-07-23  0:42 ` [PATCH 6/7] staging: rtl8188eu: introduce new supporting files " Phillip Potter
2021-07-23  7:29   ` Fabio Aiuto
2021-07-23 11:09   ` Greg KH
2021-07-23 11:19     ` Phillip Potter
2021-07-23  0:42 ` [PATCH 7/7] staging: rtl8188eu: attach newly imported driver to build system Phillip Potter
2021-07-23  7:19   ` kernel test robot
2021-07-23 14:33   ` kernel test robot
2021-07-23  1:56 ` [PATCH 0/7] staging: rtl8188eu: replace driver with better version Larry Finger
2021-07-23  7:29   ` Phillip Potter
2021-07-23 11:01 ` Greg KH
2021-07-23 11:05   ` Phillip Potter
2021-07-23 21:08 ` Larry Finger
2021-07-23 21:27   ` Phillip Potter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210723004214.912295-5-phil@philpotter.co.uk \
    --to=phil@philpotter.co.uk \
    --cc=Larry.Finger@lwfinger.net \
    --cc=dan.carpenter@oracle.com \
    --cc=fabioaiuto83@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-staging@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).