ioctl_cfg80211.c revision 38eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3
1b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger/******************************************************************************
2b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger *
3b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger *
5b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger * This program is free software; you can redistribute it and/or modify it
6b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger * under the terms of version 2 of the GNU General Public License as
7b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger * published by the Free Software Foundation.
8b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger *
9b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger * This program is distributed in the hope that it will be useful, but WITHOUT
10b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger * more details.
13b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger *
14b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger ******************************************************************************/
15b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define  _IOCTL_CFG80211_C_
16b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
17b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#include <osdep_service.h>
18b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#include <drv_types.h>
19b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#include <rtw_ioctl_set.h>
20b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#include <xmit_osdep.h>
21b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
22b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#include "ioctl_cfg80211.h"
23b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#include <linux/version.h>
24b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
25b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_MAX_MGMT_TX_CNT 8
26b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
27b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 65535	/* ms */
28b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_MAX_NUM_PMKIDS 4
29b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
30b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_CH_MAX_2G_CHANNEL               14	/* Max channel in 2G band */
31b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
32b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic const u32 rtw_cipher_suites[] = {
33b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	WLAN_CIPHER_SUITE_WEP40,
34b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	WLAN_CIPHER_SUITE_WEP104,
35b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	WLAN_CIPHER_SUITE_TKIP,
36b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	WLAN_CIPHER_SUITE_CCMP,
37b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
38b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
39b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RATETAB_ENT(_rate, _rateid, _flags) {			\
40b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.bitrate	= (_rate),				\
41b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.hw_value	= (_rateid),				\
42b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.flags		= (_flags),				\
43b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
44b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
45b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define CHAN2G(_channel, _freq, _flags) {			\
46b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.band			= IEEE80211_BAND_2GHZ,		\
47b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.center_freq		= (_freq),			\
48b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.hw_value		= (_channel),			\
49b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.flags			= (_flags),			\
50b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.max_antenna_gain	= 0,				\
51b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.max_power		= 30,				\
52b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
53b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
54b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define CHAN5G(_channel, _flags) {				\
55b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.band			= IEEE80211_BAND_5GHZ,		\
56b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.center_freq		= 5000 + (5 * (_channel)),	\
57b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.hw_value		= (_channel),			\
58b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.flags			= (_flags),			\
59b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.max_antenna_gain	= 0,				\
60b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.max_power		= 30,				\
61b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
62b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
63b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct ieee80211_rate rtw_rates[] = {
64b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(10, 0x1, 0),
65b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(20, 0x2, 0),
66b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(55, 0x4, 0),
67b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(110, 0x8, 0),
68b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(60, 0x10, 0),
69b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(90, 0x20, 0),
70b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(120, 0x40, 0),
71b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(180, 0x80, 0),
72b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(240, 0x100, 0),
73b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(360, 0x200, 0),
74b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(480, 0x400, 0),
75b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(540, 0x800, 0),
76b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
77b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
78b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define rtw_a_rates		(rtw_rates + 4)
79b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_A_RATES_NUM	8
80b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define rtw_g_rates		(rtw_rates + 0)
81b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_G_RATES_NUM	12
82b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
83b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_2G_CHANNELS_NUM 14
84b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_5G_CHANNELS_NUM 37
85b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
86b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct ieee80211_channel rtw_2ghz_channels[] = {
87b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(1, 2412, 0),
88b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(2, 2417, 0),
89b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(3, 2422, 0),
90b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(4, 2427, 0),
91b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(5, 2432, 0),
92b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(6, 2437, 0),
93b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(7, 2442, 0),
94b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(8, 2447, 0),
95b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(9, 2452, 0),
96b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(10, 2457, 0),
97b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(11, 2462, 0),
98b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(12, 2467, 0),
99b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(13, 2472, 0),
100b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(14, 2484, 0),
101b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
102b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
103b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct ieee80211_channel rtw_5ghz_a_channels[] = {
104b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(34, 0), CHAN5G(36, 0),
105b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(38, 0), CHAN5G(40, 0),
106b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(42, 0), CHAN5G(44, 0),
107b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(46, 0), CHAN5G(48, 0),
108b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(52, 0), CHAN5G(56, 0),
109b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(60, 0), CHAN5G(64, 0),
110b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(100, 0), CHAN5G(104, 0),
111b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(108, 0), CHAN5G(112, 0),
112b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(116, 0), CHAN5G(120, 0),
113b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(124, 0), CHAN5G(128, 0),
114b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(132, 0), CHAN5G(136, 0),
115b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(140, 0), CHAN5G(149, 0),
116b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(153, 0), CHAN5G(157, 0),
117b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(161, 0), CHAN5G(165, 0),
118b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(184, 0), CHAN5G(188, 0),
119b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(192, 0), CHAN5G(196, 0),
120b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(200, 0), CHAN5G(204, 0),
121b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(208, 0), CHAN5G(212, 0),
122b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(216, 0),
123b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
124b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
125b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_2g_channels_init(struct ieee80211_channel *channels)
126b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
127b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy((void *)channels, (void *)rtw_2ghz_channels,
128b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct ieee80211_channel) * RTW_2G_CHANNELS_NUM);
129b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
130b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
131b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_5g_channels_init(struct ieee80211_channel *channels)
132b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
133b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy((void *)channels, (void *)rtw_5ghz_a_channels,
134b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct ieee80211_channel) * RTW_5G_CHANNELS_NUM);
135b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
136b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
137b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_2g_rates_init(struct ieee80211_rate *rates)
138b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
139b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(rates, rtw_g_rates,
140b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM);
141b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
142b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
143b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_5g_rates_init(struct ieee80211_rate *rates)
144b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
145b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(rates, rtw_a_rates,
146b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM);
147b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
148b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
149b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct ieee80211_supported_band *
150b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerrtw_spt_band_alloc(enum ieee80211_band band)
151b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
152b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_supported_band *spt_band = NULL;
153b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int n_channels, n_bitrates;
154b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
155b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (band == IEEE80211_BAND_2GHZ) {
156b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		n_channels = RTW_2G_CHANNELS_NUM;
157b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		n_bitrates = RTW_G_RATES_NUM;
158b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else if (band == IEEE80211_BAND_5GHZ) {
159b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		n_channels = RTW_5G_CHANNELS_NUM;
160b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		n_bitrates = RTW_A_RATES_NUM;
161b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
162b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
163b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
164b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spt_band = kzalloc(sizeof(struct ieee80211_supported_band) +
165b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   sizeof(struct ieee80211_channel) * n_channels +
166b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   sizeof(struct ieee80211_rate) * n_bitrates,
167b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   GFP_KERNEL);
168b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!spt_band)
169b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
170b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
171b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spt_band->channels =
172b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		(struct ieee80211_channel *)(((u8 *) spt_band) +
173b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     sizeof(struct
174b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    ieee80211_supported_band));
175b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spt_band->bitrates =
176b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		(struct ieee80211_rate *)(((u8 *) spt_band->channels) +
177b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  sizeof(struct ieee80211_channel) *
178b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  n_channels);
179b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spt_band->band = band;
180b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spt_band->n_channels = n_channels;
181b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spt_band->n_bitrates = n_bitrates;
182b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
183b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (band == IEEE80211_BAND_2GHZ) {
184b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_2g_channels_init(spt_band->channels);
185b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_2g_rates_init(spt_band->bitrates);
186b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else if (band == IEEE80211_BAND_5GHZ) {
187b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_5g_channels_init(spt_band->channels);
188b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_5g_rates_init(spt_band->bitrates);
189b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
190b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
191b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* spt_band.ht_cap */
192b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
193b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
194b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return spt_band;
195b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
196b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
197b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic const struct ieee80211_txrx_stypes
198b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerrtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
199b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	[NL80211_IFTYPE_ADHOC] = {
200b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.tx = 0xffff,
201b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.rx = BIT(IEEE80211_STYPE_ACTION >> 4)
202b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	},
203b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	[NL80211_IFTYPE_STATION] = {
204b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.tx = 0xffff,
205b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
206b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
207b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	},
208b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	[NL80211_IFTYPE_AP] = {
209b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.tx = 0xffff,
210b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
211b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
212b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
213b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
214b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_AUTH >> 4) |
215b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
216b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_ACTION >> 4)
217b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	},
218b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	[NL80211_IFTYPE_AP_VLAN] = {
219b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* copy AP */
220b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.tx = 0xffff,
221b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
222b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
223b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
224b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
225b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_AUTH >> 4) |
226b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
227b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_ACTION >> 4)
228b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	},
229b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	[NL80211_IFTYPE_P2P_CLIENT] = {
230b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.tx = 0xffff,
231b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
232b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
233b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	},
234b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	[NL80211_IFTYPE_P2P_GO] = {
235b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.tx = 0xffff,
236b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
237b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
238b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
239b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
240b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_AUTH >> 4) |
241b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
242b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_ACTION >> 4)
243b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	},
244b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
245b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
246b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define MAX_BSSINFO_LEN 1000
247b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter,
248b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   struct wlan_network *pnetwork)
249b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
250b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
251b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_channel *notify_channel;
252b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cfg80211_bss *bss;
253b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* struct ieee80211_supported_band *band; */
254b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u16 channel;
255b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 freq;
256b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u64 notify_timestamp;
257b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u16 notify_capability;
258b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u16 notify_interval;
259b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 *notify_ie;
260b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	size_t notify_ielen;
261b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	s32 notify_signal;
262b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 buf[MAX_BSSINFO_LEN], *pbuf;
263f844717c6a5b30ed605e6fbfcab685c6d2e58592Jes Sorensen	size_t len;
264b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_hdr *pwlanhdr;
265b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *wdev = padapter->rtw_wdev;
266b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wiphy *wiphy = wdev->wiphy;
267b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
268b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
269b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* DBG_8723A("%s\n", __func__); */
270b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
271f844717c6a5b30ed605e6fbfcab685c6d2e58592Jes Sorensen	if (pnetwork->network.IELength > MAX_IE_SZ) {
272b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s IE Length too long > %d byte\n", __func__,
273f844717c6a5b30ed605e6fbfcab685c6d2e58592Jes Sorensen			  MAX_IE_SZ);
274b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
275b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
276b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
27737cb982c2685029e716bfeccf55ec244a6919a32Jes Sorensen	channel = pnetwork->network.DSConfig;
278b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (channel <= RTW_CH_MAX_2G_CHANNEL)
279b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
280b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_2GHZ);
281b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
282b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
283b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_5GHZ);
284b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
285b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	notify_channel = ieee80211_get_channel(wiphy, freq);
286b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
287b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	notify_timestamp = jiffies_to_msecs(jiffies) * 1000;	/* uSec */
288b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
289b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	notify_interval =
2909a7e35f1eabe4090f7f9943d51afe2a4b6086aaeJes Sorensen		get_unaligned_le16(
291b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			rtw_get_beacon_interval23a_from_ie(pnetwork->network.IEs));
292b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	notify_capability =
2936a235443be58fbdfebb02f536c6338ba82ab399aJes Sorensen		get_unaligned_le16(
294b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			rtw_get_capability23a_from_ie(pnetwork->network.IEs));
295b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
296b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	notify_ie = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
297b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	notify_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
298b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
299b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM:
300b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *  signal strength in mBm (100*dBm)
301b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 */
302b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, _FW_LINKED) &&
303b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    is_same_network23a(&pmlmepriv->cur_network.network,
304b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    &pnetwork->network)) {
305b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		notify_signal = 100 * translate_percentage_to_dbm(padapter->recvpriv.signal_strength);	/* dbm */
306b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
307b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		notify_signal = 100 * translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength);	/* dbm */
308b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
309b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pbuf = buf;
310b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
311b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwlanhdr = (struct ieee80211_hdr *)pbuf;
312b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3131daffaeecb4bf01c4a34fc2330c745ace5af3f60Jes Sorensen	pwlanhdr->seq_ctrl = 0;
314b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
315b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pnetwork->network.reserved == 1) {	/*  WIFI_BEACON */
31643c34be13047dd53e70bc4759ff314424db7036bJes Sorensen		eth_broadcast_addr(pwlanhdr->addr1);
317036cdd9cb34a10aabb80a97a41fb9dcfead7d113Jes Sorensen		pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
318036cdd9cb34a10aabb80a97a41fb9dcfead7d113Jes Sorensen						      IEEE80211_STYPE_BEACON);
319b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
320b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(pwlanhdr->addr1, myid(&padapter->eeprompriv), ETH_ALEN);
321036cdd9cb34a10aabb80a97a41fb9dcfead7d113Jes Sorensen		pwlanhdr->frame_control =
322036cdd9cb34a10aabb80a97a41fb9dcfead7d113Jes Sorensen			cpu_to_le16(IEEE80211_FTYPE_MGMT |
323036cdd9cb34a10aabb80a97a41fb9dcfead7d113Jes Sorensen				    IEEE80211_STYPE_PROBE_RESP);
324b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
325b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
326b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pwlanhdr->addr2, pnetwork->network.MacAddress, ETH_ALEN);
327b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pwlanhdr->addr3, pnetwork->network.MacAddress, ETH_ALEN);
328b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
329b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pbuf += sizeof(struct ieee80211_hdr_3addr);
330b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	len = sizeof(struct ieee80211_hdr_3addr);
331b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
332b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pbuf, pnetwork->network.IEs, pnetwork->network.IELength);
333b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	len += pnetwork->network.IELength;
334b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
335b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	bss = cfg80211_inform_bss_frame(wiphy, notify_channel,
336b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					(struct ieee80211_mgmt *)buf, len,
337b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					notify_signal, GFP_ATOMIC);
338b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
339b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (unlikely(!bss)) {
340b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("rtw_cfg80211_inform_bss error\n");
341b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
342b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
343b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
344b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	cfg80211_put_bss(wiphy, bss);
345b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
346b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
347b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
348b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
349b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
350b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter)
351b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
352b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
353b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wlan_network *cur_network = &pmlmepriv->cur_network;
354b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *pwdev = padapter->rtw_wdev;
355b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
356b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
357b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
358b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pwdev->iftype != NL80211_IFTYPE_STATION &&
359b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
360b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
361b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
362b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
363b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
364b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
36556828797acdb99d23b5e5e5c52e7d571d59b783fJes Sorensen	if (padapter->mlmepriv.to_roaming > 0) {
366b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct wiphy *wiphy = pwdev->wiphy;
367b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct ieee80211_channel *notify_channel;
368b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		u32 freq;
36937cb982c2685029e716bfeccf55ec244a6919a32Jes Sorensen		u16 channel = cur_network->network.DSConfig;
370b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
371b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (channel <= RTW_CH_MAX_2G_CHANNEL)
372b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			freq =
373b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    ieee80211_channel_to_frequency(channel,
374b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							   IEEE80211_BAND_2GHZ);
375b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		else
376b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			freq =
377b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    ieee80211_channel_to_frequency(channel,
378b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							   IEEE80211_BAND_5GHZ);
379b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
380b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		notify_channel = ieee80211_get_channel(wiphy, freq);
381b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
382b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s call cfg80211_roamed\n", __func__);
383b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		cfg80211_roamed(padapter->pnetdev, notify_channel,
384b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				cur_network->network.MacAddress,
385b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->assoc_req +
386b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				sizeof(struct ieee80211_hdr_3addr) + 2,
387b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->assoc_req_len -
388b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				sizeof(struct ieee80211_hdr_3addr) - 2,
389b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->assoc_rsp +
390b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				sizeof(struct ieee80211_hdr_3addr) + 6,
391b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->assoc_rsp_len -
392b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				sizeof(struct ieee80211_hdr_3addr) - 6,
393b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				GFP_ATOMIC);
394b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
395b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		cfg80211_connect_result(padapter->pnetdev,
396b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					cur_network->network.MacAddress,
397b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pmlmepriv->assoc_req +
398b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					sizeof(struct ieee80211_hdr_3addr) + 2,
399b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pmlmepriv->assoc_req_len -
400b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					sizeof(struct ieee80211_hdr_3addr) - 2,
401b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pmlmepriv->assoc_rsp +
402b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					sizeof(struct ieee80211_hdr_3addr) + 6,
403b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pmlmepriv->assoc_rsp_len -
404b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					sizeof(struct ieee80211_hdr_3addr) - 6,
405b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					WLAN_STATUS_SUCCESS, GFP_ATOMIC);
406b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
407b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
408b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
409b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter)
410b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
411b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
412b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *pwdev = padapter->rtw_wdev;
413b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
414b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
415b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
416b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pwdev->iftype != NL80211_IFTYPE_STATION &&
417b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
418b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
419b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
420b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
421b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
422b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
423b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!padapter->mlmepriv.not_indic_disco) {
424b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING)) {
425b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			cfg80211_connect_result(padapter->pnetdev, NULL, NULL,
426b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						0, NULL, 0,
427b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						WLAN_STATUS_UNSPECIFIED_FAILURE,
428b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						GFP_ATOMIC);
429b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		} else {
430b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			cfg80211_disconnected(padapter->pnetdev, 0, NULL,
431b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      0, GFP_ATOMIC);
432b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
433b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
434b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
435b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
436b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
43716b9632da2c071d74934447e266717787bec449bJes Sorensenstatic int set_pairwise_key(struct rtw_adapter *padapter, struct sta_info *psta)
438b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
439b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cmd_obj *ph2c;
440b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct set_stakey_parm *psetstakey_para;
441b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
44216b9632da2c071d74934447e266717787bec449bJes Sorensen	int res = _SUCCESS;
443b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
444b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
445b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ph2c == NULL) {
446b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		res = _FAIL;
447b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
448b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
449b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
450b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
451b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (psetstakey_para == NULL) {
452b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		kfree(ph2c);
453b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		res = _FAIL;
454b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
455b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
456b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
457b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
458b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
4597989bcf3e21683f413dd1488718166d3ff474bf3Jes Sorensen	psetstakey_para->algorithm = psta->dot118021XPrivacy;
460b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
461b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
462b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
463b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
464b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
465b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
466b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
467b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
468b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return res;
469b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
470b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
4717989bcf3e21683f413dd1488718166d3ff474bf3Jes Sorensenstatic int set_group_key(struct rtw_adapter *padapter, u8 *key, u32 alg,
4724e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen			 u8 keyid)
473b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
474b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 keylen;
475b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cmd_obj *pcmd;
476b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct setkey_parm *psetkeyparm;
477b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
478b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int res = _SUCCESS;
479b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
480b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
481b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
4824e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen	if (keyid >= 4) {
4834e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen		res = _FAIL;
4844e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen		goto exit;
4854e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen	}
4864e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen
487b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
488b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!pcmd) {
489b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		res = _FAIL;
490b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
491b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
492b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
493b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!psetkeyparm) {
494b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		kfree(pcmd);
495b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		res = _FAIL;
496b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
497b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
498b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
4994e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen	psetkeyparm->keyid = keyid;
500b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (is_wep_enc(alg))
5014e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen		padapter->mlmepriv.key_mask |= BIT(psetkeyparm->keyid);
502b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
503b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psetkeyparm->algorithm = alg;
504b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
505b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psetkeyparm->set_tx = 1;
506b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
507b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (alg) {
5089e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	case WLAN_CIPHER_SUITE_WEP40:
509b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		keylen = 5;
510b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
5119e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	case WLAN_CIPHER_SUITE_WEP104:
512b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		keylen = 13;
513b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
5149e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	case WLAN_CIPHER_SUITE_TKIP:
5159e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	case WLAN_CIPHER_SUITE_CCMP:
516b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
517b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		keylen = 16;
518b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
519b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
520b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(&psetkeyparm->key[0], key, keylen);
521b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
522b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->cmdcode = _SetKey_CMD_;
523b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->parmbuf = (u8 *) psetkeyparm;
524b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->cmdsz = (sizeof(struct setkey_parm));
525b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->rsp = NULL;
526b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->rspsz = 0;
527b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
528b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
529b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
530b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
531b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return res;
532b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
533b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
534e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensenstatic int set_wep_key(struct rtw_adapter *padapter, u8 *key, u16 keylen,
5354e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen		       u8 keyid)
536b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
5379e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	u32 alg;
538b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
539b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (keylen) {
540b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case 5:
5419e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		alg = WLAN_CIPHER_SUITE_WEP40;
542b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
543b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case 13:
5449e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		alg = WLAN_CIPHER_SUITE_WEP104;
545b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
546b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
5479e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		alg = 0;
548b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
549b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
550b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return set_group_key(padapter, key, alg, keyid);
551b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
552b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
553b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_ap_set_encryption(struct net_device *dev,
554b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  struct ieee_param *param,
555b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  u32 param_len)
556b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
557b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
558e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	u16 wep_key_len;
5594e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen	u8 wep_key_idx;
560b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_info *psta = NULL, *pbcmc_sta = NULL;
561b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(dev);
562b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
563b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
564b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_priv *pstapriv = &padapter->stapriv;
565b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
566b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
567b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
568b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param->u.crypt.err = 0;
569b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
570b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
571b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* sizeof(struct ieee_param) = 64 bytes; */
572b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (param_len !=  (u32) ((u8 *) param->u.crypt.key -
573b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	   (u8 *) param) + param->u.crypt.key_len) */
574b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) {
575b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
576b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
577b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
578b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
579b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (is_broadcast_ether_addr(param->sta_addr)) {
580b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (param->u.crypt.idx >= WEP_KEYS) {
581b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EINVAL;
582b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
583b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
584b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
585b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psta = rtw_get_stainfo23a(pstapriv, param->sta_addr);
586b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (!psta) {
587b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* ret = -EINVAL; */
588b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("rtw_set_encryption(), sta has already "
589b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  "been removed or never been added\n");
590b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
591b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
592b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
593b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
594b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
595b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* todo:clear default encryption keys */
596b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
597b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("clear default encryption keys, keyid =%d\n",
598b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  param->u.crypt.idx);
599b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
600b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
601b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
602b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
603b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
604b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("r871x_set_encryption, crypt.alg = WEP\n");
605b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
606b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_idx = param->u.crypt.idx;
607b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_len = param->u.crypt.key_len;
608b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
609b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("r871x_set_encryption, wep_key_idx =%d, len =%d\n",
610b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  wep_key_idx, wep_key_len);
611b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
612b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
613b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EINVAL;
614b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
615b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
616b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
617b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (wep_key_len > 0) {
618b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			wep_key_len = wep_key_len <= 5 ? 5 : 13;
619b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
620b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
621b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
622b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* wep default key has not been set, so use
623b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   this key index as default key. */
624b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
625b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->ndisencryptstatus =
626b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				Ndis802_11Encryption1Enabled;
6279e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen			psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
6289e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen			psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
629b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
630b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (wep_key_len == 13) {
6319e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
6329e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104;
633b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
634b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
635b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
636b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
637b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
638e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen		memcpy(&psecuritypriv->wep_key[wep_key_idx].key,
639b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       param->u.crypt.key, wep_key_len);
640b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
641e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen		psecuritypriv->wep_key[wep_key_idx].keylen = wep_key_len;
642b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
643b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		set_wep_key(padapter, param->u.crypt.key, wep_key_len,
644b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    wep_key_idx);
645b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
646b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
647b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
648b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
649b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
650b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) {	/*  group key */
651b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (param->u.crypt.set_tx == 0) {	/* group key */
652b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (strcmp(param->u.crypt.alg, "WEP") == 0) {
6539cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen				DBG_8723A("%s, set group_key, WEP\n", __func__);
654b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
655b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
656b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       dot118021XGrpKey[param->u.crypt.idx].
657b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       skey, param->u.crypt.key,
658b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       (param->u.crypt.key_len >
659b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					16 ? 16 : param->u.crypt.key_len));
660b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6619e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
662b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if (param->u.crypt.key_len == 13) {
663b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy =
6649e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen					    WLAN_CIPHER_SUITE_WEP104;
665b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
666b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
667b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
668b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s, set group_key, TKIP\n",
669b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__);
670b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6719e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_TKIP;
672b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
673b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
674b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       dot118021XGrpKey[param->u.crypt.idx].
675b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       skey, param->u.crypt.key,
676b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       (param->u.crypt.key_len >
677b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					16 ? 16 : param->u.crypt.key_len));
678b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
679b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
680b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* set mic key */
681b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
682b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       dot118021XGrptxmickey[param->u.crypt.
683b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							     idx].skey,
684b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       &param->u.crypt.key[16], 8);
685b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
686b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       dot118021XGrprxmickey[param->u.crypt.
687b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							     idx].skey,
688b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       &param->u.crypt.key[24], 8);
689b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6909216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen				psecuritypriv->busetkipkey = 1;
691b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
692b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
693b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s, set group_key, CCMP\n",
694b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__);
695b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6969e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_CCMP;
697b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
698b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
699b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       dot118021XGrpKey[param->u.crypt.idx].
700b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       skey, param->u.crypt.key,
701b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       (param->u.crypt.key_len >
702b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					16 ? 16 : param->u.crypt.key_len));
703b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			} else {
704b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s, set group_key, none\n",
705b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__);
706b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
707b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psecuritypriv->dot118021XGrpPrivacy =
7089e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				    0;
709b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
710b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
711b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
712b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7139216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen			psecuritypriv->binstallGrpkey = 1;
714b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
715b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->dot11PrivacyAlgrthm =
716b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psecuritypriv->dot118021XGrpPrivacy;
717b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
718b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			set_group_key(padapter, param->u.crypt.key,
719b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      psecuritypriv->dot118021XGrpPrivacy,
720b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      param->u.crypt.idx);
721b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
722b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
723b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pbcmc_sta) {
724b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pbcmc_sta->ieee8021x_blocked = false;
725b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* rx will use bmc_sta's dot118021XPrivacy */
726b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pbcmc_sta->dot118021XPrivacy =
727b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy;
728b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
729b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
730b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
731b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
732b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
733b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
734b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
735b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
736b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (psecuritypriv->dot11AuthAlgrthm ==
737b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    dot11AuthAlgrthm_8021X && psta) {	/*  psk/802_1x */
738b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
739b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (param->u.crypt.set_tx == 1) {
740b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* pairwise key */
741b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psta->dot118021x_UncstKey.skey,
742b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       param->u.crypt.key,
743b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       (param->u.crypt.key_len >
744b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					16 ? 16 : param->u.crypt.key_len));
745b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
746b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if (!strcmp(param->u.crypt.alg, "WEP")) {
747b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A("%s, set pairwise key, WEP\n",
748b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						  __func__);
749b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7509e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen					psta->dot118021XPrivacy = WLAN_CIPHER_SUITE_WEP40;
751b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					if (param->u.crypt.key_len == 13) {
752b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						psta->dot118021XPrivacy =
7539e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen							WLAN_CIPHER_SUITE_WEP104;
754b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					}
755b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				} else if (!strcmp(param->u.crypt.alg, "TKIP")) {
756b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A("%s, set pairwise key, "
757b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						  "TKIP\n", __func__);
758b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7599e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen					psta->dot118021XPrivacy = WLAN_CIPHER_SUITE_TKIP;
760b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
761b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
762b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* set mic key */
763b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psta->dot11tkiptxmickey.skey,
764b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       &param->u.crypt.key[16], 8);
765b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psta->dot11tkiprxmickey.skey,
766b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       &param->u.crypt.key[24], 8);
767b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7689216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen					psecuritypriv->busetkipkey = 1;
769b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
770b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				} else if (!strcmp(param->u.crypt.alg, "CCMP")) {
771b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
772b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A("%s, set pairwise key, "
773b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						  "CCMP\n", __func__);
774b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7759e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen					psta->dot118021XPrivacy = WLAN_CIPHER_SUITE_CCMP;
776b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				} else {
777b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A("%s, set pairwise key, "
778b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						  "none\n", __func__);
779b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7809e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen					psta->dot118021XPrivacy = 0;
781b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
782b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
783b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				set_pairwise_key(padapter, psta);
784b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
785b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psta->ieee8021x_blocked = false;
786b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
787b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psta->bpairwise_key_installed = true;
788b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			} else {	/* group key??? */
789b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if (!strcmp(param->u.crypt.alg, "WEP")) {
790b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psecuritypriv->
791b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrpKey[param->u.crypt.
792b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								idx].skey,
793b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       param->u.crypt.key,
794b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       (param->u.crypt.key_len >
795b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						16 ? 16 : param->u.crypt.
796b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						key_len));
797b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
798b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy =
7999e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen						WLAN_CIPHER_SUITE_WEP40;
800b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					if (param->u.crypt.key_len == 13) {
801b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						psecuritypriv->
802b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    dot118021XGrpPrivacy =
8039e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen							WLAN_CIPHER_SUITE_WEP104;
804b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					}
805b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				} else if (!strcmp(param->u.crypt.alg, "TKIP")) {
806b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy =
8079e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen					    WLAN_CIPHER_SUITE_TKIP;
808b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
809b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psecuritypriv->
810b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrpKey[param->u.crypt.
811b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								idx].skey,
812b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       param->u.crypt.key,
813b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       (param->u.crypt.key_len >
814b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						16 ? 16 : param->u.crypt.
815b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						key_len));
816b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
817b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* DEBUG_ERR("set key length :param->u"
818b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					   ".crypt.key_len =%d\n",
819b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					   param->u.crypt.key_len); */
820b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* set mic key */
821b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psecuritypriv->
822b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrptxmickey[param->u.
823b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								     crypt.idx].
824b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       skey, &param->u.crypt.key[16],
825b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       8);
826b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psecuritypriv->
827b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrprxmickey[param->u.
828b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								     crypt.idx].
829b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       skey, &param->u.crypt.key[24],
830b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       8);
831b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
8329216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen					psecuritypriv->busetkipkey = 1;
833b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
834b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				} else if (!strcmp(param->u.crypt.alg, "CCMP")) {
835b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy =
8369e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen						WLAN_CIPHER_SUITE_CCMP;
837b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
838b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psecuritypriv->
839b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrpKey[param->u.crypt.
840b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								idx].skey,
841b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       param->u.crypt.key,
842b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       (param->u.crypt.key_len >
843b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						16 ? 16 : param->u.crypt.
844b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						key_len));
845b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				} else {
846b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy =
8479e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen						0;
848b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
849b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
850b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psecuritypriv->dot118021XGrpKeyid =
851b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					param->u.crypt.idx;
852b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
8539216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen				psecuritypriv->binstallGrpkey = 1;
854b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
855b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psecuritypriv->dot11PrivacyAlgrthm =
856b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy;
857b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
858b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				set_group_key(padapter, param->u.crypt.key,
859b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      psecuritypriv->
860b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      dot118021XGrpPrivacy,
861b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      param->u.crypt.idx);
862b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
863b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
864b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if (pbcmc_sta) {
865b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* rx will use bmc_sta's
866b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					   dot118021XPrivacy */
867b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pbcmc_sta->ieee8021x_blocked = false;
868b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;
869b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
870b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
871b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
872b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
873b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
874b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
875b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
876b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
877b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
878b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
879b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif
880b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
881b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_encryption(struct net_device *dev,
882b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct ieee_param *param, u32 param_len)
883b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
884b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
885e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	u32 wep_key_idx;
886e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	u16 wep_key_len;
887b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(dev);
888b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
889b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
890b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
891b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
892b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
893b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param->u.crypt.err = 0;
894b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
895b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
896b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (param_len <
897b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    (u32) ((u8 *) param->u.crypt.key - (u8 *) param) +
898b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    param->u.crypt.key_len) {
899b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
900b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
901b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
902b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
903b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (is_broadcast_ether_addr(param->sta_addr)) {
904b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (param->u.crypt.idx >= WEP_KEYS) {
905b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EINVAL;
906b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
907b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
908b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
909b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
910b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
911b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
912b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
913b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (strcmp(param->u.crypt.alg, "WEP") == 0) {
914b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
915b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			 ("wpa_set_encryption, crypt.alg = WEP\n"));
916b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("wpa_set_encryption, crypt.alg = WEP\n");
917b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
918b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_idx = param->u.crypt.idx;
919b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_len = param->u.crypt.key_len;
920b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
921b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if ((wep_key_idx > WEP_KEYS) || (wep_key_len <= 0)) {
922b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EINVAL;
923b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
924b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
925b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
926b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
927b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* wep default key has not been set, so use this
928b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   key index as default key. */
929b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
930b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			wep_key_len = wep_key_len <= 5 ? 5 : 13;
931b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
932b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->ndisencryptstatus =
933b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				Ndis802_11Encryption1Enabled;
9349e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen			psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
9359e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen			psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
936b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
937b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (wep_key_len == 13) {
9389e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
9399e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104;
940b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
941b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
942b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
943b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
944b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
945e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen		memcpy(&psecuritypriv->wep_key[wep_key_idx].key,
946b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       param->u.crypt.key, wep_key_len);
947b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
948e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen		psecuritypriv->wep_key[wep_key_idx].keylen = wep_key_len;
949b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
950b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_set_key23a(padapter, psecuritypriv, wep_key_idx, 0);
951b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
952b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
953b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
954b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
955b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (padapter->securitypriv.dot11AuthAlgrthm ==
956b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    dot11AuthAlgrthm_8021X) {	/*  802_1x */
957b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct sta_info *psta, *pbcmc_sta;
958b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct sta_priv *pstapriv = &padapter->stapriv;
959b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
960b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (check_fwstate(pmlmepriv,
961b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  WIFI_STATION_STATE | WIFI_MP_STATE)) {
962b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* sta mode */
963b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psta = rtw_get_stainfo23a(pstapriv, get_bssid(pmlmepriv));
964b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (psta == NULL) {
965b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s, : Obtain Sta_info fail\n",
966b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__);
967b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			} else {
968b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* Jeff: don't disable ieee8021x_blocked
969b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   while clearing key */
970b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if (strcmp(param->u.crypt.alg, "none") != 0)
971b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psta->ieee8021x_blocked = false;
972b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
973b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if ((padapter->securitypriv.ndisencryptstatus ==
974b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     Ndis802_11Encryption2Enabled) ||
975b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    (padapter->securitypriv.ndisencryptstatus ==
976b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     Ndis802_11Encryption3Enabled)) {
977b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psta->dot118021XPrivacy =
978b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						padapter->securitypriv.
979b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						dot11PrivacyAlgrthm;
980b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
981b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
982b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if (param->u.crypt.set_tx == 1) {
983b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* pairwise key */
984b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A("%s, : param->u.crypt.set_tx"
985b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						  " == 1\n", __func__);
986b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
987b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psta->dot118021x_UncstKey.skey,
988b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       param->u.crypt.key,
989b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       (param->u.crypt.key_len >
990b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						16 ? 16 : param->u.crypt.
991b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						key_len));
992b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
993b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					if (strcmp(param->u.crypt.alg,
994b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   "TKIP") == 0) {
995b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						memcpy(psta->dot11tkiptxmickey.
996b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       skey,
997b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       &param->u.crypt.key[16],
998b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       8);
999b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						memcpy(psta->dot11tkiprxmickey.
1000b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       skey,
1001b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       &param->u.crypt.key[24],
1002b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       8);
1003b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1004b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						padapter->securitypriv.
10059216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen							busetkipkey = 0;
1006b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					}
1007b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A(" ~~~~set sta key:unicastkey\n");
1008b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1009b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					rtw_setstakey_cmd23a(padapter,
1010b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							  (unsigned char *)psta,
1011b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							  true);
1012b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				} else {	/* group key */
1013b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(padapter->securitypriv.
1014b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrpKey[param->u.crypt.
1015b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								idx].skey,
1016b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       param->u.crypt.key,
1017b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       (param->u.crypt.key_len >
1018b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						16 ? 16 : param->u.crypt.
1019b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						key_len));
1020b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(padapter->securitypriv.
1021b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrptxmickey[param->u.
1022b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								     crypt.idx].
1023b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       skey, &param->u.crypt.key[16],
1024b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       8);
1025b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(padapter->securitypriv.
1026b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrprxmickey[param->u.
1027b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								     crypt.idx].
1028b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       skey, &param->u.crypt.key[24],
1029b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       8);
1030b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					padapter->securitypriv.binstallGrpkey =
10319216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen						1;
1032b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* DEBUG_ERR((" param->u.crypt.key_len"
1033b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					   "=%d\n", param->u.crypt.key_len)); */
1034b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A
1035b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					    (" ~~~~set sta key:groupkey\n");
1036b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1037b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					padapter->securitypriv.
1038b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					    dot118021XGrpKeyid =
1039b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						param->u.crypt.idx;
1040b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1041b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					rtw_set_key23a(padapter,
1042b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    &padapter->securitypriv,
1043b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    param->u.crypt.idx, 1);
1044b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
1045b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
1046b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1047b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
1048b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pbcmc_sta) {
1049b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* Jeff: don't disable ieee8021x_blocked
1050b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   while clearing key */
1051b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if (strcmp(param->u.crypt.alg, "none") != 0)
1052b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pbcmc_sta->ieee8021x_blocked = false;
1053b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1054b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if ((padapter->securitypriv.ndisencryptstatus ==
1055b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     Ndis802_11Encryption2Enabled) ||
1056b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    (padapter->securitypriv.ndisencryptstatus ==
1057b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     Ndis802_11Encryption3Enabled)) {
1058b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pbcmc_sta->dot118021XPrivacy =
1059b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					    padapter->securitypriv.
1060b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					    dot11PrivacyAlgrthm;
1061b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
1062b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
1063b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		} else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {	/* adhoc mode */
1064b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1065b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1066b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1067b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
1068b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1069b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ret =%d\n", __func__, ret);
1070b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1071b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1072b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1073b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1074b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1075b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1076b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
1077b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				u8 key_index, bool pairwise,
1078b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				const u8 *mac_addr, struct key_params *params)
1079b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1080b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	char *alg_name;
1081b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 param_len;
10826f1c59bf2c00eeba0f9ad9ce176cce731de1a8e5Jes Sorensen	struct ieee_param *param;
1083b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1084b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
1085b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1086b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1087b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1088a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): adding key for %pM\n", __func__, ndev->name,
1089b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  mac_addr);
1090b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("cipher = 0x%x\n", params->cipher);
1091b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("key_len = 0x%x\n", params->key_len);
1092b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("seq_len = 0x%x\n", params->seq_len);
1093b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("key_index =%d\n", key_index);
1094b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("pairwise =%d\n", pairwise);
1095b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1096b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param_len = sizeof(struct ieee_param) + params->key_len;
1097b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param = kzalloc(param_len, GFP_KERNEL);
10986f1c59bf2c00eeba0f9ad9ce176cce731de1a8e5Jes Sorensen	if (!param)
10996f1c59bf2c00eeba0f9ad9ce176cce731de1a8e5Jes Sorensen		return -ENOMEM;
1100b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1101b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param->cmd = IEEE_CMD_SET_ENCRYPTION;
110243c34be13047dd53e70bc4759ff314424db7036bJes Sorensen	eth_broadcast_addr(param->sta_addr);
1103b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1104b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (params->cipher) {
1105b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case IW_AUTH_CIPHER_NONE:
1106b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* todo: remove key */
1107b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* remove = 1; */
1108b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		alg_name = "none";
1109b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1110b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_WEP40:
1111b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_WEP104:
1112b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		alg_name = "WEP";
1113b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1114b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_TKIP:
1115b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		alg_name = "TKIP";
1116b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1117b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_CCMP:
1118b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		alg_name = "CCMP";
1119b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1120b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1121b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
1122b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOTSUPP;
1123b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto addkey_end;
1124b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1125b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1126b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1127b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1128b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
1129b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		param->u.crypt.set_tx = 0;	/* for wpa/wpa2 group key */
1130b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
1131b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		param->u.crypt.set_tx = 1;	/* for wpa/wpa2 pairwise key */
1132b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1133b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1134b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* param->u.crypt.idx = key_index - 1; */
1135b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param->u.crypt.idx = key_index;
1136b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1137b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (params->seq_len && params->seq) {
1138b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(param->u.crypt.seq, params->seq, params->seq_len);
1139b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1140b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1141b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (params->key_len && params->key) {
1142b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		param->u.crypt.key_len = params->key_len;
1143b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(param->u.crypt.key, params->key, params->key_len);
1144b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1145b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1146b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1147b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_cfg80211_set_encryption(ndev, param, param_len);
1148b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1149b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
1150b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (mac_addr)
1151b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			memcpy(param->sta_addr, (void *)mac_addr, ETH_ALEN);
1152b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1153b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_cfg80211_ap_set_encryption(ndev, param, param_len);
1154b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif
1155b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
1156b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("error! fw_state = 0x%x, iftype =%d\n",
1157b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  pmlmepriv->fw_state, rtw_wdev->iftype);
1158b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1159b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1160b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1161b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingeraddkey_end:
1162b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(param);
1163b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1164b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1165b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1166b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1167b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int
1168b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingercfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,
1169b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		     u8 key_index, bool pairwise, const u8 *mac_addr,
1170b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		     void *cookie,
1171b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		     void (*callback) (void *cookie, struct key_params *))
1172b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1173a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
1174b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1175b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1176b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1177b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
1178b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				u8 key_index, bool pairwise,
1179b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				const u8 *mac_addr)
1180b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1181b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(ndev);
1182b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
1183b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1184a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): key_index =%d\n", __func__, ndev->name, key_index);
1185b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1186b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (key_index == psecuritypriv->dot11PrivacyKeyIndex) {
1187b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* clear the flag of wep default key set. */
1188b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->bWepDefaultKeyIdxSet = 0;
1189b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1190b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1191b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1192b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1193b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1194b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
1195b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					struct net_device *ndev, u8 key_index,
1196b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					bool unicast, bool multicast)
1197b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1198b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(ndev);
1199b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
1200b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1201a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): key_index =%d, unicast =%d, multicast =%d.\n",
1202a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		  __func__, ndev->name, key_index, unicast, multicast);
1203b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1204e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	if (key_index < NUM_WEP_KEYS &&
1205e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	    (psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP40 ||
1206e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	     psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP104)) {
1207b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* set wep default key */
1208b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1209b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1210b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11PrivacyKeyIndex = key_index;
1211b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
12129e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
12139e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
1214e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen		if (psecuritypriv->wep_key[key_index].keylen == 13) {
1215e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen			psecuritypriv->dot11PrivacyAlgrthm =
1216e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen				WLAN_CIPHER_SUITE_WEP104;
1217e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen			psecuritypriv->dot118021XGrpPrivacy =
1218e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen				WLAN_CIPHER_SUITE_WEP104;
1219b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1220b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1221b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* set the flag to represent that wep default key
1222b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		   has been set */
1223b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->bWepDefaultKeyIdxSet = 1;
1224b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1225b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1226b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1227b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1228b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1229b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_get_station(struct wiphy *wiphy,
1230b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct net_device *ndev,
1231b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    u8 *mac, struct station_info *sinfo)
1232b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1233b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1234b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1235b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1236b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_info *psta = NULL;
1237b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_priv *pstapriv = &padapter->stapriv;
1238b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1239b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	sinfo->filled = 0;
1240b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1241b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mac) {
1242a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("%s(%s): mac ==%p\n", __func__, ndev->name, mac);
1243b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOENT;
1244b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1245b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1246b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1247b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psta = rtw_get_stainfo23a(pstapriv, mac);
1248b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (psta == NULL) {
1249b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, sta_info is null\n", __func__);
1250b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOENT;
1251b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1252b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1253a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): mac =" MAC_FMT "\n", __func__, ndev->name,
1254b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  MAC_ARG(mac));
1255b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1256b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* for infra./P2PClient mode */
1257b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
1258b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    check_fwstate(pmlmepriv, _FW_LINKED)) {
1259b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct wlan_network *cur_network = &pmlmepriv->cur_network;
1260b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1261b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (memcmp(mac, cur_network->network.MacAddress, ETH_ALEN)) {
1262b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("%s, mismatch bssid =" MAC_FMT "\n", __func__,
1263b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  MAC_ARG(cur_network->network.MacAddress));
1264b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -ENOENT;
1265b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
1266b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1267b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1268b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->filled |= STATION_INFO_SIGNAL;
1269b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.
1270b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							    signal_strength);
1271b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1272b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->filled |= STATION_INFO_TX_BITRATE;
1273b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->txrate.legacy = rtw_get_cur_max_rate23a(padapter);
1274b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1275b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->filled |= STATION_INFO_RX_PACKETS;
1276b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->rx_packets = sta_rx_data_pkts(psta);
1277b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1278b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->filled |= STATION_INFO_TX_PACKETS;
1279b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->tx_packets = psta->sta_stats.tx_pkts;
1280b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1281b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1282b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* for Ad-Hoc/AP mode */
1283b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
1284b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	     check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1285b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	     check_fwstate(pmlmepriv, WIFI_AP_STATE)) &&
1286b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    check_fwstate(pmlmepriv, _FW_LINKED)
1287b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    ) {
1288b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* TODO: should acquire station info... */
1289b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1290b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1291b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
1292b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1293b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1294b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1295efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensenint cfg80211_infrastructure_mode(struct rtw_adapter* padapter,
1296efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				 enum nl80211_iftype ifmode)
1297efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen{
1298efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1299efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	struct wlan_network *cur_network = &pmlmepriv->cur_network;
1300efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	enum nl80211_iftype old_mode;
1301efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1302efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	old_mode = cur_network->network.ifmode;
1303efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1304efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
1305efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		 ("+%s: old =%d new =%d fw_state = 0x%08x\n", __func__,
1306efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		  old_mode, ifmode, get_fwstate(pmlmepriv)));
1307efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1308efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	if (old_mode != ifmode) {
1309efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		spin_lock_bh(&pmlmepriv->lock);
1310efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1311efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1312efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			 (" change mode!"));
1313efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1314efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		if (old_mode == NL80211_IFTYPE_AP ||
1315efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    old_mode == NL80211_IFTYPE_P2P_GO) {
1316efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			/* change to other mode from Ndis802_11APMode */
1317efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			cur_network->join_res = -1;
1318efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1319efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen#ifdef CONFIG_8723AU_AP_MODE
1320efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			stop_ap_mode23a(padapter);
1321efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen#endif
1322efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		}
1323efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1324efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		if (check_fwstate(pmlmepriv, _FW_LINKED) ||
1325efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    old_mode == NL80211_IFTYPE_ADHOC)
1326efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			rtw_disassoc_cmd23a(padapter, 0, true);
1327efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1328efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		if (check_fwstate(pmlmepriv, _FW_LINKED) ||
1329efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
1330efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			rtw_free_assoc_resources23a(padapter, 1);
1331efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1332efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		if (old_mode == NL80211_IFTYPE_STATION ||
1333efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    old_mode == NL80211_IFTYPE_P2P_CLIENT ||
1334efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    old_mode == NL80211_IFTYPE_ADHOC) {
1335efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1336efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				/* will clr Linked_state; before this function,
1337efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				   we must have chked whether issue
1338efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				   dis-assoc_cmd or not */
1339efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				rtw_indicate_disconnect23a(padapter);
1340efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			}
1341efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	       }
1342efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1343efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		cur_network->network.ifmode = ifmode;
1344efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1345efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		_clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
1346efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1347efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		switch (ifmode) {
1348efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_ADHOC:
1349efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
1350efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			break;
1351efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1352efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_P2P_CLIENT:
1353efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_STATION:
1354efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			set_fwstate(pmlmepriv, WIFI_STATION_STATE);
1355efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			break;
1356efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1357efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_P2P_GO:
1358efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_AP:
1359efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			set_fwstate(pmlmepriv, WIFI_AP_STATE);
1360efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen#ifdef CONFIG_8723AU_AP_MODE
1361efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			start_ap_mode23a(padapter);
1362efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			/* rtw_indicate_connect23a(padapter); */
1363efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen#endif
1364efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			break;
1365efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1366efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		default:
1367efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			break;
1368efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		}
1369efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1370efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		/* SecClearAllKeys(adapter); */
1371efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1372efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		/* RT_TRACE(COMP_OID_SET, DBG_LOUD,
1373efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		   ("set_infrastructure: fw_state:%x after changing mode\n", */
1374efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		/* get_fwstate(pmlmepriv))); */
1375efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1376efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		spin_unlock_bh(&pmlmepriv->lock);
1377efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	}
1378efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1379efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	return _SUCCESS;
1380efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen}
1381efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1382b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_change_iface(struct wiphy *wiphy,
1383b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     struct net_device *ndev,
1384b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     enum nl80211_iftype type, u32 *flags,
1385b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     struct vif_params *params)
1386b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1387b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	enum nl80211_iftype old_type;
1388b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1389b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1390b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
1391b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1392b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1393a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): call netdev_open23a\n", __func__, ndev->name);
1394b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (netdev_open23a(ndev) != 0) {
1395b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
1396b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1397b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1398b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1399b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (_FAIL == rtw_pwr_wakeup(padapter)) {
1400b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
1401b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1402b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1403b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1404b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	old_type = rtw_wdev->iftype;
1405a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): old_iftype =%d, new_iftype =%d\n",
1406a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		  __func__, ndev->name, old_type, type);
1407b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1408b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (old_type != type) {
1409b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmeext->action_public_rxseq = 0xffff;
1410b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmeext->action_public_dialog_token = 0xff;
1411b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1412b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1413b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (type) {
1414b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_ADHOC:
1415b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_P2P_CLIENT:
1416b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_STATION:
1417b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_P2P_GO:
1418b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_AP:
1419efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	case NL80211_IFTYPE_UNSPECIFIED:
1420b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1421b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
1422b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EOPNOTSUPP;
1423b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1424b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1425b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_wdev->iftype = type;
1426b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1427efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	if (cfg80211_infrastructure_mode(padapter, type) != _SUCCESS) {
1428b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_wdev->iftype = old_type;
1429b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
1430b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1431b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1432b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1433efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	rtw_setopmode_cmd23a(padapter, type);
1434b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1435b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
1436b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1437b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1438b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1439b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
1440b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     bool aborted)
1441b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1442b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pwdev_priv->scan_req_lock);
1443b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pwdev_priv->scan_request != NULL) {
1444b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s with scan req\n", __func__);
1445141bd353c5a9ba987dbe7b28ffdd034bb3ed55baJes Sorensen
1446b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (pwdev_priv->scan_request->wiphy !=
1447b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		    pwdev_priv->rtw_wdev->wiphy)
1448b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("error wiphy compare\n");
1449b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		else
1450b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			cfg80211_scan_done(pwdev_priv->scan_request, aborted);
1451b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1452b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->scan_request = NULL;
1453b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
1454b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s without scan req\n", __func__);
1455b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1456b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pwdev_priv->scan_req_lock);
1457b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1458b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1459b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter)
1460b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1461b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct list_head *plist, *phead, *ptmp;
1462b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1463b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1464b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wlan_network *pnetwork;
1465b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1466b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1467b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1468b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	phead = get_list_head(queue);
1469b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1470b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	list_for_each_safe(plist, ptmp, phead) {
1471b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pnetwork = container_of(plist, struct wlan_network, list);
1472b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1473b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* report network only if the current channel set
1474b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		   contains the channel to which this network belongs */
1475b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (rtw_ch_set_search_ch23a
1476b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		    (padapter->mlmeextpriv.channel_set,
147737cb982c2685029e716bfeccf55ec244a6919a32Jes Sorensen		     pnetwork->network.DSConfig) >= 0)
1478b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			rtw_cfg80211_inform_bss(padapter, pnetwork);
1479b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1480b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1481b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1482b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1483b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* call this after other things have been done */
1484b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev),
1485b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					false);
1486b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1487b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1488b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter,
1489b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       char *buf, int len)
1490b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1491b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1492b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	uint wps_ielen = 0;
1493b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 *wps_ie;
1494b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1495b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1496b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ielen =%d\n", __func__, len);
1497b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1498b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (len > 0) {
1499b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wps_ie = rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen);
1500b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (wps_ie) {
1501b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("probe_req_wps_ielen =%d\n", wps_ielen);
1502141bd353c5a9ba987dbe7b28ffdd034bb3ed55baJes Sorensen
1503b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pmlmepriv->wps_probe_req_ie) {
1504b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->wps_probe_req_ie_len = 0;
1505b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				kfree(pmlmepriv->wps_probe_req_ie);
1506b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->wps_probe_req_ie = NULL;
1507b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
1508b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1509b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pmlmepriv->wps_probe_req_ie =
1510b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				kmalloc(wps_ielen, GFP_KERNEL);
1511b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pmlmepriv->wps_probe_req_ie == NULL) {
1512b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
1513b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__, __LINE__);
1514b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				return -EINVAL;
1515b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
1516b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			memcpy(pmlmepriv->wps_probe_req_ie, wps_ie, wps_ielen);
1517b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pmlmepriv->wps_probe_req_ie_len = wps_ielen;
1518b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1519b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1520b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1521b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1522b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1523b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1524b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_scan(struct wiphy *wiphy,
1525b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     struct cfg80211_scan_request *request)
1526b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1527b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int i;
1528b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 _status = false;
1529b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1530b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1531b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1532b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1533b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
1534b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
1535b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cfg80211_ssid *ssids = request->ssids;
1536b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	bool need_indicate_scan_done = false;
1537b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1538a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name);
1539b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1540b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pwdev_priv->scan_req_lock);
1541b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->scan_request = request;
1542b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pwdev_priv->scan_req_lock);
1543b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1544b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1545b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s under WIFI_AP_STATE\n", __func__);
1546b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* need_indicate_scan_done = true; */
1547b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* goto check_need_indicate_scan_done; */
1548b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1549b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1550b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rtw_pwr_wakeup(padapter) == _FAIL) {
1551b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		need_indicate_scan_done = true;
1552b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto check_need_indicate_scan_done;
1553b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1554b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1555b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (request->ie && request->ie_len > 0) {
1556b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_cfg80211_set_probe_req_wpsp2pie(padapter,
1557b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    (u8 *) request->ie,
1558b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    request->ie_len);
1559b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1560b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1561b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) {
1562b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, bBusyTraffic == true\n", __func__);
1563b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		need_indicate_scan_done = true;
1564b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto check_need_indicate_scan_done;
1565b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1566b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rtw_is_scan_deny(padapter)) {
15679cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): scan deny\n", __func__,
15689cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name);
1569b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		need_indicate_scan_done = true;
1570b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto check_need_indicate_scan_done;
1571b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1572b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1573b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ==
1574b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    true) {
1575b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, fwstate = 0x%x\n", __func__, pmlmepriv->fw_state);
1576b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		need_indicate_scan_done = true;
1577b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto check_need_indicate_scan_done;
1578b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1579b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1580b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memset(ssid, 0, sizeof(struct cfg80211_ssid) * RTW_SSID_SCAN_AMOUNT);
1581b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* parsing request ssids, n_ssids */
1582b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
1583b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("ssid =%s, len =%d\n", ssids[i].ssid,
1584b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  ssids[i].ssid_len);
1585b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(ssid[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
1586b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ssid[i].ssid_len = ssids[i].ssid_len;
1587b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1588b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1589b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* parsing channels, n_channels */
1590b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memset(ch, 0,
1591b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct rtw_ieee80211_channel) * RTW_CHANNEL_SCAN_AMOUNT);
1592b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1593b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (request->n_channels == 1) {
1594b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		for (i = 0; i < request->n_channels &&
1595b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		     i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
15969cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			DBG_8723A("%s:(%s):" CHAN_FMT "\n",
15979cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen				  __func__, padapter->pnetdev->name,
1598b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  CHAN_ARG(request->channels[i]));
1599b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ch[i].hw_value = request->channels[i]->hw_value;
1600b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ch[i].flags = request->channels[i]->flags;
1601b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1602b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1603b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1604b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pmlmepriv->lock);
1605b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (request->n_channels == 1) {
1606b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(&ch[1], &ch[0], sizeof(struct rtw_ieee80211_channel));
1607b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(&ch[2], &ch[0], sizeof(struct rtw_ieee80211_channel));
1608b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		_status = rtw_sitesurvey_cmd23a(padapter, ssid,
1609b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     RTW_SSID_SCAN_AMOUNT, ch, 3);
1610b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
1611b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		_status = rtw_sitesurvey_cmd23a(padapter, ssid,
1612b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     RTW_SSID_SCAN_AMOUNT, NULL, 0);
1613b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1614b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pmlmepriv->lock);
1615b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1616b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (_status == false)
1617b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -1;
1618b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1619b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingercheck_need_indicate_scan_done:
1620b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (need_indicate_scan_done)
1621b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_cfg80211_surveydone_event_callback(padapter);
1622b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1623b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1624b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1625b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1626b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1627b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
1628b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1629b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1630b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1631b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
1632b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct cfg80211_ibss_params *params)
1633b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1634a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
1635b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1636b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1637b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1638b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1639b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1640a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
1641b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1642b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1643b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1644b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv,
1645b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					u32 wpa_version)
1646b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1647b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, wpa_version =%d\n", __func__, wpa_version);
1648b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1649b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!wpa_version) {
1650b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
1651b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return 0;
1652b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1653b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1654b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) {
1655b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
1656b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1657b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1658b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger/*
1659b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (wpa_version & NL80211_WPA_VERSION_2)
1660b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	{
1661b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;
1662b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1663b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger*/
1664b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1665b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1666b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1667b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1668b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
1669b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      enum nl80211_auth_type sme_auth_type)
1670b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1671b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, nl80211_auth_type =%d\n", __func__, sme_auth_type);
1672b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1673b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (sme_auth_type) {
1674b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_AUTHTYPE_AUTOMATIC:
1675b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1676b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1677b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1678b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_AUTHTYPE_OPEN_SYSTEM:
1679b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1680b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1681b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (psecuritypriv->ndisauthtype > Ndis802_11AuthModeWPA)
1682b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->dot11AuthAlgrthm =
1683b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				dot11AuthAlgrthm_8021X;
1684b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1685b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_AUTHTYPE_SHARED_KEY:
1686b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1687b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1688b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1689b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1690b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
1691b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1692b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* return -ENOTSUPP; */
1693b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1694b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1695b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1696b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1697b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1698b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv,
1699b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   u32 cipher, bool ucast)
1700b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1701b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 ndisencryptstatus = Ndis802_11EncryptionDisabled;
1702b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1703b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :
1704b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    &psecuritypriv->dot118021XGrpPrivacy;
1705b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1706b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ucast =%d, cipher = 0x%x\n", __func__, ucast, cipher);
1707b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1708b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!cipher) {
17099e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = 0;
1710b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1711b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return 0;
1712b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1713b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1714b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (cipher) {
1715b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case IW_AUTH_CIPHER_NONE:
17169e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = 0;
1717b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11EncryptionDisabled;
1718b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1719b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_WEP40:
17209e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = WLAN_CIPHER_SUITE_WEP40;
1721b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11Encryption1Enabled;
1722b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1723b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_WEP104:
17249e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = WLAN_CIPHER_SUITE_WEP104;
1725b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11Encryption1Enabled;
1726b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1727b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_TKIP:
17289e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = WLAN_CIPHER_SUITE_TKIP;
1729b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11Encryption2Enabled;
1730b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1731b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_CCMP:
17329e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = WLAN_CIPHER_SUITE_CCMP;
1733b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11Encryption3Enabled;
1734b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1735b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
1736b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Unsupported cipher: 0x%x\n", cipher);
1737b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -ENOTSUPP;
1738b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1739b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1740b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ucast)
1741b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1742b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1743b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1744b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1745b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1746b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv,
1747b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    u32 key_mgt)
1748b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1749b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, key_mgt = 0x%x\n", __func__, key_mgt);
1750b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1751b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (key_mgt == WLAN_AKM_SUITE_8021X)
1752b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1753b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else if (key_mgt == WLAN_AKM_SUITE_PSK)
1754b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1755b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
1756b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Invalid key mgt: 0x%x\n", key_mgt);
1757b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1758b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1759b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1760b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1761b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
1762b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   size_t ielen)
1763b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
17649bf29cb9404c8368d7a501e5266e0cfcf0bce702Jes Sorensen	u8 *buf = NULL;
1765b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int group_cipher = 0, pairwise_cipher = 0;
1766b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
176758aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen	const u8 *pwpa, *pwpa2;
1768b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int i;
1769b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1770b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!pie || !ielen) {
1771b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* Treat this as normal case, but need to clear
1772b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		   WIFI_UNDER_WPS */
1773b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1774b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1775b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1776b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) {
1777b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
1778b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1779b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1780b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	buf = kzalloc(ielen, GFP_KERNEL);
1781b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (buf == NULL) {
1782b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOMEM;
1783b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1784b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1785b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(buf, pie, ielen);
1786b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1787b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* dump */
1788b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("set wpa_ie(length:%zu):\n", ielen);
1789b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	for (i = 0; i < ielen; i = i + 8)
1790b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
1791b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  buf[i], buf[i + 1],
1792b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  buf[i + 2], buf[i + 3], buf[i + 4],
1793b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  buf[i + 5], buf[i + 6], buf[i + 7]);
1794b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ielen < RSN_HEADER_LEN) {
1795b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
1796b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			 ("Ie len too short %d\n", (int)ielen));
1797b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -1;
1798b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1799b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1800b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
180158aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen	pwpa = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
180258aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen				       WLAN_OUI_TYPE_MICROSOFT_WPA,
180358aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen				       buf, ielen);
180458aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen	if (pwpa && pwpa[1] > 0) {
180558aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen		if (rtw_parse_wpa_ie23a(pwpa, pwpa[1] + 2, &group_cipher,
180658aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen					&pairwise_cipher, NULL) == _SUCCESS) {
1807b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			padapter->securitypriv.dot11AuthAlgrthm =
1808b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				dot11AuthAlgrthm_8021X;
1809b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			padapter->securitypriv.ndisauthtype =
1810b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				Ndis802_11AuthModeWPAPSK;
181158aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			memcpy(padapter->securitypriv.supplicant_ie, pwpa,
181258aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			       pwpa[1] + 2);
1813b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
181458aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			DBG_8723A("got wpa_ie, wpa_ielen:%u\n", pwpa[1]);
1815b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1816b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1817b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
181858aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen	pwpa2 = cfg80211_find_ie(WLAN_EID_RSN, buf, ielen);
181958aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen	if (pwpa2 && pwpa2[1] > 0) {
182058aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen		if (rtw_parse_wpa2_ie23a (pwpa2, pwpa2[1] + 2, &group_cipher,
182158aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen					  &pairwise_cipher, NULL) == _SUCCESS) {
1822b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			padapter->securitypriv.dot11AuthAlgrthm =
1823b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				dot11AuthAlgrthm_8021X;
1824b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			padapter->securitypriv.ndisauthtype =
1825b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				Ndis802_11AuthModeWPA2PSK;
182658aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			memcpy(padapter->securitypriv.supplicant_ie, pwpa2,
182758aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			       pwpa2[1] + 2);
1828b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
182958aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			DBG_8723A("got wpa2_ie, wpa2_ielen:%u\n", pwpa2[1]);
1830b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1831b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1832b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1833b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (group_cipher == 0) {
1834b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		group_cipher = WPA_CIPHER_NONE;
1835b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1836b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pairwise_cipher == 0) {
1837b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pairwise_cipher = WPA_CIPHER_NONE;
1838b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1839b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1840b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (group_cipher) {
1841b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_NONE:
18429e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = 0;
1843b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1844b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11EncryptionDisabled;
1845b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1846b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_WEP40:
18479e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
1848b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1849b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption1Enabled;
1850b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1851b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_TKIP:
18529e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_TKIP;
1853b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1854b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption2Enabled;
1855b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1856b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_CCMP:
18579e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_CCMP;
1858b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1859b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption3Enabled;
1860b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1861b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_WEP104:
18629e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104;
1863b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1864b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption1Enabled;
1865b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1866b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1867b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1868b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (pairwise_cipher) {
1869b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_NONE:
18709e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = 0;
1871b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1872b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11EncryptionDisabled;
1873b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1874b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_WEP40:
18759e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
1876b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1877b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption1Enabled;
1878b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1879b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_TKIP:
18809e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_TKIP;
1881b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1882b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption2Enabled;
1883b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1884b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_CCMP:
18859e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_CCMP;
1886b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1887b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption3Enabled;
1888b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1889b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_WEP104:
18909e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
1891b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1892b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption1Enabled;
1893b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1894b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1895b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1896b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	{			/* handle wps_ie */
1897b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		uint wps_ielen;
1898b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		u8 *wps_ie;
1899b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1900b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wps_ie = rtw_get_wps_ie23a(buf, ielen, NULL, &wps_ielen);
1901b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (wps_ie && wps_ielen > 0) {
1902b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("got wps_ie, wps_ielen:%u\n", wps_ielen);
1903b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			padapter->securitypriv.wps_ie_len =
1904b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				wps_ielen <
1905b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				MAX_WPS_IE_LEN ? wps_ielen : MAX_WPS_IE_LEN;
1906b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			memcpy(padapter->securitypriv.wps_ie, wps_ie,
1907b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			       padapter->securitypriv.wps_ie_len);
1908b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
1909b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		} else {
1910b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1911b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1912b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1913b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1914b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* TKIP and AES disallow multicast packets until installing group key */
19159e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	if (padapter->securitypriv.dot11PrivacyAlgrthm ==
19169e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	    WLAN_CIPHER_SUITE_TKIP ||
19179e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	    padapter->securitypriv.dot11PrivacyAlgrthm ==
19189e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	    WLAN_CIPHER_SUITE_CCMP)
1919b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* WPS open need to enable multicast */
1920b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true)*/
1921763b4247cafdb978630d4da7ff48c8113c7d961eJes Sorensen		rtl8723a_off_rcr_am(padapter);
1922b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1923b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1924b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->"
1925b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  "securitypriv.ndisencryptstatus =%d padapter->"
1926b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  "securitypriv.ndisauthtype =%d\n", pairwise_cipher,
1927b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  padapter->securitypriv.ndisencryptstatus,
1928b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  padapter->securitypriv.ndisauthtype));
1929b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1930b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
1931b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(buf);
1932b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret)
1933b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1934b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1935b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1936b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
19376893c8ebba521ea9d0f1cc4a53233fcb09271d52Jes Sorensenstatic int rtw_cfg80211_add_wep(struct rtw_adapter *padapter,
1938deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				struct rtw_wep_key *wep, u8 keyid)
19391e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen{
1940deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen	int res;
19411e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	struct security_priv *psecuritypriv = &padapter->securitypriv;
19421e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
1943deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen	if (keyid >= NUM_WEP_KEYS) {
19441e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
19451e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen			 ("%s:keyid>4 =>fail\n", __func__));
19461e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		res = _FAIL;
19471e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		goto exit;
19481e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	}
19491e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
1950deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen	switch (wep->keylen) {
19511e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	case 5:
19521e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
19531e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
19541e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen			 ("%s:wep->KeyLength = 5\n", __func__));
19551e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		break;
19561e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	case 13:
19571e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
19581e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
19591e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen			 ("%s:wep->KeyLength = 13\n", __func__));
19601e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		break;
19611e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	default:
19621e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		psecuritypriv->dot11PrivacyAlgrthm = 0;
19631e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
19641e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen			 ("%s:wep->KeyLength!= 5 or 13\n", __func__));
19651e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		res = _FAIL;
19661e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		goto exit;
19671e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	}
19681e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
19691e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1970deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		 ("%s:before memcpy, wep->KeyLength = 0x%x keyid =%x\n",
1971deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		  __func__, wep->keylen, keyid));
19721e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
1973deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen	memcpy(&psecuritypriv->wep_key[keyid], wep, sizeof(struct rtw_wep_key));
19741e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
19751e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	psecuritypriv->dot11PrivacyKeyIndex = keyid;
19761e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
19771e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
19781e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		 ("%s:security key material : "
19791e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  "%x %x %x %x %x %x %x %x %x %x %x %x %x\n", __func__,
19801e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[0],
19811e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[1],
19821e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[2],
19831e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[3],
19841e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[4],
19851e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[5],
19861e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[6],
19871e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[7],
19881e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[8],
19891e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[9],
19901e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[10],
19911e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[11],
19921e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[12]));
19931e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
19941e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	res = rtw_set_key23a(padapter, psecuritypriv, keyid, 1);
19951e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
19961e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensenexit:
19971e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
19981e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	return res;
19991e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen}
20001e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
2001b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
2002b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				struct cfg80211_connect_params *sme)
2003b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2004b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2005b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct list_head *phead, *plist, *ptmp;
2006b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wlan_network *pnetwork = NULL;
2007b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	enum ndis_802_11_auth_mode authmode;
2008b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cfg80211_ssid ndis_ssid;
2009b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 *dst_ssid;
2010b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 *src_ssid;
2011b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 *dst_bssid;
2012b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	const u8 *src_bssid;
2013b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* u8 matched_by_bssid = false; */
2014b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* u8 matched_by_ssid = false; */
2015b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 matched = false;
2016b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2017b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2018b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
2019b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_queue *queue = &pmlmepriv->scanned_queue;
2020b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2021a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("=>" "%s(%s)\n", __func__, ndev->name);
2022b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("privacy =%d, key =%p, key_len =%d, key_idx =%d\n",
2023b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  sme->privacy, sme->key, sme->key_len, sme->key_idx);
2024b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2025b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (wdev_to_priv(padapter->rtw_wdev)->block) {
2026b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EBUSY;
2027b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s wdev_priv.block is set\n", __func__);
2028b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2029b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2030b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2031b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (_FAIL == rtw_pwr_wakeup(padapter)) {
2032b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
2033b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2034b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2035b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2036b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2037b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
2038b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2039b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2040b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2041b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!sme->ssid || !sme->ssid_len) {
2042b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
2043b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2044b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2045b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2046b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (sme->ssid_len > IW_ESSID_MAX_SIZE) {
2047b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -E2BIG;
2048b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2049b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2050b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2051b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memset(&ndis_ssid, 0, sizeof(struct cfg80211_ssid));
2052b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ndis_ssid.ssid_len = sme->ssid_len;
2053b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(ndis_ssid.ssid, sme->ssid, sme->ssid_len);
2054b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2055b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("ssid =%s, len =%zu\n", ndis_ssid.ssid, sme->ssid_len);
2056b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2057b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (sme->bssid)
2058b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("bssid =" MAC_FMT "\n", MAC_ARG(sme->bssid));
2059b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2060b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
2061b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EBUSY;
2062b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, fw_state = 0x%x, goto exit\n", __func__,
2063b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  pmlmepriv->fw_state);
2064b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2065b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2066b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
2067b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_scan_abort23a(padapter);
2068b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2069b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2070b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&queue->lock);
2071b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2072b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	phead = get_list_head(queue);
2073b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2074b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	list_for_each_safe(plist, ptmp, phead) {
2075b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pnetwork = container_of(plist, struct wlan_network, list);
2076b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2077b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		dst_ssid = pnetwork->network.Ssid.ssid;
2078b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		dst_bssid = pnetwork->network.MacAddress;
2079b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2080b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (sme->bssid) {
2081b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (memcmp(pnetwork->network.MacAddress,
2082b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   sme->bssid, ETH_ALEN))
2083b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				continue;
2084b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2085b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2086b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (sme->ssid && sme->ssid_len) {
2087b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pnetwork->network.Ssid.ssid_len != sme->ssid_len ||
2088b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    memcmp(pnetwork->network.Ssid.ssid, sme->ssid,
2089b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   sme->ssid_len))
2090b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				continue;
2091b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2092b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2093b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (sme->bssid) {
2094b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			src_bssid = sme->bssid;
2095b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2096b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
2097b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("matched by bssid\n");
2098b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2099b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				ndis_ssid.ssid_len =
2100b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    pnetwork->network.Ssid.ssid_len;
2101b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(ndis_ssid.ssid,
2102b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       pnetwork->network.Ssid.ssid,
2103b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       pnetwork->network.Ssid.ssid_len);
2104b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2105b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				matched = true;
2106b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				break;
2107b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
2108b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2109b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		} else if (sme->ssid && sme->ssid_len) {
2110b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			src_ssid = ndis_ssid.ssid;
2111b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2112b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.ssid_len)) &&
2113b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    (pnetwork->network.Ssid.ssid_len ==
2114b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     ndis_ssid.ssid_len)) {
2115b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("matched by ssid\n");
2116b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				matched = true;
2117b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				break;
2118b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
2119b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2120b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2121b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2122b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&queue->lock);
2123b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2124b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!matched || (pnetwork == NULL)) {
2125b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOENT;
2126b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("connect, matched == false, goto exit\n");
2127b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2128b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2129b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2130efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	if (cfg80211_infrastructure_mode(
2131efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    padapter, pnetwork->network.ifmode) != _SUCCESS) {
2132b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
2133b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2134b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2135b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2136b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
21379e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	psecuritypriv->dot11PrivacyAlgrthm = 0;
21389e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	psecuritypriv->dot118021XGrpPrivacy = 0;
2139b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
2140b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
2141b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2142b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret =
2143b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    rtw_cfg80211_set_wpa_version(psecuritypriv,
2144b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					 sme->crypto.wpa_versions);
2145b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0)
2146b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2147b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2148b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type);
2149b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2150b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0)
2151b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2152b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2153b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ie_len =%zu\n", __func__, sme->ie_len);
2154b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2155b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_cfg80211_set_wpa_ie(padapter, sme->ie, sme->ie_len);
2156b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0)
2157b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2158b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2159b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (sme->crypto.n_ciphers_pairwise) {
2160b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_cfg80211_set_cipher(psecuritypriv,
2161b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      sme->crypto.ciphers_pairwise[0],
2162b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      true);
2163b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ret < 0)
2164b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
2165b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2166b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2167b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* For WEP Shared auth */
2168b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if ((psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Shared ||
2169b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	     psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Auto) &&
2170b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    sme->key) {
2171deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		struct rtw_wep_key wep_key;
2172deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		u8 wep_key_idx, wep_key_len;
2173b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s(): Shared/Auto WEP\n", __func__);
2174b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2175b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_idx = sme->key_idx;
2176b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_len = sme->key_len;
2177b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2178deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		if (wep_key_idx > WEP_KEYS || !wep_key_len ||
2179deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		    wep_key_len > WLAN_KEY_LEN_WEP104) {
2180b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EINVAL;
2181b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
2182b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2183b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2184deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		wep_key_len = wep_key_len <= 5 ? 5 : 13;
2185b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2186deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		memset(&wep_key, 0, sizeof(struct rtw_wep_key));
2187b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2188deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		wep_key.keylen = wep_key_len;
2189b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2190deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		if (wep_key_len == 13) {
2191deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen			padapter->securitypriv.dot11PrivacyAlgrthm =
2192deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				WLAN_CIPHER_SUITE_WEP104;
2193deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen			padapter->securitypriv.dot118021XGrpPrivacy =
2194deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				WLAN_CIPHER_SUITE_WEP104;
2195b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		} else {
2196deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen			padapter->securitypriv.dot11PrivacyAlgrthm =
2197deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				WLAN_CIPHER_SUITE_WEP40;
2198deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen			padapter->securitypriv.dot118021XGrpPrivacy =
2199deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				WLAN_CIPHER_SUITE_WEP40;
2200b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2201b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2202deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		memcpy(wep_key.key, (void *)sme->key, wep_key.keylen);
2203b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2204deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		if (rtw_cfg80211_add_wep(padapter, &wep_key, wep_key_idx) !=
2205deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		    _SUCCESS)
2206b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EOPNOTSUPP;
2207b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2208b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ret < 0)
2209b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
2210b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2211b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2212b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_cfg80211_set_cipher(psecuritypriv,
2213b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      sme->crypto.cipher_group, false);
2214b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0)
2215b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return ret;
2216b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2217b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (sme->crypto.n_akm_suites) {
2218b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_cfg80211_set_key_mgt(psecuritypriv,
2219b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       sme->crypto.akm_suites[0]);
2220b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ret < 0)
2221b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
2222b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2223b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2224b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	authmode = psecuritypriv->ndisauthtype;
2225b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_set_802_11_authentication_mode23a(padapter, authmode);
2226b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2227b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* rtw_set_802_11_encryption_mode(padapter,
2228b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	   padapter->securitypriv.ndisencryptstatus); */
2229b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2230b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rtw_set_802_11_ssid23a(padapter, &ndis_ssid) == false) {
2231b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -1;
2232b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2233b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2234b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2235b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("set ssid:dot11AuthAlgrthm =%d, dot11PrivacyAlgrthm =%d, "
2236b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  "dot118021XGrpPrivacy =%d\n", psecuritypriv->dot11AuthAlgrthm,
2237b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  psecuritypriv->dot11PrivacyAlgrthm,
2238b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  psecuritypriv->dot118021XGrpPrivacy);
2239b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2240b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
2241b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2242b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("<=%s, ret %d\n", __func__, ret);
2243b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2244b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2245b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2246b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2247b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev,
2248b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   u16 reason_code)
2249b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2250b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2251b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2252a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2253b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2254b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_set_roaming(padapter, 0);
2255b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2256b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2257b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_scan_abort23a(padapter);
2258b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		LeaveAllPowerSaveMode23a(padapter);
2259b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_disassoc_cmd23a(padapter, 500, false);
2260b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2261b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s...call rtw_indicate_disconnect23a\n", __func__);
2262b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2263b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->mlmepriv.not_indic_disco = true;
2264b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_indicate_disconnect23a(padapter);
2265b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->mlmepriv.not_indic_disco = false;
2266b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2267b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_free_assoc_resources23a(padapter, 1);
2268b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2269b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2270b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2271b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2272b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2273b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_txpower(struct wiphy *wiphy,
2274b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct wireless_dev *wdev,
2275b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    enum nl80211_tx_power_setting type, int mbm)
2276b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2277b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2278b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2279b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2280b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2281b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_get_txpower(struct wiphy *wiphy,
2282b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct wireless_dev *wdev, int *dbm)
2283b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2284b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2285b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	*dbm = (12);
2286b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2287b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2288b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2289b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerinline bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter)
2290b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2291b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(adapter->rtw_wdev);
2292b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return rtw_wdev_priv->power_mgmt;
2293b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2294b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2295b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy,
2296b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct net_device *ndev,
2297b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       bool enabled, int timeout)
2298b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2299b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2300b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(padapter->rtw_wdev);
2301b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2302a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): enabled:%u, timeout:%d\n",
2303a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		  __func__, ndev->name, enabled, timeout);
2304b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2305b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_wdev_priv->power_mgmt = enabled;
2306b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2307b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!enabled)
2308b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		LPS_Leave23a(padapter);
2309b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2310b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2311b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2312b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2313b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,
2314b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct net_device *netdev,
2315b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct cfg80211_pmksa *pmksa)
2316b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2317b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 index, blInserted = false;
2318b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2319b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
2320b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 strZeroMacAddress[ETH_ALEN] = { 0x00 };
2321b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2322a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, netdev->name);
2323b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2324b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!memcmp(pmksa->bssid, strZeroMacAddress, ETH_ALEN)) {
2325b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2326b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2327b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2328b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	blInserted = false;
2329b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2330b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* overwrite PMKID */
2331b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	for (index = 0; index < NUM_PMKID_CACHE; index++) {
2332b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (!memcmp(psecuritypriv->PMKIDList[index].Bssid,
2333b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    pmksa->bssid, ETH_ALEN)) {
2334b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* BSSID is matched, the same AP => rewrite with
2335b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   new PMKID. */
2336a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen			DBG_8723A("%s(%s):  BSSID exists in the PMKList.\n",
2337a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen				  __func__, netdev->name);
2338b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2339b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			memcpy(psecuritypriv->PMKIDList[index].PMKID,
2340b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			       pmksa->pmkid, WLAN_PMKID_LEN);
2341b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->PMKIDList[index].bUsed = true;
2342b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->PMKIDIndex = index + 1;
2343b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			blInserted = true;
2344b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			break;
2345b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2346b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2347b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2348b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!blInserted) {
2349b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/*  Find a new entry */
2350a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("%s(%s): Use new entry index = %d for this PMKID\n",
2351a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen			  __func__, netdev->name, psecuritypriv->PMKIDIndex);
2352b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2353b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2354b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       Bssid, pmksa->bssid, ETH_ALEN);
2355b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2356b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2357b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2358b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed =
2359b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			true;
2360b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->PMKIDIndex++;
2361b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (psecuritypriv->PMKIDIndex == 16) {
2362b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->PMKIDIndex = 0;
2363b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2364b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2365b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2366b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2367b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2368b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2369b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,
2370b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct net_device *netdev,
2371b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct cfg80211_pmksa *pmksa)
2372b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2373b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 index, bMatched = false;
2374b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2375b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
2376b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2377a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, netdev->name);
2378b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2379b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	for (index = 0; index < NUM_PMKID_CACHE; index++) {
2380b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (!memcmp(psecuritypriv->PMKIDList[index].Bssid,
2381b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    pmksa->bssid, ETH_ALEN)) {
2382b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
238343c34be13047dd53e70bc4759ff314424db7036bJes Sorensen			eth_zero_addr(psecuritypriv->PMKIDList[index].Bssid);
2384b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			memset(psecuritypriv->PMKIDList[index].PMKID, 0x00,
2385b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			       WLAN_PMKID_LEN);
2386b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->PMKIDList[index].bUsed = false;
2387b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			bMatched = true;
2388b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			break;
2389b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2390b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2391b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2392b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (false == bMatched) {
2393a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("%s(%s): do not have matched BSSID\n", __func__,
2394a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen			  netdev->name);
2395b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2396b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2397b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2398b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2399b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2400b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2401b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy,
2402b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct net_device *netdev)
2403b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2404b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2405b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
2406b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2407a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, netdev->name);
2408b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2409b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memset(&psecuritypriv->PMKIDList[0], 0x00,
2410b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
2411b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psecuritypriv->PMKIDIndex = 0;
2412b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2413b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2414b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2415b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2416b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
2417b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter,
2418b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     u8 *pmgmt_frame, uint frame_len)
2419b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2420b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	s32 freq;
2421b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int channel;
2422b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2423b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *ndev = padapter->pnetdev;
2424b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2425b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2426b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2427b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#if defined(RTW_USE_CFG80211_STA_EVENT)
2428b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	{
2429b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct station_info sinfo;
2430b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		u8 ie_offset;
2431b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ieee80211_is_assoc_req(hdr->frame_control))
2432b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ie_offset = _ASOCREQ_IE_OFFSET_;
2433b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		else		/*  WIFI_REASSOCREQ */
2434b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ie_offset = _REASOCREQ_IE_OFFSET_;
2435b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2436b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo.filled = 0;
2437b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
2438b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo.assoc_req_ies = pmgmt_frame + WLAN_HDR_A3_LEN + ie_offset;
2439b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo.assoc_req_ies_len =
2440b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			frame_len - WLAN_HDR_A3_LEN - ie_offset;
2441b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC);
2442b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2443b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2444b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	channel = pmlmeext->cur_channel;
2445b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (channel <= RTW_CH_MAX_2G_CHANNEL)
2446b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
2447b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_2GHZ);
2448b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
2449b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
2450b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_5GHZ);
2451b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2452b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_cfg80211_rx_mgmt(padapter, freq, 0, pmgmt_frame, frame_len,
2453b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     GFP_ATOMIC);
2454b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2455b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2456b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2457b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter,
2458b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					unsigned char *da,
2459b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					unsigned short reason)
2460b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2461b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	s32 freq;
2462b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int channel;
2463b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 *pmgmt_frame;
2464b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	uint frame_len;
2465b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_hdr *pwlanhdr;
24661daffaeecb4bf01c4a34fc2330c745ace5af3f60Jes Sorensen	u8 mgmt_buf[128];
2467b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2468b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2469b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *ndev = padapter->pnetdev;
2470b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2471b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2472b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
24731daffaeecb4bf01c4a34fc2330c745ace5af3f60Jes Sorensen	memset(mgmt_buf, 0, 128);
24741daffaeecb4bf01c4a34fc2330c745ace5af3f60Jes Sorensen
2475b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#if defined(RTW_USE_CFG80211_STA_EVENT)
2476b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	cfg80211_del_sta(ndev, da, GFP_ATOMIC);
2477b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2478b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	channel = pmlmeext->cur_channel;
2479b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (channel <= RTW_CH_MAX_2G_CHANNEL)
2480b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
2481b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_2GHZ);
2482b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
2483b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
2484b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_5GHZ);
2485b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2486b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmgmt_frame = mgmt_buf;
2487b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwlanhdr = (struct ieee80211_hdr *)pmgmt_frame;
2488b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2489036cdd9cb34a10aabb80a97a41fb9dcfead7d113Jes Sorensen	pwlanhdr->frame_control =
2490036cdd9cb34a10aabb80a97a41fb9dcfead7d113Jes Sorensen		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
2491b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2492b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pwlanhdr->addr1, myid(&padapter->eeprompriv), ETH_ALEN);
2493b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pwlanhdr->addr2, da, ETH_ALEN);
2494b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
2495b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
24961daffaeecb4bf01c4a34fc2330c745ace5af3f60Jes Sorensen	pwlanhdr->seq_ctrl =
24971daffaeecb4bf01c4a34fc2330c745ace5af3f60Jes Sorensen		cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2498b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmlmeext->mgnt_seq++;
2499b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2500b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmgmt_frame += sizeof(struct ieee80211_hdr_3addr);
2501b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	frame_len = sizeof(struct ieee80211_hdr_3addr);
2502b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2503b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	reason = cpu_to_le16(reason);
2504b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmgmt_frame = rtw_set_fixed_ie23a(pmgmt_frame,
2505b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       WLAN_REASON_PREV_AUTH_NOT_VALID,
2506b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       (unsigned char *)&reason, &frame_len);
2507b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2508b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_cfg80211_rx_mgmt(padapter, freq, 0, mgmt_buf, frame_len,
2509b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     GFP_ATOMIC);
2510b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2511b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2512b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2513b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_monitor_if_open(struct net_device *ndev)
2514b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2515b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2516b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2517b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2518b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2519b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2520b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2521b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2522b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_monitor_if_close(struct net_device *ndev)
2523b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2524b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2525b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2526b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2527b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2528b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2529b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2530b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2531b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb,
2532b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      struct net_device *ndev)
2533b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2534b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2535b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int rtap_len;
2536b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int qos_len = 0;
2537b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int dot11_hdr_len = 24;
2538b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int snap_len = 6;
2539b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned char *pdata;
2540b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned char src_mac_addr[6];
2541b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned char dst_mac_addr[6];
2542b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_hdr *dot11_hdr;
2543b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_radiotap_header *rtap_hdr;
2544b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(ndev);
2545b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2546a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2547b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2548b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
2549b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto fail;
2550b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2551b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
2552b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (unlikely(rtap_hdr->it_version))
2553b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto fail;
2554b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2555b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtap_len = ieee80211_get_radiotap_len(skb->data);
2556b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (unlikely(skb->len < rtap_len))
2557b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto fail;
2558b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2559b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rtap_len != 14) {
2560b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("radiotap len (should be 14): %d\n", rtap_len);
2561b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto fail;
2562b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2563b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2564b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* Skip the ratio tap header */
2565b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	skb_pull(skb, rtap_len);
2566b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2567b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	dot11_hdr = (struct ieee80211_hdr *)skb->data;
2568b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* Check if the QoS bit is set */
2569b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ieee80211_is_data(dot11_hdr->frame_control)) {
2570b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* Check if this ia a Wireless Distribution System (WDS) frame
2571b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 * which has 4 MAC addresses
2572b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 */
2573b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ieee80211_is_data_qos(dot11_hdr->frame_control))
2574b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			qos_len = IEEE80211_QOS_CTL_LEN;
2575b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ieee80211_has_a4(dot11_hdr->frame_control))
2576b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			dot11_hdr_len += 6;
2577b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2578b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
2579b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
2580b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2581b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/*
2582b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 * Skip the 802.11 header, QoS (if any) and SNAP,
2583b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 * but leave spaces for two MAC addresses
2584b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 */
2585b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		skb_pull(skb, dot11_hdr_len + qos_len + snap_len -
2586b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			 ETH_ALEN * 2);
2587b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pdata = (unsigned char *)skb->data;
2588b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(pdata, dst_mac_addr, ETH_ALEN);
2589b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(pdata + ETH_ALEN, src_mac_addr, ETH_ALEN);
2590b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2591b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("should be eapol packet\n");
2592b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2593b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* Use the real net device to transmit the packet */
2594b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_xmit23a_entry23a(skb, padapter->pnetdev);
2595b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2596b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return ret;
2597b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2598b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else if (ieee80211_is_action(dot11_hdr->frame_control)) {
259938eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen		struct ieee80211_mgmt *mgmt;
2600b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* only for action frames */
2601b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct xmit_frame *pmgntframe;
2602b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct pkt_attrib *pattrib;
2603b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		unsigned char *pframe;
2604b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* u8 category, action, OUI_Subtype, dialogToken = 0; */
2605b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* unsigned char        *frame_body; */
2606b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2607b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2608b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		u32 len = skb->len;
2609b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		u8 category, action;
2610b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
261138eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen		mgmt = (struct ieee80211_mgmt *)dot11_hdr;
2612b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2613a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("RTW_Tx:da =" MAC_FMT " via %s(%s)\n",
261438eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen			  MAC_ARG(mgmt->da), __func__, ndev->name);
261538eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen		category = mgmt->u.action.category;
261638eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen		action = mgmt->u.action.u.wme_action.action_code;
261738eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen		if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)
2618b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("RTW_Tx:%s\n", action_public_str23a(action));
2619b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		else
2620b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category,
2621b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  action);
262298fb81291d30f83838379bf1522fead6673b5fdfJes Sorensen
2623b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* starting alloc mgmt frame to dump it */
2624b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2625b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (pmgntframe == NULL)
2626b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto fail;
2627b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2628b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* update attribute */
2629b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib = &pmgntframe->attrib;
2630b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		update_mgntframe_attrib23a(padapter, pattrib);
2631b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib->retry_ctrl = false;
2632b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2633b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2634b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2635b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2636b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2637b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(pframe, skb->data, len);
2638b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib->pktlen = len;
2639b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2640b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* update seq number */
2641b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmeext->mgnt_seq = le16_to_cpu(dot11_hdr->seq_ctrl) >> 4;
2642b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib->seqnum = pmlmeext->mgnt_seq;
2643b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmeext->mgnt_seq++;
2644b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2645b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib->last_txcmdsz = pattrib->pktlen;
2646b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2647b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		dump_mgntframe23a(padapter, pmgntframe);
2648b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2649b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2650b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerfail:
2651b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2652b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	dev_kfree_skb(skb);
2653b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2654b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2655b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2656b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2657b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int
2658b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerrtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)
2659b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2660b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2661b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2662b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2663b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2664b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2665b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2666b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2667b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic const struct net_device_ops rtw_cfg80211_monitor_if_ops = {
2668b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.ndo_open = rtw_cfg80211_monitor_if_open,
2669b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.ndo_stop = rtw_cfg80211_monitor_if_close,
2670b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
2671b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,
2672b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
2673b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2674b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_add_monitor_if(struct rtw_adapter *padapter, char *name,
2675b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct net_device **ndev)
2676b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2677b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2678b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *mon_ndev = NULL;
2679b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *mon_wdev = NULL;
2680b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
2681b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2682b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!name) {
26839cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): without specific name\n",
26849cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  __func__, padapter->pnetdev->name);
2685b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
2686b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2687b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2688b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2689b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pwdev_priv->pmon_ndev) {
26909cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): monitor interface exist: %s\n", __func__,
26919cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name, pwdev_priv->pmon_ndev->name);
2692b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EBUSY;
2693b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2694b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2695b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2696b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev = alloc_etherdev(sizeof(struct rtw_adapter));
2697b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mon_ndev) {
26989cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): allocate ndev fail\n", __func__,
26999cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name);
2700b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOMEM;
2701b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2702b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2703b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2704b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;
2705b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	strncpy(mon_ndev->name, name, IFNAMSIZ);
2706b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->name[IFNAMSIZ - 1] = 0;
2707b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->destructor = rtw_ndev_destructor;
2708b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2709b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;
2710b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2711b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*  wdev */
2712b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
2713b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mon_wdev) {
27149cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): allocate mon_wdev fail\n", __func__,
27159cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name);
2716b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOMEM;
2717b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2718b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2719b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2720b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_wdev->wiphy = padapter->rtw_wdev->wiphy;
2721b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_wdev->netdev = mon_ndev;
2722b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_wdev->iftype = NL80211_IFTYPE_MONITOR;
2723b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->ieee80211_ptr = mon_wdev;
2724b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2725b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = register_netdevice(mon_ndev);
2726b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret) {
2727b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2728b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2729b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2730b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	*ndev = pwdev_priv->pmon_ndev = mon_ndev;
2731b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1);
2732b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2733b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerout:
2734b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret) {
2735b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		kfree(mon_wdev);
2736b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		mon_wdev = NULL;
2737b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2738b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2739b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret && mon_ndev) {
2740b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		free_netdev(mon_ndev);
2741b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		*ndev = mon_ndev = NULL;
2742b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2743b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2744b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2745b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2746b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2747b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct wireless_dev *
2748b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingercfg80211_rtw_add_virtual_intf(struct wiphy *wiphy, const char *name,
2749b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			      enum nl80211_iftype type, u32 *flags,
2750b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			      struct vif_params *params)
2751b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2752b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2753b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *ndev = NULL;
2754b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2755b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
27569cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen	DBG_8723A("%s(%s): wiphy:%s, name:%s, type:%d\n", __func__,
27579cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		  padapter->pnetdev->name, wiphy_name(wiphy), name, type);
2758b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2759b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (type) {
2760b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_ADHOC:
2761b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_AP_VLAN:
2762b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_WDS:
2763b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_MESH_POINT:
2764b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENODEV;
2765b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2766b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_MONITOR:
2767b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret =
2768b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		    rtw_cfg80211_add_monitor_if(padapter, (char *)name, &ndev);
2769b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2770b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2771b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_P2P_CLIENT:
2772b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_STATION:
2773b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENODEV;
2774b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2775b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2776b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_P2P_GO:
2777b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_AP:
2778b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENODEV;
2779b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2780b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
2781b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENODEV;
2782b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Unsupported interface type\n");
2783b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2784b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2785b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
27869cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen	DBG_8723A("%s(%s): ndev:%p, ret:%d\n", __func__,
27879cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		  padapter->pnetdev->name,
2788b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  ndev, ret);
2789b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2790b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ndev ? ndev->ieee80211_ptr : ERR_PTR(ret);
2791b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2792b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2793b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy,
2794b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					 struct wireless_dev *wdev)
2795b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2796b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv =
2797b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    (struct rtw_wdev_priv *)wiphy_priv(wiphy);
2798b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *ndev;
2799b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ndev = wdev ? wdev->netdev : NULL;
2800b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2801b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!ndev)
2802b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2803b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2804b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unregister_netdevice(ndev);
2805b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2806b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ndev == pwdev_priv->pmon_ndev) {
2807b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->pmon_ndev = NULL;
2808b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->ifname_mon[0] = '\0';
2809a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("%s(%s): remove monitor interface\n",
2810a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen			  __func__, ndev->name);
2811b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2812b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2813b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
2814b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2815b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2816b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2817b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head,
2818b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  size_t head_len, const u8 *tail, size_t tail_len)
2819b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2820b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2821b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 *pbuf = NULL;
2822b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	uint len, wps_ielen = 0;
2823b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2824b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* struct sta_priv *pstapriv = &padapter->stapriv; */
2825b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2826b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s beacon_head_len =%zu, beacon_tail_len =%zu\n",
2827b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  __func__, head_len, tail_len);
2828b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2829b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2830b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2831b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2832b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (head_len < 24)
2833b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2834b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2835b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pbuf = kzalloc(head_len + tail_len, GFP_KERNEL);
2836b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!pbuf)
2837b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -ENOMEM;
2838b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*  24 = beacon header len. */
2839b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pbuf, (void *)head + 24, head_len - 24);
2840b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pbuf + head_len - 24, (void *)tail, tail_len);
2841b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2842b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	len = head_len + tail_len - 24;
2843b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2844b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* check wps ie if inclued */
2845b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rtw_get_wps_ie23a
2846b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    (pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL,
2847b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	     &wps_ielen))
2848b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("add bcn, wps_ielen =%d\n", wps_ielen);
2849b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2850b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* pbss_network->IEs will not include p2p_ie, wfd ie */
28519300c94b8a817f3b96cf00d2bdeed6751c2744d8Jes Sorensen	rtw_ies_remove_ie23a(pbuf, &len, _BEACON_IE_OFFSET_,
28529300c94b8a817f3b96cf00d2bdeed6751c2744d8Jes Sorensen			     WLAN_EID_VENDOR_SPECIFIC, P2P_OUI23A, 4);
28539300c94b8a817f3b96cf00d2bdeed6751c2744d8Jes Sorensen	rtw_ies_remove_ie23a(pbuf, &len, _BEACON_IE_OFFSET_,
28549300c94b8a817f3b96cf00d2bdeed6751c2744d8Jes Sorensen			     WLAN_EID_VENDOR_SPECIFIC, WFD_OUI23A, 4);
2855b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2856b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rtw_check_beacon_data23a(adapter, pbuf, len) == _SUCCESS) {
2857b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = 0;
2858b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
2859b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
2860b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2861b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2862b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(pbuf);
2863b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2864b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2865b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2866b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2867b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,
2868b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				 struct cfg80211_ap_settings *settings)
2869b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2870b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2871b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
2872b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2873a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): hidden_ssid:%d, auth_type:%d\n",
2874a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		  __func__, ndev->name, settings->hidden_ssid,
2875b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  settings->auth_type);
2876b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2877b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_add_beacon(adapter, settings->beacon.head,
2878b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     settings->beacon.head_len, settings->beacon.tail,
2879b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     settings->beacon.tail_len);
2880b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2881b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode =
2882b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		settings->hidden_ssid;
2883b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2884b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (settings->ssid && settings->ssid_len) {
2885b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct wlan_bssid_ex *pbss_network =
2886b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			&adapter->mlmepriv.cur_network.network;
2887b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct wlan_bssid_ex *pbss_network_ext =
2888b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			&adapter->mlmeextpriv.mlmext_info.network;
2889b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2890b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(pbss_network->Ssid.ssid, (void *)settings->ssid,
2891b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       settings->ssid_len);
2892b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pbss_network->Ssid.ssid_len = settings->ssid_len;
2893b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(pbss_network_ext->Ssid.ssid, (void *)settings->ssid,
2894b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       settings->ssid_len);
2895b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pbss_network_ext->Ssid.ssid_len = settings->ssid_len;
2896b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2897b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2898b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2899b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2900b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2901b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_change_beacon(struct wiphy *wiphy,
2902b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      struct net_device *ndev,
2903b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      struct cfg80211_beacon_data *info)
2904b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2905b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2906b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
2907b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2908a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2909b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2910b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail,
2911b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     info->tail_len);
2912b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2913b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2914b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2915b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2916b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
2917b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2918a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2919b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2920b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2921b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2922b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_add_station(struct wiphy *wiphy,
2923b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct net_device *ndev, u8 *mac,
2924b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct station_parameters *params)
2925b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2926a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2927b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2928b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2929b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2930b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2931b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_del_station(struct wiphy *wiphy,
2932b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct net_device *ndev, u8 *mac)
2933b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2934b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2935b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct list_head *phead, *plist, *ptmp;
2936b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 updated = 0;
2937b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_info *psta;
2938b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(ndev);
2939b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2940b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_priv *pstapriv = &padapter->stapriv;
2941b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2942a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("+%s(%s)\n", __func__, ndev->name);
2943b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2944b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true) {
2945b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, fw_state != FW_LINKED|WIFI_AP_STATE\n",
2946b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  __func__);
2947b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2948b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2949b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2950b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mac) {
2951b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("flush all sta, and cam_entry\n");
2952b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2953b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		flush_all_cam_entry23a(padapter);	/* clear CAM */
2954b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2955b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_sta_flush23a(padapter);
2956b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2957b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return ret;
2958b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2959b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2960b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("free sta macaddr =" MAC_FMT "\n", MAC_ARG(mac));
2961b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2962b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (is_broadcast_ether_addr(mac))
2963b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2964b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2965b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pstapriv->asoc_list_lock);
2966b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2967b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	phead = &pstapriv->asoc_list;
2968b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2969b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* check asoc_queue */
2970b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	list_for_each_safe(plist, ptmp, phead) {
2971b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psta = container_of(plist, struct sta_info, asoc_list);
2972b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2973b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (!memcmp(mac, psta->hwaddr, ETH_ALEN)) {
2974b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (psta->dot8021xalg == 1 &&
2975b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    psta->bpairwise_key_installed == false) {
2976b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s, sta's dot8021xalg = 1 and "
2977b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  "key_installed = false\n", __func__);
2978b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			} else {
2979b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("free psta =%p, aid =%d\n", psta,
2980b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  psta->aid);
2981b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2982b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				list_del_init(&psta->asoc_list);
2983b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pstapriv->asoc_list_cnt--;
2984b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2985b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* spin_unlock_bh(&pstapriv->asoc_list_lock); */
2986b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				updated =
2987b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    ap_free_sta23a(padapter, psta, true,
2988b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						WLAN_REASON_DEAUTH_LEAVING);
2989b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* spin_lock_bh(&pstapriv->asoc_list_lock); */
2990b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2991b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psta = NULL;
2992b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2993b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				break;
2994b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
2995b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2996b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2997b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2998b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pstapriv->asoc_list_lock);
2999b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3000b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	associated_clients_update23a(padapter, updated);
3001b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3002a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("-%s(%s)\n", __func__, ndev->name);
3003b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3004b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3005b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3006b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3007b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_change_station(struct wiphy *wiphy,
3008b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct net_device *ndev, u8 *mac,
3009b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct station_parameters *params)
3010b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3011a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
3012b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
3013b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3014b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3015b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_dump_station(struct wiphy *wiphy,
3016b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     struct net_device *ndev, int idx, u8 *mac,
3017b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     struct station_info *sinfo)
3018b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3019a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
3020b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3021b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* TODO: dump scanned queue */
3022b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3023b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return -ENOENT;
3024b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3025b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3026b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,
3027b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   struct bss_parameters *params)
3028b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3029a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
3030b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
3031b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3032b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* CONFIG_8723AU_AP_MODE */
3033b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3034b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_rx_action(struct rtw_adapter *adapter, u8 *frame,
3035b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    uint frame_len, const char *msg)
3036b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3037b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	s32 freq;
3038b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int channel;
3039b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 category, action;
3040b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3041b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	channel = rtw_get_oper_ch23a(adapter);
3042b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3043b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_action_frame_parse23a(frame, frame_len, &category, &action);
3044b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3045b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("RTW_Rx:cur_ch =%d\n", channel);
3046b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (msg)
3047b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("RTW_Rx:%s\n", msg);
3048b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
3049b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("RTW_Rx:category(%u), action(%u)\n", category,
3050b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  action);
3051b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3052b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (channel <= RTW_CH_MAX_2G_CHANNEL)
3053b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
3054b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_2GHZ);
3055b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
3056b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
3057b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_5GHZ);
3058b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3059b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_cfg80211_rx_mgmt(adapter, freq, 0, frame, frame_len, GFP_ATOMIC);
3060b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3061b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3062b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch,
3063b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				 const u8 *buf, size_t len)
3064b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3065b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct xmit_frame *pmgntframe;
3066b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct pkt_attrib *pattrib;
3067b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned char *pframe;
3068b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = _FAIL;
3069b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	bool ack = true;
3070b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_hdr *pwlanhdr;
3071b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3072b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3073b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3074b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (_FAIL == rtw_pwr_wakeup(padapter)) {
3075b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EFAULT;
3076b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
3077b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3078b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3079b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_set_scan_deny(padapter, 1000);
3080b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3081b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_scan_abort23a(padapter);
3082b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3083b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (tx_ch != rtw_get_oper_ch23a(padapter)) {
3084b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
3085b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pmlmeext->cur_channel = tx_ch;
3086b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		set_channel_bwmode23a(padapter, tx_ch,
3087b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   HAL_PRIME_CHNL_OFFSET_DONT_CARE,
3088b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   HT_CHANNEL_WIDTH_20);
3089b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3090b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3091b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* starting alloc mgmt frame to dump it */
3092b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3093b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pmgntframe == NULL) {
3094b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* ret = -ENOMEM; */
3095b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = _FAIL;
3096b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
3097b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3098b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3099b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* update attribute */
3100b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib = &pmgntframe->attrib;
3101b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	update_mgntframe_attrib23a(padapter, pattrib);
3102b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib->retry_ctrl = false;
3103b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3104b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3105b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3106b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pframe = (u8 *) (pmgntframe->buf_addr) + TXDESC_OFFSET;
3107b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3108b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pframe, (void *)buf, len);
3109b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib->pktlen = len;
3110b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3111b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwlanhdr = (struct ieee80211_hdr *)pframe;
3112b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* update seq number */
3113b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmlmeext->mgnt_seq = le16_to_cpu(pwlanhdr->seq_ctrl) >> 4;
3114b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib->seqnum = pmlmeext->mgnt_seq;
3115b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmlmeext->mgnt_seq++;
3116b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3117b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib->last_txcmdsz = pattrib->pktlen;
3118b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3119b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe) != _SUCCESS) {
3120b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ack = false;
3121b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = _FAIL;
3122b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3123b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, ack == _FAIL\n", __func__);
3124b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
3125b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, ack =%d, ok!\n", __func__, ack);
3126b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = _SUCCESS;
3127b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3128b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3129b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
3130b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3131b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ret =%d\n", __func__, ret);
3132b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3133b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3134b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3135b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3136b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
3137b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				struct cfg80211_mgmt_tx_params *params,
3138b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				u64 *cookie)
3139b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3140b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter =
3141b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		(struct rtw_adapter *)wiphy_to_adapter(wiphy);
3142b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
3143b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int tx_ret;
3144b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 dump_limit = RTW_MAX_MGMT_TX_CNT;
3145b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 dump_cnt = 0;
3146b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	bool ack = true;
3147b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 category, action;
3148b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned long start = jiffies;
3149b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	size_t len = params->len;
3150b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_channel *chan = params->chan;
3151b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	const u8 *buf = params->buf;
3152b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)buf;
3153b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 tx_ch = (u8) ieee80211_frequency_to_channel(chan->center_freq);
3154b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3155b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* cookie generation */
3156b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	*cookie = (unsigned long)buf;
3157b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
31589cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen	DBG_8723A("%s(%s): len =%zu, ch =%d\n", __func__,
31599cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		  padapter->pnetdev->name, len, tx_ch);
3160b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3161b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* indicate ack before issue frame to avoid racing with rsp frame */
3162b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_cfg80211_mgmt_tx_status(padapter, *cookie, buf, len, ack,
3163b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    GFP_KERNEL);
3164b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3165b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rtw_action_frame_parse23a(buf, len, &category, &action) == false) {
31669cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): frame_control:0x%x\n", __func__,
31679cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name,
3168b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  le16_to_cpu(hdr->frame_control));
3169b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
3170b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3171b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3172b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("RTW_Tx:tx_ch =%d, da =" MAC_FMT "\n", tx_ch,
3173b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  MAC_ARG(hdr->addr1));
3174b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (category == WLAN_CATEGORY_PUBLIC)
3175b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("RTW_Tx:%s\n", action_public_str23a(action));
3176b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
3177b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("RTW_Tx:category(%u), action(%u)\n",
3178b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  category, action);
3179b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3180b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	do {
3181b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		dump_cnt++;
3182b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, buf, len);
3183b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} while (dump_cnt < dump_limit && tx_ret != _SUCCESS);
3184b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3185b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (tx_ret != _SUCCESS || dump_cnt > 1) {
31869cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): %s (%d/%d) in %d ms\n",
31879cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  __func__, padapter->pnetdev->name,
3188b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt,
3189b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  dump_limit, jiffies_to_msecs(jiffies - start));
3190b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3191b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3192b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
3193b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3194b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3195b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3196b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,
3197b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     struct wireless_dev *wdev,
3198b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     u16 frame_type, bool reg)
3199b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3200b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
3201b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
3202b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3203b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return;
3204b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3205b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3206b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_beacon_wpsp2pie(struct net_device *ndev, char *buf,
3207b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					    int len)
3208b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3209b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
3210b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	uint wps_ielen = 0;
3211b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 *wps_ie;
3212c17416ef707312429aafcdc4597db73906f3572eLarry Finger#ifdef CONFIG_8723AU_AP_MODE
3213c17416ef707312429aafcdc4597db73906f3572eLarry Finger	u8 wps_oui[8] = { 0x0, 0x50, 0xf2, 0x04 };
3214c17416ef707312429aafcdc4597db73906f3572eLarry Finger#endif
3215b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(ndev);
3216b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3217b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3218b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3219a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): ielen =%d\n", __func__, ndev->name, len);
3220b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3221b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (len > 0) {
3222b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wps_ie = rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen);
3223b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (wps_ie) {
3224b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("bcn_wps_ielen =%d\n", wps_ielen);
3225b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3226b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pmlmepriv->wps_beacon_ie) {
3227b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->wps_beacon_ie_len = 0;
3228b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				kfree(pmlmepriv->wps_beacon_ie);
3229b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->wps_beacon_ie = NULL;
3230b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
3231b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3232b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pmlmepriv->wps_beacon_ie =
3233b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				kmalloc(wps_ielen, GFP_KERNEL);
3234b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pmlmepriv->wps_beacon_ie == NULL) {
3235b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
3236b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__, __LINE__);
3237b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				return -EINVAL;
3238b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
3239b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			memcpy(pmlmepriv->wps_beacon_ie, wps_ie, wps_ielen);
3240b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pmlmepriv->wps_beacon_ie_len = wps_ielen;
3241b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3242c17416ef707312429aafcdc4597db73906f3572eLarry Finger#ifdef CONFIG_8723AU_AP_MODE
32439300c94b8a817f3b96cf00d2bdeed6751c2744d8Jes Sorensen			update_beacon23a(padapter, WLAN_EID_VENDOR_SPECIFIC,
32449300c94b8a817f3b96cf00d2bdeed6751c2744d8Jes Sorensen					 wps_oui, true);
3245c17416ef707312429aafcdc4597db73906f3572eLarry Finger#endif
3246b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
3247b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3248b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmeext->bstart_bss = true;
3249b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3250b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3251b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3252b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3253b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3254b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3255b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_probe_resp_wpsp2pie(struct net_device *net,
3256b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						char *buf, int len)
3257b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3258b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(net);
3259b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3260c17416ef707312429aafcdc4597db73906f3572eLarry Finger	int ret = 0;
3261c17416ef707312429aafcdc4597db73906f3572eLarry Finger	uint wps_ielen = 0;
3262c17416ef707312429aafcdc4597db73906f3572eLarry Finger	u8 *wps_ie;
3263b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3264b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (len > 0) {
3265b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wps_ie = rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen);
3266b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (wps_ie) {
3267b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			uint attr_contentlen = 0;
3268b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			u16 uconfig_method, *puconfig_method = NULL;
3269b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3270b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pmlmepriv->wps_probe_resp_ie) {
3271b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->wps_probe_resp_ie_len = 0;
3272b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				kfree(pmlmepriv->wps_probe_resp_ie);
3273b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->wps_probe_resp_ie = NULL;
3274b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
3275b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3276b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pmlmepriv->wps_probe_resp_ie =
3277b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				kmalloc(wps_ielen, GFP_KERNEL);
3278b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pmlmepriv->wps_probe_resp_ie == NULL) {
3279b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
3280b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__, __LINE__);
3281b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				return -EINVAL;
3282b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3283b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
3284b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3285b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* add PUSH_BUTTON config_method by driver self in
3286b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   wpsie of probe_resp at GO Mode */
3287b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			puconfig_method = (u16 *)rtw_get_wps_attr_content23a(wps_ie, wps_ielen,
3288b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							      WPS_ATTR_CONF_METHOD,
3289b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							      NULL,
3290b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							      &attr_contentlen);
3291b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (puconfig_method) {
3292b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				uconfig_method = WPS_CM_PUSH_BUTTON;
3293b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				uconfig_method = cpu_to_be16(uconfig_method);
3294b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3295b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				*puconfig_method |= uconfig_method;
3296b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
3297b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3298b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			memcpy(pmlmepriv->wps_probe_resp_ie, wps_ie, wps_ielen);
3299b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pmlmepriv->wps_probe_resp_ie_len = wps_ielen;
3300b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3301b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
3302b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3303b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3304b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3305b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3306b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3307b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3308b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_assoc_resp_wpsp2pie(struct net_device *net,
3309b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						char *buf, int len)
3310b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3311b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
3312b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(net);
3313b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3314b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3315b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ielen =%d\n", __func__, len);
3316b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3317b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (len > 0) {
3318b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (pmlmepriv->wps_assoc_resp_ie) {
3319b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pmlmepriv->wps_assoc_resp_ie_len = 0;
3320b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			kfree(pmlmepriv->wps_assoc_resp_ie);
3321b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pmlmepriv->wps_assoc_resp_ie = NULL;
3322b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
3323b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3324b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmepriv->wps_assoc_resp_ie = kmalloc(len, GFP_KERNEL);
3325b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (pmlmepriv->wps_assoc_resp_ie == NULL) {
3326b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
3327b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  __func__, __LINE__);
3328b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			return -EINVAL;
3329b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3330b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
3331b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(pmlmepriv->wps_assoc_resp_ie, buf, len);
3332b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmepriv->wps_assoc_resp_ie_len = len;
3333b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3334b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3335b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3336b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3337b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3338b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerint rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device *net, char *buf, int len,
3339b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   int type)
3340b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3341b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
3342b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	uint wps_ielen = 0;
3343b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3344b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ielen =%d\n", __func__, len);
3345b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
334698fb81291d30f83838379bf1522fead6673b5fdfJes Sorensen	if (rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen) && (wps_ielen > 0)) {
3347b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (net) {
3348b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			switch (type) {
3349b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			case 0x1:	/* BEACON */
3350b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				ret =
3351b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    rtw_cfg80211_set_beacon_wpsp2pie(net, buf,
3352b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								     len);
3353b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				break;
3354b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			case 0x2:	/* PROBE_RESP */
3355b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				ret =
3356b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    rtw_cfg80211_set_probe_resp_wpsp2pie(net,
3357b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger									 buf,
3358b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger									 len);
3359b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				break;
3360b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			case 0x4:	/* ASSOC_RESP */
3361b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				ret =
3362b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    rtw_cfg80211_set_assoc_resp_wpsp2pie(net,
3363b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger									 buf,
3364b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger									 len);
3365b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				break;
3366b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
3367b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
3368b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3369b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3370b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3371b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3372b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3373b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3374b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct cfg80211_ops rtw_cfg80211_ops = {
3375b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.change_virtual_intf = cfg80211_rtw_change_iface,
3376b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.add_key = cfg80211_rtw_add_key,
3377b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.get_key = cfg80211_rtw_get_key,
3378b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.del_key = cfg80211_rtw_del_key,
3379b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_default_key = cfg80211_rtw_set_default_key,
3380b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.get_station = cfg80211_rtw_get_station,
3381b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.scan = cfg80211_rtw_scan,
3382b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_wiphy_params = cfg80211_rtw_set_wiphy_params,
3383b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.connect = cfg80211_rtw_connect,
3384b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.disconnect = cfg80211_rtw_disconnect,
3385b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.join_ibss = cfg80211_rtw_join_ibss,
3386b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.leave_ibss = cfg80211_rtw_leave_ibss,
3387b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_tx_power = cfg80211_rtw_set_txpower,
3388b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.get_tx_power = cfg80211_rtw_get_txpower,
3389b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_power_mgmt = cfg80211_rtw_set_power_mgmt,
3390b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_pmksa = cfg80211_rtw_set_pmksa,
3391b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.del_pmksa = cfg80211_rtw_del_pmksa,
3392b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.flush_pmksa = cfg80211_rtw_flush_pmksa,
3393b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3394b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
3395b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.add_virtual_intf = cfg80211_rtw_add_virtual_intf,
3396b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.del_virtual_intf = cfg80211_rtw_del_virtual_intf,
3397b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3398b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.start_ap = cfg80211_rtw_start_ap,
3399b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.change_beacon = cfg80211_rtw_change_beacon,
3400b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.stop_ap = cfg80211_rtw_stop_ap,
3401b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3402b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.add_station = cfg80211_rtw_add_station,
3403b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.del_station = cfg80211_rtw_del_station,
3404b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.change_station = cfg80211_rtw_change_station,
3405b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.dump_station = cfg80211_rtw_dump_station,
3406b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.change_bss = cfg80211_rtw_change_bss,
3407b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* CONFIG_8723AU_AP_MODE */
3408b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3409b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.mgmt_tx = cfg80211_rtw_mgmt_tx,
3410b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,
3411b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
3412b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3413b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap,
3414b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       enum ieee80211_band band, u8 rf_type)
3415b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3416b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3417b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define MAX_BIT_RATE_40MHZ_MCS15	300	/* Mbps */
3418b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define MAX_BIT_RATE_40MHZ_MCS7		150	/* Mbps */
3419b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3420b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->ht_supported = true;
3421b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3422b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
3423b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 |
3424b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;
3425b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3426b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*
3427b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *Maximum length of AMPDU that the STA can receive.
3428b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
3429b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 */
3430b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
3431b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3432b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*Minimum MPDU start spacing , */
3433b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
3434b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3435b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
3436b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3437b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*
3438b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *hw->wiphy->bands[IEEE80211_BAND_2GHZ]
3439b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *base on ant_num
3440b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *rx_mask: RX mask
3441b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7
3442b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15
3443b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *if rx_ant >= 3 rx_mask[2]= 0xff;
3444b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *if BW_40 rx_mask[4]= 0x01;
3445b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *highest supported RX rate
3446b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 */
3447b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rf_type == RF_1T1R) {
3448b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[0] = 0xFF;
3449b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[1] = 0x00;
3450b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[4] = 0x01;
3451b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3452b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS7;
3453b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else if ((rf_type == RF_1T2R) || (rf_type == RF_2T2R)) {
3454b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[0] = 0xFF;
3455b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[1] = 0xFF;
3456b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[4] = 0x01;
3457b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3458b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS15;
3459b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
3460b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, error rf_type =%d\n", __func__, rf_type);
3461b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3462b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3463b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3464b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3465b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter)
3466b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3467b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 rf_type;
3468b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_supported_band *bands;
3469b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *pwdev = padapter->rtw_wdev;
3470b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wiphy *wiphy = pwdev->wiphy;
3471b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3472c2370e83ab5432e2d32e9c097930c69366d27b4cJes Sorensen	rf_type = rtl8723a_get_rf_type(padapter);
3473b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3474b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s:rf_type =%d\n", __func__, rf_type);
3475b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3476b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
3477b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	{
3478b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		bands = wiphy->bands[IEEE80211_BAND_2GHZ];
3479b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (bands)
3480b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			rtw_cfg80211_init_ht_capab(&bands->ht_cap,
3481b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   IEEE80211_BAND_2GHZ,
3482b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   rf_type);
3483b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3484b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3485b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
3486b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	{
3487b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		bands = wiphy->bands[IEEE80211_BAND_5GHZ];
3488b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (bands)
3489b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			rtw_cfg80211_init_ht_capab(&bands->ht_cap,
3490b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   IEEE80211_BAND_5GHZ,
3491b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   rf_type);
3492b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3493b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3494b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3495b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_cfg80211_preinit_wiphy(struct rtw_adapter *padapter,
3496b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct wiphy *wiphy)
3497b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3498b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3499b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3500b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;
3501b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
3502b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS;
3503b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3504b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->max_remain_on_channel_duration =
3505b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    RTW_MAX_REMAIN_ON_CHANNEL_DURATION;
3506b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3507b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
3508b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    BIT(NL80211_IFTYPE_ADHOC) |
3509b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
3510b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) |
3511b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif
3512b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    0;
3513b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3514b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
3515b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes;
3516b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* CONFIG_8723AU_AP_MODE */
3517b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3518b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
3519b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3520b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*
3521b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	   wiphy->iface_combinations = &rtw_combinations;
3522b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	   wiphy->n_iface_combinations = 1;
3523b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 */
3524b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3525b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->cipher_suites = rtw_cipher_suites;
3526b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);
3527b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3528b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
3529b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->bands[IEEE80211_BAND_2GHZ] =
3530b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    rtw_spt_band_alloc(IEEE80211_BAND_2GHZ);
3531b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
3532b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->bands[IEEE80211_BAND_5GHZ] =
3533b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    rtw_spt_band_alloc(IEEE80211_BAND_5GHZ);
3534b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3535b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
3536b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME;
3537b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3538b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
3539b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
3540b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
3541b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
3542b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3543b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3544b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerint rtw_wdev_alloc(struct rtw_adapter *padapter, struct device *dev)
3545b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3546b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
3547b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wiphy *wiphy;
3548b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *wdev;
3549b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv;
3550b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *pnetdev = padapter->pnetdev;
3551b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3552b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
3553b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3554b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* wiphy */
3555b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wdev_priv));
3556b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!wiphy) {
3557b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Couldn't allocate wiphy device\n");
3558b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOMEM;
3559b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
3560b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3561b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	set_wiphy_dev(wiphy, dev);
3562b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_cfg80211_preinit_wiphy(padapter, wiphy);
3563b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3564b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = wiphy_register(wiphy);
3565b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0) {
3566b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Couldn't register wiphy device\n");
3567b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto free_wiphy;
3568b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3569b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3570b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*  wdev */
3571b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
3572b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!wdev) {
3573b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Couldn't allocate wireless device\n");
3574b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOMEM;
3575b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto unregister_wiphy;
3576b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3577b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wdev->wiphy = wiphy;
3578b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wdev->netdev = pnetdev;
3579b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* wdev->iftype = NL80211_IFTYPE_STATION; */
3580b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*  for rtw_setopmode_cmd23a() in cfg80211_rtw_change_iface() */
3581b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wdev->iftype = NL80211_IFTYPE_MONITOR;
3582b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	padapter->rtw_wdev = wdev;
3583b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pnetdev->ieee80211_ptr = wdev;
3584b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3585b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* init pwdev_priv */
3586b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv = wdev_to_priv(wdev);
3587b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->rtw_wdev = wdev;
3588b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->pmon_ndev = NULL;
3589b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->ifname_mon[0] = '\0';
3590b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->padapter = padapter;
3591b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->scan_request = NULL;
3592b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_init(&pwdev_priv->scan_req_lock);
3593b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3594b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->p2p_enabled = false;
3595b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->provdisc_req_issued = false;
3596b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_wdev_invit_info_init(&pwdev_priv->invit_info);
3597b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3598b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
3599b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->power_mgmt = true;
3600b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
3601b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->power_mgmt = false;
3602b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3603b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3604b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerunregister_wiphy:
3605b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy_unregister(wiphy);
3606b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerfree_wiphy:
3607b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy_free(wiphy);
3608b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
3609b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3610b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3611b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3612b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_wdev_free(struct wireless_dev *wdev)
3613b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3614b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
3615b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3616b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!wdev)
3617b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
3618b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3619b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(wdev->wiphy->bands[IEEE80211_BAND_2GHZ]);
3620b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(wdev->wiphy->bands[IEEE80211_BAND_5GHZ]);
3621b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3622b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy_free(wdev->wiphy);
3623b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3624b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(wdev);
3625b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3626b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3627b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_wdev_unregister(struct wireless_dev *wdev)
3628b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3629b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv;
3630b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3631b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
3632b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3633b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!wdev)
3634b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
3635b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3636b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv = wdev_to_priv(wdev);
3637b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3638b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_cfg80211_indicate_scan_done(pwdev_priv, true);
3639b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3640b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pwdev_priv->pmon_ndev) {
3641b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, unregister monitor interface\n", __func__);
3642b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		unregister_netdev(pwdev_priv->pmon_ndev);
3643b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3644b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3645b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy_unregister(wdev->wiphy);
3646b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3647