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