ioctl_cfg80211.c revision f78c0710cd60cd108d436490955909983f309c62
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
4202dcf6b4c73a3b92774955b83e5bd7c5cec2c87e6Jes Sorensenstatic int set_group_key(struct rtw_adapter *padapter, struct key_params *parms,
4212dcf6b4c73a3b92774955b83e5bd7c5cec2c87e6Jes Sorensen			 u32 alg, u8 keyid)
422b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
423b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cmd_obj *pcmd;
424b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct setkey_parm *psetkeyparm;
425b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
426b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int res = _SUCCESS;
427b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
428b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
429b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
4304e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen	if (keyid >= 4) {
4314e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen		res = _FAIL;
4324e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen		goto exit;
4334e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen	}
4344e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen
435b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
436b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!pcmd) {
437b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		res = _FAIL;
438b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
439b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
440b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
441b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!psetkeyparm) {
442b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		kfree(pcmd);
443b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		res = _FAIL;
444b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
445b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
446b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
4474e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen	psetkeyparm->keyid = keyid;
448b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (is_wep_enc(alg))
4494e489d91b4fe320b1260a504a61eb806f3044e61Jes Sorensen		padapter->mlmepriv.key_mask |= BIT(psetkeyparm->keyid);
450b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
451b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psetkeyparm->algorithm = alg;
452b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
453b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psetkeyparm->set_tx = 1;
454b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
4552dcf6b4c73a3b92774955b83e5bd7c5cec2c87e6Jes Sorensen	memcpy(&psetkeyparm->key, parms->key, parms->key_len);
456b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
457b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->cmdcode = _SetKey_CMD_;
458b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->parmbuf = (u8 *) psetkeyparm;
459b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->cmdsz = (sizeof(struct setkey_parm));
460b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->rsp = NULL;
461b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pcmd->rspsz = 0;
462b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
463b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
464b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
465b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
466b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return res;
467b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
468b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
469f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensenstatic int rtw_cfg80211_ap_set_encryption(struct net_device *dev, u8 key_index,
470f88ab54c10b1270257f39268e88c1949fd903fb2Jes Sorensen					  int set_tx, const u8 *sta_addr,
4715dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen					  struct key_params *keyparms)
472b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
473b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
474c36e122f6eba4e31c67d572c1e01ef845747010dJes Sorensen	int key_len;
475b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_info *psta = NULL, *pbcmc_sta = NULL;
476b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(dev);
477b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
478b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_priv *pstapriv = &padapter->stapriv;
479b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
480b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
481b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
4827ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen	if (!is_broadcast_ether_addr(sta_addr)) {
483f88ab54c10b1270257f39268e88c1949fd903fb2Jes Sorensen		psta = rtw_get_stainfo23a(pstapriv, sta_addr);
484b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (!psta) {
485b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* ret = -EINVAL; */
486b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("rtw_set_encryption(), sta has already "
487b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  "been removed or never been added\n");
488b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
489b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
490b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
491b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
492c36e122f6eba4e31c67d572c1e01ef845747010dJes Sorensen	key_len = keyparms->key_len;
493c36e122f6eba4e31c67d572c1e01ef845747010dJes Sorensen
4945dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen	if (!psta && (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
4955dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen		      keyparms->cipher == WLAN_CIPHER_SUITE_WEP104)) {
496b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("r871x_set_encryption, crypt.alg = WEP\n");
497b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
498b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("r871x_set_encryption, wep_key_idx =%d, len =%d\n",
499f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen			  key_index, key_len);
500b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
501b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
502b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* wep default key has not been set, so use
503b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   this key index as default key. */
504b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
505b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->ndisencryptstatus =
506b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				Ndis802_11Encryption1Enabled;
50755db5d02f81bd45c3a47f4ab4a917a70c6e13916Jes Sorensen			psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher;
50855db5d02f81bd45c3a47f4ab4a917a70c6e13916Jes Sorensen			psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher;
509b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
510f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen			psecuritypriv->dot11PrivacyKeyIndex = key_index;
511b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
512b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
513f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen		memcpy(&psecuritypriv->wep_key[key_index].key,
514c36e122f6eba4e31c67d572c1e01ef845747010dJes Sorensen		       keyparms->key, key_len);
515b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
516f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen		psecuritypriv->wep_key[key_index].keylen = key_len;
517b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
5182dcf6b4c73a3b92774955b83e5bd7c5cec2c87e6Jes Sorensen		set_group_key(padapter, keyparms, keyparms->cipher, key_index);
519b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
520b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
521b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
522b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
5234e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen	if (!psta) {	/*  group key */
5240996cf9c693fd58d116619005ac1e1382865e0dbJes Sorensen		if (set_tx == 0) {	/* group key */
5255dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen			if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
5265dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen			    keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
5279cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen				DBG_8723A("%s, set group_key, WEP\n", __func__);
528b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
529b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
530f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen				       dot118021XGrpKey[key_index].skey,
5317ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen				       keyparms->key, key_len);
532b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
53355db5d02f81bd45c3a47f4ab4a917a70c6e13916Jes Sorensen				psecuritypriv->dot118021XGrpPrivacy =
53455db5d02f81bd45c3a47f4ab4a917a70c6e13916Jes Sorensen					keyparms->cipher;
5355dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen			} else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) {
536b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s, set group_key, TKIP\n",
537b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__);
538b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
5394e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				psecuritypriv->dot118021XGrpPrivacy =
5404e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen					WLAN_CIPHER_SUITE_TKIP;
541b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
542b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
543f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen				       dot118021XGrpKey[key_index].skey,
544fd381874eb3efded6c088f649a03c03b9690d588Jes Sorensen				       keyparms->key,
545c36e122f6eba4e31c67d572c1e01ef845747010dJes Sorensen				       (key_len > 16 ? 16 : key_len));
546b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
547b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* set mic key */
548b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
549f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen				       dot118021XGrptxmickey[key_index].skey,
550fd381874eb3efded6c088f649a03c03b9690d588Jes Sorensen				       &keyparms->key[16], 8);
551b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
552f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen				       dot118021XGrprxmickey[key_index].skey,
553fd381874eb3efded6c088f649a03c03b9690d588Jes Sorensen				       &keyparms->key[24], 8);
554b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
5559216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen				psecuritypriv->busetkipkey = 1;
556b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
5575dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen			} else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) {
5585dab9e7d2af054ad1df60ef51e25b2dd5e85517bJes Sorensen					DBG_8723A("%s, set group_key, CCMP\n",
559b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__);
560b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
5614e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				psecuritypriv->dot118021XGrpPrivacy =
5624e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen					WLAN_CIPHER_SUITE_CCMP;
563b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
564b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				memcpy(psecuritypriv->
565fd381874eb3efded6c088f649a03c03b9690d588Jes Sorensen				       dot118021XGrpKey[key_index].skey,
566fd381874eb3efded6c088f649a03c03b9690d588Jes Sorensen				       keyparms->key,
567c36e122f6eba4e31c67d572c1e01ef845747010dJes Sorensen				       (key_len > 16 ? 16 : key_len));
568b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			} else {
569b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s, set group_key, none\n",
570b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__);
571b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
5727ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen				psecuritypriv->dot118021XGrpPrivacy = 0;
573b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
574b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
575f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen			psecuritypriv->dot118021XGrpKeyid = key_index;
576b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
5779216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen			psecuritypriv->binstallGrpkey = 1;
578b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
579b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->dot11PrivacyAlgrthm =
580b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psecuritypriv->dot118021XGrpPrivacy;
581b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
5822dcf6b4c73a3b92774955b83e5bd7c5cec2c87e6Jes Sorensen			set_group_key(padapter, keyparms,
583b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      psecuritypriv->dot118021XGrpPrivacy,
584f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen				      key_index);
585b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
586b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
587b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pbcmc_sta) {
588b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pbcmc_sta->ieee8021x_blocked = false;
589b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* rx will use bmc_sta's dot118021XPrivacy */
590b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pbcmc_sta->dot118021XPrivacy =
591b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psecuritypriv->dot118021XGrpPrivacy;
592b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
593b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
594b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
595b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
596b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
597b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
598b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
599b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6004e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) {
6014e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen		/*  psk/802_1x */
6020996cf9c693fd58d116619005ac1e1382865e0dbJes Sorensen		if (set_tx == 1) {
6034e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			/* pairwise key */
6044e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			memcpy(psta->dot118021x_UncstKey.skey,
605fd381874eb3efded6c088f649a03c03b9690d588Jes Sorensen			       keyparms->key, (key_len > 16 ? 16 : key_len));
606b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6074e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
6084e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			    keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
6094e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				DBG_8723A("%s, set pairwise key, WEP\n",
6104e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen					  __func__);
611b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
61255db5d02f81bd45c3a47f4ab4a917a70c6e13916Jes Sorensen				psecuritypriv->dot118021XGrpPrivacy =
61355db5d02f81bd45c3a47f4ab4a917a70c6e13916Jes Sorensen					keyparms->cipher;
6144e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			} else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) {
6154e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				DBG_8723A("%s, set pairwise key, TKIP\n",
6164e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen					  __func__);
617b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6184e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				psta->dot118021XPrivacy =
6194e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen					WLAN_CIPHER_SUITE_TKIP;
620b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6214e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				/* set mic key */
6224e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				memcpy(psta->dot11tkiptxmickey.skey,
623fd381874eb3efded6c088f649a03c03b9690d588Jes Sorensen				       &keyparms->key[16], 8);
6244e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				memcpy(psta->dot11tkiprxmickey.skey,
625fd381874eb3efded6c088f649a03c03b9690d588Jes Sorensen				       &keyparms->key[24], 8);
626b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6274e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				psecuritypriv->busetkipkey = 1;
628b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6294e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			} else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) {
6304e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				DBG_8723A("%s, set pairwise key, CCMP\n",
6314e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen					  __func__);
632b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6334e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				psta->dot118021XPrivacy =
6344e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen					WLAN_CIPHER_SUITE_CCMP;
6354e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			} else {
6364e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				DBG_8723A("%s, set pairwise key, none\n",
6374e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen					  __func__);
638b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6394e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				psta->dot118021XPrivacy = 0;
6404e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			}
641b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6424e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			set_pairwise_key(padapter, psta);
643b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6444e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			psta->ieee8021x_blocked = false;
645b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6464e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			psta->bpairwise_key_installed = true;
6474e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen		} else {	/* group key??? */
6484e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
6494e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			    keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
6504e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				memcpy(psecuritypriv->
651f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen				       dot118021XGrpKey[key_index].skey,
6527ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen				       keyparms->key, key_len);
6534e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen
6544e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				psecuritypriv->dot118021XGrpPrivacy =
65555db5d02f81bd45c3a47f4ab4a917a70c6e13916Jes Sorensen					keyparms->cipher;
6564e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			} else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) {
6574e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				psecuritypriv->dot118021XGrpPrivacy =
6584e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen					WLAN_CIPHER_SUITE_TKIP;
659b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6604e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				memcpy(psecuritypriv->
661f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen				       dot118021XGrpKey[key_index].skey,
662fd381874eb3efded6c088f649a03c03b9690d588Jes Sorensen				       keyparms->key,
663c36e122f6eba4e31c67d572c1e01ef845747010dJes Sorensen				       (key_len > 16 ? 16 : key_len));
664b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6654e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				/* set mic key */
6664e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				memcpy(psecuritypriv->
667f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen				       dot118021XGrptxmickey[key_index].skey,
668fd381874eb3efded6c088f649a03c03b9690d588Jes Sorensen				       &keyparms->key[16], 8);
6694e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				memcpy(psecuritypriv->
670f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen				       dot118021XGrprxmickey[key_index].skey,
671fd381874eb3efded6c088f649a03c03b9690d588Jes Sorensen				       &keyparms->key[24], 8);
672b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
6734e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				psecuritypriv->busetkipkey = 1;
6744e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			} else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) {
6754e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				psecuritypriv->dot118021XGrpPrivacy =
6764e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen					WLAN_CIPHER_SUITE_CCMP;
6774e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen
6784e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				memcpy(psecuritypriv->
679f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen				       dot118021XGrpKey[key_index].skey,
680fd381874eb3efded6c088f649a03c03b9690d588Jes Sorensen				       keyparms->key,
681c36e122f6eba4e31c67d572c1e01ef845747010dJes Sorensen				       (key_len > 16 ? 16 : key_len));
6824e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			} else {
6834e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				psecuritypriv->dot118021XGrpPrivacy = 0;
6844e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			}
6854e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen
686f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen			psecuritypriv->dot118021XGrpKeyid = key_index;
6874e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen
6884e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			psecuritypriv->binstallGrpkey = 1;
6894e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen
6904e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			psecuritypriv->dot11PrivacyAlgrthm =
6914e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				psecuritypriv->dot118021XGrpPrivacy;
6924e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen
6932dcf6b4c73a3b92774955b83e5bd7c5cec2c87e6Jes Sorensen			set_group_key(padapter, keyparms,
6944e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				      psecuritypriv->dot118021XGrpPrivacy,
695f7ce87cdb7b8e7a674fa66d3948c5f6986737377Jes Sorensen				      key_index);
6964e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen
6974e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
6984e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen			if (pbcmc_sta) {
6994e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				/* rx will use bmc_sta's
7004e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				   dot118021XPrivacy */
7014e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				pbcmc_sta->ieee8021x_blocked = false;
7024e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen				pbcmc_sta->dot118021XPrivacy =
7034e297c21bf2932178e7bdaeff654914b576e5f70Jes Sorensen					psecuritypriv->dot118021XGrpPrivacy;
704b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
705b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
706b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
707b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
708b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
709b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
710b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
711b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
712b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif
713b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7145292a891979aab582cb66e5105fc2ab78ff2a070Jes Sorensenstatic int rtw_cfg80211_set_encryption(struct net_device *dev, u8 key_index,
715f88ab54c10b1270257f39268e88c1949fd903fb2Jes Sorensen				       int set_tx, const u8 *sta_addr,
716a9e346fb88d6daeef37c21a3c55ebd70f1501fd2Jes Sorensen				       struct key_params *keyparms)
717b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
718b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
719d0dc266692d1bd4579fd9abd4a9b80f8d0ab5150Jes Sorensen	int key_len;
720b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(dev);
721b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
722b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
723b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
724b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
725b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
726d0dc266692d1bd4579fd9abd4a9b80f8d0ab5150Jes Sorensen	key_len = keyparms->key_len;
727d0dc266692d1bd4579fd9abd4a9b80f8d0ab5150Jes Sorensen
7288188b1cb6165655d087edf89b6619e62021762d8Jes Sorensen	if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
7298188b1cb6165655d087edf89b6619e62021762d8Jes Sorensen	    keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
730b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
731b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			 ("wpa_set_encryption, crypt.alg = WEP\n"));
732b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("wpa_set_encryption, crypt.alg = WEP\n");
733b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
734b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
735b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* wep default key has not been set, so use this
736b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   key index as default key. */
737b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
738b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->ndisencryptstatus =
739b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				Ndis802_11Encryption1Enabled;
7407ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen			psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher;
7417ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen			psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher;
742b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7435292a891979aab582cb66e5105fc2ab78ff2a070Jes Sorensen			psecuritypriv->dot11PrivacyKeyIndex = key_index;
744b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
745b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7465292a891979aab582cb66e5105fc2ab78ff2a070Jes Sorensen		memcpy(&psecuritypriv->wep_key[key_index].key,
747e1343f90809ab29bd1ec286fef1d9e6fcc59b404Jes Sorensen		       keyparms->key, key_len);
748b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7495292a891979aab582cb66e5105fc2ab78ff2a070Jes Sorensen		psecuritypriv->wep_key[key_index].keylen = key_len;
750b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7515292a891979aab582cb66e5105fc2ab78ff2a070Jes Sorensen		rtw_set_key23a(padapter, psecuritypriv, key_index, 0);
752b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
753b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
754b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
755b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
756b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (padapter->securitypriv.dot11AuthAlgrthm ==
757b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    dot11AuthAlgrthm_8021X) {	/*  802_1x */
758b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct sta_info *psta, *pbcmc_sta;
759b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct sta_priv *pstapriv = &padapter->stapriv;
760b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
761b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (check_fwstate(pmlmepriv,
762b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  WIFI_STATION_STATE | WIFI_MP_STATE)) {
763b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* sta mode */
764b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psta = rtw_get_stainfo23a(pstapriv, get_bssid(pmlmepriv));
765b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (psta == NULL) {
766b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s, : Obtain Sta_info fail\n",
767b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__);
768b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			} else {
769b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* Jeff: don't disable ieee8021x_blocked
770b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   while clearing key */
771efd4216c2d558f2faf03284e95a9c1c1297d801aJes Sorensen				if (keyparms->cipher != IW_AUTH_CIPHER_NONE &&
772efd4216c2d558f2faf03284e95a9c1c1297d801aJes Sorensen				    keyparms->cipher != 0)
773b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psta->ieee8021x_blocked = false;
774b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
775b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if ((padapter->securitypriv.ndisencryptstatus ==
776b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     Ndis802_11Encryption2Enabled) ||
777b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    (padapter->securitypriv.ndisencryptstatus ==
778b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     Ndis802_11Encryption3Enabled)) {
779b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					psta->dot118021XPrivacy =
780b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						padapter->securitypriv.
781b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						dot11PrivacyAlgrthm;
782b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
783b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7840996cf9c693fd58d116619005ac1e1382865e0dbJes Sorensen				if (set_tx == 1) {
785b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					/* pairwise key */
7860996cf9c693fd58d116619005ac1e1382865e0dbJes Sorensen					DBG_8723A("%s, : set_tx == 1\n",
7870996cf9c693fd58d116619005ac1e1382865e0dbJes Sorensen						  __func__);
788b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
789b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(psta->dot118021x_UncstKey.skey,
790e1343f90809ab29bd1ec286fef1d9e6fcc59b404Jes Sorensen					       keyparms->key,
791d0dc266692d1bd4579fd9abd4a9b80f8d0ab5150Jes Sorensen					       (key_len > 16 ? 16 : key_len));
792b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
7938188b1cb6165655d087edf89b6619e62021762d8Jes Sorensen					if (keyparms->cipher ==
7948188b1cb6165655d087edf89b6619e62021762d8Jes Sorensen					    WLAN_CIPHER_SUITE_TKIP) {
795b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						memcpy(psta->dot11tkiptxmickey.
796b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       skey,
797e1343f90809ab29bd1ec286fef1d9e6fcc59b404Jes Sorensen						       &keyparms->key[16], 8);
798b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						memcpy(psta->dot11tkiprxmickey.
799b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						       skey,
800e1343f90809ab29bd1ec286fef1d9e6fcc59b404Jes Sorensen						       &keyparms->key[24], 8);
801b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
802b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						padapter->securitypriv.
8039216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen							busetkipkey = 0;
804b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					}
805b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A(" ~~~~set sta key:unicastkey\n");
806b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
807b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					rtw_setstakey_cmd23a(padapter,
808b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							  (unsigned char *)psta,
809b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							  true);
810b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				} else {	/* group key */
811b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(padapter->securitypriv.
8125292a891979aab582cb66e5105fc2ab78ff2a070Jes Sorensen					       dot118021XGrpKey[key_index].skey,
813e1343f90809ab29bd1ec286fef1d9e6fcc59b404Jes Sorensen					       keyparms->key,
814d0dc266692d1bd4579fd9abd4a9b80f8d0ab5150Jes Sorensen					       (key_len > 16 ? 16 : key_len));
815b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(padapter->securitypriv.
8165292a891979aab582cb66e5105fc2ab78ff2a070Jes Sorensen					       dot118021XGrptxmickey[key_index].
817e1343f90809ab29bd1ec286fef1d9e6fcc59b404Jes Sorensen					       skey, &keyparms->key[16], 8);
818b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					memcpy(padapter->securitypriv.
8195292a891979aab582cb66e5105fc2ab78ff2a070Jes Sorensen					       dot118021XGrprxmickey[key_index].
820e1343f90809ab29bd1ec286fef1d9e6fcc59b404Jes Sorensen					       skey, &keyparms->key[24], 8);
821b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					padapter->securitypriv.binstallGrpkey =
8229216c517fb0192d1828169d8af2bac59ee8e3173Jes Sorensen						1;
823b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					DBG_8723A
824b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					    (" ~~~~set sta key:groupkey\n");
825b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
826b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					padapter->securitypriv.
8275292a891979aab582cb66e5105fc2ab78ff2a070Jes Sorensen					    dot118021XGrpKeyid = key_index;
828b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
829b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					rtw_set_key23a(padapter,
830b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    &padapter->securitypriv,
8315292a891979aab582cb66e5105fc2ab78ff2a070Jes Sorensen						    key_index, 1);
832b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
833b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
834b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
835b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
836b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pbcmc_sta) {
837b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* Jeff: don't disable ieee8021x_blocked
838b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   while clearing key */
839efd4216c2d558f2faf03284e95a9c1c1297d801aJes Sorensen				if (keyparms->cipher != IW_AUTH_CIPHER_NONE &&
840efd4216c2d558f2faf03284e95a9c1c1297d801aJes Sorensen				    keyparms->cipher != 0)
841b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pbcmc_sta->ieee8021x_blocked = false;
842b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
843b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				if ((padapter->securitypriv.ndisencryptstatus ==
844b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     Ndis802_11Encryption2Enabled) ||
845b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    (padapter->securitypriv.ndisencryptstatus ==
846b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     Ndis802_11Encryption3Enabled)) {
847b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					pbcmc_sta->dot118021XPrivacy =
848b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					    padapter->securitypriv.
849b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					    dot11PrivacyAlgrthm;
850b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				}
851b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
852b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		} else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {	/* adhoc mode */
853b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
854b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
855b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
856b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
857b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
858b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ret =%d\n", __func__, ret);
859b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
860b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
861b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
862b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
863b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
864b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
865b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
866b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				u8 key_index, bool pairwise,
867b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				const u8 *mac_addr, struct key_params *params)
868b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
8690996cf9c693fd58d116619005ac1e1382865e0dbJes Sorensen	int set_tx, ret = 0;
870b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
871b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
872b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
873f88ab54c10b1270257f39268e88c1949fd903fb2Jes Sorensen	u8 sta_addr[ETH_ALEN];
874b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
875a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): adding key for %pM\n", __func__, ndev->name,
876b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  mac_addr);
877b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("cipher = 0x%x\n", params->cipher);
878b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("key_len = 0x%x\n", params->key_len);
879b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("seq_len = 0x%x\n", params->seq_len);
880b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("key_index =%d\n", key_index);
881b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("pairwise =%d\n", pairwise);
882b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
883b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (params->cipher) {
884b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case IW_AUTH_CIPHER_NONE:
885b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_WEP40:
8867ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen		if (params->key_len != WLAN_KEY_LEN_WEP40) {
8877ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen			ret = -EINVAL;
8887ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen			goto exit;
8897ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen		}
890b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_WEP104:
8917ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen		if (params->key_len != WLAN_KEY_LEN_WEP104) {
8927ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen			ret = -EINVAL;
8937ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen			goto exit;
8947ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen		}
895b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_TKIP:
896b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_CCMP:
897b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
898b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
899b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOTSUPP;
900efd4216c2d558f2faf03284e95a9c1c1297d801aJes Sorensen		goto exit;
901b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
902b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
9037ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen	if (key_index >= WEP_KEYS || params->key_len < 0) {
9047ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen		ret = -EINVAL;
9057ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen		goto exit;
9067ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen	}
9077ef2743da1bb1edcad5cdfafe75652445fa3cc1bJes Sorensen
908f88ab54c10b1270257f39268e88c1949fd903fb2Jes Sorensen	eth_broadcast_addr(sta_addr);
909b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
9100996cf9c693fd58d116619005ac1e1382865e0dbJes Sorensen	if (!mac_addr || is_broadcast_ether_addr(mac_addr))
9110996cf9c693fd58d116619005ac1e1382865e0dbJes Sorensen		set_tx = 0;	/* for wpa/wpa2 group key */
9120996cf9c693fd58d116619005ac1e1382865e0dbJes Sorensen	else
9130996cf9c693fd58d116619005ac1e1382865e0dbJes Sorensen		set_tx = 1;	/* for wpa/wpa2 pairwise key */
914b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
915b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
9160996cf9c693fd58d116619005ac1e1382865e0dbJes Sorensen		ret = rtw_cfg80211_set_encryption(ndev, key_index, set_tx,
917f0bf8dd53d1a1c952784f1e5cf0c076cb514bdafJes Sorensen						  sta_addr, params);
918b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
919b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
920b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (mac_addr)
921f88ab54c10b1270257f39268e88c1949fd903fb2Jes Sorensen			ether_addr_copy(sta_addr, mac_addr);
922b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
9230996cf9c693fd58d116619005ac1e1382865e0dbJes Sorensen		ret = rtw_cfg80211_ap_set_encryption(ndev, key_index, set_tx,
924f0bf8dd53d1a1c952784f1e5cf0c076cb514bdafJes Sorensen						     sta_addr, params);
925b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif
926b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
927b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("error! fw_state = 0x%x, iftype =%d\n",
928b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  pmlmepriv->fw_state, rtw_wdev->iftype);
929b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
930b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
931b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
932efd4216c2d558f2faf03284e95a9c1c1297d801aJes Sorensenexit:
933b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
934b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
935b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
936b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int
937b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingercfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,
938b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		     u8 key_index, bool pairwise, const u8 *mac_addr,
939b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		     void *cookie,
940b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		     void (*callback) (void *cookie, struct key_params *))
941b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
942a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
943b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
944b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
945b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
946b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
947b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				u8 key_index, bool pairwise,
948b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				const u8 *mac_addr)
949b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
950b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(ndev);
951b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
952b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
953a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): key_index =%d\n", __func__, ndev->name, key_index);
954b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
955b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (key_index == psecuritypriv->dot11PrivacyKeyIndex) {
956b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* clear the flag of wep default key set. */
957b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->bWepDefaultKeyIdxSet = 0;
958b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
959b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
960b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
961b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
962b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
963b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
964b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					struct net_device *ndev, u8 key_index,
965b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					bool unicast, bool multicast)
966b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
967b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(ndev);
968b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
969b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
970a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): key_index =%d, unicast =%d, multicast =%d.\n",
971a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		  __func__, ndev->name, key_index, unicast, multicast);
972b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
973e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	if (key_index < NUM_WEP_KEYS &&
974e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	    (psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP40 ||
975e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen	     psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP104)) {
976b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* set wep default key */
977b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
978b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
979b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11PrivacyKeyIndex = key_index;
980b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
9819e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
9829e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
983e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen		if (psecuritypriv->wep_key[key_index].keylen == 13) {
984e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen			psecuritypriv->dot11PrivacyAlgrthm =
985e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen				WLAN_CIPHER_SUITE_WEP104;
986e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen			psecuritypriv->dot118021XGrpPrivacy =
987e0827909a27c5d90bf88f714e108de9419fd8b29Jes Sorensen				WLAN_CIPHER_SUITE_WEP104;
988b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
989b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
990b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* set the flag to represent that wep default key
991b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		   has been set */
992b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->bWepDefaultKeyIdxSet = 1;
993b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
994b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
995b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
996b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
997b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
99827fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensenstatic u16 rtw_get_cur_max_rate(struct rtw_adapter *adapter)
99927fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen{
100027fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	int i = 0;
100127fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	const u8 *p;
100227fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	u16 rate = 0, max_rate = 0;
100327fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
100427fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
100527fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	struct registry_priv *pregistrypriv = &adapter->registrypriv;
100627fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
100727fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
100827fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	struct ieee80211_ht_cap *pht_capie;
100927fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	u8 rf_type = 0;
101027fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
101127fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	u16 mcs_rate = 0;
101227fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
10131d33b0766385957c0e70ff32ec501d1f775c8316Jes Sorensen	p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
10141de65ccb1f90be71cd7deb3c963f7440560e4325Jes Sorensen			     pcur_bss->IEs, pcur_bss->IELength);
101527fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	if (p && p[1] > 0) {
101627fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		pht_capie = (struct ieee80211_ht_cap *)(p + 2);
101727fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
101827fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		memcpy(&mcs_rate, &pht_capie->mcs, 2);
101927fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
102027fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		/* bw_40MHz = (pht_capie->cap_info&
102127fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		   IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1:0; */
102227fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		/* cur_bwmod is updated by beacon, pmlmeinfo is
102327fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		   updated by association response */
102427fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		bw_40MHz = (pmlmeext->cur_bwmode &&
102527fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			    (pmlmeinfo->HT_info.ht_param &
102627fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			     IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) ? 1:0;
102727fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
102827fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		/* short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP
102927fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		   _SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; */
103027fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		short_GI_20 = (pmlmeinfo->ht_cap.cap_info &
103127fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			       cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) ? 1:0;
103227fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		short_GI_40 = (pmlmeinfo->ht_cap.cap_info &
103327fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			       cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) ? 1:0;
103427fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
103527fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		rf_type = rtl8723a_get_rf_type(adapter);
103627fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		max_rate = rtw_mcs_rate23a(rf_type, bw_40MHz &
103727fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen					   pregistrypriv->cbw40_enable,
103827fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen					   short_GI_20, short_GI_40,
103927fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen					   &pmlmeinfo->ht_cap.mcs);
104027fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	} else {
104127fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		while (pcur_bss->SupportedRates[i] != 0 &&
104227fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		       pcur_bss->SupportedRates[i] != 0xFF) {
104327fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			rate = pcur_bss->SupportedRates[i] & 0x7F;
104427fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			if (rate>max_rate)
104527fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen				max_rate = rate;
104627fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen			i++;
104727fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		}
104827fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
104927fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		max_rate = max_rate * 10 / 2;
105027fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	}
105127fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
105227fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen	return max_rate;
105327fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen}
105427fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen
1055b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_get_station(struct wiphy *wiphy,
1056b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct net_device *ndev,
1057f9da455b93f6ba076935b4ef4589f61e529ae046Linus Torvalds				    const u8 *mac, struct station_info *sinfo)
1058b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1059b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1060b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1061b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1062b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_info *psta = NULL;
1063b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_priv *pstapriv = &padapter->stapriv;
1064b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1065b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	sinfo->filled = 0;
1066b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1067b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mac) {
1068a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("%s(%s): mac ==%p\n", __func__, ndev->name, mac);
1069b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOENT;
1070b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1071b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1072b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1073b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psta = rtw_get_stainfo23a(pstapriv, mac);
1074b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (psta == NULL) {
1075b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, sta_info is null\n", __func__);
1076b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOENT;
1077b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1078b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1079a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): mac =" MAC_FMT "\n", __func__, ndev->name,
1080b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  MAC_ARG(mac));
1081b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1082b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* for infra./P2PClient mode */
1083b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
1084b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    check_fwstate(pmlmepriv, _FW_LINKED)) {
1085b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct wlan_network *cur_network = &pmlmepriv->cur_network;
1086b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1087cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen		if (!ether_addr_equal(mac, cur_network->network.MacAddress)) {
1088b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("%s, mismatch bssid =" MAC_FMT "\n", __func__,
1089b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  MAC_ARG(cur_network->network.MacAddress));
1090b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -ENOENT;
1091b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
1092b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1093b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1094b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->filled |= STATION_INFO_SIGNAL;
1095b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.
1096b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger							    signal_strength);
1097b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1098b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->filled |= STATION_INFO_TX_BITRATE;
109927fd731ece203c37f0a3708cafc95e9cead8cd2dJes Sorensen		sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter);
1100b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1101b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->filled |= STATION_INFO_RX_PACKETS;
1102b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->rx_packets = sta_rx_data_pkts(psta);
1103b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1104b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->filled |= STATION_INFO_TX_PACKETS;
1105b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo->tx_packets = psta->sta_stats.tx_pkts;
1106b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1107b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1108b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* for Ad-Hoc/AP mode */
1109b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
1110b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	     check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1111b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	     check_fwstate(pmlmepriv, WIFI_AP_STATE)) &&
1112b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    check_fwstate(pmlmepriv, _FW_LINKED)
1113b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    ) {
1114b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* TODO: should acquire station info... */
1115b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1116b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1117b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
1118b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1119b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1120b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
11214e66cf096c736532e277a992e8b0b3045af30b1dGreg Donaldint cfg80211_infrastructure_mode(struct rtw_adapter *padapter,
1122efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				 enum nl80211_iftype ifmode)
1123efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen{
1124efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1125efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	struct wlan_network *cur_network = &pmlmepriv->cur_network;
1126efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	enum nl80211_iftype old_mode;
1127efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1128efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	old_mode = cur_network->network.ifmode;
1129efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1130efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
1131efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		 ("+%s: old =%d new =%d fw_state = 0x%08x\n", __func__,
1132efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		  old_mode, ifmode, get_fwstate(pmlmepriv)));
1133efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1134efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	if (old_mode != ifmode) {
1135efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		spin_lock_bh(&pmlmepriv->lock);
1136efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1137efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1138efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			 (" change mode!"));
1139efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1140efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		if (old_mode == NL80211_IFTYPE_AP ||
1141efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    old_mode == NL80211_IFTYPE_P2P_GO) {
1142efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			/* change to other mode from Ndis802_11APMode */
1143efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			cur_network->join_res = -1;
1144efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1145efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen#ifdef CONFIG_8723AU_AP_MODE
1146efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			stop_ap_mode23a(padapter);
1147efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen#endif
1148efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		}
1149efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1150efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		if (check_fwstate(pmlmepriv, _FW_LINKED) ||
1151efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    old_mode == NL80211_IFTYPE_ADHOC)
1152efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			rtw_disassoc_cmd23a(padapter, 0, true);
1153efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1154efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		if (check_fwstate(pmlmepriv, _FW_LINKED) ||
1155efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
1156efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			rtw_free_assoc_resources23a(padapter, 1);
1157efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1158efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		if (old_mode == NL80211_IFTYPE_STATION ||
1159efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    old_mode == NL80211_IFTYPE_P2P_CLIENT ||
1160efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    old_mode == NL80211_IFTYPE_ADHOC) {
1161efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1162efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				/* will clr Linked_state; before this function,
1163efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				   we must have chked whether issue
1164efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				   dis-assoc_cmd or not */
1165efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen				rtw_indicate_disconnect23a(padapter);
1166efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			}
1167efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	       }
1168efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1169efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		cur_network->network.ifmode = ifmode;
1170efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1171efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		_clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
1172efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1173efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		switch (ifmode) {
1174efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_ADHOC:
1175efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
1176efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			break;
1177efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1178efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_P2P_CLIENT:
1179efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_STATION:
1180efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			set_fwstate(pmlmepriv, WIFI_STATION_STATE);
1181efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			break;
1182efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1183efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_P2P_GO:
1184efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		case NL80211_IFTYPE_AP:
1185efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			set_fwstate(pmlmepriv, WIFI_AP_STATE);
1186efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen#ifdef CONFIG_8723AU_AP_MODE
1187efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			start_ap_mode23a(padapter);
1188efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			/* rtw_indicate_connect23a(padapter); */
1189efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen#endif
1190efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			break;
1191efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1192efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		default:
1193efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen			break;
1194efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		}
1195efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1196efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		/* SecClearAllKeys(adapter); */
1197efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1198efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		/* RT_TRACE(COMP_OID_SET, DBG_LOUD,
1199efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		   ("set_infrastructure: fw_state:%x after changing mode\n", */
1200efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		/* get_fwstate(pmlmepriv))); */
1201efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1202efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		spin_unlock_bh(&pmlmepriv->lock);
1203efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	}
1204efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1205efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	return _SUCCESS;
1206efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen}
1207efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen
1208b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_change_iface(struct wiphy *wiphy,
1209b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     struct net_device *ndev,
1210b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     enum nl80211_iftype type, u32 *flags,
1211b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     struct vif_params *params)
1212b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1213b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	enum nl80211_iftype old_type;
1214b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1215b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1216b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
1217b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1218b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1219a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): call netdev_open23a\n", __func__, ndev->name);
1220b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1221b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	old_type = rtw_wdev->iftype;
1222a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): old_iftype =%d, new_iftype =%d\n",
1223a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		  __func__, ndev->name, old_type, type);
1224b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1225b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (old_type != type) {
1226b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmeext->action_public_rxseq = 0xffff;
1227b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmeext->action_public_dialog_token = 0xff;
1228b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1229b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1230b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (type) {
1231b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_ADHOC:
1232b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_P2P_CLIENT:
1233b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_STATION:
1234b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_P2P_GO:
1235b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_AP:
1236efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	case NL80211_IFTYPE_UNSPECIFIED:
1237b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1238b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
1239b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EOPNOTSUPP;
1240b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1241b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1242b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_wdev->iftype = type;
1243b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1244efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	if (cfg80211_infrastructure_mode(padapter, type) != _SUCCESS) {
1245b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_wdev->iftype = old_type;
1246b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
1247b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1248b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1249b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1250efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	rtw_setopmode_cmd23a(padapter, type);
1251b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1252b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
1253b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1254b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1255b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1256b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
1257b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     bool aborted)
1258b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1259b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pwdev_priv->scan_req_lock);
1260b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pwdev_priv->scan_request != NULL) {
1261b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s with scan req\n", __func__);
1262141bd353c5a9ba987dbe7b28ffdd034bb3ed55baJes Sorensen
1263b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (pwdev_priv->scan_request->wiphy !=
1264b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		    pwdev_priv->rtw_wdev->wiphy)
1265b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			DBG_8723A("error wiphy compare\n");
1266b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		else
1267b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			cfg80211_scan_done(pwdev_priv->scan_request, aborted);
1268b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1269b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->scan_request = NULL;
1270b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
1271b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s without scan req\n", __func__);
1272b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1273b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pwdev_priv->scan_req_lock);
1274b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1275b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1276b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter)
1277b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1278b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct list_head *plist, *phead, *ptmp;
1279b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1280b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1281b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wlan_network *pnetwork;
1282b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1283b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1284b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1285b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	phead = get_list_head(queue);
1286b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1287b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	list_for_each_safe(plist, ptmp, phead) {
1288b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pnetwork = container_of(plist, struct wlan_network, list);
1289b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1290b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* report network only if the current channel set
1291b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		   contains the channel to which this network belongs */
1292b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (rtw_ch_set_search_ch23a
1293b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		    (padapter->mlmeextpriv.channel_set,
129437cb982c2685029e716bfeccf55ec244a6919a32Jes Sorensen		     pnetwork->network.DSConfig) >= 0)
1295b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			rtw_cfg80211_inform_bss(padapter, pnetwork);
1296b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1297b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1298b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1299b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1300b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* call this after other things have been done */
1301b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev),
1302b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					false);
1303b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1304b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1305b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter,
1306b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       char *buf, int len)
1307b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1308b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1309d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen	const u8 *wps_ie;
1310b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1311b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1312b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ielen =%d\n", __func__, len);
1313b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1314b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (len > 0) {
1315d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1316d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen						 WLAN_OUI_TYPE_MICROSOFT_WPS,
1317d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen						 buf, len);
1318b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (wps_ie) {
1319d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen			DBG_8723A("probe_req_wps_ielen =%d\n", wps_ie[1]);
1320141bd353c5a9ba987dbe7b28ffdd034bb3ed55baJes Sorensen
1321b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pmlmepriv->wps_probe_req_ie) {
1322b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->wps_probe_req_ie_len = 0;
1323b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				kfree(pmlmepriv->wps_probe_req_ie);
1324b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pmlmepriv->wps_probe_req_ie = NULL;
1325b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
1326b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1327d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen			pmlmepriv->wps_probe_req_ie = kmemdup(wps_ie, wps_ie[1],
13284a6eea4dcbc0328c3126fed264c42b0725bea659Benoit Taine							      GFP_KERNEL);
1329b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pmlmepriv->wps_probe_req_ie == NULL) {
1330b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
1331b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  __func__, __LINE__);
1332b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				return -EINVAL;
1333b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
1334d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen			pmlmepriv->wps_probe_req_ie_len = wps_ie[1];
1335b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1336b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1337b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1338b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1339b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1340b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1341b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_scan(struct wiphy *wiphy,
1342b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     struct cfg80211_scan_request *request)
1343b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1344b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int i;
1345b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 _status = false;
1346b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1347b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1348b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1349b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1350b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
1351b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
1352b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct cfg80211_ssid *ssids = request->ssids;
1353b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	bool need_indicate_scan_done = false;
1354b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1355a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name);
1356b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1357b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pwdev_priv->scan_req_lock);
1358b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->scan_request = request;
1359b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pwdev_priv->scan_req_lock);
1360b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1361b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1362b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s under WIFI_AP_STATE\n", __func__);
1363b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* need_indicate_scan_done = true; */
1364b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* goto check_need_indicate_scan_done; */
1365b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1366b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1367b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rtw_pwr_wakeup(padapter) == _FAIL) {
1368b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		need_indicate_scan_done = true;
1369b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto check_need_indicate_scan_done;
1370b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1371b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1372b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (request->ie && request->ie_len > 0) {
1373b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_cfg80211_set_probe_req_wpsp2pie(padapter,
1374b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    (u8 *) request->ie,
1375b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						    request->ie_len);
1376b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1377b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1378b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) {
1379b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, bBusyTraffic == true\n", __func__);
1380b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		need_indicate_scan_done = true;
1381b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto check_need_indicate_scan_done;
1382b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1383b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rtw_is_scan_deny(padapter)) {
13849cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): scan deny\n", __func__,
13859cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name);
1386b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		need_indicate_scan_done = true;
1387b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto check_need_indicate_scan_done;
1388b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1389b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1390b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ==
1391b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    true) {
1392b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, fwstate = 0x%x\n", __func__, pmlmepriv->fw_state);
1393b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		need_indicate_scan_done = true;
1394b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto check_need_indicate_scan_done;
1395b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1396b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1397b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memset(ssid, 0, sizeof(struct cfg80211_ssid) * RTW_SSID_SCAN_AMOUNT);
1398b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* parsing request ssids, n_ssids */
1399b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
1400b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("ssid =%s, len =%d\n", ssids[i].ssid,
1401b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  ssids[i].ssid_len);
1402b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(ssid[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
1403b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ssid[i].ssid_len = ssids[i].ssid_len;
1404b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1405b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1406b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* parsing channels, n_channels */
1407b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memset(ch, 0,
1408b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct rtw_ieee80211_channel) * RTW_CHANNEL_SCAN_AMOUNT);
1409b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1410b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (request->n_channels == 1) {
1411b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		for (i = 0; i < request->n_channels &&
1412b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		     i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
14139cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			DBG_8723A("%s:(%s):" CHAN_FMT "\n",
14149cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen				  __func__, padapter->pnetdev->name,
1415b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  CHAN_ARG(request->channels[i]));
1416b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ch[i].hw_value = request->channels[i]->hw_value;
1417b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ch[i].flags = request->channels[i]->flags;
1418b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1419b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1420b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1421b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pmlmepriv->lock);
1422b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (request->n_channels == 1) {
1423b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(&ch[1], &ch[0], sizeof(struct rtw_ieee80211_channel));
1424b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(&ch[2], &ch[0], sizeof(struct rtw_ieee80211_channel));
1425b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		_status = rtw_sitesurvey_cmd23a(padapter, ssid,
1426b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     RTW_SSID_SCAN_AMOUNT, ch, 3);
1427b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
1428b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		_status = rtw_sitesurvey_cmd23a(padapter, ssid,
1429b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     RTW_SSID_SCAN_AMOUNT, NULL, 0);
1430b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1431b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pmlmepriv->lock);
1432b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1433b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (_status == false)
1434b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -1;
1435b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1436b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingercheck_need_indicate_scan_done:
1437b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (need_indicate_scan_done)
1438b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_cfg80211_surveydone_event_callback(padapter);
1439b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1440b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1441b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1442b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1443b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1444b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
1445b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1446b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1447b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1448b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
1449b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct cfg80211_ibss_params *params)
1450b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1451a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
1452b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1453b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1454b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1455b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1456b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1457a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
1458b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1459b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1460b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1461b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv,
1462b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					u32 wpa_version)
1463b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1464b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, wpa_version =%d\n", __func__, wpa_version);
1465b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1466b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!wpa_version) {
1467b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
1468b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return 0;
1469b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1470b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1471b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) {
1472b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
1473b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1474b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1475b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger/*
1476b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (wpa_version & NL80211_WPA_VERSION_2)
1477b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	{
1478b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;
1479b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1480b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger*/
1481b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1482b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1483b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1484b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1485b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
1486b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      enum nl80211_auth_type sme_auth_type)
1487b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1488b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, nl80211_auth_type =%d\n", __func__, sme_auth_type);
1489b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1490b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (sme_auth_type) {
1491b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_AUTHTYPE_AUTOMATIC:
1492b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1493b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1494b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1495b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_AUTHTYPE_OPEN_SYSTEM:
1496b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1497b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1498b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (psecuritypriv->ndisauthtype > Ndis802_11AuthModeWPA)
1499b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->dot11AuthAlgrthm =
1500b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				dot11AuthAlgrthm_8021X;
1501b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1502b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_AUTHTYPE_SHARED_KEY:
1503b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1504b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1505b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1506b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1507b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
1508b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1509b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* return -ENOTSUPP; */
1510b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1511b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1512b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1513b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1514b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1515b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv,
1516b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   u32 cipher, bool ucast)
1517b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1518b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 ndisencryptstatus = Ndis802_11EncryptionDisabled;
1519b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1520b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :
1521b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    &psecuritypriv->dot118021XGrpPrivacy;
1522b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1523b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ucast =%d, cipher = 0x%x\n", __func__, ucast, cipher);
1524b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1525b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!cipher) {
15269e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = 0;
1527b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1528b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return 0;
1529b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1530b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1531b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (cipher) {
1532b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case IW_AUTH_CIPHER_NONE:
15339e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = 0;
1534b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11EncryptionDisabled;
1535b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1536b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_WEP40:
15379e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = WLAN_CIPHER_SUITE_WEP40;
1538b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11Encryption1Enabled;
1539b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1540b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_WEP104:
15419e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = WLAN_CIPHER_SUITE_WEP104;
1542b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11Encryption1Enabled;
1543b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1544b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_TKIP:
15459e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = WLAN_CIPHER_SUITE_TKIP;
1546b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11Encryption2Enabled;
1547b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1548b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WLAN_CIPHER_SUITE_CCMP:
15499e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		*profile_cipher = WLAN_CIPHER_SUITE_CCMP;
1550b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ndisencryptstatus = Ndis802_11Encryption3Enabled;
1551b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1552b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
1553b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Unsupported cipher: 0x%x\n", cipher);
1554b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -ENOTSUPP;
1555b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1556b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1557b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ucast)
1558b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1559b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1560b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1561b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1562b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1563b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv,
1564b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    u32 key_mgt)
1565b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1566b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, key_mgt = 0x%x\n", __func__, key_mgt);
1567b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1568b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (key_mgt == WLAN_AKM_SUITE_8021X)
1569b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1570b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else if (key_mgt == WLAN_AKM_SUITE_PSK)
1571b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1572b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
1573b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Invalid key mgt: 0x%x\n", key_mgt);
1574b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1575b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
1576b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1577b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1578b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
1579b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   size_t ielen)
1580b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1581d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen	const u8 *wps_ie;
1582b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int group_cipher = 0, pairwise_cipher = 0;
1583b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
158458aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen	const u8 *pwpa, *pwpa2;
1585b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int i;
1586b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1587b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!pie || !ielen) {
1588b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* Treat this as normal case, but need to clear
1589b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		   WIFI_UNDER_WPS */
1590b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1591b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1592b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1593b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) {
1594b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
1595b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1596b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1597b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1598b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* dump */
1599b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("set wpa_ie(length:%zu):\n", ielen);
1600b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	for (i = 0; i < ielen; i = i + 8)
16017579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen		DBG_8723A("0x%.2x 0x%.2x 0x%.2x 0x%.2x "
16027579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen			  "0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
16037579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen			  pie[i], pie[i + 1], pie[i + 2], pie[i + 3],
16047579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen			  pie[i + 4], pie[i + 5], pie[i + 6], pie[i + 7]);
1605b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ielen < RSN_HEADER_LEN) {
1606b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
1607b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			 ("Ie len too short %d\n", (int)ielen));
1608b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -1;
1609b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1610b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1611b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
161258aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen	pwpa = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
161358aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen				       WLAN_OUI_TYPE_MICROSOFT_WPA,
16147579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen				       pie, ielen);
161558aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen	if (pwpa && pwpa[1] > 0) {
161658aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen		if (rtw_parse_wpa_ie23a(pwpa, pwpa[1] + 2, &group_cipher,
161758aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen					&pairwise_cipher, NULL) == _SUCCESS) {
1618b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			padapter->securitypriv.dot11AuthAlgrthm =
1619b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				dot11AuthAlgrthm_8021X;
1620b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			padapter->securitypriv.ndisauthtype =
1621b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				Ndis802_11AuthModeWPAPSK;
162258aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			memcpy(padapter->securitypriv.supplicant_ie, pwpa,
162358aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			       pwpa[1] + 2);
1624b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
162558aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			DBG_8723A("got wpa_ie, wpa_ielen:%u\n", pwpa[1]);
1626b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1627b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1628b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
16297579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen	pwpa2 = cfg80211_find_ie(WLAN_EID_RSN, pie, ielen);
163058aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen	if (pwpa2 && pwpa2[1] > 0) {
163158aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen		if (rtw_parse_wpa2_ie23a (pwpa2, pwpa2[1] + 2, &group_cipher,
163258aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen					  &pairwise_cipher, NULL) == _SUCCESS) {
1633b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			padapter->securitypriv.dot11AuthAlgrthm =
1634b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				dot11AuthAlgrthm_8021X;
1635b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			padapter->securitypriv.ndisauthtype =
1636b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				Ndis802_11AuthModeWPA2PSK;
163758aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			memcpy(padapter->securitypriv.supplicant_ie, pwpa2,
163858aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			       pwpa2[1] + 2);
1639b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
164058aedb498f8a9870ff871058d4b91d77457fc14cJes Sorensen			DBG_8723A("got wpa2_ie, wpa2_ielen:%u\n", pwpa2[1]);
1641b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
1642b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1643b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1644b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (group_cipher == 0) {
1645b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		group_cipher = WPA_CIPHER_NONE;
1646b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1647b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pairwise_cipher == 0) {
1648b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pairwise_cipher = WPA_CIPHER_NONE;
1649b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1650b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1651b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (group_cipher) {
1652b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_NONE:
16539e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = 0;
1654b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1655b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11EncryptionDisabled;
1656b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1657b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_WEP40:
16589e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
1659b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1660b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption1Enabled;
1661b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1662b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_TKIP:
16639e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_TKIP;
1664b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1665b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption2Enabled;
1666b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1667b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_CCMP:
16689e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_CCMP;
1669b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1670b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption3Enabled;
1671b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1672b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_WEP104:
16739e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104;
1674b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1675b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption1Enabled;
1676b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1677b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1678b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1679b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (pairwise_cipher) {
1680b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_NONE:
16819e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = 0;
1682b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1683b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11EncryptionDisabled;
1684b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1685b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_WEP40:
16869e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
1687b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1688b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption1Enabled;
1689b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1690b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_TKIP:
16919e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_TKIP;
1692b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1693b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption2Enabled;
1694b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1695b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_CCMP:
16969e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_CCMP;
1697b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1698b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption3Enabled;
1699b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1700b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case WPA_CIPHER_WEP104:
17019e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen		padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
1702b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->securitypriv.ndisencryptstatus =
1703b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			Ndis802_11Encryption1Enabled;
1704b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
1705b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1706b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1707d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen	wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1708d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen					 WLAN_OUI_TYPE_MICROSOFT_WPS,
17097579a7e47d6572455c48f822dd47bd1993ec9d95Jes Sorensen					 pie, ielen);
1710d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen	if (wps_ie && wps_ie[1] > 0) {
1711d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		DBG_8723A("got wps_ie, wps_ielen:%u\n", wps_ie[1]);
1712d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		padapter->securitypriv.wps_ie_len = wps_ie[1];
1713d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		memcpy(padapter->securitypriv.wps_ie, wps_ie,
1714d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		       padapter->securitypriv.wps_ie_len);
1715d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
1716d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen	} else {
1717d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1718b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1719b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1720b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* TKIP and AES disallow multicast packets until installing group key */
17219e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	if (padapter->securitypriv.dot11PrivacyAlgrthm ==
17229e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	    WLAN_CIPHER_SUITE_TKIP ||
17239e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	    padapter->securitypriv.dot11PrivacyAlgrthm ==
17249e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	    WLAN_CIPHER_SUITE_CCMP)
1725b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* WPS open need to enable multicast */
1726b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true)*/
1727763b4247cafdb978630d4da7ff48c8113c7d961eJes Sorensen		rtl8723a_off_rcr_am(padapter);
1728b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1729b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1730b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->"
1731b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  "securitypriv.ndisencryptstatus =%d padapter->"
1732b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  "securitypriv.ndisauthtype =%d\n", pairwise_cipher,
1733b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  padapter->securitypriv.ndisencryptstatus,
1734b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  padapter->securitypriv.ndisauthtype));
1735b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1736b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
1737b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret)
1738b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1739b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
1740b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
1741b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
17426893c8ebba521ea9d0f1cc4a53233fcb09271d52Jes Sorensenstatic int rtw_cfg80211_add_wep(struct rtw_adapter *padapter,
1743deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				struct rtw_wep_key *wep, u8 keyid)
17441e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen{
1745deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen	int res;
17461e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	struct security_priv *psecuritypriv = &padapter->securitypriv;
17471e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
1748deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen	if (keyid >= NUM_WEP_KEYS) {
17491e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
17501e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen			 ("%s:keyid>4 =>fail\n", __func__));
17511e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		res = _FAIL;
17521e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		goto exit;
17531e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	}
17541e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
1755deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen	switch (wep->keylen) {
17564d9c63bbd207b20ae648bd6bd3ebcf6e52619616Jes Sorensen	case WLAN_KEY_LEN_WEP40:
17571e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
17581e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
17591e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen			 ("%s:wep->KeyLength = 5\n", __func__));
17601e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		break;
17614d9c63bbd207b20ae648bd6bd3ebcf6e52619616Jes Sorensen	case WLAN_KEY_LEN_WEP104:
17621e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
17631e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
17641e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen			 ("%s:wep->KeyLength = 13\n", __func__));
17651e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		break;
17661e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	default:
17671e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		psecuritypriv->dot11PrivacyAlgrthm = 0;
17681e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
17691e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen			 ("%s:wep->KeyLength!= 5 or 13\n", __func__));
17701e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		res = _FAIL;
17711e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		goto exit;
17721e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	}
17731e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
17741e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1775deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		 ("%s:before memcpy, wep->KeyLength = 0x%x keyid =%x\n",
1776deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		  __func__, wep->keylen, keyid));
17771e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
1778deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen	memcpy(&psecuritypriv->wep_key[keyid], wep, sizeof(struct rtw_wep_key));
17791e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
17801e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	psecuritypriv->dot11PrivacyKeyIndex = keyid;
17811e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
17821e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
17831e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		 ("%s:security key material : "
17841e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  "%x %x %x %x %x %x %x %x %x %x %x %x %x\n", __func__,
17851e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[0],
17861e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[1],
17871e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[2],
17881e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[3],
17891e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[4],
17901e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[5],
17911e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[6],
17921e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[7],
17931e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[8],
17941e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[9],
17951e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[10],
17961e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[11],
17971e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen		  psecuritypriv->wep_key[keyid].key[12]));
17981e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
17991e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	res = rtw_set_key23a(padapter, psecuritypriv, keyid, 1);
18001e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
18011e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensenexit:
18021e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
18031e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen	return res;
18041e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen}
18051e6e7f6030f3cec00641c5a356b5986723f33df6Jes Sorensen
1806e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensenstatic int rtw_set_ssid(struct rtw_adapter *padapter,
1807e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen			struct wlan_network *newnetwork)
180897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen{
180997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
181097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	struct wlan_network *pnetwork = &pmlmepriv->cur_network;
181197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	int status = _SUCCESS;
181297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	u32 cur_time = 0;
181397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
181497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	DBG_8723A_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n",
1815e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen			newnetwork->network.Ssid.ssid, get_fwstate(pmlmepriv));
181697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
181797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	if (padapter->hw_init_completed == false) {
181897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
181997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			 ("set_ssid: hw_init_completed == false =>exit!!!\n"));
182097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		status = _FAIL;
182197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		goto exit;
182297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	}
182397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
182497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	spin_lock_bh(&pmlmepriv->lock);
182597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
182697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	DBG_8723A("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
182797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
182897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		goto handle_tkip_countermeasure;
182997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
183097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
183197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
183297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			 ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
183397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
1834e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen		if (pmlmepriv->assoc_ssid.ssid_len ==
1835e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen		    newnetwork->network.Ssid.ssid_len &&
1836e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen		    !memcmp(&pmlmepriv->assoc_ssid.ssid,
1837e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen			    newnetwork->network.Ssid.ssid,
1838e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen			    newnetwork->network.Ssid.ssid_len)) {
183997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
184097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				RT_TRACE(_module_rtl871x_ioctl_set_c_,
184197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					 _drv_err_, ("New SSID is same SSID, "
184297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen						     "fw_state = 0x%08x\n",
184397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen						     get_fwstate(pmlmepriv)));
184497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
184597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				if (rtw_is_same_ibss23a(padapter, pnetwork)) {
184697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					/*
184797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					 * it means driver is in
184897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					 * WIFI_ADHOC_MASTER_STATE, we needn't
184997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					 * create bss again.
185097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					 */
185197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					goto release_mlme_lock;
185297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				}
185397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
185497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				/*
185597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				 * if in WIFI_ADHOC_MASTER_STATE |
185697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				 * WIFI_ADHOC_STATE, create bss or
185797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				 * rejoin again
185897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				 */
185997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				rtw_disassoc_cmd23a(padapter, 0, true);
186097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
186197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				if (check_fwstate(pmlmepriv, _FW_LINKED))
186297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					rtw_indicate_disconnect23a(padapter);
186397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
186497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				rtw_free_assoc_resources23a(padapter, 1);
186597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
186697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				if (check_fwstate(pmlmepriv,
186797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen						  WIFI_ADHOC_MASTER_STATE)) {
186897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					_clr_fwstate_(pmlmepriv,
186997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen						      WIFI_ADHOC_MASTER_STATE);
187097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen					set_fwstate(pmlmepriv,
187197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen						    WIFI_ADHOC_STATE);
187297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				}
187397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			} else {
187497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				rtw_lps_ctrl_wk_cmd23a(padapter,
187597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen						       LPS_CTRL_JOINBSS, 1);
187697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			}
187797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		} else {
187897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
187997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				 ("Set SSID not the same ssid\n"));
188097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1881e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen				 ("set_ssid =[%s] len = 0x%x\n",
1882e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen				  newnetwork->network.Ssid.ssid,
1883e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen				  newnetwork->network.Ssid.ssid_len));
188497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
188597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				 ("assoc_ssid =[%s] len = 0x%x\n",
188697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				  pmlmepriv->assoc_ssid.ssid,
188797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				  pmlmepriv->assoc_ssid.ssid_len));
188897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
188997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			rtw_disassoc_cmd23a(padapter, 0, true);
189097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
189197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			if (check_fwstate(pmlmepriv, _FW_LINKED))
189297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				rtw_indicate_disconnect23a(padapter);
189397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
189497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			rtw_free_assoc_resources23a(padapter, 1);
189597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
189697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
189797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
189897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen				set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
189997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			}
190097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		}
190197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	}
190297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
190397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensenhandle_tkip_countermeasure:
190497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
190597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	if (padapter->securitypriv.btkip_countermeasure == true) {
190697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		cur_time = jiffies;
190797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
190897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		if ((cur_time -
190997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		     padapter->securitypriv.btkip_countermeasure_time) >
191097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		    60 * HZ) {
191197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			padapter->securitypriv.btkip_countermeasure = false;
191297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			padapter->securitypriv.btkip_countermeasure_time = 0;
191397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		} else {
191497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			status = _FAIL;
191597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen			goto release_mlme_lock;
191697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		}
191797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	}
191897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
1919e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen	memcpy(&pmlmepriv->assoc_ssid, &newnetwork->network.Ssid,
1920e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen	       sizeof(struct cfg80211_ssid));
1921e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen
192297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	pmlmepriv->assoc_by_bssid = false;
192397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
192472795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen	pmlmepriv->to_join = true;
192572795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen
192672795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen	if (!check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
192772795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen		pmlmepriv->cur_network.join_res = -2;
192897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
192972795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen		status = rtw_do_join_network(padapter, newnetwork);
193072795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen		if (status == _SUCCESS) {
193172795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen			pmlmepriv->to_join = false;
193272795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen		} else {
193372795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen			if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
193472795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				/* switch to ADHOC_MASTER */
193572795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				status = rtw_do_join_adhoc(padapter);
193672795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				if (status != _SUCCESS)
193772795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen					goto release_mlme_lock;
193872795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen			} else {
193972795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				/* can't associate ; reset under-linking */
194072795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
194172795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				status = _FAIL;
194272795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen				pmlmepriv->to_join = false;
194372795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen			}
194472795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen		}
194572795e9de7deae0952d1174cfb37cb869b582d29Jes Sorensen	}
194697c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensenrelease_mlme_lock:
194797c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	spin_unlock_bh(&pmlmepriv->lock);
194897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
194997c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensenexit:
195097c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
195197c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		 ("-%s: status =%d\n", __func__, status));
195297c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
195397c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen	return status;
195497c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen}
195597c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen
1956b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
1957b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				struct cfg80211_connect_params *sme)
1958b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
1959b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
1960b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct list_head *phead, *plist, *ptmp;
1961b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wlan_network *pnetwork = NULL;
1962b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* u8 matched_by_bssid = false; */
1963b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* u8 matched_by_ssid = false; */
1964b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 matched = false;
1965b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1966b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1967b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
1968b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1969b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1970a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("=>" "%s(%s)\n", __func__, ndev->name);
1971b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("privacy =%d, key =%p, key_len =%d, key_idx =%d\n",
1972b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  sme->privacy, sme->key, sme->key_len, sme->key_idx);
1973b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1974b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (_FAIL == rtw_pwr_wakeup(padapter)) {
1975b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
1976b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1977b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1978b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1979b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1980b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
1981b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1982b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1983b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1984c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen	if (!sme->ssid || !sme->ssid_len ||
1985c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen	    sme->ssid_len > IEEE80211_MAX_SSID_LEN) {
1986b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
1987b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
1988b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
1989b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1990c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen	DBG_8723A("ssid =%s, len =%zu\n", sme->ssid, sme->ssid_len);
1991b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1992b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (sme->bssid)
1993b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("bssid =" MAC_FMT "\n", MAC_ARG(sme->bssid));
1994b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
1995b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
1996b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EBUSY;
1997b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, fw_state = 0x%x, goto exit\n", __func__,
1998b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  pmlmepriv->fw_state);
1999b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2000b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2001b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
2002b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_scan_abort23a(padapter);
2003b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2004b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2005b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&queue->lock);
2006b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2007b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	phead = get_list_head(queue);
2008b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2009b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	list_for_each_safe(plist, ptmp, phead) {
2010b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pnetwork = container_of(plist, struct wlan_network, list);
2011b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2012b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (sme->bssid) {
2013cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen			if (!ether_addr_equal(pnetwork->network.MacAddress,
2014cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen					      sme->bssid))
2015b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				continue;
2016b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2017b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2018b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (sme->ssid && sme->ssid_len) {
2019b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (pnetwork->network.Ssid.ssid_len != sme->ssid_len ||
2020b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    memcmp(pnetwork->network.Ssid.ssid, sme->ssid,
2021b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   sme->ssid_len))
2022b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				continue;
2023b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2024b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2025b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (sme->bssid) {
20269ab98d42401d50d6ab5f6ef59e1d63c486391f1cJes Sorensen			if (ether_addr_equal(pnetwork->network.MacAddress,
20279ab98d42401d50d6ab5f6ef59e1d63c486391f1cJes Sorensen					     sme->bssid)) {
2028b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("matched by bssid\n");
2029b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2030b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				matched = true;
2031b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				break;
2032b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
2033b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		} else if (sme->ssid && sme->ssid_len) {
20349ab98d42401d50d6ab5f6ef59e1d63c486391f1cJes Sorensen			if (!memcmp(pnetwork->network.Ssid.ssid,
20359ab98d42401d50d6ab5f6ef59e1d63c486391f1cJes Sorensen				    sme->ssid, sme->ssid_len) &&
2036c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen			    pnetwork->network.Ssid.ssid_len == sme->ssid_len) {
2037b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("matched by ssid\n");
2038c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen
2039b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				matched = true;
2040b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				break;
2041b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
2042b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2043b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2044b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2045b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&queue->lock);
2046b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2047c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen	if (!matched || !pnetwork) {
2048b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOENT;
2049b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("connect, matched == false, goto exit\n");
2050b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2051b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2052b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2053efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	if (cfg80211_infrastructure_mode(
2054efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen		    padapter, pnetwork->network.ifmode) != _SUCCESS) {
2055b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EPERM;
2056b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2057b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2058b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2059b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
20609e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	psecuritypriv->dot11PrivacyAlgrthm = 0;
20619e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	psecuritypriv->dot118021XGrpPrivacy = 0;
2062b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
2063b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
2064b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2065c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen	ret = rtw_cfg80211_set_wpa_version(psecuritypriv,
2066c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen					   sme->crypto.wpa_versions);
2067b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0)
2068b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2069b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2070b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type);
2071b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2072b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0)
2073b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2074b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2075b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ie_len =%zu\n", __func__, sme->ie_len);
2076b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2077b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_cfg80211_set_wpa_ie(padapter, sme->ie, sme->ie_len);
2078b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0)
2079b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2080b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2081b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (sme->crypto.n_ciphers_pairwise) {
2082b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_cfg80211_set_cipher(psecuritypriv,
2083b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      sme->crypto.ciphers_pairwise[0],
2084b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      true);
2085b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ret < 0)
2086b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
2087b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2088b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2089b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* For WEP Shared auth */
2090b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if ((psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Shared ||
2091b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	     psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Auto) &&
2092b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    sme->key) {
2093deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		struct rtw_wep_key wep_key;
2094deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		u8 wep_key_idx, wep_key_len;
2095b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s(): Shared/Auto WEP\n", __func__);
2096b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2097b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_idx = sme->key_idx;
2098b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wep_key_len = sme->key_len;
2099b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2100deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		if (wep_key_idx > WEP_KEYS || !wep_key_len ||
2101deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		    wep_key_len > WLAN_KEY_LEN_WEP104) {
2102b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EINVAL;
2103b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
2104b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2105b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2106deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		wep_key_len = wep_key_len <= 5 ? 5 : 13;
2107b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2108deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		memset(&wep_key, 0, sizeof(struct rtw_wep_key));
2109b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2110deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		wep_key.keylen = wep_key_len;
2111b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2112deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		if (wep_key_len == 13) {
2113deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen			padapter->securitypriv.dot11PrivacyAlgrthm =
2114deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				WLAN_CIPHER_SUITE_WEP104;
2115deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen			padapter->securitypriv.dot118021XGrpPrivacy =
2116deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				WLAN_CIPHER_SUITE_WEP104;
2117b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		} else {
2118deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen			padapter->securitypriv.dot11PrivacyAlgrthm =
2119deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				WLAN_CIPHER_SUITE_WEP40;
2120deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen			padapter->securitypriv.dot118021XGrpPrivacy =
2121deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen				WLAN_CIPHER_SUITE_WEP40;
2122b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2123b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2124deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		memcpy(wep_key.key, (void *)sme->key, wep_key.keylen);
2125b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2126deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		if (rtw_cfg80211_add_wep(padapter, &wep_key, wep_key_idx) !=
2127deff11554fa4a0bf0f3616d29f0636ab5ff52758Jes Sorensen		    _SUCCESS)
2128b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			ret = -EOPNOTSUPP;
2129b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2130b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ret < 0)
2131b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
2132b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2133b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2134b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_cfg80211_set_cipher(psecuritypriv,
2135b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      sme->crypto.cipher_group, false);
2136b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0)
2137c5178b0bc2ea2e72d45a90ae346a9b2fda0b5f08Jes Sorensen		goto exit;
2138b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2139b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (sme->crypto.n_akm_suites) {
2140b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_cfg80211_set_key_mgt(psecuritypriv,
2141b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					       sme->crypto.akm_suites[0]);
2142b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ret < 0)
2143b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto exit;
2144b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2145b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
214639dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen	if (psecuritypriv->ndisauthtype > 3)
214739dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
214839dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen
214939dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen	if (rtw_set_auth23a(padapter, psecuritypriv) != _SUCCESS) {
215039dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen		ret = -EBUSY;
215139dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen		goto exit;
215239dbc446a7168e4d7542d6523132ee44189d0ba2Jes Sorensen	}
2153b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2154b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* rtw_set_802_11_encryption_mode(padapter,
2155b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	   padapter->securitypriv.ndisencryptstatus); */
2156b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2157e73d82efa4583e5ecaf598d85341403806a16e62Jes Sorensen	if (rtw_set_ssid(padapter, pnetwork) != _SUCCESS) {
215897c4361d50e833a0c178cf425590a15e9663f3d0Jes Sorensen		ret = -EBUSY;
2159b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2160b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2161b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2162b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("set ssid:dot11AuthAlgrthm =%d, dot11PrivacyAlgrthm =%d, "
2163b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  "dot118021XGrpPrivacy =%d\n", psecuritypriv->dot11AuthAlgrthm,
2164b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  psecuritypriv->dot11PrivacyAlgrthm,
2165b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  psecuritypriv->dot118021XGrpPrivacy);
2166b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2167b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
2168b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2169b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("<=%s, ret %d\n", __func__, ret);
2170b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2171b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2172b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2173b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2174b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev,
2175b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   u16 reason_code)
2176b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2177b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2178b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2179a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2180b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2181b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_set_roaming(padapter, 0);
2182b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2183b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2184b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_scan_abort23a(padapter);
2185b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		LeaveAllPowerSaveMode23a(padapter);
2186b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_disassoc_cmd23a(padapter, 500, false);
2187b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2188b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s...call rtw_indicate_disconnect23a\n", __func__);
2189b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2190b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->mlmepriv.not_indic_disco = true;
2191b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_indicate_disconnect23a(padapter);
2192b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		padapter->mlmepriv.not_indic_disco = false;
2193b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2194b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		rtw_free_assoc_resources23a(padapter, 1);
2195b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2196b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2197b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2198b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2199b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2200b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_txpower(struct wiphy *wiphy,
2201b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct wireless_dev *wdev,
2202b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    enum nl80211_tx_power_setting type, int mbm)
2203b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2204b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2205b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2206b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2207b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2208b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_get_txpower(struct wiphy *wiphy,
2209b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct wireless_dev *wdev, int *dbm)
2210b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2211b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2212b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	*dbm = (12);
2213b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2214b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2215b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2216b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerinline bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter)
2217b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2218b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(adapter->rtw_wdev);
2219b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return rtw_wdev_priv->power_mgmt;
2220b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2221b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2222b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy,
2223b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct net_device *ndev,
2224b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       bool enabled, int timeout)
2225b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2226b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2227b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(padapter->rtw_wdev);
2228b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2229a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): enabled:%u, timeout:%d\n",
2230a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		  __func__, ndev->name, enabled, timeout);
2231b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2232b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_wdev_priv->power_mgmt = enabled;
2233b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2234b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!enabled)
2235b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		LPS_Leave23a(padapter);
2236b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2237b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2238b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2239b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2240b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,
2241b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct net_device *netdev,
2242b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct cfg80211_pmksa *pmksa)
2243b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2244b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 index, blInserted = false;
2245b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2246b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
2247b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2248a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, netdev->name);
2249b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2250cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen	if (is_zero_ether_addr(pmksa->bssid))
2251b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2252b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2253b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	blInserted = false;
2254b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2255b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* overwrite PMKID */
2256b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	for (index = 0; index < NUM_PMKID_CACHE; index++) {
2257cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen		if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid,
2258cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen				     pmksa->bssid)) {
2259b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			/* BSSID is matched, the same AP => rewrite with
2260b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			   new PMKID. */
2261a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen			DBG_8723A("%s(%s):  BSSID exists in the PMKList.\n",
2262a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen				  __func__, netdev->name);
2263b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2264b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			memcpy(psecuritypriv->PMKIDList[index].PMKID,
2265b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			       pmksa->pmkid, WLAN_PMKID_LEN);
2266b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->PMKIDList[index].bUsed = true;
2267b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->PMKIDIndex = index + 1;
2268b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			blInserted = true;
2269b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			break;
2270b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2271b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2272b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2273b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!blInserted) {
2274b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/*  Find a new entry */
2275a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("%s(%s): Use new entry index = %d for this PMKID\n",
2276a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen			  __func__, netdev->name, psecuritypriv->PMKIDIndex);
2277b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2278888df442ef023adbca6536888eae65b2cd8ae295Jes Sorensen		ether_addr_copy(
2279888df442ef023adbca6536888eae65b2cd8ae295Jes Sorensen			psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2280888df442ef023adbca6536888eae65b2cd8ae295Jes Sorensen			Bssid, pmksa->bssid);
2281b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2282b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2283b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2284b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed =
2285b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			true;
2286b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psecuritypriv->PMKIDIndex++;
2287b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (psecuritypriv->PMKIDIndex == 16) {
2288b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->PMKIDIndex = 0;
2289b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2290b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2291b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2292b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2293b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2294b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2295b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,
2296b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct net_device *netdev,
2297b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				  struct cfg80211_pmksa *pmksa)
2298b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2299b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 index, bMatched = false;
2300b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2301b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
2302b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2303a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, netdev->name);
2304b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2305b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	for (index = 0; index < NUM_PMKID_CACHE; index++) {
2306cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen		if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid,
2307cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen				     pmksa->bssid)) {
2308cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen			/* BSSID is matched, the same AP => Remove this PMKID
2309cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen			   information and reset it. */
231043c34be13047dd53e70bc4759ff314424db7036bJes Sorensen			eth_zero_addr(psecuritypriv->PMKIDList[index].Bssid);
2311b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			memset(psecuritypriv->PMKIDList[index].PMKID, 0x00,
2312b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			       WLAN_PMKID_LEN);
2313b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			psecuritypriv->PMKIDList[index].bUsed = false;
2314b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			bMatched = true;
2315b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			break;
2316b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2317b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2318b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2319b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (false == bMatched) {
2320a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("%s(%s): do not have matched BSSID\n", __func__,
2321a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen			  netdev->name);
2322b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2323b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2324b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2325b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2326b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2327b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2328b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy,
2329b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct net_device *netdev)
2330b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2331b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2332b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct security_priv *psecuritypriv = &padapter->securitypriv;
2333b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2334a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, netdev->name);
2335b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2336b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memset(&psecuritypriv->PMKIDList[0], 0x00,
2337b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	       sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
2338b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	psecuritypriv->PMKIDIndex = 0;
2339b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2340b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2341b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2342b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2343b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
2344b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter,
2345b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     u8 *pmgmt_frame, uint frame_len)
2346b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2347b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	s32 freq;
2348b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int channel;
2349b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2350b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *ndev = padapter->pnetdev;
2351b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2352b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2353b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2354b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#if defined(RTW_USE_CFG80211_STA_EVENT)
2355b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	{
2356b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct station_info sinfo;
2357b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		u8 ie_offset;
235860e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen
2359b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ieee80211_is_assoc_req(hdr->frame_control))
236060e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen			ie_offset = offsetof(struct ieee80211_mgmt,
236160e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen					     u.assoc_req.variable);
2362b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		else		/*  WIFI_REASSOCREQ */
236360e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen			ie_offset = offsetof(struct ieee80211_mgmt,
236460e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen					     u.reassoc_req.variable);
2365b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2366b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo.filled = 0;
2367b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
236860e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen		sinfo.assoc_req_ies = pmgmt_frame + ie_offset;
236960e78f3df4f5b9bc3fd61755fd00e69c4923ac1dJes Sorensen		sinfo.assoc_req_ies_len = frame_len - ie_offset;
2370b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC);
2371b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2372b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2373b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	channel = pmlmeext->cur_channel;
2374b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (channel <= RTW_CH_MAX_2G_CHANNEL)
2375b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
2376b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_2GHZ);
2377b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
2378b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
2379b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_5GHZ);
2380b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
238156b0bd91e0087e0b172aec022bdfb4fcd9de9194Jes Sorensen	cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pmgmt_frame, frame_len,
238256b0bd91e0087e0b172aec022bdfb4fcd9de9194Jes Sorensen			 0, GFP_ATOMIC);
2383b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2384b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2385b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2386b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter,
2387b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					unsigned char *da,
2388b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					unsigned short reason)
2389b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2390b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	s32 freq;
2391b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int channel;
2392b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	uint frame_len;
2393cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	struct ieee80211_mgmt mgmt;
2394b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2395b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2396b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *ndev = padapter->pnetdev;
2397b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2398b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2399b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2400cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	memset(&mgmt, 0, sizeof(struct ieee80211_mgmt));
24011daffaeecb4bf01c4a34fc2330c745ace5af3f60Jes Sorensen
2402b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#if defined(RTW_USE_CFG80211_STA_EVENT)
2403b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	cfg80211_del_sta(ndev, da, GFP_ATOMIC);
2404b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2405b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	channel = pmlmeext->cur_channel;
2406b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (channel <= RTW_CH_MAX_2G_CHANNEL)
2407b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
2408b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_2GHZ);
2409b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
2410b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		freq = ieee80211_channel_to_frequency(channel,
2411b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						      IEEE80211_BAND_5GHZ);
2412b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2413cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	mgmt.frame_control =
2414036cdd9cb34a10aabb80a97a41fb9dcfead7d113Jes Sorensen		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
2415b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2416cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	ether_addr_copy(mgmt.da, myid(&padapter->eeprompriv));
2417cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	ether_addr_copy(mgmt.sa, da);
2418cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	ether_addr_copy(mgmt.bssid, get_my_bssid23a(&pmlmeinfo->network));
2419b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2420cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	mgmt.seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2421b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmlmeext->mgnt_seq++;
2422b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2423cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	mgmt.u.disassoc.reason_code = cpu_to_le16(reason);
2424b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2425cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	frame_len = sizeof(struct ieee80211_hdr_3addr) + 2;
2426b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2427cc531f6154167893f1cf8ab084871fe06b38fb2bJes Sorensen	cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, (u8 *)&mgmt, frame_len,
242856b0bd91e0087e0b172aec022bdfb4fcd9de9194Jes Sorensen			 0, GFP_ATOMIC);
2429b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2430b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2431b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2432b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_monitor_if_open(struct net_device *ndev)
2433b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2434b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2435b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2436b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2437b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2438b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2439b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2440b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2441b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_monitor_if_close(struct net_device *ndev)
2442b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2443b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2444b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2445b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2446b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2447b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2448b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2449b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2450b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb,
2451b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					      struct net_device *ndev)
2452b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2453b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2454b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int rtap_len;
2455b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int qos_len = 0;
2456b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int dot11_hdr_len = 24;
2457b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int snap_len = 6;
2458b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned char *pdata;
2459b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned char src_mac_addr[6];
2460b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned char dst_mac_addr[6];
2461b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_hdr *dot11_hdr;
2462b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_radiotap_header *rtap_hdr;
2463b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(ndev);
2464b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2465a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2466b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2467b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
2468b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto fail;
2469b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2470b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
2471b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (unlikely(rtap_hdr->it_version))
2472b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto fail;
2473b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2474b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtap_len = ieee80211_get_radiotap_len(skb->data);
2475b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (unlikely(skb->len < rtap_len))
2476b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto fail;
2477b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2478b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rtap_len != 14) {
2479b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("radiotap len (should be 14): %d\n", rtap_len);
2480b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto fail;
2481b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2482b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2483b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* Skip the ratio tap header */
2484b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	skb_pull(skb, rtap_len);
2485b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2486b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	dot11_hdr = (struct ieee80211_hdr *)skb->data;
2487b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* Check if the QoS bit is set */
2488b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ieee80211_is_data(dot11_hdr->frame_control)) {
2489b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* Check if this ia a Wireless Distribution System (WDS) frame
2490b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 * which has 4 MAC addresses
2491b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 */
2492b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ieee80211_is_data_qos(dot11_hdr->frame_control))
2493b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			qos_len = IEEE80211_QOS_CTL_LEN;
2494b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (ieee80211_has_a4(dot11_hdr->frame_control))
2495b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			dot11_hdr_len += 6;
2496b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2497b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
2498b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
2499b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2500b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/*
2501b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 * Skip the 802.11 header, QoS (if any) and SNAP,
2502b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 * but leave spaces for two MAC addresses
2503b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		 */
2504b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		skb_pull(skb, dot11_hdr_len + qos_len + snap_len -
2505b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			 ETH_ALEN * 2);
2506b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pdata = (unsigned char *)skb->data;
2507888df442ef023adbca6536888eae65b2cd8ae295Jes Sorensen		ether_addr_copy(pdata, dst_mac_addr);
2508888df442ef023adbca6536888eae65b2cd8ae295Jes Sorensen		ether_addr_copy(pdata + ETH_ALEN, src_mac_addr);
2509b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2510b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("should be eapol packet\n");
2511b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2512b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* Use the real net device to transmit the packet */
2513b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_xmit23a_entry23a(skb, padapter->pnetdev);
2514b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2515b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return ret;
2516b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2517b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else if (ieee80211_is_action(dot11_hdr->frame_control)) {
251838eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen		struct ieee80211_mgmt *mgmt;
2519b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* only for action frames */
2520b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct xmit_frame *pmgntframe;
2521b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct pkt_attrib *pattrib;
2522b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		unsigned char *pframe;
2523b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* u8 category, action, OUI_Subtype, dialogToken = 0; */
2524b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* unsigned char        *frame_body; */
2525b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2526b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2527b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		u32 len = skb->len;
2528b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		u8 category, action;
2529b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
253038eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen		mgmt = (struct ieee80211_mgmt *)dot11_hdr;
2531b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2532a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("RTW_Tx:da =" MAC_FMT " via %s(%s)\n",
253338eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen			  MAC_ARG(mgmt->da), __func__, ndev->name);
253438eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen		category = mgmt->u.action.category;
253538eb09b5be235eeaf1c4d0a2100d3cb2a3e0b3a3Jes Sorensen		action = mgmt->u.action.u.wme_action.action_code;
25362e74d336edb945b4a1f851e821001093e4094729Jes Sorensen		DBG_8723A("RTW_Tx:category(%u), action(%u)\n",
25372e74d336edb945b4a1f851e821001093e4094729Jes Sorensen			  category, action);
253898fb81291d30f83838379bf1522fead6673b5fdfJes Sorensen
2539b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* starting alloc mgmt frame to dump it */
2540b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2541b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (pmgntframe == NULL)
2542b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			goto fail;
2543b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2544b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* update attribute */
2545b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib = &pmgntframe->attrib;
2546b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		update_mgntframe_attrib23a(padapter, pattrib);
2547b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib->retry_ctrl = false;
2548b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2549b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2550b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2551b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2552b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2553b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(pframe, skb->data, len);
2554b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib->pktlen = len;
2555b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2556b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* update seq number */
2557b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmeext->mgnt_seq = le16_to_cpu(dot11_hdr->seq_ctrl) >> 4;
2558b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib->seqnum = pmlmeext->mgnt_seq;
2559b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pmlmeext->mgnt_seq++;
2560b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2561b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pattrib->last_txcmdsz = pattrib->pktlen;
2562b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2563b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		dump_mgntframe23a(padapter, pmgntframe);
2564b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2565b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2566b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerfail:
2567b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2568b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	dev_kfree_skb(skb);
2569b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2570b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2571b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2572b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2573b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int
2574b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerrtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)
2575b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2576b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2577b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2578b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s\n", __func__);
2579b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2580b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2581b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2582b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2583b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic const struct net_device_ops rtw_cfg80211_monitor_if_ops = {
2584b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.ndo_open = rtw_cfg80211_monitor_if_open,
2585b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.ndo_stop = rtw_cfg80211_monitor_if_close,
2586b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
2587b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,
2588b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
2589b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2590b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_cfg80211_add_monitor_if(struct rtw_adapter *padapter, char *name,
2591b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct net_device **ndev)
2592b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2593b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2594b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *mon_ndev = NULL;
2595b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *mon_wdev = NULL;
2596b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
2597b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2598b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!name) {
25999cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): without specific name\n",
26009cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  __func__, padapter->pnetdev->name);
2601b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
2602b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2603b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2604b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2605b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pwdev_priv->pmon_ndev) {
26069cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): monitor interface exist: %s\n", __func__,
26079cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name, pwdev_priv->pmon_ndev->name);
2608b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EBUSY;
2609b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2610b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2611b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2612b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev = alloc_etherdev(sizeof(struct rtw_adapter));
2613b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mon_ndev) {
26149cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): allocate ndev fail\n", __func__,
26159cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name);
2616b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOMEM;
2617b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2618b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2619b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2620b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;
2621b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	strncpy(mon_ndev->name, name, IFNAMSIZ);
2622b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->name[IFNAMSIZ - 1] = 0;
2623b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->destructor = rtw_ndev_destructor;
2624b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2625b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;
2626b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2627b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*  wdev */
2628b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
2629b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mon_wdev) {
26309cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): allocate mon_wdev fail\n", __func__,
26319cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name);
2632b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOMEM;
2633b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2634b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2635b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2636b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_wdev->wiphy = padapter->rtw_wdev->wiphy;
2637b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_wdev->netdev = mon_ndev;
2638b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_wdev->iftype = NL80211_IFTYPE_MONITOR;
2639b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	mon_ndev->ieee80211_ptr = mon_wdev;
2640b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2641b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = register_netdevice(mon_ndev);
2642b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret) {
2643b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto out;
2644b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2645b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2646b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	*ndev = pwdev_priv->pmon_ndev = mon_ndev;
2647b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1);
2648b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2649b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerout:
2650b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret) {
2651b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		kfree(mon_wdev);
2652b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		mon_wdev = NULL;
2653b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2654b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2655b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret && mon_ndev) {
2656b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		free_netdev(mon_ndev);
2657b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		*ndev = mon_ndev = NULL;
2658b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2659b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2660b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2661b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2662b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2663b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct wireless_dev *
2664b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingercfg80211_rtw_add_virtual_intf(struct wiphy *wiphy, const char *name,
2665b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			      enum nl80211_iftype type, u32 *flags,
2666b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			      struct vif_params *params)
2667b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2668b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2669b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *ndev = NULL;
2670b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2671b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
26729cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen	DBG_8723A("%s(%s): wiphy:%s, name:%s, type:%d\n", __func__,
26739cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		  padapter->pnetdev->name, wiphy_name(wiphy), name, type);
2674b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2675b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	switch (type) {
2676b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_ADHOC:
2677b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_AP_VLAN:
2678b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_WDS:
2679b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_MESH_POINT:
2680b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENODEV;
2681b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2682b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_MONITOR:
2683b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret =
2684b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		    rtw_cfg80211_add_monitor_if(padapter, (char *)name, &ndev);
2685b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2686b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2687b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_P2P_CLIENT:
2688b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_STATION:
2689b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENODEV;
2690b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2691b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2692b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_P2P_GO:
2693b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	case NL80211_IFTYPE_AP:
2694b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENODEV;
2695b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2696b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	default:
2697b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENODEV;
2698b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Unsupported interface type\n");
2699b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		break;
2700b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2701b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
27029cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen	DBG_8723A("%s(%s): ndev:%p, ret:%d\n", __func__,
27039cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		  padapter->pnetdev->name,
2704b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  ndev, ret);
2705b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2706b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ndev ? ndev->ieee80211_ptr : ERR_PTR(ret);
2707b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2708b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2709b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy,
2710b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					 struct wireless_dev *wdev)
2711b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2712b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv =
2713b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    (struct rtw_wdev_priv *)wiphy_priv(wiphy);
2714b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *ndev;
2715b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ndev = wdev ? wdev->netdev : NULL;
2716b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2717b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!ndev)
2718b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2719b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2720b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unregister_netdevice(ndev);
2721b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2722b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ndev == pwdev_priv->pmon_ndev) {
2723b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->pmon_ndev = NULL;
2724b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->ifname_mon[0] = '\0';
2725a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		DBG_8723A("%s(%s): remove monitor interface\n",
2726a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen			  __func__, ndev->name);
2727b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2728b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2729b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
2730b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2731b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2732b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2733b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head,
2734b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  size_t head_len, const u8 *tail, size_t tail_len)
2735b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2736b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2737db97812c2c5e8a18d7cf3eb679a4cfdd6125f748Jes Sorensen	u8 *pbuf;
2738fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	uint len, ielen, wps_ielen = 0;
2739b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2740ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen	struct wlan_bssid_ex *bss = &pmlmepriv->cur_network.network;
2741ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen	const struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)head;
2742fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	struct ieee80211_mgmt *tmpmgmt;
2743b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* struct sta_priv *pstapriv = &padapter->stapriv; */
2744b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2745b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s beacon_head_len =%zu, beacon_tail_len =%zu\n",
2746b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  __func__, head_len, tail_len);
2747b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2748b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2749b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2750b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2751ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen	if (head_len < offsetof(struct ieee80211_mgmt, u.beacon.variable))
2752b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2753b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2754b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pbuf = kzalloc(head_len + tail_len, GFP_KERNEL);
2755b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!pbuf)
2756b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -ENOMEM;
2757fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	tmpmgmt = (struct ieee80211_mgmt *)pbuf;
2758ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen
2759ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen	bss->beacon_interval = get_unaligned_le16(&mgmt->u.beacon.beacon_int);
2760ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen	bss->capability = get_unaligned_le16(&mgmt->u.beacon.capab_info);
2761ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen	bss->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp);
2762ddf5c2bd1044d923ad82f519c68cdf12a055a568Jes Sorensen
2763b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*  24 = beacon header len. */
2764fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	memcpy(pbuf, (void *)head, head_len);
2765fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	memcpy(pbuf + head_len, (void *)tail, tail_len);
2766b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2767fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	len = head_len + tail_len;
2768fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	ielen = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
2769b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* check wps ie if inclued */
2770d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen	if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2771d3797af488780e4f83d92ea0a3dc0a6381b566f3Jes Sorensen				    WLAN_OUI_TYPE_MICROSOFT_WPS,
2772fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen				    tmpmgmt->u.beacon.variable, ielen))
2773b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("add bcn, wps_ielen =%d\n", wps_ielen);
2774b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2775b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* pbss_network->IEs will not include p2p_ie, wfd ie */
2776fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0,
27779300c94b8a817f3b96cf00d2bdeed6751c2744d8Jes Sorensen			     WLAN_EID_VENDOR_SPECIFIC, P2P_OUI23A, 4);
2778fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0,
27799300c94b8a817f3b96cf00d2bdeed6751c2744d8Jes Sorensen			     WLAN_EID_VENDOR_SPECIFIC, WFD_OUI23A, 4);
2780b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2781fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	len = ielen + offsetof(struct ieee80211_mgmt, u.beacon.variable);
2782fb5fd46dbdd32faecd5f826f2d47e798732b7b4dJes Sorensen	if (rtw_check_beacon_data23a(adapter, tmpmgmt, len) == _SUCCESS) {
2783b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = 0;
2784b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
2785b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EINVAL;
2786b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2787b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2788b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(pbuf);
2789b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2790b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2791b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2792b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2793b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,
2794b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				 struct cfg80211_ap_settings *settings)
2795b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2796b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2797b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
2798b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2799a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s): hidden_ssid:%d, auth_type:%d\n",
2800a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen		  __func__, ndev->name, settings->hidden_ssid,
2801b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		  settings->auth_type);
2802b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2803b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_add_beacon(adapter, settings->beacon.head,
2804b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     settings->beacon.head_len, settings->beacon.tail,
2805b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     settings->beacon.tail_len);
2806b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2807b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode =
2808b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		settings->hidden_ssid;
2809b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2810b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (settings->ssid && settings->ssid_len) {
2811b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct wlan_bssid_ex *pbss_network =
2812b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			&adapter->mlmepriv.cur_network.network;
2813b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		struct wlan_bssid_ex *pbss_network_ext =
2814b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			&adapter->mlmeextpriv.mlmext_info.network;
2815b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2816b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(pbss_network->Ssid.ssid, (void *)settings->ssid,
2817b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       settings->ssid_len);
2818b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pbss_network->Ssid.ssid_len = settings->ssid_len;
2819b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		memcpy(pbss_network_ext->Ssid.ssid, (void *)settings->ssid,
2820b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		       settings->ssid_len);
2821b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pbss_network_ext->Ssid.ssid_len = settings->ssid_len;
2822b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2823b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2824b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2825b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2826b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2827b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_change_beacon(struct wiphy *wiphy,
2828b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      struct net_device *ndev,
2829b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				      struct cfg80211_beacon_data *info)
2830b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2831b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2832b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
2833b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2834a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2835b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2836b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail,
2837b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			     info->tail_len);
2838b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2839b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2840b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2841b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2842b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
2843b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2844a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2845b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2846b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2847b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2848b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_add_station(struct wiphy *wiphy,
2849f9da455b93f6ba076935b4ef4589f61e529ae046Linus Torvalds				    struct net_device *ndev, const u8 *mac,
2850b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    struct station_parameters *params)
2851b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2852a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2853b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2854b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2855b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2856b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2857b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_del_station(struct wiphy *wiphy,
2858f9da455b93f6ba076935b4ef4589f61e529ae046Linus Torvalds				    struct net_device *ndev, const u8 *mac)
2859b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2860b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
2861b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct list_head *phead, *plist, *ptmp;
2862b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 updated = 0;
2863b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_info *psta;
2864b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter = netdev_priv(ndev);
2865b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2866b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct sta_priv *pstapriv = &padapter->stapriv;
2867b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2868a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("+%s(%s)\n", __func__, ndev->name);
2869b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2870b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true) {
2871b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, fw_state != FW_LINKED|WIFI_AP_STATE\n",
2872b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  __func__);
2873b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2874b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2875b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2876b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!mac) {
2877b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("flush all sta, and cam_entry\n");
2878b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2879b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		flush_all_cam_entry23a(padapter);	/* clear CAM */
2880b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2881b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = rtw_sta_flush23a(padapter);
2882b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2883b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return ret;
2884b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2885b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2886b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("free sta macaddr =" MAC_FMT "\n", MAC_ARG(mac));
2887b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2888b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (is_broadcast_ether_addr(mac))
2889b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return -EINVAL;
2890b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2891b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_bh(&pstapriv->asoc_list_lock);
2892b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2893b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	phead = &pstapriv->asoc_list;
2894b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2895b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* check asoc_queue */
2896b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	list_for_each_safe(plist, ptmp, phead) {
2897b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		psta = container_of(plist, struct sta_info, asoc_list);
2898b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2899cc2db7cb8de67cb172b90b72bf42c784b08959adJes Sorensen		if (ether_addr_equal(mac, psta->hwaddr)) {
2900b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			if (psta->dot8021xalg == 1 &&
2901b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			    psta->bpairwise_key_installed == false) {
2902b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("%s, sta's dot8021xalg = 1 and "
2903b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  "key_installed = false\n", __func__);
2904b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			} else {
2905b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				DBG_8723A("free psta =%p, aid =%d\n", psta,
2906b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					  psta->aid);
2907b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2908b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				list_del_init(&psta->asoc_list);
2909b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				pstapriv->asoc_list_cnt--;
2910b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2911b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* spin_unlock_bh(&pstapriv->asoc_list_lock); */
2912b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				updated =
2913b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				    ap_free_sta23a(padapter, psta, true,
2914b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						WLAN_REASON_DEAUTH_LEAVING);
2915b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				/* spin_lock_bh(&pstapriv->asoc_list_lock); */
2916b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2917b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				psta = NULL;
2918b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2919b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				break;
2920b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			}
2921b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		}
2922b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2923b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2924b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_unlock_bh(&pstapriv->asoc_list_lock);
2925b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2926b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	associated_clients_update23a(padapter, updated);
2927b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2928a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("-%s(%s)\n", __func__, ndev->name);
2929b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2930b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
2931b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2932b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2933b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_change_station(struct wiphy *wiphy,
2934f9da455b93f6ba076935b4ef4589f61e529ae046Linus Torvalds				       struct net_device *ndev, const u8 *mac,
2935b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct station_parameters *params)
2936b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2937a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2938b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2939b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2940b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2941b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_dump_station(struct wiphy *wiphy,
2942b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     struct net_device *ndev, int idx, u8 *mac,
2943b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				     struct station_info *sinfo)
2944b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2945a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2946b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2947b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* TODO: dump scanned queue */
2948b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2949b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return -ENOENT;
2950b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2951b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2952b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,
2953b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   struct bss_parameters *params)
2954b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2955a790d58e6832262692416d41af99670b7aa1dca4Jes Sorensen	DBG_8723A("%s(%s)\n", __func__, ndev->name);
2956b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return 0;
2957b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
2958b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* CONFIG_8723AU_AP_MODE */
2959b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2960b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch,
2961b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				 const u8 *buf, size_t len)
2962b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
2963b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct xmit_frame *pmgntframe;
2964b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct pkt_attrib *pattrib;
2965b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned char *pframe;
2966b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = _FAIL;
2967b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_hdr *pwlanhdr;
2968b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2969b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2970b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2971b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (_FAIL == rtw_pwr_wakeup(padapter)) {
2972b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -EFAULT;
2973b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2974b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2975b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2976b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_set_scan_deny(padapter, 1000);
2977b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2978b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_scan_abort23a(padapter);
2979b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2980b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (tx_ch != rtw_get_oper_ch23a(padapter)) {
2981b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
2982b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			pmlmeext->cur_channel = tx_ch;
2983b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		set_channel_bwmode23a(padapter, tx_ch,
2984b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   HAL_PRIME_CHNL_OFFSET_DONT_CARE,
2985b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				   HT_CHANNEL_WIDTH_20);
2986b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2987b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2988b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* starting alloc mgmt frame to dump it */
2989b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2990de62f67a00286eb78d44762ce845b00742d79dd0Jes Sorensen	if (!pmgntframe) {
2991b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		/* ret = -ENOMEM; */
2992b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = _FAIL;
2993b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
2994b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
2995b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
2996b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* update attribute */
2997b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib = &pmgntframe->attrib;
2998b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	update_mgntframe_attrib23a(padapter, pattrib);
2999b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib->retry_ctrl = false;
3000b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3001b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3002b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3003b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pframe = (u8 *) (pmgntframe->buf_addr) + TXDESC_OFFSET;
3004b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3005b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	memcpy(pframe, (void *)buf, len);
3006b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib->pktlen = len;
3007b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3008b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwlanhdr = (struct ieee80211_hdr *)pframe;
3009b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* update seq number */
3010b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmlmeext->mgnt_seq = le16_to_cpu(pwlanhdr->seq_ctrl) >> 4;
3011b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib->seqnum = pmlmeext->mgnt_seq;
3012b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pmlmeext->mgnt_seq++;
3013b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3014b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pattrib->last_txcmdsz = pattrib->pktlen;
3015b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3016de62f67a00286eb78d44762ce845b00742d79dd0Jes Sorensen	ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3017b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3018de62f67a00286eb78d44762ce845b00742d79dd0Jes Sorensen	if (ret  != _SUCCESS)
3019de62f67a00286eb78d44762ce845b00742d79dd0Jes Sorensen		DBG_8723A("%s, ack == false\n", __func__);
3020de62f67a00286eb78d44762ce845b00742d79dd0Jes Sorensen	else
3021de62f67a00286eb78d44762ce845b00742d79dd0Jes Sorensen		DBG_8723A("%s, ack == true\n", __func__);
3022b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3023b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
3024b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3025b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s, ret =%d\n", __func__, ret);
3026b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3027b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3028b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3029b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3030b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
3031b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				struct cfg80211_mgmt_tx_params *params,
3032b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				u64 *cookie)
3033b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3034b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_adapter *padapter =
3035b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		(struct rtw_adapter *)wiphy_to_adapter(wiphy);
3036b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
3037b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int tx_ret;
3038b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 dump_limit = RTW_MAX_MGMT_TX_CNT;
3039b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u32 dump_cnt = 0;
3040b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	bool ack = true;
3041b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 category, action;
3042b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	unsigned long start = jiffies;
3043b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	size_t len = params->len;
3044b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_channel *chan = params->chan;
3045b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	const u8 *buf = params->buf;
3046ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen	struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *)buf;
3047b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 tx_ch = (u8) ieee80211_frequency_to_channel(chan->center_freq);
3048b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3049ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen	if (!ieee80211_is_action(hdr->frame_control))
3050ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen		return -EINVAL;
3051ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen
3052b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* cookie generation */
3053b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	*cookie = (unsigned long)buf;
3054b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
30559cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen	DBG_8723A("%s(%s): len =%zu, ch =%d\n", __func__,
30569cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		  padapter->pnetdev->name, len, tx_ch);
3057b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3058b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* indicate ack before issue frame to avoid racing with rsp frame */
305956b0bd91e0087e0b172aec022bdfb4fcd9de9194Jes Sorensen	cfg80211_mgmt_tx_status(padapter->rtw_wdev, *cookie, buf, len, ack,
306056b0bd91e0087e0b172aec022bdfb4fcd9de9194Jes Sorensen				GFP_KERNEL);
3061b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3062b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("RTW_Tx:tx_ch =%d, da =" MAC_FMT "\n", tx_ch,
3063ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen		  MAC_ARG(hdr->da));
3064ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen	category = hdr->u.action.category;
3065ea2ea44079784794838dc0ae953967990f8457d5Jes Sorensen	action = hdr->u.action.u.wme_action.action_code;
30662e74d336edb945b4a1f851e821001093e4094729Jes Sorensen	DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category, action);
3067b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3068b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	do {
3069b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		dump_cnt++;
3070b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, buf, len);
3071b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} while (dump_cnt < dump_limit && tx_ret != _SUCCESS);
3072b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3073b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (tx_ret != _SUCCESS || dump_cnt > 1) {
30749cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): %s (%d/%d) in %d ms\n",
30759cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  __func__, padapter->pnetdev->name,
3076b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt,
3077b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			  dump_limit, jiffies_to_msecs(jiffies - start));
3078b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3079b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3080b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3081b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3082b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3083b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,
3084b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     struct wireless_dev *wdev,
3085b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger					     u16 frame_type, bool reg)
3086b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3087b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
3088b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
3089b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3090b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return;
3091b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3092b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3093b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic struct cfg80211_ops rtw_cfg80211_ops = {
3094b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.change_virtual_intf = cfg80211_rtw_change_iface,
3095b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.add_key = cfg80211_rtw_add_key,
3096b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.get_key = cfg80211_rtw_get_key,
3097b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.del_key = cfg80211_rtw_del_key,
3098b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_default_key = cfg80211_rtw_set_default_key,
3099b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.get_station = cfg80211_rtw_get_station,
3100b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.scan = cfg80211_rtw_scan,
3101b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_wiphy_params = cfg80211_rtw_set_wiphy_params,
3102b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.connect = cfg80211_rtw_connect,
3103b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.disconnect = cfg80211_rtw_disconnect,
3104b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.join_ibss = cfg80211_rtw_join_ibss,
3105b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.leave_ibss = cfg80211_rtw_leave_ibss,
3106b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_tx_power = cfg80211_rtw_set_txpower,
3107b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.get_tx_power = cfg80211_rtw_get_txpower,
3108b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_power_mgmt = cfg80211_rtw_set_power_mgmt,
3109b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.set_pmksa = cfg80211_rtw_set_pmksa,
3110b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.del_pmksa = cfg80211_rtw_del_pmksa,
3111b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.flush_pmksa = cfg80211_rtw_flush_pmksa,
3112b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3113b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
3114b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.add_virtual_intf = cfg80211_rtw_add_virtual_intf,
3115b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.del_virtual_intf = cfg80211_rtw_del_virtual_intf,
3116b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3117b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.start_ap = cfg80211_rtw_start_ap,
3118b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.change_beacon = cfg80211_rtw_change_beacon,
3119b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.stop_ap = cfg80211_rtw_stop_ap,
3120b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3121b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.add_station = cfg80211_rtw_add_station,
3122b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.del_station = cfg80211_rtw_del_station,
3123b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.change_station = cfg80211_rtw_change_station,
3124b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.dump_station = cfg80211_rtw_dump_station,
3125b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.change_bss = cfg80211_rtw_change_bss,
3126b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* CONFIG_8723AU_AP_MODE */
3127b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3128b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.mgmt_tx = cfg80211_rtw_mgmt_tx,
3129b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	.mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,
3130b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger};
3131b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3132b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap,
3133b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       enum ieee80211_band band, u8 rf_type)
3134b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3135b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3136b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define MAX_BIT_RATE_40MHZ_MCS15	300	/* Mbps */
3137b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#define MAX_BIT_RATE_40MHZ_MCS7		150	/* Mbps */
3138b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3139b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->ht_supported = true;
3140b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3141b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
3142b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 |
3143b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;
3144b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3145b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*
3146b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *Maximum length of AMPDU that the STA can receive.
3147b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
3148b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 */
3149b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
3150b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3151b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*Minimum MPDU start spacing , */
3152b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
3153b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3154b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
3155b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3156b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*
3157b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *hw->wiphy->bands[IEEE80211_BAND_2GHZ]
3158b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *base on ant_num
3159b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *rx_mask: RX mask
3160b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7
3161b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15
3162b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *if rx_ant >= 3 rx_mask[2]= 0xff;
3163b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *if BW_40 rx_mask[4]= 0x01;
3164b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 *highest supported RX rate
3165b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 */
3166b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (rf_type == RF_1T1R) {
3167b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[0] = 0xFF;
3168b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[1] = 0x00;
3169b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[4] = 0x01;
3170b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3171f78c0710cd60cd108d436490955909983f309c62Kieron Browne		ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7);
3172b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else if ((rf_type == RF_1T2R) || (rf_type == RF_2T2R)) {
3173b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[0] = 0xFF;
3174b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[1] = 0xFF;
3175b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ht_cap->mcs.rx_mask[4] = 0x01;
3176b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3177f78c0710cd60cd108d436490955909983f309c62Kieron Browne		ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15);
3178b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	} else {
3179b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, error rf_type =%d\n", __func__, rf_type);
3180b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3181b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3182b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3183b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3184b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter)
3185b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3186b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	u8 rf_type;
3187b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct ieee80211_supported_band *bands;
3188b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *pwdev = padapter->rtw_wdev;
3189b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wiphy *wiphy = pwdev->wiphy;
3190b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3191c2370e83ab5432e2d32e9c097930c69366d27b4cJes Sorensen	rf_type = rtl8723a_get_rf_type(padapter);
3192b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3193b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s:rf_type =%d\n", __func__, rf_type);
3194b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3195b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
3196b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	{
3197b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		bands = wiphy->bands[IEEE80211_BAND_2GHZ];
3198b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (bands)
3199b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			rtw_cfg80211_init_ht_capab(&bands->ht_cap,
3200b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   IEEE80211_BAND_2GHZ,
3201b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   rf_type);
3202b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3203b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3204b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
3205b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	{
3206b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		bands = wiphy->bands[IEEE80211_BAND_5GHZ];
3207b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		if (bands)
3208b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger			rtw_cfg80211_init_ht_capab(&bands->ht_cap,
3209b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   IEEE80211_BAND_5GHZ,
3210b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger						   rf_type);
3211b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3212b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3213b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3214b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerstatic void rtw_cfg80211_preinit_wiphy(struct rtw_adapter *padapter,
3215b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger				       struct wiphy *wiphy)
3216b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3217b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3218b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3219b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;
3220b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
3221b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS;
3222b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3223b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->max_remain_on_channel_duration =
3224b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    RTW_MAX_REMAIN_ON_CHANNEL_DURATION;
3225b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3226b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
3227b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    BIT(NL80211_IFTYPE_ADHOC) |
3228b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
3229b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) |
3230b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif
3231b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    0;
3232b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3233b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#ifdef CONFIG_8723AU_AP_MODE
3234b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes;
3235b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger#endif /* CONFIG_8723AU_AP_MODE */
3236b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3237b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
3238b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3239b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*
3240b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	   wiphy->iface_combinations = &rtw_combinations;
3241b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	   wiphy->n_iface_combinations = 1;
3242b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	 */
3243b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3244b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->cipher_suites = rtw_cipher_suites;
3245b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);
3246b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3247b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
3248b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->bands[IEEE80211_BAND_2GHZ] =
3249b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    rtw_spt_band_alloc(IEEE80211_BAND_2GHZ);
3250b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
3251b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->bands[IEEE80211_BAND_5GHZ] =
3252b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	    rtw_spt_band_alloc(IEEE80211_BAND_5GHZ);
3253b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3254b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
3255b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME;
3256b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3257b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
3258b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
3259b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
3260b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
3261b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3262b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3263b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerint rtw_wdev_alloc(struct rtw_adapter *padapter, struct device *dev)
3264b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3265b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	int ret = 0;
3266b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wiphy *wiphy;
3267b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct wireless_dev *wdev;
3268b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv;
3269b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct net_device *pnetdev = padapter->pnetdev;
3270b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3271b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
3272b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3273b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* wiphy */
3274b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wdev_priv));
3275b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!wiphy) {
3276b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Couldn't allocate wiphy device\n");
3277b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		ret = -ENOMEM;
3278b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		goto exit;
3279b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3280d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen
3281d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen	/*  wdev */
3282d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen	wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
3283d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen	if (!wdev) {
3284d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen		DBG_8723A("Couldn't allocate wireless device\n");
3285d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen		ret = -ENOMEM;
3286d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen		goto free_wiphy;
3287d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen	}
3288d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen
3289b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	set_wiphy_dev(wiphy, dev);
3290b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_cfg80211_preinit_wiphy(padapter, wiphy);
3291b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3292b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	ret = wiphy_register(wiphy);
3293b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (ret < 0) {
3294b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("Couldn't register wiphy device\n");
3295d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen		goto free_wdev;
3296b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3297b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3298b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wdev->wiphy = wiphy;
3299b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wdev->netdev = pnetdev;
3300b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* wdev->iftype = NL80211_IFTYPE_STATION; */
3301b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/*  for rtw_setopmode_cmd23a() in cfg80211_rtw_change_iface() */
3302b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wdev->iftype = NL80211_IFTYPE_MONITOR;
3303b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	padapter->rtw_wdev = wdev;
3304b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pnetdev->ieee80211_ptr = wdev;
3305b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3306b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	/* init pwdev_priv */
3307b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv = wdev_to_priv(wdev);
3308b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->rtw_wdev = wdev;
3309b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->pmon_ndev = NULL;
3310b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->ifname_mon[0] = '\0';
3311b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->padapter = padapter;
3312b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->scan_request = NULL;
3313b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	spin_lock_init(&pwdev_priv->scan_req_lock);
3314b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3315b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv->p2p_enabled = false;
3316b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3317b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
3318b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->power_mgmt = true;
3319b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	else
3320b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		pwdev_priv->power_mgmt = false;
3321b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3322b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3323d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensenfree_wdev:
3324d165e4efbc6d76cff51abb523567a840cb6623b9Jes Sorensen	kfree(wdev);
3325b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerfree_wiphy:
3326b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy_free(wiphy);
3327b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingerexit:
3328b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	return ret;
3329b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3330b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3331b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_wdev_free(struct wireless_dev *wdev)
3332b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3333b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
3334b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3335b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!wdev)
3336b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
3337b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3338b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(wdev->wiphy->bands[IEEE80211_BAND_2GHZ]);
3339b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(wdev->wiphy->bands[IEEE80211_BAND_5GHZ]);
3340b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3341b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy_free(wdev->wiphy);
3342b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3343b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	kfree(wdev);
3344b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3345b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3346b1925ad84625302fac456d8671b2acafcabf57f5Larry Fingervoid rtw_wdev_unregister(struct wireless_dev *wdev)
3347b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger{
3348b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	struct rtw_wdev_priv *pwdev_priv;
3349b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3350b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
3351b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3352b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (!wdev)
3353b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		return;
3354b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3355b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	pwdev_priv = wdev_to_priv(wdev);
3356b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3357b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	rtw_cfg80211_indicate_scan_done(pwdev_priv, true);
3358b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3359b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	if (pwdev_priv->pmon_ndev) {
3360b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		DBG_8723A("%s, unregister monitor interface\n", __func__);
3361b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger		unregister_netdev(pwdev_priv->pmon_ndev);
3362b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	}
3363b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger
3364b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger	wiphy_unregister(wdev->wiphy);
3365b1925ad84625302fac456d8671b2acafcabf57f5Larry Finger}
3366