ioctl_cfg80211.c revision 5dab9e7d2af054ad1df60ef51e25b2dd5e85517b
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 <xmit_osdep.h>
20b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
21b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#include "ioctl_cfg80211.h"
22b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
23b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_MAX_MGMT_TX_CNT 8
24b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
25b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 65535	/* ms */
26b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_MAX_NUM_PMKIDS 4
27b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
28b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic const u32 rtw_cipher_suites[] = {
29b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	WLAN_CIPHER_SUITE_WEP40,
30b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	WLAN_CIPHER_SUITE_WEP104,
31b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	WLAN_CIPHER_SUITE_TKIP,
32b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	WLAN_CIPHER_SUITE_CCMP,
33b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
34b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
35b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RATETAB_ENT(_rate, _rateid, _flags) {			\
36b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.bitrate	= (_rate),				\
37b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.hw_value	= (_rateid),				\
38b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.flags		= (_flags),				\
39b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
40b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
41b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define CHAN2G(_channel, _freq, _flags) {			\
42b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.band			= IEEE80211_BAND_2GHZ,		\
43b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.center_freq		= (_freq),			\
44b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.hw_value		= (_channel),			\
45b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.flags			= (_flags),			\
46b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.max_antenna_gain	= 0,				\
47b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.max_power		= 30,				\
48b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
49b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
50b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define CHAN5G(_channel, _flags) {				\
51b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.band			= IEEE80211_BAND_5GHZ,		\
52b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.center_freq		= 5000 + (5 * (_channel)),	\
53b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.hw_value		= (_channel),			\
54b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.flags			= (_flags),			\
55b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.max_antenna_gain	= 0,				\
56b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.max_power		= 30,				\
57b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
58b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
59b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct ieee80211_rate rtw_rates[] = {
60b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(10, 0x1, 0),
61b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(20, 0x2, 0),
62b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(55, 0x4, 0),
63b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(110, 0x8, 0),
64b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(60, 0x10, 0),
65b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(90, 0x20, 0),
66b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(120, 0x40, 0),
67b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(180, 0x80, 0),
68b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(240, 0x100, 0),
69b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(360, 0x200, 0),
70b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(480, 0x400, 0),
71b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RATETAB_ENT(540, 0x800, 0),
72b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
73b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
74b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define rtw_a_rates		(rtw_rates + 4)
75b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_A_RATES_NUM	8
76b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define rtw_g_rates		(rtw_rates + 0)
77b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_G_RATES_NUM	12
78b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
79b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_2G_CHANNELS_NUM 14
80b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define RTW_5G_CHANNELS_NUM 37
81b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
82b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct ieee80211_channel rtw_2ghz_channels[] = {
83b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(1, 2412, 0),
84b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(2, 2417, 0),
85b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(3, 2422, 0),
86b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(4, 2427, 0),
87b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(5, 2432, 0),
88b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(6, 2437, 0),
89b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(7, 2442, 0),
90b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(8, 2447, 0),
91b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(9, 2452, 0),
92b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(10, 2457, 0),
93b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(11, 2462, 0),
94b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(12, 2467, 0),
95b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(13, 2472, 0),
96b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN2G(14, 2484, 0),
97b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
98b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
99b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct ieee80211_channel rtw_5ghz_a_channels[] = {
100b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(34, 0), CHAN5G(36, 0),
101b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(38, 0), CHAN5G(40, 0),
102b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(42, 0), CHAN5G(44, 0),
103b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(46, 0), CHAN5G(48, 0),
104b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(52, 0), CHAN5G(56, 0),
105b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(60, 0), CHAN5G(64, 0),
106b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(100, 0), CHAN5G(104, 0),
107b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(108, 0), CHAN5G(112, 0),
108b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(116, 0), CHAN5G(120, 0),
109b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(124, 0), CHAN5G(128, 0),
110b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(132, 0), CHAN5G(136, 0),
111b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(140, 0), CHAN5G(149, 0),
112b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(153, 0), CHAN5G(157, 0),
113b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(161, 0), CHAN5G(165, 0),
114b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(184, 0), CHAN5G(188, 0),
115b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(192, 0), CHAN5G(196, 0),
116b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(200, 0), CHAN5G(204, 0),
117b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(208, 0), CHAN5G(212, 0),
118b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	CHAN5G(216, 0),
119b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
120b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
121b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_2g_channels_init(struct ieee80211_channel *channels)
122b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
123b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy((void *)channels, (void *)rtw_2ghz_channels,
124b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct ieee80211_channel) * RTW_2G_CHANNELS_NUM);
125b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
126b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
127b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_5g_channels_init(struct ieee80211_channel *channels)
128b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
129b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy((void *)channels, (void *)rtw_5ghz_a_channels,
130b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct ieee80211_channel) * RTW_5G_CHANNELS_NUM);
131b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
132b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
133b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_2g_rates_init(struct ieee80211_rate *rates)
134b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
135b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(rates, rtw_g_rates,
136b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM);
137b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
138b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
139b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_5g_rates_init(struct ieee80211_rate *rates)
140b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
141b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(rates, rtw_a_rates,
142b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM);
143b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
144b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
145b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct ieee80211_supported_band *
146b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerrtw_spt_band_alloc(enum ieee80211_band band)
147b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
148b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_supported_band *spt_band = NULL;
149b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int n_channels, n_bitrates;
150b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
151b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (band == IEEE80211_BAND_2GHZ) {
152b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		n_channels = RTW_2G_CHANNELS_NUM;
153b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		n_bitrates = RTW_G_RATES_NUM;
154b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else if (band == IEEE80211_BAND_5GHZ) {
155b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		n_channels = RTW_5G_CHANNELS_NUM;
156b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		n_bitrates = RTW_A_RATES_NUM;
157b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
158b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
159b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
160b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spt_band = kzalloc(sizeof(struct ieee80211_supported_band) +
161b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   sizeof(struct ieee80211_channel) * n_channels +
162b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   sizeof(struct ieee80211_rate) * n_bitrates,
163b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   GFP_KERNEL);
164b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!spt_band)
165b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
166b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
167b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spt_band->channels =
168b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		(struct ieee80211_channel *)(((u8 *) spt_band) +
169b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     sizeof(struct
170b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    ieee80211_supported_band));
171b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spt_band->bitrates =
172b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		(struct ieee80211_rate *)(((u8 *) spt_band->channels) +
173b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  sizeof(struct ieee80211_channel) *
174b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  n_channels);
175b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spt_band->band = band;
176b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spt_band->n_channels = n_channels;
177b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spt_band->n_bitrates = n_bitrates;
178b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
179b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (band == IEEE80211_BAND_2GHZ) {
180b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_2g_channels_init(spt_band->channels);
181b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_2g_rates_init(spt_band->bitrates);
182b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else if (band == IEEE80211_BAND_5GHZ) {
183b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_5g_channels_init(spt_band->channels);
184b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_5g_rates_init(spt_band->bitrates);
185b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
186b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
187b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* spt_band.ht_cap */
188b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
189b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
190b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return spt_band;
191b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
192b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
193b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic const struct ieee80211_txrx_stypes
194b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerrtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
195b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	[NL80211_IFTYPE_ADHOC] = {
196b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.tx = 0xffff,
197b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.rx = BIT(IEEE80211_STYPE_ACTION >> 4)
198b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	},
199b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	[NL80211_IFTYPE_STATION] = {
200b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.tx = 0xffff,
201b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
202b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
203b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	},
204b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	[NL80211_IFTYPE_AP] = {
205b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.tx = 0xffff,
206b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
207b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
208b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
209b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
210b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_AUTH >> 4) |
211b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
212b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_ACTION >> 4)
213b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	},
214b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	[NL80211_IFTYPE_AP_VLAN] = {
215b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* copy AP */
216b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.tx = 0xffff,
217b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
218b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
219b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
220b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
221b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_AUTH >> 4) |
222b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
223b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_ACTION >> 4)
224b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	},
225b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	[NL80211_IFTYPE_P2P_CLIENT] = {
226b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.tx = 0xffff,
227b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
228b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
229b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	},
230b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	[NL80211_IFTYPE_P2P_GO] = {
231b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.tx = 0xffff,
232b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
233b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
234b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
235b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
236b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_AUTH >> 4) |
237b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
238b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		      BIT(IEEE80211_STYPE_ACTION >> 4)
239b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	},
240b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
241b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
242b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter,
243b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   struct wlan_network *pnetwork)
244b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
245b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
246b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_channel *notify_channel;
247b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cfg80211_bss *bss;
248b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u16 channel;
249b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 freq;
250b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 *notify_ie;
251b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	size_t notify_ielen;
252b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	s32 notify_signal;
253b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *wdev = padapter->rtw_wdev;
254b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wiphy *wiphy = wdev->wiphy;
255b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
256b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
25737cb982c2685029e716bfeccf55ec244a6919a32Jes Sorensen	channel = pnetwork->network.DSConfig;
258b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (channel <= RTW_CH_MAX_2G_CHANNEL)
259b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
260b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_2GHZ);
261b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
262b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
263b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_5GHZ);
264b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
265b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	notify_channel = ieee80211_get_channel(wiphy, freq);
266b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2671de65ccb1f90be71cd7deb3c963f7440560e4325Jes Sorensen	notify_ie = pnetwork->network.IEs;
2681de65ccb1f90be71cd7deb3c963f7440560e4325Jes Sorensen	notify_ielen = pnetwork->network.IELength;
269b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
270b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM:
271b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *  signal strength in mBm (100*dBm)
272b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 */
273b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, _FW_LINKED) &&
274b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    is_same_network23a(&pmlmepriv->cur_network.network,
275b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    &pnetwork->network)) {
276b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		notify_signal = 100 * translate_percentage_to_dbm(padapter->recvpriv.signal_strength);	/* dbm */
277b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
278b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		notify_signal = 100 * translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength);	/* dbm */
279b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
280b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2814062f7aa8f867e515267aeec62a152d2cf763a1cJes Sorensen	bss = cfg80211_inform_bss(wiphy, notify_channel,
282993c52ba61a72a8c669c8091fa75c9514776b3f7Jes Sorensen				  pnetwork->network.MacAddress,
283993c52ba61a72a8c669c8091fa75c9514776b3f7Jes Sorensen				  pnetwork->network.tsf,
28411a80e8877bf2db8a13b68018049b48e367bd76eJes Sorensen				  pnetwork->network.capability,
285143ced27acaa948cbcf34cafe0bca3c926fd35fcJes Sorensen				  pnetwork->network.beacon_interval,
2864062f7aa8f867e515267aeec62a152d2cf763a1cJes Sorensen				  notify_ie, notify_ielen,
2874062f7aa8f867e515267aeec62a152d2cf763a1cJes Sorensen				  notify_signal, GFP_ATOMIC);
288b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
289b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (unlikely(!bss)) {
290b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("rtw_cfg80211_inform_bss error\n");
291b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
292b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
293b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
294b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	cfg80211_put_bss(wiphy, bss);
295b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
296b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
297b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
298b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
299b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter)
300b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
301b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
302b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wlan_network *cur_network = &pmlmepriv->cur_network;
303b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *pwdev = padapter->rtw_wdev;
304b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
305b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
306b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
307b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pwdev->iftype != NL80211_IFTYPE_STATION &&
308b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
309b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
310b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
311b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
312b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
313b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
31456828797acdb99d23b5e5e5c52e7d571d59b783fJes Sorensen	if (padapter->mlmepriv.to_roaming > 0) {
315b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct wiphy *wiphy = pwdev->wiphy;
316b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct ieee80211_channel *notify_channel;
317b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		u32 freq;
31837cb982c2685029e716bfeccf55ec244a6919a32Jes Sorensen		u16 channel = cur_network->network.DSConfig;
319b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
320b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (channel <= RTW_CH_MAX_2G_CHANNEL)
321b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			freq =
322b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    ieee80211_channel_to_frequency(channel,
323b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							   IEEE80211_BAND_2GHZ);
324b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		else
325b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			freq =
326b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    ieee80211_channel_to_frequency(channel,
327b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							   IEEE80211_BAND_5GHZ);
328b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
329b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		notify_channel = ieee80211_get_channel(wiphy, freq);
330b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
331b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s call cfg80211_roamed\n", __func__);
332b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		cfg80211_roamed(padapter->pnetdev, notify_channel,
333b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				cur_network->network.MacAddress,
334b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->assoc_req +
335b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				sizeof(struct ieee80211_hdr_3addr) + 2,
336b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->assoc_req_len -
337b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				sizeof(struct ieee80211_hdr_3addr) - 2,
338b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->assoc_rsp +
339b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				sizeof(struct ieee80211_hdr_3addr) + 6,
340b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->assoc_rsp_len -
341b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				sizeof(struct ieee80211_hdr_3addr) - 6,
342b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				GFP_ATOMIC);
343b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
344b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		cfg80211_connect_result(padapter->pnetdev,
345b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					cur_network->network.MacAddress,
346b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pmlmepriv->assoc_req +
347b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					sizeof(struct ieee80211_hdr_3addr) + 2,
348b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pmlmepriv->assoc_req_len -
349b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					sizeof(struct ieee80211_hdr_3addr) - 2,
350b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pmlmepriv->assoc_rsp +
351b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					sizeof(struct ieee80211_hdr_3addr) + 6,
352b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pmlmepriv->assoc_rsp_len -
353b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					sizeof(struct ieee80211_hdr_3addr) - 6,
354b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					WLAN_STATUS_SUCCESS, GFP_ATOMIC);
355b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
356b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
357b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
358b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter)
359b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
360b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
361b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *pwdev = padapter->rtw_wdev;
362b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
363b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
364b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
365b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pwdev->iftype != NL80211_IFTYPE_STATION &&
366b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
367b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
368b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
369b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
370b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
371b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
372b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!padapter->mlmepriv.not_indic_disco) {
373b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING)) {
374b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			cfg80211_connect_result(padapter->pnetdev, NULL, NULL,
375b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						0, NULL, 0,
376b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						WLAN_STATUS_UNSPECIFIED_FAILURE,
377b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						GFP_ATOMIC);
378b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		} else {
379b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			cfg80211_disconnected(padapter->pnetdev, 0, NULL,
380b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      0, GFP_ATOMIC);
381b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
382b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
383b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
384b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
385b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
38616b9632da2c071d74934447e266717787bec449bJes Sorensenstatic int set_pairwise_key(struct rtw_adapter *padapter, struct sta_info *psta)
387b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
388b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cmd_obj *ph2c;
389b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct set_stakey_parm *psetstakey_para;
390b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
39116b9632da2c071d74934447e266717787bec449bJes Sorensen	int res = _SUCCESS;
392b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
393b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
394b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ph2c == NULL) {
395b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		res = _FAIL;
396b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
397b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
398b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
399b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
400b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (psetstakey_para == NULL) {
401b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		kfree(ph2c);
402b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		res = _FAIL;
403b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
404b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
405b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
406b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
407b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
4087989bcf3e21683f413dd1488718166d3ff474bf3Jes Sorensen	psetstakey_para->algorithm = psta->dot118021XPrivacy;
409b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
410888df442ef023adbca6536888eae65b2cd8ae295Jes Sorensen	ether_addr_copy(psetstakey_para->addr, psta->hwaddr);
411b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
412b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
413b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
414b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
415b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
416b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
417b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return res;
418b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
419b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
4207989bcf3e21683f413dd1488718166d3ff474bf3Jes Sorensenstatic int set_group_key(struct rtw_adapter *padapter, u8 *key, u32 alg,
4214e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen			 u8 keyid)
422b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
423b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 keylen;
424b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cmd_obj *pcmd;
425b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct setkey_parm *psetkeyparm;
426b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
427b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int res = _SUCCESS;
428b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
429b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
430b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
4314e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen	if (keyid >= 4) {
4324e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen		res = _FAIL;
4334e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen		goto exit;
4344e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen	}
4354e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen
436b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
437b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!pcmd) {
438b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		res = _FAIL;
439b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
440b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
441b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
442b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!psetkeyparm) {
443b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		kfree(pcmd);
444b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		res = _FAIL;
445b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
446b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
447b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
4484e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen	psetkeyparm->keyid = keyid;
449b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (is_wep_enc(alg))
4504e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen		padapter->mlmepriv.key_mask |= BIT(psetkeyparm->keyid);
451b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
452b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psetkeyparm->algorithm = alg;
453b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
454b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psetkeyparm->set_tx = 1;
455b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
456b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (alg) {
4579e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	case WLAN_CIPHER_SUITE_WEP40:
458b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		keylen = 5;
459b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
4609e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	case WLAN_CIPHER_SUITE_WEP104:
461b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		keylen = 13;
462b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
4639e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	case WLAN_CIPHER_SUITE_TKIP:
4649e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	case WLAN_CIPHER_SUITE_CCMP:
465b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
466b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		keylen = 16;
467b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
468b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
469b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(&psetkeyparm->key[0], key, keylen);
470b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
471b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->cmdcode = _SetKey_CMD_;
472b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->parmbuf = (u8 *) psetkeyparm;
473b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->cmdsz = (sizeof(struct setkey_parm));
474b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->rsp = NULL;
475b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->rspsz = 0;
476b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
477b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
478b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
479b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
480b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return res;
481b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
482b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
483e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensenstatic int set_wep_key(struct rtw_adapter *padapter, u8 *key, u16 keylen,
4844e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen		       u8 keyid)
485b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
4869e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	u32 alg;
487b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
488b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (keylen) {
489b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case 5:
4909e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		alg = WLAN_CIPHER_SUITE_WEP40;
491b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
492b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case 13:
4939e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		alg = WLAN_CIPHER_SUITE_WEP104;
494b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
495b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
4969e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		alg = 0;
497b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
498b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
499b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return set_group_key(padapter, key, alg, keyid);
500b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
501b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
502b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_ap_set_encryption(struct net_device *dev,
503b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  struct ieee_param *param,
5045dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen					  u32 param_len,
5055dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen					  struct key_params *keyparms)
506b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
507b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
508e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	u16 wep_key_len;
5094e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen	u8 wep_key_idx;
510b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_info *psta = NULL, *pbcmc_sta = NULL;
511b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(dev);
512b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
513b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
514b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_priv *pstapriv = &padapter->stapriv;
515b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
516b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
517b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
518b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param->u.crypt.err = 0;
519b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
520b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
521b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* sizeof(struct ieee_param) = 64 bytes; */
522b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (param_len !=  (u32) ((u8 *) param->u.crypt.key -
523b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	   (u8 *) param) + param->u.crypt.key_len) */
524b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) {
525b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
526b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
527b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
528b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
529b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (is_broadcast_ether_addr(param->sta_addr)) {
530b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (param->u.crypt.idx >= WEP_KEYS) {
531b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EINVAL;
532b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
533b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
534b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
535b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psta = rtw_get_stainfo23a(pstapriv, param->sta_addr);
536b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (!psta) {
537b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* ret = -EINVAL; */
538b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("rtw_set_encryption(), sta has already "
539b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  "been removed or never been added\n");
540b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
541b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
542b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
543b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
544b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
545b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* todo:clear default encryption keys */
546b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
547b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("clear default encryption keys, keyid =%d\n",
548b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  param->u.crypt.idx);
549b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
550b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
551b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
552b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
5535dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen	if (!psta && (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
5545dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen		      keyparms->cipher == WLAN_CIPHER_SUITE_WEP104)) {
555b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("r871x_set_encryption, crypt.alg = WEP\n");
556b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
557b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_idx = param->u.crypt.idx;
558b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_len = param->u.crypt.key_len;
559b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
560b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("r871x_set_encryption, wep_key_idx =%d, len =%d\n",
561b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  wep_key_idx, wep_key_len);
562b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
563b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
564b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EINVAL;
565b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
566b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
567b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
568b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (wep_key_len > 0) {
569b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			wep_key_len = wep_key_len <= 5 ? 5 : 13;
570b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
571b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
572b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
573b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* wep default key has not been set, so use
574b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   this key index as default key. */
575b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
576b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->ndisencryptstatus =
577b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				Ndis802_11Encryption1Enabled;
5789e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen			psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
5799e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen			psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
580b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
581b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (wep_key_len == 13) {
5829e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
5839e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104;
584b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
585b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
586b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
587b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
588b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
589e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen		memcpy(&psecuritypriv->wep_key[wep_key_idx].key,
590b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       param->u.crypt.key, wep_key_len);
591b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
592e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen		psecuritypriv->wep_key[wep_key_idx].keylen = wep_key_len;
593b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
594b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		set_wep_key(padapter, param->u.crypt.key, wep_key_len,
595b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    wep_key_idx);
596b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
597b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
598b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
599b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
600b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
601b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) {	/*  group key */
602b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (param->u.crypt.set_tx == 0) {	/* group key */
6035dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen			if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
6045dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen			    keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
6059cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen				DBG_8723A("%s, set group_key, WEP\n", __func__);
606b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
607b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
608b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       dot118021XGrpKey[param->u.crypt.idx].
609b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       skey, param->u.crypt.key,
610b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       (param->u.crypt.key_len >
611b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					16 ? 16 : param->u.crypt.key_len));
612b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6139e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
614b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if (param->u.crypt.key_len == 13) {
615b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy =
6169e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen					    WLAN_CIPHER_SUITE_WEP104;
617b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
618b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6195dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen			} else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) {
620b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s, set group_key, TKIP\n",
621b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__);
622b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6239e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_TKIP;
624b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
625b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
626b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       dot118021XGrpKey[param->u.crypt.idx].
627b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       skey, param->u.crypt.key,
628b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       (param->u.crypt.key_len >
629b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					16 ? 16 : param->u.crypt.key_len));
630b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
631b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
632b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* set mic key */
633b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
634b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       dot118021XGrptxmickey[param->u.crypt.
635b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							     idx].skey,
636b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       &param->u.crypt.key[16], 8);
637b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
638b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       dot118021XGrprxmickey[param->u.crypt.
639b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							     idx].skey,
640b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       &param->u.crypt.key[24], 8);
641b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6429216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen				psecuritypriv->busetkipkey = 1;
643b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6445dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen			} else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) {
6455dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen					DBG_8723A("%s, set group_key, CCMP\n",
646b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__);
647b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6489e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_CCMP;
649b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
650b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
651b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       dot118021XGrpKey[param->u.crypt.idx].
652b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       skey, param->u.crypt.key,
653b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       (param->u.crypt.key_len >
654b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					16 ? 16 : param->u.crypt.key_len));
655b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			} else {
656b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s, set group_key, none\n",
657b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__);
658b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
659b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psecuritypriv->dot118021XGrpPrivacy =
6609e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				    0;
661b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
662b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
663b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
664b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6659216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen			psecuritypriv->binstallGrpkey = 1;
666b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
667b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->dot11PrivacyAlgrthm =
668b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psecuritypriv->dot118021XGrpPrivacy;
669b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
670b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			set_group_key(padapter, param->u.crypt.key,
671b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      psecuritypriv->dot118021XGrpPrivacy,
672b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      param->u.crypt.idx);
673b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
674b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
675b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pbcmc_sta) {
676b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pbcmc_sta->ieee8021x_blocked = false;
677b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* rx will use bmc_sta's dot118021XPrivacy */
678b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pbcmc_sta->dot118021XPrivacy =
679b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy;
680b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
681b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
682b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
683b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
684b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
685b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
686b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
687b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
688b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (psecuritypriv->dot11AuthAlgrthm ==
689b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    dot11AuthAlgrthm_8021X && psta) {	/*  psk/802_1x */
690b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
691b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (param->u.crypt.set_tx == 1) {
692b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* pairwise key */
693b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psta->dot118021x_UncstKey.skey,
694b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       param->u.crypt.key,
695b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       (param->u.crypt.key_len >
696b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					16 ? 16 : param->u.crypt.key_len));
697b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6985dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen				if (keyparms->cipher ==
6995dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen				    WLAN_CIPHER_SUITE_WEP40 ||
7005dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen				    keyparms->cipher ==
7015dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen				    WLAN_CIPHER_SUITE_WEP104) {
702b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A("%s, set pairwise key, WEP\n",
703b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						  __func__);
704b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7059e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen					psta->dot118021XPrivacy = WLAN_CIPHER_SUITE_WEP40;
706b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					if (param->u.crypt.key_len == 13) {
707b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						psta->dot118021XPrivacy =
7089e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen							WLAN_CIPHER_SUITE_WEP104;
709b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					}
7105dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen				} else if (keyparms->cipher ==
7115dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen					   WLAN_CIPHER_SUITE_TKIP) {
712b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A("%s, set pairwise key, "
713b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						  "TKIP\n", __func__);
714b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7155dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen					psta->dot118021XPrivacy =
7165dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen						WLAN_CIPHER_SUITE_TKIP;
717b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
718b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
719b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* set mic key */
720b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psta->dot11tkiptxmickey.skey,
721b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       &param->u.crypt.key[16], 8);
722b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psta->dot11tkiprxmickey.skey,
723b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       &param->u.crypt.key[24], 8);
724b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7259216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen					psecuritypriv->busetkipkey = 1;
726b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7275dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen				} else if (keyparms->cipher ==
7285dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen					   WLAN_CIPHER_SUITE_CCMP) {
729b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A("%s, set pairwise key, "
730b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						  "CCMP\n", __func__);
731b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7325dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen					psta->dot118021XPrivacy =
7335dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen						WLAN_CIPHER_SUITE_CCMP;
734b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				} else {
735b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A("%s, set pairwise key, "
736b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						  "none\n", __func__);
737b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7389e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen					psta->dot118021XPrivacy = 0;
739b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
740b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
741b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				set_pairwise_key(padapter, psta);
742b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
743b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psta->ieee8021x_blocked = false;
744b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
745b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psta->bpairwise_key_installed = true;
746b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			} else {	/* group key??? */
7475dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen				if (keyparms->cipher ==
7485dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen				    WLAN_CIPHER_SUITE_WEP40 ||
7495dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen				    keyparms->cipher ==
7505dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen				    WLAN_CIPHER_SUITE_WEP104) {
751b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psecuritypriv->
752b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrpKey[param->u.crypt.
753b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								idx].skey,
754b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       param->u.crypt.key,
755b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       (param->u.crypt.key_len >
756b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						16 ? 16 : param->u.crypt.
757b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						key_len));
758b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
759b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy =
7609e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen						WLAN_CIPHER_SUITE_WEP40;
761b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					if (param->u.crypt.key_len == 13) {
762b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						psecuritypriv->
763b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    dot118021XGrpPrivacy =
7649e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen							WLAN_CIPHER_SUITE_WEP104;
765b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					}
7665dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen				} else if (keyparms->cipher ==
7675dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen					   WLAN_CIPHER_SUITE_TKIP) {
768b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy =
7699e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen					    WLAN_CIPHER_SUITE_TKIP;
770b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
771b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psecuritypriv->
772b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrpKey[param->u.crypt.
773b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								idx].skey,
774b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       param->u.crypt.key,
775b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       (param->u.crypt.key_len >
776b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						16 ? 16 : param->u.crypt.
777b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						key_len));
778b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
779b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* DEBUG_ERR("set key length :param->u"
780b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					   ".crypt.key_len =%d\n",
781b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					   param->u.crypt.key_len); */
782b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* set mic key */
783b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psecuritypriv->
784b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrptxmickey[param->u.
785b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								     crypt.idx].
786b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       skey, &param->u.crypt.key[16],
787b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       8);
788b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psecuritypriv->
789b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrprxmickey[param->u.
790b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								     crypt.idx].
791b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       skey, &param->u.crypt.key[24],
792b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       8);
793b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7949216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen					psecuritypriv->busetkipkey = 1;
795b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7965dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen				} else if (keyparms->cipher ==
7975dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen					   WLAN_CIPHER_SUITE_CCMP) {
798b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy =
7999e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen						WLAN_CIPHER_SUITE_CCMP;
800b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
801b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psecuritypriv->
802b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrpKey[param->u.crypt.
803b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								idx].skey,
804b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       param->u.crypt.key,
805b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       (param->u.crypt.key_len >
806b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						16 ? 16 : param->u.crypt.
807b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						key_len));
808b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				} else {
809b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy =
8109e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen						0;
811b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
812b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
813b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psecuritypriv->dot118021XGrpKeyid =
814b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					param->u.crypt.idx;
815b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
8169216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen				psecuritypriv->binstallGrpkey = 1;
817b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
818b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psecuritypriv->dot11PrivacyAlgrthm =
819b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy;
820b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
821b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				set_group_key(padapter, param->u.crypt.key,
822b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      psecuritypriv->
823b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      dot118021XGrpPrivacy,
824b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      param->u.crypt.idx);
825b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
826b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
827b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if (pbcmc_sta) {
828b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* rx will use bmc_sta's
829b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					   dot118021XPrivacy */
830b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pbcmc_sta->ieee8021x_blocked = false;
831b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;
832b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
833b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
834b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
835b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
836b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
837b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
838b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
839b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
840b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
841b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
842b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif
843b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
844b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_encryption(struct net_device *dev,
845b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct ieee_param *param, u32 param_len)
846b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
847b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
848e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	u32 wep_key_idx;
849e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	u16 wep_key_len;
850b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(dev);
851b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
852b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
853b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
854b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
855b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
856b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param->u.crypt.err = 0;
857b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
858b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
859b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (param_len <
860b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    (u32) ((u8 *) param->u.crypt.key - (u8 *) param) +
861b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    param->u.crypt.key_len) {
862b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
863b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
864b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
865b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
866b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (is_broadcast_ether_addr(param->sta_addr)) {
867b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (param->u.crypt.idx >= WEP_KEYS) {
868b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EINVAL;
869b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
870b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
871b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
872b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
873b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
874b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
875b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
876b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (strcmp(param->u.crypt.alg, "WEP") == 0) {
877b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
878b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			 ("wpa_set_encryption, crypt.alg = WEP\n"));
879b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("wpa_set_encryption, crypt.alg = WEP\n");
880b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
881b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_idx = param->u.crypt.idx;
882b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_len = param->u.crypt.key_len;
883b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
884b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if ((wep_key_idx > WEP_KEYS) || (wep_key_len <= 0)) {
885b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EINVAL;
886b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
887b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
888b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
889b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
890b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* wep default key has not been set, so use this
891b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   key index as default key. */
892b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
893b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			wep_key_len = wep_key_len <= 5 ? 5 : 13;
894b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
895b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->ndisencryptstatus =
896b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				Ndis802_11Encryption1Enabled;
8979e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen			psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
8989e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen			psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
899b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
900b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (wep_key_len == 13) {
9019e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
9029e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen				psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104;
903b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
904b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
905b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
906b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
907b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
908e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen		memcpy(&psecuritypriv->wep_key[wep_key_idx].key,
909b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       param->u.crypt.key, wep_key_len);
910b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
911e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen		psecuritypriv->wep_key[wep_key_idx].keylen = wep_key_len;
912b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
913b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_set_key23a(padapter, psecuritypriv, wep_key_idx, 0);
914b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
915b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
916b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
917b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
918b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (padapter->securitypriv.dot11AuthAlgrthm ==
919b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    dot11AuthAlgrthm_8021X) {	/*  802_1x */
920b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct sta_info *psta, *pbcmc_sta;
921b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct sta_priv *pstapriv = &padapter->stapriv;
922b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
923b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (check_fwstate(pmlmepriv,
924b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  WIFI_STATION_STATE | WIFI_MP_STATE)) {
925b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* sta mode */
926b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psta = rtw_get_stainfo23a(pstapriv, get_bssid(pmlmepriv));
927b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (psta == NULL) {
928b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s, : Obtain Sta_info fail\n",
929b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__);
930b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			} else {
931b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* Jeff: don't disable ieee8021x_blocked
932b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   while clearing key */
933b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if (strcmp(param->u.crypt.alg, "none") != 0)
934b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psta->ieee8021x_blocked = false;
935b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
936b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if ((padapter->securitypriv.ndisencryptstatus ==
937b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     Ndis802_11Encryption2Enabled) ||
938b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    (padapter->securitypriv.ndisencryptstatus ==
939b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     Ndis802_11Encryption3Enabled)) {
940b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psta->dot118021XPrivacy =
941b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						padapter->securitypriv.
942b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						dot11PrivacyAlgrthm;
943b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
944b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
945b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if (param->u.crypt.set_tx == 1) {
946b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* pairwise key */
947b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A("%s, : param->u.crypt.set_tx"
948b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						  " == 1\n", __func__);
949b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
950b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psta->dot118021x_UncstKey.skey,
951b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       param->u.crypt.key,
952b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       (param->u.crypt.key_len >
953b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						16 ? 16 : param->u.crypt.
954b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						key_len));
955b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
956b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					if (strcmp(param->u.crypt.alg,
957b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   "TKIP") == 0) {
958b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						memcpy(psta->dot11tkiptxmickey.
959b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       skey,
960b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       &param->u.crypt.key[16],
961b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       8);
962b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						memcpy(psta->dot11tkiprxmickey.
963b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       skey,
964b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       &param->u.crypt.key[24],
965b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       8);
966b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
967b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						padapter->securitypriv.
9689216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen							busetkipkey = 0;
969b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					}
970b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A(" ~~~~set sta key:unicastkey\n");
971b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
972b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					rtw_setstakey_cmd23a(padapter,
973b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							  (unsigned char *)psta,
974b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							  true);
975b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				} else {	/* group key */
976b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(padapter->securitypriv.
977b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrpKey[param->u.crypt.
978b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								idx].skey,
979b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       param->u.crypt.key,
980b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       (param->u.crypt.key_len >
981b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						16 ? 16 : param->u.crypt.
982b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						key_len));
983b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(padapter->securitypriv.
984b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrptxmickey[param->u.
985b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								     crypt.idx].
986b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       skey, &param->u.crypt.key[16],
987b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       8);
988b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(padapter->securitypriv.
989b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       dot118021XGrprxmickey[param->u.
990b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger								     crypt.idx].
991b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       skey, &param->u.crypt.key[24],
992b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       8);
993b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					padapter->securitypriv.binstallGrpkey =
9949216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen						1;
995b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* DEBUG_ERR((" param->u.crypt.key_len"
996b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					   "=%d\n", param->u.crypt.key_len)); */
997b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A
998b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					    (" ~~~~set sta key:groupkey\n");
999b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1000b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					padapter->securitypriv.
1001b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					    dot118021XGrpKeyid =
1002b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						param->u.crypt.idx;
1003b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1004b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					rtw_set_key23a(padapter,
1005b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    &padapter->securitypriv,
1006b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    param->u.crypt.idx, 1);
1007b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
1008b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
1009b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1010b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
1011b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pbcmc_sta) {
1012b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* Jeff: don't disable ieee8021x_blocked
1013b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   while clearing key */
1014b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if (strcmp(param->u.crypt.alg, "none") != 0)
1015b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pbcmc_sta->ieee8021x_blocked = false;
1016b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1017b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if ((padapter->securitypriv.ndisencryptstatus ==
1018b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     Ndis802_11Encryption2Enabled) ||
1019b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    (padapter->securitypriv.ndisencryptstatus ==
1020b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     Ndis802_11Encryption3Enabled)) {
1021b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pbcmc_sta->dot118021XPrivacy =
1022b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					    padapter->securitypriv.
1023b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					    dot11PrivacyAlgrthm;
1024b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
1025b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
1026b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		} else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {	/* adhoc mode */
1027b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1028b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1029b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1030b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
1031b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1032b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ret =%d\n", __func__, ret);
1033b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1034b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1035b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1036b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1037b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1038b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1039b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
1040b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				u8 key_index, bool pairwise,
1041b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				const u8 *mac_addr, struct key_params *params)
1042b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1043b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	char *alg_name;
1044b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 param_len;
10456f1c59bf2c00eeba0f9ad9ce176cce731de1a8e5Jes Sorensen	struct ieee_param *param;
1046b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1047b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
1048b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1049b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1050b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1051a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): adding key for %pM\n", __func__, ndev->name,
1052b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  mac_addr);
1053b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("cipher = 0x%x\n", params->cipher);
1054b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("key_len = 0x%x\n", params->key_len);
1055b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("seq_len = 0x%x\n", params->seq_len);
1056b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("key_index =%d\n", key_index);
1057b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("pairwise =%d\n", pairwise);
1058b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1059b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param_len = sizeof(struct ieee_param) + params->key_len;
1060b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param = kzalloc(param_len, GFP_KERNEL);
10616f1c59bf2c00eeba0f9ad9ce176cce731de1a8e5Jes Sorensen	if (!param)
10626f1c59bf2c00eeba0f9ad9ce176cce731de1a8e5Jes Sorensen		return -ENOMEM;
1063b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1064b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param->cmd = IEEE_CMD_SET_ENCRYPTION;
106543c34be13047dd53e70bc4759ff314424db7036bJes Sorensen	eth_broadcast_addr(param->sta_addr);
1066b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1067b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (params->cipher) {
1068b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case IW_AUTH_CIPHER_NONE:
1069b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* todo: remove key */
1070b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* remove = 1; */
1071b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		alg_name = "none";
1072b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1073b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_WEP40:
1074b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_WEP104:
1075b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		alg_name = "WEP";
1076b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1077b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_TKIP:
1078b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		alg_name = "TKIP";
1079b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1080b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_CCMP:
1081b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		alg_name = "CCMP";
1082b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1083b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1084b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
1085b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOTSUPP;
1086b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto addkey_end;
1087b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1088b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1089b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1090b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1091b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
1092b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		param->u.crypt.set_tx = 0;	/* for wpa/wpa2 group key */
1093b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
1094b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		param->u.crypt.set_tx = 1;	/* for wpa/wpa2 pairwise key */
1095b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1096b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1097b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* param->u.crypt.idx = key_index - 1; */
1098b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	param->u.crypt.idx = key_index;
1099b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1100b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (params->seq_len && params->seq) {
1101b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(param->u.crypt.seq, params->seq, params->seq_len);
1102b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1103b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1104b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (params->key_len && params->key) {
1105b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		param->u.crypt.key_len = params->key_len;
1106b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(param->u.crypt.key, params->key, params->key_len);
1107b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1108b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1109b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1110b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_cfg80211_set_encryption(ndev, param, param_len);
1111b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1112b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
1113b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (mac_addr)
1114888df442ef023adbca6536888eae65b2cd8ae295Jes Sorensen			ether_addr_copy(param->sta_addr, mac_addr);
1115b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
11165dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen		ret = rtw_cfg80211_ap_set_encryption(ndev, param, param_len,
11175dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen						     params);
1118b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif
1119b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
1120b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("error! fw_state = 0x%x, iftype =%d\n",
1121b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  pmlmepriv->fw_state, rtw_wdev->iftype);
1122b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1123b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1124b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1125b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingeraddkey_end:
1126b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(param);
1127b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1128b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1129b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1130b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1131b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int
1132b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingercfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,
1133b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		     u8 key_index, bool pairwise, const u8 *mac_addr,
1134b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		     void *cookie,
1135b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		     void (*callback) (void *cookie, struct key_params *))
1136b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1137a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
1138b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1139b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1140b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1141b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
1142b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				u8 key_index, bool pairwise,
1143b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				const u8 *mac_addr)
1144b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1145b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(ndev);
1146b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
1147b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1148a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): key_index =%d\n", __func__, ndev->name, key_index);
1149b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1150b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (key_index == psecuritypriv->dot11PrivacyKeyIndex) {
1151b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* clear the flag of wep default key set. */
1152b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->bWepDefaultKeyIdxSet = 0;
1153b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1154b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1155b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1156b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1157b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1158b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
1159b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					struct net_device *ndev, u8 key_index,
1160b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					bool unicast, bool multicast)
1161b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1162b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(ndev);
1163b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
1164b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1165a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): key_index =%d, unicast =%d, multicast =%d.\n",
1166a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		  __func__, ndev->name, key_index, unicast, multicast);
1167b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1168e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	if (key_index < NUM_WEP_KEYS &&
1169e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	    (psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP40 ||
1170e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	     psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP104)) {
1171b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* set wep default key */
1172b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1173b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1174b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11PrivacyKeyIndex = key_index;
1175b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
11769e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
11779e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
1178e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen		if (psecuritypriv->wep_key[key_index].keylen == 13) {
1179e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen			psecuritypriv->dot11PrivacyAlgrthm =
1180e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen				WLAN_CIPHER_SUITE_WEP104;
1181e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen			psecuritypriv->dot118021XGrpPrivacy =
1182e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen				WLAN_CIPHER_SUITE_WEP104;
1183b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1184b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1185b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* set the flag to represent that wep default key
1186b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		   has been set */
1187b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->bWepDefaultKeyIdxSet = 1;
1188b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1189b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1190b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1191b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1192b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
119327fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensenstatic u16 rtw_get_cur_max_rate(struct rtw_adapter *adapter)
119427fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen{
119527fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	int i = 0;
119627fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	const u8 *p;
119727fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	u16 rate = 0, max_rate = 0;
119827fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
119927fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
120027fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	struct registry_priv *pregistrypriv = &adapter->registrypriv;
120127fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
120227fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
120327fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	struct ieee80211_ht_cap *pht_capie;
120427fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	u8 rf_type = 0;
120527fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
120627fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	u16 mcs_rate = 0;
120727fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
12081d33b0766385957c0e70ff32ec501d1f775c8316Jes Sorensen	p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
12091de65ccb1f90be71cd7deb3c963f7440560e4325Jes Sorensen			     pcur_bss->IEs, pcur_bss->IELength);
121027fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	if (p && p[1] > 0) {
121127fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		pht_capie = (struct ieee80211_ht_cap *)(p + 2);
121227fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
121327fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		memcpy(&mcs_rate, &pht_capie->mcs, 2);
121427fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
121527fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		/* bw_40MHz = (pht_capie->cap_info&
121627fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		   IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1:0; */
121727fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		/* cur_bwmod is updated by beacon, pmlmeinfo is
121827fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		   updated by association response */
121927fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		bw_40MHz = (pmlmeext->cur_bwmode &&
122027fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			    (pmlmeinfo->HT_info.ht_param &
122127fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			     IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) ? 1:0;
122227fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
122327fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		/* short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP
122427fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		   _SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; */
122527fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		short_GI_20 = (pmlmeinfo->ht_cap.cap_info &
122627fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			       cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) ? 1:0;
122727fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		short_GI_40 = (pmlmeinfo->ht_cap.cap_info &
122827fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			       cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) ? 1:0;
122927fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
123027fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		rf_type = rtl8723a_get_rf_type(adapter);
123127fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		max_rate = rtw_mcs_rate23a(rf_type, bw_40MHz &
123227fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen					   pregistrypriv->cbw40_enable,
123327fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen					   short_GI_20, short_GI_40,
123427fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen					   &pmlmeinfo->ht_cap.mcs);
123527fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	} else {
123627fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		while (pcur_bss->SupportedRates[i] != 0 &&
123727fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		       pcur_bss->SupportedRates[i] != 0xFF) {
123827fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			rate = pcur_bss->SupportedRates[i] & 0x7F;
123927fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			if (rate>max_rate)
124027fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen				max_rate = rate;
124127fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			i++;
124227fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		}
124327fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
124427fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		max_rate = max_rate * 10 / 2;
124527fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	}
124627fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
124727fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	return max_rate;
124827fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen}
124927fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
1250b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_get_station(struct wiphy *wiphy,
1251b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct net_device *ndev,
1252f9da455b93f6ba076935b4ef4589f61e529ae046Linus Torvalds				    const u8 *mac, struct station_info *sinfo)
1253b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1254b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1255b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1256b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1257b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_info *psta = NULL;
1258b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_priv *pstapriv = &padapter->stapriv;
1259b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1260b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	sinfo->filled = 0;
1261b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1262b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mac) {
1263a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("%s(%s): mac ==%p\n", __func__, ndev->name, mac);
1264b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOENT;
1265b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1266b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1267b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1268b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psta = rtw_get_stainfo23a(pstapriv, mac);
1269b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (psta == NULL) {
1270b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, sta_info is null\n", __func__);
1271b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOENT;
1272b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1273b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1274a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): mac =" MAC_FMT "\n", __func__, ndev->name,
1275b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  MAC_ARG(mac));
1276b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1277b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* for infra./P2PClient mode */
1278b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
1279b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    check_fwstate(pmlmepriv, _FW_LINKED)) {
1280b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct wlan_network *cur_network = &pmlmepriv->cur_network;
1281b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1282cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen		if (!ether_addr_equal(mac, cur_network->network.MacAddress)) {
1283b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("%s, mismatch bssid =" MAC_FMT "\n", __func__,
1284b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  MAC_ARG(cur_network->network.MacAddress));
1285b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -ENOENT;
1286b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
1287b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1288b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1289b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->filled |= STATION_INFO_SIGNAL;
1290b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.
1291b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							    signal_strength);
1292b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1293b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->filled |= STATION_INFO_TX_BITRATE;
129427fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter);
1295b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1296b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->filled |= STATION_INFO_RX_PACKETS;
1297b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->rx_packets = sta_rx_data_pkts(psta);
1298b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1299b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->filled |= STATION_INFO_TX_PACKETS;
1300b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->tx_packets = psta->sta_stats.tx_pkts;
1301b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1302b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1303b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* for Ad-Hoc/AP mode */
1304b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
1305b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	     check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1306b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	     check_fwstate(pmlmepriv, WIFI_AP_STATE)) &&
1307b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    check_fwstate(pmlmepriv, _FW_LINKED)
1308b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    ) {
1309b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* TODO: should acquire station info... */
1310b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1311b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1312b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
1313b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1314b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1315b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1316efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensenint cfg80211_infrastructure_mode(struct rtw_adapter* padapter,
1317efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				 enum nl80211_iftype ifmode)
1318efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen{
1319efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1320efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	struct wlan_network *cur_network = &pmlmepriv->cur_network;
1321efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	enum nl80211_iftype old_mode;
1322efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1323efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	old_mode = cur_network->network.ifmode;
1324efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1325efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
1326efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		 ("+%s: old =%d new =%d fw_state = 0x%08x\n", __func__,
1327efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		  old_mode, ifmode, get_fwstate(pmlmepriv)));
1328efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1329efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	if (old_mode != ifmode) {
1330efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		spin_lock_bh(&pmlmepriv->lock);
1331efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1332efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1333efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			 (" change mode!"));
1334efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1335efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		if (old_mode == NL80211_IFTYPE_AP ||
1336efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    old_mode == NL80211_IFTYPE_P2P_GO) {
1337efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			/* change to other mode from Ndis802_11APMode */
1338efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			cur_network->join_res = -1;
1339efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1340efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen#ifdef CONFIG_8723AU_AP_MODE
1341efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			stop_ap_mode23a(padapter);
1342efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen#endif
1343efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		}
1344efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1345efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		if (check_fwstate(pmlmepriv, _FW_LINKED) ||
1346efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    old_mode == NL80211_IFTYPE_ADHOC)
1347efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			rtw_disassoc_cmd23a(padapter, 0, true);
1348efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1349efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		if (check_fwstate(pmlmepriv, _FW_LINKED) ||
1350efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
1351efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			rtw_free_assoc_resources23a(padapter, 1);
1352efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1353efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		if (old_mode == NL80211_IFTYPE_STATION ||
1354efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    old_mode == NL80211_IFTYPE_P2P_CLIENT ||
1355efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    old_mode == NL80211_IFTYPE_ADHOC) {
1356efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1357efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				/* will clr Linked_state; before this function,
1358efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				   we must have chked whether issue
1359efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				   dis-assoc_cmd or not */
1360efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				rtw_indicate_disconnect23a(padapter);
1361efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			}
1362efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	       }
1363efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1364efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		cur_network->network.ifmode = ifmode;
1365efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1366efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		_clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
1367efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1368efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		switch (ifmode) {
1369efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_ADHOC:
1370efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
1371efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			break;
1372efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1373efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_P2P_CLIENT:
1374efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_STATION:
1375efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			set_fwstate(pmlmepriv, WIFI_STATION_STATE);
1376efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			break;
1377efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1378efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_P2P_GO:
1379efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_AP:
1380efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			set_fwstate(pmlmepriv, WIFI_AP_STATE);
1381efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen#ifdef CONFIG_8723AU_AP_MODE
1382efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			start_ap_mode23a(padapter);
1383efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			/* rtw_indicate_connect23a(padapter); */
1384efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen#endif
1385efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			break;
1386efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1387efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		default:
1388efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			break;
1389efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		}
1390efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1391efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		/* SecClearAllKeys(adapter); */
1392efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1393efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		/* RT_TRACE(COMP_OID_SET, DBG_LOUD,
1394efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		   ("set_infrastructure: fw_state:%x after changing mode\n", */
1395efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		/* get_fwstate(pmlmepriv))); */
1396efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1397efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		spin_unlock_bh(&pmlmepriv->lock);
1398efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	}
1399efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1400efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	return _SUCCESS;
1401efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen}
1402efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1403b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_change_iface(struct wiphy *wiphy,
1404b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     struct net_device *ndev,
1405b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     enum nl80211_iftype type, u32 *flags,
1406b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     struct vif_params *params)
1407b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1408b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	enum nl80211_iftype old_type;
1409b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1410b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1411b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
1412b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1413b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1414a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): call netdev_open23a\n", __func__, ndev->name);
1415b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1416b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	old_type = rtw_wdev->iftype;
1417a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): old_iftype =%d, new_iftype =%d\n",
1418a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		  __func__, ndev->name, old_type, type);
1419b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1420b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (old_type != type) {
1421b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmeext->action_public_rxseq = 0xffff;
1422b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmeext->action_public_dialog_token = 0xff;
1423b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1424b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1425b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (type) {
1426b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_ADHOC:
1427b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_P2P_CLIENT:
1428b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_STATION:
1429b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_P2P_GO:
1430b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_AP:
1431efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	case NL80211_IFTYPE_UNSPECIFIED:
1432b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1433b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
1434b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EOPNOTSUPP;
1435b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1436b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1437b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_wdev->iftype = type;
1438b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1439efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	if (cfg80211_infrastructure_mode(padapter, type) != _SUCCESS) {
1440b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_wdev->iftype = old_type;
1441b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
1442b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1443b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1444b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1445efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	rtw_setopmode_cmd23a(padapter, type);
1446b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1447b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
1448b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1449b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1450b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1451b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
1452b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     bool aborted)
1453b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1454b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pwdev_priv->scan_req_lock);
1455b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pwdev_priv->scan_request != NULL) {
1456b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s with scan req\n", __func__);
1457141bd353c5a9ba987dbe7b28ffdd034bb3ed55baJes Sorensen
1458b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (pwdev_priv->scan_request->wiphy !=
1459b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		    pwdev_priv->rtw_wdev->wiphy)
1460b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("error wiphy compare\n");
1461b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		else
1462b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			cfg80211_scan_done(pwdev_priv->scan_request, aborted);
1463b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1464b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->scan_request = NULL;
1465b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
1466b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s without scan req\n", __func__);
1467b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1468b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pwdev_priv->scan_req_lock);
1469b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1470b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1471b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter)
1472b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1473b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct list_head *plist, *phead, *ptmp;
1474b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1475b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1476b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wlan_network *pnetwork;
1477b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1478b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1479b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1480b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	phead = get_list_head(queue);
1481b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1482b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	list_for_each_safe(plist, ptmp, phead) {
1483b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pnetwork = container_of(plist, struct wlan_network, list);
1484b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1485b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* report network only if the current channel set
1486b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		   contains the channel to which this network belongs */
1487b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (rtw_ch_set_search_ch23a
1488b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		    (padapter->mlmeextpriv.channel_set,
148937cb982c2685029e716bfeccf55ec244a6919a32Jes Sorensen		     pnetwork->network.DSConfig) >= 0)
1490b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			rtw_cfg80211_inform_bss(padapter, pnetwork);
1491b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1492b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1493b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1494b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1495b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* call this after other things have been done */
1496b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev),
1497b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					false);
1498b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1499b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1500b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter,
1501b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       char *buf, int len)
1502b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1503b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1504d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen	const u8 *wps_ie;
1505b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1506b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1507b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ielen =%d\n", __func__, len);
1508b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1509b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (len > 0) {
1510d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1511d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen						 WLAN_OUI_TYPE_MICROSOFT_WPS,
1512d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen						 buf, len);
1513b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (wps_ie) {
1514d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen			DBG_8723A("probe_req_wps_ielen =%d\n", wps_ie[1]);
1515141bd353c5a9ba987dbe7b28ffdd034bb3ed55baJes Sorensen
1516b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pmlmepriv->wps_probe_req_ie) {
1517b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->wps_probe_req_ie_len = 0;
1518b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				kfree(pmlmepriv->wps_probe_req_ie);
1519b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->wps_probe_req_ie = NULL;
1520b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
1521b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1522d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen			pmlmepriv->wps_probe_req_ie = kmemdup(wps_ie, wps_ie[1],
15234a6eea4dcbc0328c3126fed264c42b0725bea659Benoit Taine							      GFP_KERNEL);
1524b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pmlmepriv->wps_probe_req_ie == NULL) {
1525b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
1526b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__, __LINE__);
1527b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				return -EINVAL;
1528b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
1529d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen			pmlmepriv->wps_probe_req_ie_len = wps_ie[1];
1530b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1531b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1532b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1533b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1534b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1535b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1536b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_scan(struct wiphy *wiphy,
1537b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     struct cfg80211_scan_request *request)
1538b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1539b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int i;
1540b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 _status = false;
1541b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1542b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1543b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1544b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1545b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
1546b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
1547b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cfg80211_ssid *ssids = request->ssids;
1548b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	bool need_indicate_scan_done = false;
1549b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1550a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name);
1551b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1552b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pwdev_priv->scan_req_lock);
1553b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->scan_request = request;
1554b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pwdev_priv->scan_req_lock);
1555b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1556b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1557b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s under WIFI_AP_STATE\n", __func__);
1558b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* need_indicate_scan_done = true; */
1559b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* goto check_need_indicate_scan_done; */
1560b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1561b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1562b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rtw_pwr_wakeup(padapter) == _FAIL) {
1563b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		need_indicate_scan_done = true;
1564b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto check_need_indicate_scan_done;
1565b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1566b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1567b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (request->ie && request->ie_len > 0) {
1568b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_cfg80211_set_probe_req_wpsp2pie(padapter,
1569b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    (u8 *) request->ie,
1570b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    request->ie_len);
1571b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1572b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1573b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) {
1574b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, bBusyTraffic == true\n", __func__);
1575b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		need_indicate_scan_done = true;
1576b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto check_need_indicate_scan_done;
1577b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1578b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rtw_is_scan_deny(padapter)) {
15799cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): scan deny\n", __func__,
15809cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name);
1581b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		need_indicate_scan_done = true;
1582b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto check_need_indicate_scan_done;
1583b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1584b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1585b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ==
1586b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    true) {
1587b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, fwstate = 0x%x\n", __func__, pmlmepriv->fw_state);
1588b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		need_indicate_scan_done = true;
1589b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto check_need_indicate_scan_done;
1590b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1591b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1592b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memset(ssid, 0, sizeof(struct cfg80211_ssid) * RTW_SSID_SCAN_AMOUNT);
1593b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* parsing request ssids, n_ssids */
1594b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
1595b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("ssid =%s, len =%d\n", ssids[i].ssid,
1596b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  ssids[i].ssid_len);
1597b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(ssid[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
1598b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ssid[i].ssid_len = ssids[i].ssid_len;
1599b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1600b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1601b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* parsing channels, n_channels */
1602b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memset(ch, 0,
1603b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct rtw_ieee80211_channel) * RTW_CHANNEL_SCAN_AMOUNT);
1604b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1605b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (request->n_channels == 1) {
1606b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		for (i = 0; i < request->n_channels &&
1607b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		     i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
16089cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			DBG_8723A("%s:(%s):" CHAN_FMT "\n",
16099cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen				  __func__, padapter->pnetdev->name,
1610b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  CHAN_ARG(request->channels[i]));
1611b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ch[i].hw_value = request->channels[i]->hw_value;
1612b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ch[i].flags = request->channels[i]->flags;
1613b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1614b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1615b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1616b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pmlmepriv->lock);
1617b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (request->n_channels == 1) {
1618b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(&ch[1], &ch[0], sizeof(struct rtw_ieee80211_channel));
1619b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(&ch[2], &ch[0], sizeof(struct rtw_ieee80211_channel));
1620b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		_status = rtw_sitesurvey_cmd23a(padapter, ssid,
1621b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     RTW_SSID_SCAN_AMOUNT, ch, 3);
1622b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
1623b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		_status = rtw_sitesurvey_cmd23a(padapter, ssid,
1624b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     RTW_SSID_SCAN_AMOUNT, NULL, 0);
1625b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1626b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pmlmepriv->lock);
1627b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1628b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (_status == false)
1629b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -1;
1630b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1631b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingercheck_need_indicate_scan_done:
1632b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (need_indicate_scan_done)
1633b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_cfg80211_surveydone_event_callback(padapter);
1634b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1635b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1636b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1637b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1638b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1639b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
1640b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1641b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1642b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1643b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
1644b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct cfg80211_ibss_params *params)
1645b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1646a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
1647b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1648b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1649b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1650b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1651b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1652a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
1653b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1654b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1655b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1656b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv,
1657b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					u32 wpa_version)
1658b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1659b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, wpa_version =%d\n", __func__, wpa_version);
1660b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1661b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!wpa_version) {
1662b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
1663b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return 0;
1664b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1665b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1666b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) {
1667b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
1668b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1669b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1670b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger/*
1671b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (wpa_version & NL80211_WPA_VERSION_2)
1672b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	{
1673b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;
1674b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1675b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger*/
1676b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1677b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1678b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1679b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1680b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
1681b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      enum nl80211_auth_type sme_auth_type)
1682b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1683b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, nl80211_auth_type =%d\n", __func__, sme_auth_type);
1684b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1685b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (sme_auth_type) {
1686b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_AUTHTYPE_AUTOMATIC:
1687b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1688b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1689b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1690b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_AUTHTYPE_OPEN_SYSTEM:
1691b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1692b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1693b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (psecuritypriv->ndisauthtype > Ndis802_11AuthModeWPA)
1694b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->dot11AuthAlgrthm =
1695b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				dot11AuthAlgrthm_8021X;
1696b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1697b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_AUTHTYPE_SHARED_KEY:
1698b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1699b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1700b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1701b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1702b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
1703b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1704b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* return -ENOTSUPP; */
1705b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1706b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1707b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1708b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1709b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1710b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv,
1711b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   u32 cipher, bool ucast)
1712b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1713b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 ndisencryptstatus = Ndis802_11EncryptionDisabled;
1714b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1715b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :
1716b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    &psecuritypriv->dot118021XGrpPrivacy;
1717b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1718b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ucast =%d, cipher = 0x%x\n", __func__, ucast, cipher);
1719b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1720b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!cipher) {
17219e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = 0;
1722b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1723b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return 0;
1724b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1725b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1726b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (cipher) {
1727b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case IW_AUTH_CIPHER_NONE:
17289e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = 0;
1729b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11EncryptionDisabled;
1730b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1731b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_WEP40:
17329e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = WLAN_CIPHER_SUITE_WEP40;
1733b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11Encryption1Enabled;
1734b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1735b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_WEP104:
17369e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = WLAN_CIPHER_SUITE_WEP104;
1737b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11Encryption1Enabled;
1738b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1739b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_TKIP:
17409e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = WLAN_CIPHER_SUITE_TKIP;
1741b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11Encryption2Enabled;
1742b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1743b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_CCMP:
17449e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = WLAN_CIPHER_SUITE_CCMP;
1745b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11Encryption3Enabled;
1746b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1747b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
1748b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Unsupported cipher: 0x%x\n", cipher);
1749b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -ENOTSUPP;
1750b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1751b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1752b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ucast)
1753b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1754b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1755b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1756b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1757b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1758b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv,
1759b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    u32 key_mgt)
1760b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1761b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, key_mgt = 0x%x\n", __func__, key_mgt);
1762b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1763b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (key_mgt == WLAN_AKM_SUITE_8021X)
1764b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1765b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else if (key_mgt == WLAN_AKM_SUITE_PSK)
1766b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1767b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
1768b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Invalid key mgt: 0x%x\n", key_mgt);
1769b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1770b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1771b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1772b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1773b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
1774b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   size_t ielen)
1775b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1776d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen	const u8 *wps_ie;
1777b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int group_cipher = 0, pairwise_cipher = 0;
1778b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
177958aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen	const u8 *pwpa, *pwpa2;
1780b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int i;
1781b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1782b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!pie || !ielen) {
1783b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* Treat this as normal case, but need to clear
1784b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		   WIFI_UNDER_WPS */
1785b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1786b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1787b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1788b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) {
1789b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
1790b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1791b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1792b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1793b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* dump */
1794b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("set wpa_ie(length:%zu):\n", ielen);
1795b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	for (i = 0; i < ielen; i = i + 8)
17967579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen		DBG_8723A("0x%.2x 0x%.2x 0x%.2x 0x%.2x "
17977579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen			  "0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
17987579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen			  pie[i], pie[i + 1], pie[i + 2], pie[i + 3],
17997579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen			  pie[i + 4], pie[i + 5], pie[i + 6], pie[i + 7]);
1800b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ielen < RSN_HEADER_LEN) {
1801b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
1802b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			 ("Ie len too short %d\n", (int)ielen));
1803b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -1;
1804b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1805b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1806b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
180758aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen	pwpa = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
180858aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen				       WLAN_OUI_TYPE_MICROSOFT_WPA,
18097579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen				       pie, ielen);
181058aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen	if (pwpa && pwpa[1] > 0) {
181158aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen		if (rtw_parse_wpa_ie23a(pwpa, pwpa[1] + 2, &group_cipher,
181258aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen					&pairwise_cipher, NULL) == _SUCCESS) {
1813b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			padapter->securitypriv.dot11AuthAlgrthm =
1814b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				dot11AuthAlgrthm_8021X;
1815b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			padapter->securitypriv.ndisauthtype =
1816b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				Ndis802_11AuthModeWPAPSK;
181758aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			memcpy(padapter->securitypriv.supplicant_ie, pwpa,
181858aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			       pwpa[1] + 2);
1819b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
182058aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			DBG_8723A("got wpa_ie, wpa_ielen:%u\n", pwpa[1]);
1821b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1822b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1823b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
18247579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen	pwpa2 = cfg80211_find_ie(WLAN_EID_RSN, pie, ielen);
182558aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen	if (pwpa2 && pwpa2[1] > 0) {
182658aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen		if (rtw_parse_wpa2_ie23a (pwpa2, pwpa2[1] + 2, &group_cipher,
182758aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen					  &pairwise_cipher, NULL) == _SUCCESS) {
1828b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			padapter->securitypriv.dot11AuthAlgrthm =
1829b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				dot11AuthAlgrthm_8021X;
1830b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			padapter->securitypriv.ndisauthtype =
1831b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				Ndis802_11AuthModeWPA2PSK;
183258aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			memcpy(padapter->securitypriv.supplicant_ie, pwpa2,
183358aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			       pwpa2[1] + 2);
1834b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
183558aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			DBG_8723A("got wpa2_ie, wpa2_ielen:%u\n", pwpa2[1]);
1836b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1837b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1838b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1839b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (group_cipher == 0) {
1840b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		group_cipher = WPA_CIPHER_NONE;
1841b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1842b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pairwise_cipher == 0) {
1843b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pairwise_cipher = WPA_CIPHER_NONE;
1844b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1845b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1846b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (group_cipher) {
1847b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_NONE:
18489e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = 0;
1849b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1850b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11EncryptionDisabled;
1851b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1852b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_WEP40:
18539e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
1854b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1855b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption1Enabled;
1856b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1857b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_TKIP:
18589e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_TKIP;
1859b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1860b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption2Enabled;
1861b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1862b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_CCMP:
18639e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_CCMP;
1864b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1865b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption3Enabled;
1866b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1867b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_WEP104:
18689e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104;
1869b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1870b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption1Enabled;
1871b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1872b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1873b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1874b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (pairwise_cipher) {
1875b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_NONE:
18769e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = 0;
1877b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1878b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11EncryptionDisabled;
1879b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1880b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_WEP40:
18819e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
1882b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1883b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption1Enabled;
1884b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1885b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_TKIP:
18869e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_TKIP;
1887b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1888b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption2Enabled;
1889b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1890b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_CCMP:
18919e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_CCMP;
1892b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1893b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption3Enabled;
1894b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1895b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_WEP104:
18969e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
1897b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1898b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption1Enabled;
1899b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1900b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1901b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1902d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen	wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1903d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen					 WLAN_OUI_TYPE_MICROSOFT_WPS,
19047579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen					 pie, ielen);
1905d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen	if (wps_ie && wps_ie[1] > 0) {
1906d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		DBG_8723A("got wps_ie, wps_ielen:%u\n", wps_ie[1]);
1907d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		padapter->securitypriv.wps_ie_len = wps_ie[1];
1908d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		memcpy(padapter->securitypriv.wps_ie, wps_ie,
1909d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		       padapter->securitypriv.wps_ie_len);
1910d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
1911d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen	} else {
1912d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1913b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1914b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1915b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* TKIP and AES disallow multicast packets until installing group key */
19169e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	if (padapter->securitypriv.dot11PrivacyAlgrthm ==
19179e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	    WLAN_CIPHER_SUITE_TKIP ||
19189e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	    padapter->securitypriv.dot11PrivacyAlgrthm ==
19199e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	    WLAN_CIPHER_SUITE_CCMP)
1920b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* WPS open need to enable multicast */
1921b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true)*/
1922763b4247cafdb978630d4da7ff48c8113c7d961eJes Sorensen		rtl8723a_off_rcr_am(padapter);
1923b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1924b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1925b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->"
1926b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  "securitypriv.ndisencryptstatus =%d padapter->"
1927b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  "securitypriv.ndisauthtype =%d\n", pairwise_cipher,
1928b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  padapter->securitypriv.ndisencryptstatus,
1929b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  padapter->securitypriv.ndisauthtype));
1930b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1931b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
1932b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret)
1933b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1934b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1935b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1936b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
19376893c8ebba521ea9d0f1cc4a53233fcb09271d52Jes Sorensenstatic int rtw_cfg80211_add_wep(struct rtw_adapter *padapter,
1938deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				struct rtw_wep_key *wep, u8 keyid)
19391e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen{
1940deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen	int res;
19411e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	struct security_priv *psecuritypriv = &padapter->securitypriv;
19421e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
1943deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen	if (keyid >= NUM_WEP_KEYS) {
19441e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
19451e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen			 ("%s:keyid>4 =>fail\n", __func__));
19461e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		res = _FAIL;
19471e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		goto exit;
19481e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	}
19491e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
1950deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen	switch (wep->keylen) {
19514d9c63bbd207b20ae648bd6bd3ebcf6e52619616Jes Sorensen	case WLAN_KEY_LEN_WEP40:
19521e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
19531e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
19541e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen			 ("%s:wep->KeyLength = 5\n", __func__));
19551e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		break;
19564d9c63bbd207b20ae648bd6bd3ebcf6e52619616Jes Sorensen	case WLAN_KEY_LEN_WEP104:
19571e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
19581e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
19591e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen			 ("%s:wep->KeyLength = 13\n", __func__));
19601e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		break;
19611e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	default:
19621e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		psecuritypriv->dot11PrivacyAlgrthm = 0;
19631e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
19641e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen			 ("%s:wep->KeyLength!= 5 or 13\n", __func__));
19651e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		res = _FAIL;
19661e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		goto exit;
19671e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	}
19681e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
19691e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1970deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		 ("%s:before memcpy, wep->KeyLength = 0x%x keyid =%x\n",
1971deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		  __func__, wep->keylen, keyid));
19721e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
1973deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen	memcpy(&psecuritypriv->wep_key[keyid], wep, sizeof(struct rtw_wep_key));
19741e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
19751e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	psecuritypriv->dot11PrivacyKeyIndex = keyid;
19761e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
19771e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
19781e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		 ("%s:security key material : "
19791e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  "%x %x %x %x %x %x %x %x %x %x %x %x %x\n", __func__,
19801e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[0],
19811e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[1],
19821e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[2],
19831e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[3],
19841e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[4],
19851e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[5],
19861e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[6],
19871e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[7],
19881e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[8],
19891e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[9],
19901e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[10],
19911e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[11],
19921e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[12]));
19931e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
19941e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	res = rtw_set_key23a(padapter, psecuritypriv, keyid, 1);
19951e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
19961e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensenexit:
19971e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
19981e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	return res;
19991e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen}
20001e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
2001e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensenstatic int rtw_set_ssid(struct rtw_adapter *padapter,
2002e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen			struct wlan_network *newnetwork)
200397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen{
200497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
200597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	struct wlan_network *pnetwork = &pmlmepriv->cur_network;
200697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	int status = _SUCCESS;
200797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	u32 cur_time = 0;
200897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
200997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	DBG_8723A_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n",
2010e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen			newnetwork->network.Ssid.ssid, get_fwstate(pmlmepriv));
201197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
201297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	if (padapter->hw_init_completed == false) {
201397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
201497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			 ("set_ssid: hw_init_completed == false =>exit!!!\n"));
201597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		status = _FAIL;
201697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		goto exit;
201797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	}
201897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
201997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	spin_lock_bh(&pmlmepriv->lock);
202097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
202197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	DBG_8723A("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
202297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
202397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		goto handle_tkip_countermeasure;
202497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
202597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
202697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
202797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			 ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
202897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
2029e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen		if (pmlmepriv->assoc_ssid.ssid_len ==
2030e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen		    newnetwork->network.Ssid.ssid_len &&
2031e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen		    !memcmp(&pmlmepriv->assoc_ssid.ssid,
2032e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen			    newnetwork->network.Ssid.ssid,
2033e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen			    newnetwork->network.Ssid.ssid_len)) {
203497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
203597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				RT_TRACE(_module_rtl871x_ioctl_set_c_,
203697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					 _drv_err_, ("New SSID is same SSID, "
203797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen						     "fw_state = 0x%08x\n",
203897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen						     get_fwstate(pmlmepriv)));
203997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
204097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				if (rtw_is_same_ibss23a(padapter, pnetwork)) {
204197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					/*
204297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					 * it means driver is in
204397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					 * WIFI_ADHOC_MASTER_STATE, we needn't
204497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					 * create bss again.
204597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					 */
204697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					goto release_mlme_lock;
204797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				}
204897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
204997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				/*
205097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				 * if in WIFI_ADHOC_MASTER_STATE |
205197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				 * WIFI_ADHOC_STATE, create bss or
205297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				 * rejoin again
205397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				 */
205497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				rtw_disassoc_cmd23a(padapter, 0, true);
205597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
205697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				if (check_fwstate(pmlmepriv, _FW_LINKED))
205797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					rtw_indicate_disconnect23a(padapter);
205897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
205997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				rtw_free_assoc_resources23a(padapter, 1);
206097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
206197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				if (check_fwstate(pmlmepriv,
206297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen						  WIFI_ADHOC_MASTER_STATE)) {
206397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					_clr_fwstate_(pmlmepriv,
206497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen						      WIFI_ADHOC_MASTER_STATE);
206597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					set_fwstate(pmlmepriv,
206697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen						    WIFI_ADHOC_STATE);
206797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				}
206897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			} else {
206997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				rtw_lps_ctrl_wk_cmd23a(padapter,
207097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen						       LPS_CTRL_JOINBSS, 1);
207197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			}
207297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		} else {
207397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
207497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				 ("Set SSID not the same ssid\n"));
207597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
2076e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen				 ("set_ssid =[%s] len = 0x%x\n",
2077e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen				  newnetwork->network.Ssid.ssid,
2078e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen				  newnetwork->network.Ssid.ssid_len));
207997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
208097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				 ("assoc_ssid =[%s] len = 0x%x\n",
208197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				  pmlmepriv->assoc_ssid.ssid,
208297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				  pmlmepriv->assoc_ssid.ssid_len));
208397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
208497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			rtw_disassoc_cmd23a(padapter, 0, true);
208597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
208697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			if (check_fwstate(pmlmepriv, _FW_LINKED))
208797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				rtw_indicate_disconnect23a(padapter);
208897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
208997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			rtw_free_assoc_resources23a(padapter, 1);
209097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
209197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
209297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
209397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
209497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			}
209597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		}
209697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	}
209797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
209897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensenhandle_tkip_countermeasure:
209997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
210097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	if (padapter->securitypriv.btkip_countermeasure == true) {
210197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		cur_time = jiffies;
210297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
210397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		if ((cur_time -
210497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		     padapter->securitypriv.btkip_countermeasure_time) >
210597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		    60 * HZ) {
210697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			padapter->securitypriv.btkip_countermeasure = false;
210797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			padapter->securitypriv.btkip_countermeasure_time = 0;
210897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		} else {
210997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			status = _FAIL;
211097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			goto release_mlme_lock;
211197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		}
211297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	}
211397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
2114e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen	memcpy(&pmlmepriv->assoc_ssid, &newnetwork->network.Ssid,
2115e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen	       sizeof(struct cfg80211_ssid));
2116e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen
211797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	pmlmepriv->assoc_by_bssid = false;
211897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
211972795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen	pmlmepriv->to_join = true;
212072795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen
212172795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen	if (!check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
212272795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen		pmlmepriv->cur_network.join_res = -2;
212397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
212472795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen		status = rtw_do_join_network(padapter, newnetwork);
212572795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen		if (status == _SUCCESS) {
212672795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen			pmlmepriv->to_join = false;
212772795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen		} else {
212872795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen			if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
212972795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				/* switch to ADHOC_MASTER */
213072795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				status = rtw_do_join_adhoc(padapter);
213172795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				if (status != _SUCCESS)
213272795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen					goto release_mlme_lock;
213372795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen			} else {
213472795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				/* can't associate ; reset under-linking */
213572795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
213672795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				status = _FAIL;
213772795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				pmlmepriv->to_join = false;
213872795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen			}
213972795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen		}
214072795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen	}
214197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensenrelease_mlme_lock:
214297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	spin_unlock_bh(&pmlmepriv->lock);
214397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
214497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensenexit:
214597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
214697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		 ("-%s: status =%d\n", __func__, status));
214797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
214897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	return status;
214997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen}
215097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
2151b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
2152b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				struct cfg80211_connect_params *sme)
2153b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2154b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2155b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct list_head *phead, *plist, *ptmp;
2156b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wlan_network *pnetwork = NULL;
2157b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* u8 matched_by_bssid = false; */
2158b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* u8 matched_by_ssid = false; */
2159b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 matched = false;
2160b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2161b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2162b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
2163b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_queue *queue = &pmlmepriv->scanned_queue;
2164b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2165a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("=>" "%s(%s)\n", __func__, ndev->name);
2166b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("privacy =%d, key =%p, key_len =%d, key_idx =%d\n",
2167b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  sme->privacy, sme->key, sme->key_len, sme->key_idx);
2168b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2169b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (_FAIL == rtw_pwr_wakeup(padapter)) {
2170b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
2171b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2172b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2173b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2174b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2175b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
2176b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2177b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2178b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2179c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen	if (!sme->ssid || !sme->ssid_len ||
2180c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen	    sme->ssid_len > IEEE80211_MAX_SSID_LEN) {
2181b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
2182b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2183b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2184b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2185c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen	DBG_8723A("ssid =%s, len =%zu\n", sme->ssid, sme->ssid_len);
2186b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2187b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (sme->bssid)
2188b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("bssid =" MAC_FMT "\n", MAC_ARG(sme->bssid));
2189b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2190b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
2191b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EBUSY;
2192b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, fw_state = 0x%x, goto exit\n", __func__,
2193b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  pmlmepriv->fw_state);
2194b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2195b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2196b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
2197b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_scan_abort23a(padapter);
2198b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2199b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2200b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&queue->lock);
2201b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2202b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	phead = get_list_head(queue);
2203b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2204b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	list_for_each_safe(plist, ptmp, phead) {
2205b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pnetwork = container_of(plist, struct wlan_network, list);
2206b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2207b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (sme->bssid) {
2208cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen			if (!ether_addr_equal(pnetwork->network.MacAddress,
2209cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen					      sme->bssid))
2210b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				continue;
2211b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2212b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2213b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (sme->ssid && sme->ssid_len) {
2214b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pnetwork->network.Ssid.ssid_len != sme->ssid_len ||
2215b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    memcmp(pnetwork->network.Ssid.ssid, sme->ssid,
2216b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   sme->ssid_len))
2217b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				continue;
2218b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2219b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2220b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (sme->bssid) {
22219ab98d42401d50d6ab5f6ef59e1d63c486391f1cJes Sorensen			if (ether_addr_equal(pnetwork->network.MacAddress,
22229ab98d42401d50d6ab5f6ef59e1d63c486391f1cJes Sorensen					     sme->bssid)) {
2223b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("matched by bssid\n");
2224b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2225b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				matched = true;
2226b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				break;
2227b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
2228b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		} else if (sme->ssid && sme->ssid_len) {
22299ab98d42401d50d6ab5f6ef59e1d63c486391f1cJes Sorensen			if (!memcmp(pnetwork->network.Ssid.ssid,
22309ab98d42401d50d6ab5f6ef59e1d63c486391f1cJes Sorensen				    sme->ssid, sme->ssid_len) &&
2231c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen			    pnetwork->network.Ssid.ssid_len == sme->ssid_len) {
2232b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("matched by ssid\n");
2233c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen
2234b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				matched = true;
2235b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				break;
2236b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
2237b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2238b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2239b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2240b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&queue->lock);
2241b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2242c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen	if (!matched || !pnetwork) {
2243b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOENT;
2244b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("connect, matched == false, goto exit\n");
2245b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2246b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2247b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2248efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	if (cfg80211_infrastructure_mode(
2249efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    padapter, pnetwork->network.ifmode) != _SUCCESS) {
2250b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
2251b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2252b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2253b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2254b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
22559e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	psecuritypriv->dot11PrivacyAlgrthm = 0;
22569e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	psecuritypriv->dot118021XGrpPrivacy = 0;
2257b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
2258b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
2259b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2260c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen	ret = rtw_cfg80211_set_wpa_version(psecuritypriv,
2261c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen					   sme->crypto.wpa_versions);
2262b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0)
2263b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2264b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2265b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type);
2266b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2267b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0)
2268b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2269b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2270b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ie_len =%zu\n", __func__, sme->ie_len);
2271b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2272b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_cfg80211_set_wpa_ie(padapter, sme->ie, sme->ie_len);
2273b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0)
2274b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2275b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2276b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (sme->crypto.n_ciphers_pairwise) {
2277b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_cfg80211_set_cipher(psecuritypriv,
2278b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      sme->crypto.ciphers_pairwise[0],
2279b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      true);
2280b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ret < 0)
2281b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
2282b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2283b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2284b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* For WEP Shared auth */
2285b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if ((psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Shared ||
2286b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	     psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Auto) &&
2287b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    sme->key) {
2288deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		struct rtw_wep_key wep_key;
2289deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		u8 wep_key_idx, wep_key_len;
2290b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s(): Shared/Auto WEP\n", __func__);
2291b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2292b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_idx = sme->key_idx;
2293b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_len = sme->key_len;
2294b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2295deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		if (wep_key_idx > WEP_KEYS || !wep_key_len ||
2296deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		    wep_key_len > WLAN_KEY_LEN_WEP104) {
2297b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EINVAL;
2298b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
2299b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2300b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2301deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		wep_key_len = wep_key_len <= 5 ? 5 : 13;
2302b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2303deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		memset(&wep_key, 0, sizeof(struct rtw_wep_key));
2304b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2305deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		wep_key.keylen = wep_key_len;
2306b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2307deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		if (wep_key_len == 13) {
2308deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen			padapter->securitypriv.dot11PrivacyAlgrthm =
2309deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				WLAN_CIPHER_SUITE_WEP104;
2310deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen			padapter->securitypriv.dot118021XGrpPrivacy =
2311deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				WLAN_CIPHER_SUITE_WEP104;
2312b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		} else {
2313deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen			padapter->securitypriv.dot11PrivacyAlgrthm =
2314deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				WLAN_CIPHER_SUITE_WEP40;
2315deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen			padapter->securitypriv.dot118021XGrpPrivacy =
2316deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				WLAN_CIPHER_SUITE_WEP40;
2317b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2318b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2319deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		memcpy(wep_key.key, (void *)sme->key, wep_key.keylen);
2320b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2321deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		if (rtw_cfg80211_add_wep(padapter, &wep_key, wep_key_idx) !=
2322deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		    _SUCCESS)
2323b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EOPNOTSUPP;
2324b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2325b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ret < 0)
2326b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
2327b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2328b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2329b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_cfg80211_set_cipher(psecuritypriv,
2330b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      sme->crypto.cipher_group, false);
2331b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0)
2332c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen		goto exit;
2333b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2334b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (sme->crypto.n_akm_suites) {
2335b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_cfg80211_set_key_mgt(psecuritypriv,
2336b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       sme->crypto.akm_suites[0]);
2337b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ret < 0)
2338b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
2339b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2340b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
234139dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen	if (psecuritypriv->ndisauthtype > 3)
234239dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
234339dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen
234439dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen	if (rtw_set_auth23a(padapter, psecuritypriv) != _SUCCESS) {
234539dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen		ret = -EBUSY;
234639dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen		goto exit;
234739dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen	}
2348b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2349b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* rtw_set_802_11_encryption_mode(padapter,
2350b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	   padapter->securitypriv.ndisencryptstatus); */
2351b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2352e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen	if (rtw_set_ssid(padapter, pnetwork) != _SUCCESS) {
235397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		ret = -EBUSY;
2354b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2355b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2356b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2357b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("set ssid:dot11AuthAlgrthm =%d, dot11PrivacyAlgrthm =%d, "
2358b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  "dot118021XGrpPrivacy =%d\n", psecuritypriv->dot11AuthAlgrthm,
2359b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  psecuritypriv->dot11PrivacyAlgrthm,
2360b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  psecuritypriv->dot118021XGrpPrivacy);
2361b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2362b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
2363b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2364b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("<=%s, ret %d\n", __func__, ret);
2365b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2366b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2367b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2368b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2369b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev,
2370b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   u16 reason_code)
2371b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2372b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2373b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2374a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2375b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2376b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_set_roaming(padapter, 0);
2377b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2378b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2379b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_scan_abort23a(padapter);
2380b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		LeaveAllPowerSaveMode23a(padapter);
2381b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_disassoc_cmd23a(padapter, 500, false);
2382b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2383b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s...call rtw_indicate_disconnect23a\n", __func__);
2384b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2385b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->mlmepriv.not_indic_disco = true;
2386b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_indicate_disconnect23a(padapter);
2387b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->mlmepriv.not_indic_disco = false;
2388b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2389b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_free_assoc_resources23a(padapter, 1);
2390b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2391b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2392b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2393b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2394b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2395b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_txpower(struct wiphy *wiphy,
2396b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct wireless_dev *wdev,
2397b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    enum nl80211_tx_power_setting type, int mbm)
2398b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2399b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2400b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2401b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2402b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2403b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_get_txpower(struct wiphy *wiphy,
2404b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct wireless_dev *wdev, int *dbm)
2405b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2406b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2407b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	*dbm = (12);
2408b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2409b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2410b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2411b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerinline bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter)
2412b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2413b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(adapter->rtw_wdev);
2414b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return rtw_wdev_priv->power_mgmt;
2415b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2416b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2417b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy,
2418b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct net_device *ndev,
2419b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       bool enabled, int timeout)
2420b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2421b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2422b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(padapter->rtw_wdev);
2423b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2424a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): enabled:%u, timeout:%d\n",
2425a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		  __func__, ndev->name, enabled, timeout);
2426b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2427b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_wdev_priv->power_mgmt = enabled;
2428b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2429b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!enabled)
2430b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		LPS_Leave23a(padapter);
2431b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2432b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2433b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2434b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2435b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,
2436b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct net_device *netdev,
2437b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct cfg80211_pmksa *pmksa)
2438b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2439b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 index, blInserted = false;
2440b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2441b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
2442b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2443a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, netdev->name);
2444b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2445cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen	if (is_zero_ether_addr(pmksa->bssid))
2446b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2447b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2448b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	blInserted = false;
2449b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2450b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* overwrite PMKID */
2451b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	for (index = 0; index < NUM_PMKID_CACHE; index++) {
2452cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen		if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid,
2453cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen				     pmksa->bssid)) {
2454b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* BSSID is matched, the same AP => rewrite with
2455b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   new PMKID. */
2456a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen			DBG_8723A("%s(%s):  BSSID exists in the PMKList.\n",
2457a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen				  __func__, netdev->name);
2458b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2459b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			memcpy(psecuritypriv->PMKIDList[index].PMKID,
2460b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			       pmksa->pmkid, WLAN_PMKID_LEN);
2461b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->PMKIDList[index].bUsed = true;
2462b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->PMKIDIndex = index + 1;
2463b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			blInserted = true;
2464b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			break;
2465b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2466b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2467b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2468b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!blInserted) {
2469b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/*  Find a new entry */
2470a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("%s(%s): Use new entry index = %d for this PMKID\n",
2471a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen			  __func__, netdev->name, psecuritypriv->PMKIDIndex);
2472b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2473888df442ef023adbca6536888eae65b2cd8ae295Jes Sorensen		ether_addr_copy(
2474888df442ef023adbca6536888eae65b2cd8ae295Jes Sorensen			psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2475888df442ef023adbca6536888eae65b2cd8ae295Jes Sorensen			Bssid, pmksa->bssid);
2476b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2477b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2478b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2479b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed =
2480b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			true;
2481b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->PMKIDIndex++;
2482b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (psecuritypriv->PMKIDIndex == 16) {
2483b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->PMKIDIndex = 0;
2484b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2485b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2486b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2487b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2488b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2489b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2490b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,
2491b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct net_device *netdev,
2492b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct cfg80211_pmksa *pmksa)
2493b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2494b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 index, bMatched = false;
2495b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2496b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
2497b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2498a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, netdev->name);
2499b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2500b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	for (index = 0; index < NUM_PMKID_CACHE; index++) {
2501cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen		if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid,
2502cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen				     pmksa->bssid)) {
2503cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen			/* BSSID is matched, the same AP => Remove this PMKID
2504cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen			   information and reset it. */
250543c34be13047dd53e70bc4759ff314424db7036bJes Sorensen			eth_zero_addr(psecuritypriv->PMKIDList[index].Bssid);
2506b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			memset(psecuritypriv->PMKIDList[index].PMKID, 0x00,
2507b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			       WLAN_PMKID_LEN);
2508b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->PMKIDList[index].bUsed = false;
2509b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			bMatched = true;
2510b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			break;
2511b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2512b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2513b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2514b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (false == bMatched) {
2515a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("%s(%s): do not have matched BSSID\n", __func__,
2516a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen			  netdev->name);
2517b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2518b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2519b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2520b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2521b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2522b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2523b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy,
2524b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct net_device *netdev)
2525b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2526b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2527b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
2528b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2529a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, netdev->name);
2530b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2531b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memset(&psecuritypriv->PMKIDList[0], 0x00,
2532b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
2533b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psecuritypriv->PMKIDIndex = 0;
2534b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2535b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2536b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2537b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2538b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
2539b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter,
2540b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     u8 *pmgmt_frame, uint frame_len)
2541b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2542b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	s32 freq;
2543b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int channel;
2544b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2545b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *ndev = padapter->pnetdev;
2546b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2547b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2548b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2549b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#if defined(RTW_USE_CFG80211_STA_EVENT)
2550b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	{
2551b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct station_info sinfo;
2552b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		u8 ie_offset;
255360e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen
2554b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ieee80211_is_assoc_req(hdr->frame_control))
255560e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen			ie_offset = offsetof(struct ieee80211_mgmt,
255660e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen					     u.assoc_req.variable);
2557b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		else		/*  WIFI_REASSOCREQ */
255860e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen			ie_offset = offsetof(struct ieee80211_mgmt,
255960e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen					     u.reassoc_req.variable);
2560b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2561b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo.filled = 0;
2562b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
256360e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen		sinfo.assoc_req_ies = pmgmt_frame + ie_offset;
256460e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen		sinfo.assoc_req_ies_len = frame_len - ie_offset;
2565b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC);
2566b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2567b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2568b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	channel = pmlmeext->cur_channel;
2569b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (channel <= RTW_CH_MAX_2G_CHANNEL)
2570b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
2571b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_2GHZ);
2572b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
2573b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
2574b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_5GHZ);
2575b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
257656b0bd91e0087e0b172aec022bdfb4fcd9de9194Jes Sorensen	cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pmgmt_frame, frame_len,
257756b0bd91e0087e0b172aec022bdfb4fcd9de9194Jes Sorensen			 0, GFP_ATOMIC);
2578b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2579b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2580b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2581b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter,
2582b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					unsigned char *da,
2583b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					unsigned short reason)
2584b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2585b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	s32 freq;
2586b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int channel;
2587b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	uint frame_len;
2588cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	struct ieee80211_mgmt mgmt;
2589b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2590b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2591b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *ndev = padapter->pnetdev;
2592b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2593b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2594b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2595cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	memset(&mgmt, 0, sizeof(struct ieee80211_mgmt));
25961daffaeecb4bf01c4a34fc2330c745ace5af3f60Jes Sorensen
2597b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#if defined(RTW_USE_CFG80211_STA_EVENT)
2598b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	cfg80211_del_sta(ndev, da, GFP_ATOMIC);
2599b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2600b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	channel = pmlmeext->cur_channel;
2601b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (channel <= RTW_CH_MAX_2G_CHANNEL)
2602b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
2603b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_2GHZ);
2604b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
2605b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
2606b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_5GHZ);
2607b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2608cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	mgmt.frame_control =
2609036cdd9cb34a10aabb80a97a41fb9dcfead7d113Jes Sorensen		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
2610b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2611cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	ether_addr_copy(mgmt.da, myid(&padapter->eeprompriv));
2612cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	ether_addr_copy(mgmt.sa, da);
2613cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	ether_addr_copy(mgmt.bssid, get_my_bssid23a(&pmlmeinfo->network));
2614b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2615cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	mgmt.seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2616b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmlmeext->mgnt_seq++;
2617b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2618cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	mgmt.u.disassoc.reason_code = cpu_to_le16(reason);
2619b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2620cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	frame_len = sizeof(struct ieee80211_hdr_3addr) + 2;
2621b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2622cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, (u8 *)&mgmt, frame_len,
262356b0bd91e0087e0b172aec022bdfb4fcd9de9194Jes Sorensen			 0, GFP_ATOMIC);
2624b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2625b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2626b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2627b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_monitor_if_open(struct net_device *ndev)
2628b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2629b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2630b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2631b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2632b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2633b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2634b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2635b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2636b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_monitor_if_close(struct net_device *ndev)
2637b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2638b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2639b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2640b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2641b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2642b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2643b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2644b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2645b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb,
2646b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      struct net_device *ndev)
2647b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2648b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2649b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int rtap_len;
2650b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int qos_len = 0;
2651b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int dot11_hdr_len = 24;
2652b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int snap_len = 6;
2653b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned char *pdata;
2654b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned char src_mac_addr[6];
2655b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned char dst_mac_addr[6];
2656b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_hdr *dot11_hdr;
2657b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_radiotap_header *rtap_hdr;
2658b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(ndev);
2659b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2660a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2661b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2662b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
2663b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto fail;
2664b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2665b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
2666b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (unlikely(rtap_hdr->it_version))
2667b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto fail;
2668b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2669b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtap_len = ieee80211_get_radiotap_len(skb->data);
2670b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (unlikely(skb->len < rtap_len))
2671b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto fail;
2672b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2673b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rtap_len != 14) {
2674b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("radiotap len (should be 14): %d\n", rtap_len);
2675b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto fail;
2676b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2677b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2678b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* Skip the ratio tap header */
2679b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	skb_pull(skb, rtap_len);
2680b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2681b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	dot11_hdr = (struct ieee80211_hdr *)skb->data;
2682b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* Check if the QoS bit is set */
2683b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ieee80211_is_data(dot11_hdr->frame_control)) {
2684b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* Check if this ia a Wireless Distribution System (WDS) frame
2685b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 * which has 4 MAC addresses
2686b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 */
2687b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ieee80211_is_data_qos(dot11_hdr->frame_control))
2688b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			qos_len = IEEE80211_QOS_CTL_LEN;
2689b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ieee80211_has_a4(dot11_hdr->frame_control))
2690b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			dot11_hdr_len += 6;
2691b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2692b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
2693b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
2694b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2695b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/*
2696b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 * Skip the 802.11 header, QoS (if any) and SNAP,
2697b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 * but leave spaces for two MAC addresses
2698b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 */
2699b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		skb_pull(skb, dot11_hdr_len + qos_len + snap_len -
2700b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			 ETH_ALEN * 2);
2701b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pdata = (unsigned char *)skb->data;
2702888df442ef023adbca6536888eae65b2cd8ae295Jes Sorensen		ether_addr_copy(pdata, dst_mac_addr);
2703888df442ef023adbca6536888eae65b2cd8ae295Jes Sorensen		ether_addr_copy(pdata + ETH_ALEN, src_mac_addr);
2704b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2705b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("should be eapol packet\n");
2706b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2707b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* Use the real net device to transmit the packet */
2708b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_xmit23a_entry23a(skb, padapter->pnetdev);
2709b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2710b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return ret;
2711b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2712b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else if (ieee80211_is_action(dot11_hdr->frame_control)) {
271338eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen		struct ieee80211_mgmt *mgmt;
2714b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* only for action frames */
2715b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct xmit_frame *pmgntframe;
2716b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct pkt_attrib *pattrib;
2717b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		unsigned char *pframe;
2718b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* u8 category, action, OUI_Subtype, dialogToken = 0; */
2719b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* unsigned char        *frame_body; */
2720b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2721b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2722b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		u32 len = skb->len;
2723b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		u8 category, action;
2724b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
272538eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen		mgmt = (struct ieee80211_mgmt *)dot11_hdr;
2726b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2727a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("RTW_Tx:da =" MAC_FMT " via %s(%s)\n",
272838eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen			  MAC_ARG(mgmt->da), __func__, ndev->name);
272938eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen		category = mgmt->u.action.category;
273038eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen		action = mgmt->u.action.u.wme_action.action_code;
27312e74d336edb945b4a1f851e821001093e4094729Jes Sorensen		DBG_8723A("RTW_Tx:category(%u), action(%u)\n",
27322e74d336edb945b4a1f851e821001093e4094729Jes Sorensen			  category, action);
273398fb81291d30f83838379bf1522fead6673b5fdfJes Sorensen
2734b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* starting alloc mgmt frame to dump it */
2735b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2736b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (pmgntframe == NULL)
2737b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto fail;
2738b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2739b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* update attribute */
2740b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib = &pmgntframe->attrib;
2741b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		update_mgntframe_attrib23a(padapter, pattrib);
2742b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib->retry_ctrl = false;
2743b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2744b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2745b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2746b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2747b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2748b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(pframe, skb->data, len);
2749b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib->pktlen = len;
2750b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2751b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* update seq number */
2752b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmeext->mgnt_seq = le16_to_cpu(dot11_hdr->seq_ctrl) >> 4;
2753b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib->seqnum = pmlmeext->mgnt_seq;
2754b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmeext->mgnt_seq++;
2755b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2756b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib->last_txcmdsz = pattrib->pktlen;
2757b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2758b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		dump_mgntframe23a(padapter, pmgntframe);
2759b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2760b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2761b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerfail:
2762b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2763b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	dev_kfree_skb(skb);
2764b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2765b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2766b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2767b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2768b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int
2769b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerrtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)
2770b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2771b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2772b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2773b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2774b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2775b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2776b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2777b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2778b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic const struct net_device_ops rtw_cfg80211_monitor_if_ops = {
2779b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.ndo_open = rtw_cfg80211_monitor_if_open,
2780b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.ndo_stop = rtw_cfg80211_monitor_if_close,
2781b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
2782b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,
2783b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
2784b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2785b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_add_monitor_if(struct rtw_adapter *padapter, char *name,
2786b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct net_device **ndev)
2787b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2788b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2789b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *mon_ndev = NULL;
2790b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *mon_wdev = NULL;
2791b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
2792b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2793b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!name) {
27949cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): without specific name\n",
27959cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  __func__, padapter->pnetdev->name);
2796b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
2797b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2798b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2799b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2800b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pwdev_priv->pmon_ndev) {
28019cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): monitor interface exist: %s\n", __func__,
28029cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name, pwdev_priv->pmon_ndev->name);
2803b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EBUSY;
2804b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2805b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2806b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2807b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev = alloc_etherdev(sizeof(struct rtw_adapter));
2808b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mon_ndev) {
28099cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): allocate ndev fail\n", __func__,
28109cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name);
2811b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOMEM;
2812b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2813b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2814b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2815b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;
2816b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	strncpy(mon_ndev->name, name, IFNAMSIZ);
2817b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->name[IFNAMSIZ - 1] = 0;
2818b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->destructor = rtw_ndev_destructor;
2819b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2820b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;
2821b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2822b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*  wdev */
2823b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
2824b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mon_wdev) {
28259cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): allocate mon_wdev fail\n", __func__,
28269cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name);
2827b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOMEM;
2828b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2829b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2830b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2831b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_wdev->wiphy = padapter->rtw_wdev->wiphy;
2832b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_wdev->netdev = mon_ndev;
2833b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_wdev->iftype = NL80211_IFTYPE_MONITOR;
2834b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->ieee80211_ptr = mon_wdev;
2835b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2836b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = register_netdevice(mon_ndev);
2837b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret) {
2838b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2839b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2840b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2841b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	*ndev = pwdev_priv->pmon_ndev = mon_ndev;
2842b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1);
2843b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2844b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerout:
2845b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret) {
2846b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		kfree(mon_wdev);
2847b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		mon_wdev = NULL;
2848b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2849b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2850b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret && mon_ndev) {
2851b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		free_netdev(mon_ndev);
2852b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		*ndev = mon_ndev = NULL;
2853b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2854b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2855b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2856b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2857b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2858b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct wireless_dev *
2859b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingercfg80211_rtw_add_virtual_intf(struct wiphy *wiphy, const char *name,
2860b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			      enum nl80211_iftype type, u32 *flags,
2861b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			      struct vif_params *params)
2862b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2863b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2864b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *ndev = NULL;
2865b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2866b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
28679cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen	DBG_8723A("%s(%s): wiphy:%s, name:%s, type:%d\n", __func__,
28689cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		  padapter->pnetdev->name, wiphy_name(wiphy), name, type);
2869b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2870b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (type) {
2871b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_ADHOC:
2872b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_AP_VLAN:
2873b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_WDS:
2874b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_MESH_POINT:
2875b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENODEV;
2876b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2877b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_MONITOR:
2878b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret =
2879b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		    rtw_cfg80211_add_monitor_if(padapter, (char *)name, &ndev);
2880b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2881b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2882b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_P2P_CLIENT:
2883b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_STATION:
2884b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENODEV;
2885b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2886b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2887b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_P2P_GO:
2888b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_AP:
2889b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENODEV;
2890b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2891b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
2892b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENODEV;
2893b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Unsupported interface type\n");
2894b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2895b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2896b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
28979cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen	DBG_8723A("%s(%s): ndev:%p, ret:%d\n", __func__,
28989cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		  padapter->pnetdev->name,
2899b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  ndev, ret);
2900b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2901b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ndev ? ndev->ieee80211_ptr : ERR_PTR(ret);
2902b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2903b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2904b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy,
2905b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					 struct wireless_dev *wdev)
2906b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2907b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv =
2908b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    (struct rtw_wdev_priv *)wiphy_priv(wiphy);
2909b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *ndev;
2910b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ndev = wdev ? wdev->netdev : NULL;
2911b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2912b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!ndev)
2913b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2914b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2915b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unregister_netdevice(ndev);
2916b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2917b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ndev == pwdev_priv->pmon_ndev) {
2918b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->pmon_ndev = NULL;
2919b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->ifname_mon[0] = '\0';
2920a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("%s(%s): remove monitor interface\n",
2921a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen			  __func__, ndev->name);
2922b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2923b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2924b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
2925b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2926b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2927b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2928b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head,
2929b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  size_t head_len, const u8 *tail, size_t tail_len)
2930b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2931b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2932db97812c2c5e8a18d7cf3eb679a4cfdd6125f748Jes Sorensen	u8 *pbuf;
2933fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	uint len, ielen, wps_ielen = 0;
2934b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2935ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen	struct wlan_bssid_ex *bss = &pmlmepriv->cur_network.network;
2936ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen	const struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)head;
2937fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	struct ieee80211_mgmt *tmpmgmt;
2938b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* struct sta_priv *pstapriv = &padapter->stapriv; */
2939b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2940b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s beacon_head_len =%zu, beacon_tail_len =%zu\n",
2941b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  __func__, head_len, tail_len);
2942b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2943b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2944b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2945b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2946ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen	if (head_len < offsetof(struct ieee80211_mgmt, u.beacon.variable))
2947b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2948b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2949b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pbuf = kzalloc(head_len + tail_len, GFP_KERNEL);
2950b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!pbuf)
2951b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -ENOMEM;
2952fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	tmpmgmt = (struct ieee80211_mgmt *)pbuf;
2953ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen
2954ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen	bss->beacon_interval = get_unaligned_le16(&mgmt->u.beacon.beacon_int);
2955ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen	bss->capability = get_unaligned_le16(&mgmt->u.beacon.capab_info);
2956ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen	bss->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp);
2957ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen
2958b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*  24 = beacon header len. */
2959fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	memcpy(pbuf, (void *)head, head_len);
2960fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	memcpy(pbuf + head_len, (void *)tail, tail_len);
2961b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2962fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	len = head_len + tail_len;
2963fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	ielen = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
2964b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* check wps ie if inclued */
2965d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen	if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2966d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen				    WLAN_OUI_TYPE_MICROSOFT_WPS,
2967fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen				    tmpmgmt->u.beacon.variable, ielen))
2968b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("add bcn, wps_ielen =%d\n", wps_ielen);
2969b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2970b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* pbss_network->IEs will not include p2p_ie, wfd ie */
2971fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0,
29729300c94b8a817f3b96cf00d2bdeed6751c2744d8Jes Sorensen			     WLAN_EID_VENDOR_SPECIFIC, P2P_OUI23A, 4);
2973fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0,
29749300c94b8a817f3b96cf00d2bdeed6751c2744d8Jes Sorensen			     WLAN_EID_VENDOR_SPECIFIC, WFD_OUI23A, 4);
2975b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2976fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	len = ielen + offsetof(struct ieee80211_mgmt, u.beacon.variable);
2977fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	if (rtw_check_beacon_data23a(adapter, tmpmgmt, len) == _SUCCESS) {
2978b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = 0;
2979b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
2980b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
2981b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2982b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2983b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(pbuf);
2984b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2985b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2986b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2987b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2988b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,
2989b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				 struct cfg80211_ap_settings *settings)
2990b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2991b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2992b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
2993b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2994a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): hidden_ssid:%d, auth_type:%d\n",
2995a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		  __func__, ndev->name, settings->hidden_ssid,
2996b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  settings->auth_type);
2997b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2998b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_add_beacon(adapter, settings->beacon.head,
2999b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     settings->beacon.head_len, settings->beacon.tail,
3000b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     settings->beacon.tail_len);
3001b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3002b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode =
3003b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		settings->hidden_ssid;
3004b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3005b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (settings->ssid && settings->ssid_len) {
3006b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct wlan_bssid_ex *pbss_network =
3007b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			&adapter->mlmepriv.cur_network.network;
3008b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct wlan_bssid_ex *pbss_network_ext =
3009b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			&adapter->mlmeextpriv.mlmext_info.network;
3010b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3011b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(pbss_network->Ssid.ssid, (void *)settings->ssid,
3012b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       settings->ssid_len);
3013b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pbss_network->Ssid.ssid_len = settings->ssid_len;
3014b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(pbss_network_ext->Ssid.ssid, (void *)settings->ssid,
3015b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       settings->ssid_len);
3016b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pbss_network_ext->Ssid.ssid_len = settings->ssid_len;
3017b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3018b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3019b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3020b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3021b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3022b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_change_beacon(struct wiphy *wiphy,
3023b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      struct net_device *ndev,
3024b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      struct cfg80211_beacon_data *info)
3025b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3026b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
3027b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
3028b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3029a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
3030b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3031b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail,
3032b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     info->tail_len);
3033b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3034b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3035b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3036b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3037b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
3038b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3039a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
3040b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
3041b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3042b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3043b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_add_station(struct wiphy *wiphy,
3044f9da455b93f6ba076935b4ef4589f61e529ae046Linus Torvalds				    struct net_device *ndev, const u8 *mac,
3045b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct station_parameters *params)
3046b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3047a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
3048b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3049b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
3050b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3051b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3052b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_del_station(struct wiphy *wiphy,
3053f9da455b93f6ba076935b4ef4589f61e529ae046Linus Torvalds				    struct net_device *ndev, const u8 *mac)
3054b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3055b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
3056b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct list_head *phead, *plist, *ptmp;
3057b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 updated = 0;
3058b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_info *psta;
3059b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(ndev);
3060b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3061b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_priv *pstapriv = &padapter->stapriv;
3062b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3063a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("+%s(%s)\n", __func__, ndev->name);
3064b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3065b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true) {
3066b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, fw_state != FW_LINKED|WIFI_AP_STATE\n",
3067b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  __func__);
3068b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
3069b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3070b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3071b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mac) {
3072b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("flush all sta, and cam_entry\n");
3073b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3074b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		flush_all_cam_entry23a(padapter);	/* clear CAM */
3075b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3076b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_sta_flush23a(padapter);
3077b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3078b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return ret;
3079b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3080b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3081b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("free sta macaddr =" MAC_FMT "\n", MAC_ARG(mac));
3082b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3083b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (is_broadcast_ether_addr(mac))
3084b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
3085b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3086b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pstapriv->asoc_list_lock);
3087b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3088b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	phead = &pstapriv->asoc_list;
3089b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3090b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* check asoc_queue */
3091b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	list_for_each_safe(plist, ptmp, phead) {
3092b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psta = container_of(plist, struct sta_info, asoc_list);
3093b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3094cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen		if (ether_addr_equal(mac, psta->hwaddr)) {
3095b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (psta->dot8021xalg == 1 &&
3096b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    psta->bpairwise_key_installed == false) {
3097b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s, sta's dot8021xalg = 1 and "
3098b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  "key_installed = false\n", __func__);
3099b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			} else {
3100b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("free psta =%p, aid =%d\n", psta,
3101b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  psta->aid);
3102b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3103b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				list_del_init(&psta->asoc_list);
3104b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pstapriv->asoc_list_cnt--;
3105b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3106b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* spin_unlock_bh(&pstapriv->asoc_list_lock); */
3107b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				updated =
3108b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    ap_free_sta23a(padapter, psta, true,
3109b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						WLAN_REASON_DEAUTH_LEAVING);
3110b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* spin_lock_bh(&pstapriv->asoc_list_lock); */
3111b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3112b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psta = NULL;
3113b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3114b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				break;
3115b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
3116b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
3117b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3118b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3119b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pstapriv->asoc_list_lock);
3120b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3121b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	associated_clients_update23a(padapter, updated);
3122b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3123a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("-%s(%s)\n", __func__, ndev->name);
3124b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3125b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3126b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3127b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3128b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_change_station(struct wiphy *wiphy,
3129f9da455b93f6ba076935b4ef4589f61e529ae046Linus Torvalds				       struct net_device *ndev, const u8 *mac,
3130b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct station_parameters *params)
3131b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3132a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
3133b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
3134b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3135b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3136b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_dump_station(struct wiphy *wiphy,
3137b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     struct net_device *ndev, int idx, u8 *mac,
3138b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     struct station_info *sinfo)
3139b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3140a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
3141b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3142b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* TODO: dump scanned queue */
3143b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3144b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return -ENOENT;
3145b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3146b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3147b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,
3148b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   struct bss_parameters *params)
3149b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3150a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
3151b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
3152b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3153b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* CONFIG_8723AU_AP_MODE */
3154b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3155b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch,
3156b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				 const u8 *buf, size_t len)
3157b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3158b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct xmit_frame *pmgntframe;
3159b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct pkt_attrib *pattrib;
3160b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned char *pframe;
3161b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = _FAIL;
3162b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_hdr *pwlanhdr;
3163b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3164b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3165b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3166b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (_FAIL == rtw_pwr_wakeup(padapter)) {
3167b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EFAULT;
3168b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
3169b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3170b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3171b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_set_scan_deny(padapter, 1000);
3172b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3173b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_scan_abort23a(padapter);
3174b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3175b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (tx_ch != rtw_get_oper_ch23a(padapter)) {
3176b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
3177b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pmlmeext->cur_channel = tx_ch;
3178b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		set_channel_bwmode23a(padapter, tx_ch,
3179b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   HAL_PRIME_CHNL_OFFSET_DONT_CARE,
3180b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   HT_CHANNEL_WIDTH_20);
3181b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3182b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3183b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* starting alloc mgmt frame to dump it */
3184b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3185de62f67a00286eb78d44762ce845b00742d79dd0Jes Sorensen	if (!pmgntframe) {
3186b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* ret = -ENOMEM; */
3187b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = _FAIL;
3188b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
3189b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3190b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3191b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* update attribute */
3192b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib = &pmgntframe->attrib;
3193b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	update_mgntframe_attrib23a(padapter, pattrib);
3194b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib->retry_ctrl = false;
3195b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3196b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3197b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3198b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pframe = (u8 *) (pmgntframe->buf_addr) + TXDESC_OFFSET;
3199b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3200b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pframe, (void *)buf, len);
3201b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib->pktlen = len;
3202b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3203b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwlanhdr = (struct ieee80211_hdr *)pframe;
3204b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* update seq number */
3205b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmlmeext->mgnt_seq = le16_to_cpu(pwlanhdr->seq_ctrl) >> 4;
3206b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib->seqnum = pmlmeext->mgnt_seq;
3207b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmlmeext->mgnt_seq++;
3208b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3209b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib->last_txcmdsz = pattrib->pktlen;
3210b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3211de62f67a00286eb78d44762ce845b00742d79dd0Jes Sorensen	ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3212b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3213de62f67a00286eb78d44762ce845b00742d79dd0Jes Sorensen	if (ret  != _SUCCESS)
3214de62f67a00286eb78d44762ce845b00742d79dd0Jes Sorensen		DBG_8723A("%s, ack == false\n", __func__);
3215de62f67a00286eb78d44762ce845b00742d79dd0Jes Sorensen	else
3216de62f67a00286eb78d44762ce845b00742d79dd0Jes Sorensen		DBG_8723A("%s, ack == true\n", __func__);
3217b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3218b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
3219b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3220b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ret =%d\n", __func__, ret);
3221b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3222b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3223b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3224b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3225b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
3226b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				struct cfg80211_mgmt_tx_params *params,
3227b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				u64 *cookie)
3228b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3229b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter =
3230b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		(struct rtw_adapter *)wiphy_to_adapter(wiphy);
3231b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
3232b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int tx_ret;
3233b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 dump_limit = RTW_MAX_MGMT_TX_CNT;
3234b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 dump_cnt = 0;
3235b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	bool ack = true;
3236b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 category, action;
3237b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned long start = jiffies;
3238b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	size_t len = params->len;
3239b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_channel *chan = params->chan;
3240b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	const u8 *buf = params->buf;
3241ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen	struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *)buf;
3242b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 tx_ch = (u8) ieee80211_frequency_to_channel(chan->center_freq);
3243b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3244ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen	if (!ieee80211_is_action(hdr->frame_control))
3245ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen		return -EINVAL;
3246ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen
3247b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* cookie generation */
3248b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	*cookie = (unsigned long)buf;
3249b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
32509cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen	DBG_8723A("%s(%s): len =%zu, ch =%d\n", __func__,
32519cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		  padapter->pnetdev->name, len, tx_ch);
3252b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3253b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* indicate ack before issue frame to avoid racing with rsp frame */
325456b0bd91e0087e0b172aec022bdfb4fcd9de9194Jes Sorensen	cfg80211_mgmt_tx_status(padapter->rtw_wdev, *cookie, buf, len, ack,
325556b0bd91e0087e0b172aec022bdfb4fcd9de9194Jes Sorensen				GFP_KERNEL);
3256b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3257b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("RTW_Tx:tx_ch =%d, da =" MAC_FMT "\n", tx_ch,
3258ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen		  MAC_ARG(hdr->da));
3259ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen	category = hdr->u.action.category;
3260ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen	action = hdr->u.action.u.wme_action.action_code;
32612e74d336edb945b4a1f851e821001093e4094729Jes Sorensen	DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category, action);
3262b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3263b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	do {
3264b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		dump_cnt++;
3265b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, buf, len);
3266b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} while (dump_cnt < dump_limit && tx_ret != _SUCCESS);
3267b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3268b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (tx_ret != _SUCCESS || dump_cnt > 1) {
32699cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): %s (%d/%d) in %d ms\n",
32709cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  __func__, padapter->pnetdev->name,
3271b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt,
3272b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  dump_limit, jiffies_to_msecs(jiffies - start));
3273b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3274b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3275b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3276b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3277b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3278b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,
3279b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     struct wireless_dev *wdev,
3280b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     u16 frame_type, bool reg)
3281b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3282b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
3283b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
3284b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3285b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return;
3286b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3287b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3288b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct cfg80211_ops rtw_cfg80211_ops = {
3289b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.change_virtual_intf = cfg80211_rtw_change_iface,
3290b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.add_key = cfg80211_rtw_add_key,
3291b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.get_key = cfg80211_rtw_get_key,
3292b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.del_key = cfg80211_rtw_del_key,
3293b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_default_key = cfg80211_rtw_set_default_key,
3294b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.get_station = cfg80211_rtw_get_station,
3295b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.scan = cfg80211_rtw_scan,
3296b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_wiphy_params = cfg80211_rtw_set_wiphy_params,
3297b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.connect = cfg80211_rtw_connect,
3298b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.disconnect = cfg80211_rtw_disconnect,
3299b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.join_ibss = cfg80211_rtw_join_ibss,
3300b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.leave_ibss = cfg80211_rtw_leave_ibss,
3301b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_tx_power = cfg80211_rtw_set_txpower,
3302b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.get_tx_power = cfg80211_rtw_get_txpower,
3303b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_power_mgmt = cfg80211_rtw_set_power_mgmt,
3304b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_pmksa = cfg80211_rtw_set_pmksa,
3305b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.del_pmksa = cfg80211_rtw_del_pmksa,
3306b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.flush_pmksa = cfg80211_rtw_flush_pmksa,
3307b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3308b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
3309b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.add_virtual_intf = cfg80211_rtw_add_virtual_intf,
3310b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.del_virtual_intf = cfg80211_rtw_del_virtual_intf,
3311b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3312b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.start_ap = cfg80211_rtw_start_ap,
3313b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.change_beacon = cfg80211_rtw_change_beacon,
3314b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.stop_ap = cfg80211_rtw_stop_ap,
3315b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3316b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.add_station = cfg80211_rtw_add_station,
3317b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.del_station = cfg80211_rtw_del_station,
3318b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.change_station = cfg80211_rtw_change_station,
3319b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.dump_station = cfg80211_rtw_dump_station,
3320b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.change_bss = cfg80211_rtw_change_bss,
3321b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* CONFIG_8723AU_AP_MODE */
3322b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3323b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.mgmt_tx = cfg80211_rtw_mgmt_tx,
3324b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,
3325b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
3326b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3327b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap,
3328b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       enum ieee80211_band band, u8 rf_type)
3329b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3330b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3331b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define MAX_BIT_RATE_40MHZ_MCS15	300	/* Mbps */
3332b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define MAX_BIT_RATE_40MHZ_MCS7		150	/* Mbps */
3333b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3334b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->ht_supported = true;
3335b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3336b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
3337b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 |
3338b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;
3339b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3340b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*
3341b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *Maximum length of AMPDU that the STA can receive.
3342b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
3343b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 */
3344b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
3345b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3346b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*Minimum MPDU start spacing , */
3347b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
3348b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3349b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
3350b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3351b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*
3352b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *hw->wiphy->bands[IEEE80211_BAND_2GHZ]
3353b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *base on ant_num
3354b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *rx_mask: RX mask
3355b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7
3356b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15
3357b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *if rx_ant >= 3 rx_mask[2]= 0xff;
3358b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *if BW_40 rx_mask[4]= 0x01;
3359b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *highest supported RX rate
3360b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 */
3361b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rf_type == RF_1T1R) {
3362b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[0] = 0xFF;
3363b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[1] = 0x00;
3364b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[4] = 0x01;
3365b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3366b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS7;
3367b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else if ((rf_type == RF_1T2R) || (rf_type == RF_2T2R)) {
3368b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[0] = 0xFF;
3369b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[1] = 0xFF;
3370b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[4] = 0x01;
3371b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3372b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS15;
3373b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
3374b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, error rf_type =%d\n", __func__, rf_type);
3375b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3376b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3377b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3378b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3379b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter)
3380b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3381b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 rf_type;
3382b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_supported_band *bands;
3383b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *pwdev = padapter->rtw_wdev;
3384b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wiphy *wiphy = pwdev->wiphy;
3385b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3386c2370e83ab5432e2d32e9c097930c69366d27b4cJes Sorensen	rf_type = rtl8723a_get_rf_type(padapter);
3387b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3388b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s:rf_type =%d\n", __func__, rf_type);
3389b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3390b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
3391b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	{
3392b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		bands = wiphy->bands[IEEE80211_BAND_2GHZ];
3393b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (bands)
3394b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			rtw_cfg80211_init_ht_capab(&bands->ht_cap,
3395b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   IEEE80211_BAND_2GHZ,
3396b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   rf_type);
3397b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3398b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3399b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
3400b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	{
3401b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		bands = wiphy->bands[IEEE80211_BAND_5GHZ];
3402b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (bands)
3403b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			rtw_cfg80211_init_ht_capab(&bands->ht_cap,
3404b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   IEEE80211_BAND_5GHZ,
3405b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   rf_type);
3406b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3407b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3408b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3409b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_cfg80211_preinit_wiphy(struct rtw_adapter *padapter,
3410b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct wiphy *wiphy)
3411b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3412b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3413b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3414b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;
3415b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
3416b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS;
3417b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3418b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->max_remain_on_channel_duration =
3419b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    RTW_MAX_REMAIN_ON_CHANNEL_DURATION;
3420b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3421b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
3422b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    BIT(NL80211_IFTYPE_ADHOC) |
3423b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
3424b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) |
3425b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif
3426b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    0;
3427b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3428b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
3429b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes;
3430b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* CONFIG_8723AU_AP_MODE */
3431b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3432b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
3433b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3434b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*
3435b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	   wiphy->iface_combinations = &rtw_combinations;
3436b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	   wiphy->n_iface_combinations = 1;
3437b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 */
3438b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3439b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->cipher_suites = rtw_cipher_suites;
3440b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);
3441b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3442b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
3443b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->bands[IEEE80211_BAND_2GHZ] =
3444b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    rtw_spt_band_alloc(IEEE80211_BAND_2GHZ);
3445b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
3446b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->bands[IEEE80211_BAND_5GHZ] =
3447b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    rtw_spt_band_alloc(IEEE80211_BAND_5GHZ);
3448b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3449b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
3450b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME;
3451b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3452b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
3453b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
3454b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
3455b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
3456b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3457b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3458b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerint rtw_wdev_alloc(struct rtw_adapter *padapter, struct device *dev)
3459b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3460b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
3461b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wiphy *wiphy;
3462b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *wdev;
3463b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv;
3464b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *pnetdev = padapter->pnetdev;
3465b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3466b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
3467b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3468b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* wiphy */
3469b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wdev_priv));
3470b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!wiphy) {
3471b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Couldn't allocate wiphy device\n");
3472b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOMEM;
3473b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
3474b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3475d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen
3476d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen	/*  wdev */
3477d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen	wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
3478d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen	if (!wdev) {
3479d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen		DBG_8723A("Couldn't allocate wireless device\n");
3480d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen		ret = -ENOMEM;
3481d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen		goto free_wiphy;
3482d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen	}
3483d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen
3484b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	set_wiphy_dev(wiphy, dev);
3485b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_cfg80211_preinit_wiphy(padapter, wiphy);
3486b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3487b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = wiphy_register(wiphy);
3488b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0) {
3489b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Couldn't register wiphy device\n");
3490d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen		goto free_wdev;
3491b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3492b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3493b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wdev->wiphy = wiphy;
3494b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wdev->netdev = pnetdev;
3495b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* wdev->iftype = NL80211_IFTYPE_STATION; */
3496b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*  for rtw_setopmode_cmd23a() in cfg80211_rtw_change_iface() */
3497b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wdev->iftype = NL80211_IFTYPE_MONITOR;
3498b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	padapter->rtw_wdev = wdev;
3499b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pnetdev->ieee80211_ptr = wdev;
3500b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3501b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* init pwdev_priv */
3502b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv = wdev_to_priv(wdev);
3503b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->rtw_wdev = wdev;
3504b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->pmon_ndev = NULL;
3505b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->ifname_mon[0] = '\0';
3506b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->padapter = padapter;
3507b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->scan_request = NULL;
3508b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_init(&pwdev_priv->scan_req_lock);
3509b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3510b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->p2p_enabled = false;
3511b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3512b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
3513b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->power_mgmt = true;
3514b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
3515b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->power_mgmt = false;
3516b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3517b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3518d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensenfree_wdev:
3519d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen	kfree(wdev);
3520b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerfree_wiphy:
3521b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy_free(wiphy);
3522b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
3523b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3524b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3525b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3526b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_wdev_free(struct wireless_dev *wdev)
3527b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3528b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
3529b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3530b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!wdev)
3531b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
3532b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3533b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(wdev->wiphy->bands[IEEE80211_BAND_2GHZ]);
3534b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(wdev->wiphy->bands[IEEE80211_BAND_5GHZ]);
3535b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3536b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy_free(wdev->wiphy);
3537b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3538b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(wdev);
3539b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3540b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3541b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_wdev_unregister(struct wireless_dev *wdev)
3542b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3543b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv;
3544b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3545b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
3546b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3547b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!wdev)
3548b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
3549b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3550b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv = wdev_to_priv(wdev);
3551b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3552b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_cfg80211_indicate_scan_done(pwdev_priv, true);
3553b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3554b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pwdev_priv->pmon_ndev) {
3555b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, unregister monitor interface\n", __func__);
3556b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		unregister_netdev(pwdev_priv->pmon_ndev);
3557b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3558b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3559b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy_unregister(wdev->wiphy);
3560b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3561