xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlinux/moal_cfg80211.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /** @file moal_cfg80211.c
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun  * @brief This file contains the functions for CFG80211.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright 2011-2022 NXP
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * This software file (the File) is distributed by NXP
9*4882a593Smuzhiyun  * under the terms of the GNU General Public License Version 2, June 1991
10*4882a593Smuzhiyun  * (the License).  You may use, redistribute and/or modify the File in
11*4882a593Smuzhiyun  * accordance with the terms and conditions of the License, a copy of which
12*4882a593Smuzhiyun  * is available by writing to the Free Software Foundation, Inc.,
13*4882a593Smuzhiyun  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14*4882a593Smuzhiyun  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17*4882a593Smuzhiyun  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18*4882a593Smuzhiyun  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
19*4882a593Smuzhiyun  * this warranty disclaimer.
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include "moal_cfg80211.h"
24*4882a593Smuzhiyun #ifdef UAP_CFG80211
25*4882a593Smuzhiyun #ifdef UAP_SUPPORT
26*4882a593Smuzhiyun #include "moal_uap.h"
27*4882a593Smuzhiyun #endif
28*4882a593Smuzhiyun #endif
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun /********************************************************
31*4882a593Smuzhiyun  *				Local Variables
32*4882a593Smuzhiyun  ********************************************************/
33*4882a593Smuzhiyun /** Supported rates to be advertised to the cfg80211 */
34*4882a593Smuzhiyun static struct ieee80211_rate cfg80211_rates[] = {
35*4882a593Smuzhiyun 	{
36*4882a593Smuzhiyun 		.bitrate = 10,
37*4882a593Smuzhiyun 		.hw_value = 2,
38*4882a593Smuzhiyun 	},
39*4882a593Smuzhiyun 	{
40*4882a593Smuzhiyun 		.bitrate = 20,
41*4882a593Smuzhiyun 		.hw_value = 4,
42*4882a593Smuzhiyun 	},
43*4882a593Smuzhiyun 	{
44*4882a593Smuzhiyun 		.bitrate = 55,
45*4882a593Smuzhiyun 		.hw_value = 11,
46*4882a593Smuzhiyun 	},
47*4882a593Smuzhiyun 	{
48*4882a593Smuzhiyun 		.bitrate = 110,
49*4882a593Smuzhiyun 		.hw_value = 22,
50*4882a593Smuzhiyun 	},
51*4882a593Smuzhiyun 	{
52*4882a593Smuzhiyun 		.bitrate = 60,
53*4882a593Smuzhiyun 		.hw_value = 12,
54*4882a593Smuzhiyun 	},
55*4882a593Smuzhiyun 	{
56*4882a593Smuzhiyun 		.bitrate = 90,
57*4882a593Smuzhiyun 		.hw_value = 18,
58*4882a593Smuzhiyun 	},
59*4882a593Smuzhiyun 	{
60*4882a593Smuzhiyun 		.bitrate = 120,
61*4882a593Smuzhiyun 		.hw_value = 24,
62*4882a593Smuzhiyun 	},
63*4882a593Smuzhiyun 	{
64*4882a593Smuzhiyun 		.bitrate = 180,
65*4882a593Smuzhiyun 		.hw_value = 36,
66*4882a593Smuzhiyun 	},
67*4882a593Smuzhiyun 	{
68*4882a593Smuzhiyun 		.bitrate = 240,
69*4882a593Smuzhiyun 		.hw_value = 48,
70*4882a593Smuzhiyun 	},
71*4882a593Smuzhiyun 	{
72*4882a593Smuzhiyun 		.bitrate = 360,
73*4882a593Smuzhiyun 		.hw_value = 72,
74*4882a593Smuzhiyun 	},
75*4882a593Smuzhiyun 	{
76*4882a593Smuzhiyun 		.bitrate = 480,
77*4882a593Smuzhiyun 		.hw_value = 96,
78*4882a593Smuzhiyun 	},
79*4882a593Smuzhiyun 	{
80*4882a593Smuzhiyun 		.bitrate = 540,
81*4882a593Smuzhiyun 		.hw_value = 108,
82*4882a593Smuzhiyun 	},
83*4882a593Smuzhiyun };
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun /** Channel definitions for 2 GHz to be advertised to cfg80211 */
86*4882a593Smuzhiyun static struct ieee80211_channel cfg80211_channels_2ghz[] = {
87*4882a593Smuzhiyun 	{.center_freq = 2412, .hw_value = 1, .max_power = 20},
88*4882a593Smuzhiyun 	{.center_freq = 2417, .hw_value = 2, .max_power = 20},
89*4882a593Smuzhiyun 	{.center_freq = 2422, .hw_value = 3, .max_power = 20},
90*4882a593Smuzhiyun 	{.center_freq = 2427, .hw_value = 4, .max_power = 20},
91*4882a593Smuzhiyun 	{.center_freq = 2432, .hw_value = 5, .max_power = 20},
92*4882a593Smuzhiyun 	{.center_freq = 2437, .hw_value = 6, .max_power = 20},
93*4882a593Smuzhiyun 	{.center_freq = 2442, .hw_value = 7, .max_power = 20},
94*4882a593Smuzhiyun 	{.center_freq = 2447, .hw_value = 8, .max_power = 20},
95*4882a593Smuzhiyun 	{.center_freq = 2452, .hw_value = 9, .max_power = 20},
96*4882a593Smuzhiyun 	{.center_freq = 2457, .hw_value = 10, .max_power = 20},
97*4882a593Smuzhiyun 	{.center_freq = 2462, .hw_value = 11, .max_power = 20},
98*4882a593Smuzhiyun 	{.center_freq = 2467, .hw_value = 12, .max_power = 20},
99*4882a593Smuzhiyun 	{.center_freq = 2472, .hw_value = 13, .max_power = 20},
100*4882a593Smuzhiyun 	{.center_freq = 2484, .hw_value = 14, .max_power = 20},
101*4882a593Smuzhiyun };
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun /** Channel definitions for 5 GHz to be advertised to cfg80211 */
104*4882a593Smuzhiyun static struct ieee80211_channel cfg80211_channels_5ghz[] = {
105*4882a593Smuzhiyun 	{.center_freq = 5180, .hw_value = 36, .max_power = 20},
106*4882a593Smuzhiyun 	{.center_freq = 5200, .hw_value = 40, .max_power = 20},
107*4882a593Smuzhiyun 	{.center_freq = 5220, .hw_value = 44, .max_power = 20},
108*4882a593Smuzhiyun 	{.center_freq = 5240, .hw_value = 48, .max_power = 20},
109*4882a593Smuzhiyun 	{.center_freq = 5260, .hw_value = 52, .max_power = 20},
110*4882a593Smuzhiyun 	{.center_freq = 5280, .hw_value = 56, .max_power = 20},
111*4882a593Smuzhiyun 	{.center_freq = 5300, .hw_value = 60, .max_power = 20},
112*4882a593Smuzhiyun 	{.center_freq = 5320, .hw_value = 64, .max_power = 20},
113*4882a593Smuzhiyun 	{.center_freq = 5500, .hw_value = 100, .max_power = 20},
114*4882a593Smuzhiyun 	{.center_freq = 5520, .hw_value = 104, .max_power = 20},
115*4882a593Smuzhiyun 	{.center_freq = 5540, .hw_value = 108, .max_power = 20},
116*4882a593Smuzhiyun 	{.center_freq = 5560, .hw_value = 112, .max_power = 20},
117*4882a593Smuzhiyun 	{.center_freq = 5580, .hw_value = 116, .max_power = 20},
118*4882a593Smuzhiyun 	{.center_freq = 5600, .hw_value = 120, .max_power = 20},
119*4882a593Smuzhiyun 	{.center_freq = 5620, .hw_value = 124, .max_power = 20},
120*4882a593Smuzhiyun 	{.center_freq = 5640, .hw_value = 128, .max_power = 20},
121*4882a593Smuzhiyun 	{.center_freq = 5660, .hw_value = 132, .max_power = 20},
122*4882a593Smuzhiyun 	{.center_freq = 5680, .hw_value = 136, .max_power = 20},
123*4882a593Smuzhiyun 	{.center_freq = 5700, .hw_value = 140, .max_power = 20},
124*4882a593Smuzhiyun 	{.center_freq = 5720, .hw_value = 144, .max_power = 20},
125*4882a593Smuzhiyun 	{.center_freq = 5745, .hw_value = 149, .max_power = 20},
126*4882a593Smuzhiyun 	{.center_freq = 5765, .hw_value = 153, .max_power = 20},
127*4882a593Smuzhiyun 	{.center_freq = 5785, .hw_value = 157, .max_power = 20},
128*4882a593Smuzhiyun 	{.center_freq = 5805, .hw_value = 161, .max_power = 20},
129*4882a593Smuzhiyun 	{.center_freq = 5825, .hw_value = 165, .max_power = 20},
130*4882a593Smuzhiyun 	{.center_freq = 5845, .hw_value = 169, .max_power = 20},
131*4882a593Smuzhiyun 	{.center_freq = 5865, .hw_value = 173, .max_power = 20},
132*4882a593Smuzhiyun 	{.center_freq = 5885, .hw_value = 177, .max_power = 20},
133*4882a593Smuzhiyun };
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun struct ieee80211_supported_band cfg80211_band_2ghz = {
136*4882a593Smuzhiyun 	.channels = cfg80211_channels_2ghz,
137*4882a593Smuzhiyun 	.band = IEEE80211_BAND_2GHZ,
138*4882a593Smuzhiyun 	.n_channels = ARRAY_SIZE(cfg80211_channels_2ghz),
139*4882a593Smuzhiyun 	.bitrates = cfg80211_rates,
140*4882a593Smuzhiyun 	.n_bitrates = ARRAY_SIZE(cfg80211_rates),
141*4882a593Smuzhiyun };
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun struct ieee80211_supported_band cfg80211_band_5ghz = {
144*4882a593Smuzhiyun 	.channels = cfg80211_channels_5ghz,
145*4882a593Smuzhiyun 	.band = IEEE80211_BAND_5GHZ,
146*4882a593Smuzhiyun 	.n_channels = ARRAY_SIZE(cfg80211_channels_5ghz),
147*4882a593Smuzhiyun 	.bitrates = cfg80211_rates + 4,
148*4882a593Smuzhiyun 	.n_bitrates = ARRAY_SIZE(cfg80211_rates) - 4,
149*4882a593Smuzhiyun };
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun extern pmoal_handle m_handle[];
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 29) < LINUX_VERSION_CODE
154*4882a593Smuzhiyun #ifdef UAP_SUPPORT
155*4882a593Smuzhiyun /** Network device handlers for uAP */
156*4882a593Smuzhiyun extern const struct net_device_ops woal_uap_netdev_ops;
157*4882a593Smuzhiyun #endif
158*4882a593Smuzhiyun #ifdef STA_SUPPORT
159*4882a593Smuzhiyun /** Network device handlers for STA */
160*4882a593Smuzhiyun extern const struct net_device_ops woal_netdev_ops;
161*4882a593Smuzhiyun #endif
162*4882a593Smuzhiyun #endif
163*4882a593Smuzhiyun /********************************************************
164*4882a593Smuzhiyun  *				Local Functions
165*4882a593Smuzhiyun  ********************************************************/
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun /********************************************************
168*4882a593Smuzhiyun  *				Global Functions
169*4882a593Smuzhiyun  ********************************************************/
170*4882a593Smuzhiyun #ifdef UAP_SUPPORT
171*4882a593Smuzhiyun #if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 20, 0)
172*4882a593Smuzhiyun int woal_11ax_cfg(moal_private *priv, t_u8 action, mlan_ds_11ax_he_cfg *he_cfg);
173*4882a593Smuzhiyun #endif
174*4882a593Smuzhiyun #endif
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun /**
177*4882a593Smuzhiyun  * @brief Get the private structure from wiphy
178*4882a593Smuzhiyun  *
179*4882a593Smuzhiyun  * @param wiphy     A pointer to wiphy structure
180*4882a593Smuzhiyun  *
181*4882a593Smuzhiyun  * @return          Pointer to moal_private
182*4882a593Smuzhiyun  */
woal_get_wiphy_priv(struct wiphy * wiphy)183*4882a593Smuzhiyun void *woal_get_wiphy_priv(struct wiphy *wiphy)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun 	return (void *)(*(unsigned long *)wiphy_priv(wiphy));
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun /**
189*4882a593Smuzhiyun  * @brief Get the private structure from net device
190*4882a593Smuzhiyun  *
191*4882a593Smuzhiyun  * @param dev       A pointer to net_device structure
192*4882a593Smuzhiyun  *
193*4882a593Smuzhiyun  * @return          Pointer to moal_private
194*4882a593Smuzhiyun  */
woal_get_netdev_priv(struct net_device * dev)195*4882a593Smuzhiyun void *woal_get_netdev_priv(struct net_device *dev)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun 	return (void *)netdev_priv(dev);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun /**
201*4882a593Smuzhiyun  *  @brief Get current frequency of active interface
202*4882a593Smuzhiyun  *
203*4882a593Smuzhiyun  *  @param priv        A pointer to moal_private
204*4882a593Smuzhiyun  *
205*4882a593Smuzhiyun  *  @return              channel frequency
206*4882a593Smuzhiyun  */
woal_get_active_intf_freq(moal_private * priv)207*4882a593Smuzhiyun int woal_get_active_intf_freq(moal_private *priv)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun 	moal_handle *handle = priv->phandle;
210*4882a593Smuzhiyun 	int i;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	if (priv->media_connected == MTRUE
213*4882a593Smuzhiyun #ifdef UAP_SUPPORT
214*4882a593Smuzhiyun 	    || priv->bss_started == MTRUE
215*4882a593Smuzhiyun #endif
216*4882a593Smuzhiyun 	)
217*4882a593Smuzhiyun 		return ieee80211_channel_to_frequency(
218*4882a593Smuzhiyun 			priv->channel
219*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 39) <= CFG80211_VERSION_CODE
220*4882a593Smuzhiyun 			,
221*4882a593Smuzhiyun 			(priv->channel <= 14 ? IEEE80211_BAND_2GHZ :
222*4882a593Smuzhiyun 					       IEEE80211_BAND_5GHZ)
223*4882a593Smuzhiyun #endif
224*4882a593Smuzhiyun 		);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	for (i = 0; i < handle->priv_num; i++) {
227*4882a593Smuzhiyun #ifdef STA_SUPPORT
228*4882a593Smuzhiyun 		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) {
229*4882a593Smuzhiyun 			if (handle->priv[i]->media_connected == MTRUE)
230*4882a593Smuzhiyun 				return ieee80211_channel_to_frequency(
231*4882a593Smuzhiyun 					handle->priv[i]->channel
232*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 39) <= CFG80211_VERSION_CODE
233*4882a593Smuzhiyun 					,
234*4882a593Smuzhiyun 					(handle->priv[i]->channel <= 14 ?
235*4882a593Smuzhiyun 						 IEEE80211_BAND_2GHZ :
236*4882a593Smuzhiyun 						 IEEE80211_BAND_5GHZ)
237*4882a593Smuzhiyun #endif
238*4882a593Smuzhiyun 				);
239*4882a593Smuzhiyun 		}
240*4882a593Smuzhiyun #endif
241*4882a593Smuzhiyun #ifdef UAP_SUPPORT
242*4882a593Smuzhiyun 		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_UAP) {
243*4882a593Smuzhiyun 			if (handle->priv[i]->bss_started == MTRUE)
244*4882a593Smuzhiyun 				return ieee80211_channel_to_frequency(
245*4882a593Smuzhiyun 					handle->priv[i]->channel
246*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 39) <= CFG80211_VERSION_CODE
247*4882a593Smuzhiyun 					,
248*4882a593Smuzhiyun 					(handle->priv[i]->channel <= 14 ?
249*4882a593Smuzhiyun 						 IEEE80211_BAND_2GHZ :
250*4882a593Smuzhiyun 						 IEEE80211_BAND_5GHZ)
251*4882a593Smuzhiyun #endif
252*4882a593Smuzhiyun 				);
253*4882a593Smuzhiyun 		}
254*4882a593Smuzhiyun #endif
255*4882a593Smuzhiyun 	}
256*4882a593Smuzhiyun 	return 0;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun /**
260*4882a593Smuzhiyun  *  @brief Convert driver band configuration to IEEE band type
261*4882a593Smuzhiyun  *
262*4882a593Smuzhiyun  *  @param band     Driver band configuration
263*4882a593Smuzhiyun  *
264*4882a593Smuzhiyun  *  @return         IEEE band type
265*4882a593Smuzhiyun  */
woal_band_cfg_to_ieee_band(t_u32 band)266*4882a593Smuzhiyun t_u8 woal_band_cfg_to_ieee_band(t_u32 band)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun 	t_u8 ret_radio_type;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	ENTER();
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	switch (band) {
273*4882a593Smuzhiyun 	case BAND_A:
274*4882a593Smuzhiyun 	case BAND_AN:
275*4882a593Smuzhiyun 	case BAND_A | BAND_AN:
276*4882a593Smuzhiyun 		ret_radio_type = IEEE80211_BAND_5GHZ;
277*4882a593Smuzhiyun 		break;
278*4882a593Smuzhiyun 	case BAND_B:
279*4882a593Smuzhiyun 	case BAND_G:
280*4882a593Smuzhiyun 	case BAND_B | BAND_G:
281*4882a593Smuzhiyun 	case BAND_GN:
282*4882a593Smuzhiyun 	case BAND_B | BAND_GN:
283*4882a593Smuzhiyun 	/* Fall Through */
284*4882a593Smuzhiyun 	default:
285*4882a593Smuzhiyun 		ret_radio_type = IEEE80211_BAND_2GHZ;
286*4882a593Smuzhiyun 		break;
287*4882a593Smuzhiyun 	}
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	LEAVE();
290*4882a593Smuzhiyun 	return ret_radio_type;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun /**
294*4882a593Smuzhiyun  *  @brief Convert IEEE band type to radio_type
295*4882a593Smuzhiyun  *
296*4882a593Smuzhiyun  *  @param ieeeband     IEEE band
297*4882a593Smuzhiyun  *
298*4882a593Smuzhiyun  *  @return           radio_type
299*4882a593Smuzhiyun  */
woal_ieee_band_to_radio_type(t_u8 ieee_band)300*4882a593Smuzhiyun t_u8 woal_ieee_band_to_radio_type(t_u8 ieee_band)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	t_u8 radio_type = 0;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	ENTER();
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	switch (ieee_band) {
307*4882a593Smuzhiyun 	case IEEE80211_BAND_5GHZ:
308*4882a593Smuzhiyun 		radio_type = BAND_5GHZ;
309*4882a593Smuzhiyun 		break;
310*4882a593Smuzhiyun 	case IEEE80211_BAND_2GHZ:
311*4882a593Smuzhiyun 	default:
312*4882a593Smuzhiyun 		radio_type = BAND_2GHZ;
313*4882a593Smuzhiyun 		break;
314*4882a593Smuzhiyun 	}
315*4882a593Smuzhiyun 	LEAVE();
316*4882a593Smuzhiyun 	return radio_type;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun /**
320*4882a593Smuzhiyun  *  @brief Set/Enable encryption key
321*4882a593Smuzhiyun  *
322*4882a593Smuzhiyun  *  @param priv             A pointer to moal_private structure
323*4882a593Smuzhiyun  *  @param is_enable_wep    Enable WEP default key
324*4882a593Smuzhiyun  *  @param cipher           Cipher suite selector
325*4882a593Smuzhiyun  *  @param key              A pointer to key
326*4882a593Smuzhiyun  *  @param key_len          Key length
327*4882a593Smuzhiyun  *  @param seq              A pointer to sequence
328*4882a593Smuzhiyun  *  @param seq_len          Sequence length
329*4882a593Smuzhiyun  *  @param key_index        Key index
330*4882a593Smuzhiyun  *  @param addr             Mac for which key is to be set
331*4882a593Smuzhiyun  *  @param disable          Key disabled or not
332*4882a593Smuzhiyun  *  @param wait_option      wait option
333*4882a593Smuzhiyun  *
334*4882a593Smuzhiyun  *  @return                 MLAN_STATUS_SUCCESS -- success, otherwise fail
335*4882a593Smuzhiyun  */
woal_cfg80211_set_key(moal_private * priv,t_u8 is_enable_wep,t_u32 cipher,const t_u8 * key,int key_len,const t_u8 * seq,int seq_len,t_u8 key_index,const t_u8 * addr,int disable,t_u8 wait_option)336*4882a593Smuzhiyun mlan_status woal_cfg80211_set_key(moal_private *priv, t_u8 is_enable_wep,
337*4882a593Smuzhiyun 				  t_u32 cipher, const t_u8 *key, int key_len,
338*4882a593Smuzhiyun 				  const t_u8 *seq, int seq_len, t_u8 key_index,
339*4882a593Smuzhiyun 				  const t_u8 *addr, int disable,
340*4882a593Smuzhiyun 				  t_u8 wait_option)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
343*4882a593Smuzhiyun 	mlan_ds_sec_cfg *sec = NULL;
344*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
345*4882a593Smuzhiyun 	t_u8 bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	ENTER();
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun #ifdef UAP_CFG80211
350*4882a593Smuzhiyun #ifdef UAP_SUPPORT
351*4882a593Smuzhiyun 	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
352*4882a593Smuzhiyun 		if (is_enable_wep) {
353*4882a593Smuzhiyun 			PRINTM(MIOCTL, "Enable UAP default key=%d\n",
354*4882a593Smuzhiyun 			       key_index);
355*4882a593Smuzhiyun 			priv->uap_wep_key[key_index].is_default = MTRUE;
356*4882a593Smuzhiyun 			goto done;
357*4882a593Smuzhiyun 		}
358*4882a593Smuzhiyun 		if (key && key_len &&
359*4882a593Smuzhiyun 		    ((cipher == WLAN_CIPHER_SUITE_WEP40) ||
360*4882a593Smuzhiyun 		     (cipher == WLAN_CIPHER_SUITE_WEP104))) {
361*4882a593Smuzhiyun 			priv->uap_wep_key[key_index].length = key_len;
362*4882a593Smuzhiyun 			moal_memcpy_ext(
363*4882a593Smuzhiyun 				priv->phandle, priv->uap_wep_key[key_index].key,
364*4882a593Smuzhiyun 				key, key_len,
365*4882a593Smuzhiyun 				sizeof(priv->uap_wep_key[key_index].key));
366*4882a593Smuzhiyun 			priv->cipher = cipher;
367*4882a593Smuzhiyun 			priv->uap_wep_key[key_index].key_index = key_index;
368*4882a593Smuzhiyun 			priv->uap_wep_key[key_index].is_default = MFALSE;
369*4882a593Smuzhiyun 			PRINTM(MIOCTL, "Set UAP WEP key: key_index=%d len=%d\n",
370*4882a593Smuzhiyun 			       key_index, key_len);
371*4882a593Smuzhiyun 			goto done;
372*4882a593Smuzhiyun 		}
373*4882a593Smuzhiyun 	}
374*4882a593Smuzhiyun #endif
375*4882a593Smuzhiyun #endif
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	/* Allocate an IOCTL request buffer */
378*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
379*4882a593Smuzhiyun 	if (req == NULL) {
380*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
381*4882a593Smuzhiyun 		goto done;
382*4882a593Smuzhiyun 	}
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	/* Fill request buffer */
385*4882a593Smuzhiyun 	sec = (mlan_ds_sec_cfg *)req->pbuf;
386*4882a593Smuzhiyun 	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
387*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_SEC_CFG;
388*4882a593Smuzhiyun 	req->action = MLAN_ACT_SET;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	if (is_enable_wep) {
391*4882a593Smuzhiyun 		sec->param.encrypt_key.key_index = key_index;
392*4882a593Smuzhiyun 		sec->param.encrypt_key.is_current_wep_key = MTRUE;
393*4882a593Smuzhiyun 	} else if (!disable) {
394*4882a593Smuzhiyun 		if (cipher != WLAN_CIPHER_SUITE_WEP40 &&
395*4882a593Smuzhiyun 		    cipher != WLAN_CIPHER_SUITE_WEP104 &&
396*4882a593Smuzhiyun 		    cipher != WLAN_CIPHER_SUITE_TKIP &&
397*4882a593Smuzhiyun 		    cipher != WLAN_CIPHER_SUITE_SMS4 &&
398*4882a593Smuzhiyun 		    cipher != WLAN_CIPHER_SUITE_AES_CMAC &&
399*4882a593Smuzhiyun #if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE
400*4882a593Smuzhiyun 		    cipher != WLAN_CIPHER_SUITE_CCMP_256 &&
401*4882a593Smuzhiyun #endif
402*4882a593Smuzhiyun #if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
403*4882a593Smuzhiyun 		    cipher != WLAN_CIPHER_SUITE_GCMP &&
404*4882a593Smuzhiyun #endif
405*4882a593Smuzhiyun #if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE
406*4882a593Smuzhiyun 		    cipher != WLAN_CIPHER_SUITE_BIP_GMAC_128 &&
407*4882a593Smuzhiyun 		    cipher != WLAN_CIPHER_SUITE_BIP_GMAC_256 &&
408*4882a593Smuzhiyun 		    cipher != WLAN_CIPHER_SUITE_GCMP_256 &&
409*4882a593Smuzhiyun #endif
410*4882a593Smuzhiyun 		    cipher != WLAN_CIPHER_SUITE_CCMP) {
411*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid cipher suite specified\n");
412*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
413*4882a593Smuzhiyun 			goto done;
414*4882a593Smuzhiyun 		}
415*4882a593Smuzhiyun 		sec->param.encrypt_key.key_index = key_index;
416*4882a593Smuzhiyun 		if (key && key_len) {
417*4882a593Smuzhiyun 			moal_memcpy_ext(priv->phandle,
418*4882a593Smuzhiyun 					sec->param.encrypt_key.key_material,
419*4882a593Smuzhiyun 					key, key_len, MLAN_MAX_KEY_LENGTH);
420*4882a593Smuzhiyun 			sec->param.encrypt_key.key_len = key_len;
421*4882a593Smuzhiyun 		}
422*4882a593Smuzhiyun 		/* Set WAPI key */
423*4882a593Smuzhiyun 		if (cipher == WLAN_CIPHER_SUITE_SMS4) {
424*4882a593Smuzhiyun 			sec->param.encrypt_key.is_wapi_key = MTRUE;
425*4882a593Smuzhiyun 			if (seq_len) {
426*4882a593Smuzhiyun 				moal_memcpy_ext(priv->phandle,
427*4882a593Smuzhiyun 						sec->param.encrypt_key.pn, seq,
428*4882a593Smuzhiyun 						PN_SIZE, PN_SIZE);
429*4882a593Smuzhiyun 				DBG_HEXDUMP(MCMD_D, "WAPI PN",
430*4882a593Smuzhiyun 					    sec->param.encrypt_key.pn, seq_len);
431*4882a593Smuzhiyun 			}
432*4882a593Smuzhiyun 		}
433*4882a593Smuzhiyun 		if (addr) {
434*4882a593Smuzhiyun 			moal_memcpy_ext(priv->phandle,
435*4882a593Smuzhiyun 					sec->param.encrypt_key.mac_addr, addr,
436*4882a593Smuzhiyun 					ETH_ALEN, MLAN_MAC_ADDR_LENGTH);
437*4882a593Smuzhiyun 			if (memcmp(sec->param.encrypt_key.mac_addr, bcast_addr,
438*4882a593Smuzhiyun 				   ETH_ALEN) == 0)
439*4882a593Smuzhiyun 				sec->param.encrypt_key.key_flags =
440*4882a593Smuzhiyun 					KEY_FLAG_GROUP_KEY;
441*4882a593Smuzhiyun 			else
442*4882a593Smuzhiyun 				sec->param.encrypt_key.key_flags =
443*4882a593Smuzhiyun 					KEY_FLAG_SET_TX_KEY;
444*4882a593Smuzhiyun 		} else {
445*4882a593Smuzhiyun 			moal_memcpy_ext(priv->phandle,
446*4882a593Smuzhiyun 					sec->param.encrypt_key.mac_addr,
447*4882a593Smuzhiyun 					bcast_addr, ETH_ALEN,
448*4882a593Smuzhiyun 					MLAN_MAC_ADDR_LENGTH);
449*4882a593Smuzhiyun 			sec->param.encrypt_key.key_flags =
450*4882a593Smuzhiyun 				KEY_FLAG_GROUP_KEY | KEY_FLAG_SET_TX_KEY;
451*4882a593Smuzhiyun 		}
452*4882a593Smuzhiyun 		if (seq && seq_len) {
453*4882a593Smuzhiyun 			moal_memcpy_ext(priv->phandle,
454*4882a593Smuzhiyun 					sec->param.encrypt_key.pn, seq, seq_len,
455*4882a593Smuzhiyun 					PN_SIZE);
456*4882a593Smuzhiyun 			sec->param.encrypt_key.key_flags |=
457*4882a593Smuzhiyun 				KEY_FLAG_RX_SEQ_VALID;
458*4882a593Smuzhiyun 		}
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun #if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
461*4882a593Smuzhiyun 		if (cipher == WLAN_CIPHER_SUITE_GCMP)
462*4882a593Smuzhiyun 			sec->param.encrypt_key.key_flags |= KEY_FLAG_GCMP;
463*4882a593Smuzhiyun #endif
464*4882a593Smuzhiyun #if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE
465*4882a593Smuzhiyun 		else if (cipher == WLAN_CIPHER_SUITE_GCMP_256)
466*4882a593Smuzhiyun 			sec->param.encrypt_key.key_flags |= KEY_FLAG_GCMP_256;
467*4882a593Smuzhiyun #endif
468*4882a593Smuzhiyun #if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE
469*4882a593Smuzhiyun 		if (cipher == WLAN_CIPHER_SUITE_CCMP_256)
470*4882a593Smuzhiyun 			sec->param.encrypt_key.key_flags |= KEY_FLAG_CCMP_256;
471*4882a593Smuzhiyun #endif
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 		if (cipher == WLAN_CIPHER_SUITE_AES_CMAC
474*4882a593Smuzhiyun #if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE
475*4882a593Smuzhiyun 		    || cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
476*4882a593Smuzhiyun 		    cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256
477*4882a593Smuzhiyun #endif
478*4882a593Smuzhiyun 		) {
479*4882a593Smuzhiyun 			sec->param.encrypt_key.key_flags |=
480*4882a593Smuzhiyun 				KEY_FLAG_AES_MCAST_IGTK;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun #if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE
483*4882a593Smuzhiyun 			if (cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128)
484*4882a593Smuzhiyun 				sec->param.encrypt_key.key_flags |=
485*4882a593Smuzhiyun 					KEY_FLAG_GMAC_128;
486*4882a593Smuzhiyun 			else if (cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256)
487*4882a593Smuzhiyun 				sec->param.encrypt_key.key_flags |=
488*4882a593Smuzhiyun 					KEY_FLAG_GMAC_256;
489*4882a593Smuzhiyun #endif
490*4882a593Smuzhiyun 		}
491*4882a593Smuzhiyun 	} else {
492*4882a593Smuzhiyun 		if (key_index == KEY_INDEX_CLEAR_ALL)
493*4882a593Smuzhiyun 			sec->param.encrypt_key.key_disable = MTRUE;
494*4882a593Smuzhiyun 		else {
495*4882a593Smuzhiyun 			sec->param.encrypt_key.key_remove = MTRUE;
496*4882a593Smuzhiyun 			sec->param.encrypt_key.key_index = key_index;
497*4882a593Smuzhiyun 		}
498*4882a593Smuzhiyun 		sec->param.encrypt_key.key_flags = KEY_FLAG_REMOVE_KEY;
499*4882a593Smuzhiyun 		if (addr)
500*4882a593Smuzhiyun 			moal_memcpy_ext(priv->phandle,
501*4882a593Smuzhiyun 					sec->param.encrypt_key.mac_addr, addr,
502*4882a593Smuzhiyun 					ETH_ALEN, MLAN_MAC_ADDR_LENGTH);
503*4882a593Smuzhiyun 	}
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	/* Send IOCTL request to MLAN */
506*4882a593Smuzhiyun 	ret = woal_request_ioctl(priv, req, wait_option);
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun done:
509*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_PENDING)
510*4882a593Smuzhiyun 		kfree(req);
511*4882a593Smuzhiyun 	LEAVE();
512*4882a593Smuzhiyun 	return ret;
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun /**
516*4882a593Smuzhiyun  * @brief Set/Enable the WEP key to driver
517*4882a593Smuzhiyun  *
518*4882a593Smuzhiyun  * @param priv      A pointer to moal_private structure
519*4882a593Smuzhiyun  * @param key       A pointer to key data
520*4882a593Smuzhiyun  * @param key_len   Length of the key data
521*4882a593Smuzhiyun  * @param index     Key index
522*4882a593Smuzhiyun  * @param wait_option wait_option
523*4882a593Smuzhiyun  *
524*4882a593Smuzhiyun  * @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
525*4882a593Smuzhiyun  */
woal_cfg80211_set_wep_keys(moal_private * priv,const t_u8 * key,int key_len,t_u8 index,t_u8 wait_option)526*4882a593Smuzhiyun mlan_status woal_cfg80211_set_wep_keys(moal_private *priv, const t_u8 *key,
527*4882a593Smuzhiyun 				       int key_len, t_u8 index,
528*4882a593Smuzhiyun 				       t_u8 wait_option)
529*4882a593Smuzhiyun {
530*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
531*4882a593Smuzhiyun 	t_u32 cipher = 0;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	ENTER();
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	if (key_len) {
536*4882a593Smuzhiyun 		if (key_len == 5)
537*4882a593Smuzhiyun 			cipher = WLAN_CIPHER_SUITE_WEP40;
538*4882a593Smuzhiyun 		else
539*4882a593Smuzhiyun 			cipher = WLAN_CIPHER_SUITE_WEP104;
540*4882a593Smuzhiyun 		ret = woal_cfg80211_set_key(priv, 0, cipher, key, key_len, NULL,
541*4882a593Smuzhiyun 					    0, index, NULL, 0, wait_option);
542*4882a593Smuzhiyun 	} else {
543*4882a593Smuzhiyun 		/* No key provided so it is enable key. We
544*4882a593Smuzhiyun 		 * want to just set the transmit key index
545*4882a593Smuzhiyun 		 */
546*4882a593Smuzhiyun 		ret = woal_cfg80211_set_key(priv, 1, cipher, key, key_len, NULL,
547*4882a593Smuzhiyun 					    0, index, NULL, 0, wait_option);
548*4882a593Smuzhiyun 	}
549*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS)
550*4882a593Smuzhiyun 		PRINTM(MERROR, "woal_cfg80211_set_wep_keys Fail\n");
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	LEAVE();
553*4882a593Smuzhiyun 	return ret;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun /**
557*4882a593Smuzhiyun  * @brief clear all mgmt ies
558*4882a593Smuzhiyun  *
559*4882a593Smuzhiyun  * @param priv              A pointer to moal private structure
560*4882a593Smuzhiyun  * @param wait_option       wait_option
561*4882a593Smuzhiyun  * @return                  N/A
562*4882a593Smuzhiyun  */
woal_clear_all_mgmt_ies(moal_private * priv,t_u8 wait_option)563*4882a593Smuzhiyun void woal_clear_all_mgmt_ies(moal_private *priv, t_u8 wait_option)
564*4882a593Smuzhiyun {
565*4882a593Smuzhiyun 	t_u16 mask = 0;
566*4882a593Smuzhiyun 	/* clear BEACON WPS/P2P IE */
567*4882a593Smuzhiyun 	if (priv->beacon_wps_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
568*4882a593Smuzhiyun 		PRINTM(MCMND, "Clear BEACON WPS ie\n");
569*4882a593Smuzhiyun 		if (woal_cfg80211_mgmt_frame_ie(
570*4882a593Smuzhiyun 			    priv, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
571*4882a593Smuzhiyun 			    MGMT_MASK_BEACON_WPS_P2P, wait_option))
572*4882a593Smuzhiyun 			PRINTM(MERROR, "%s: clear beacon wps ie failed \n",
573*4882a593Smuzhiyun 			       __func__);
574*4882a593Smuzhiyun 		priv->beacon_wps_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
575*4882a593Smuzhiyun 	}
576*4882a593Smuzhiyun 	if (priv->assocresp_qos_map_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
577*4882a593Smuzhiyun 		PRINTM(MCMND, "Clear associate response QOS map ie\n");
578*4882a593Smuzhiyun 		if (woal_cfg80211_mgmt_frame_ie(
579*4882a593Smuzhiyun 			    priv, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
580*4882a593Smuzhiyun 			    MGMT_MASK_ASSOC_RESP_QOS_MAP, wait_option))
581*4882a593Smuzhiyun 			PRINTM(MERROR,
582*4882a593Smuzhiyun 			       "%s: Clear associate response QOS map ie failed \n",
583*4882a593Smuzhiyun 			       __func__);
584*4882a593Smuzhiyun 		priv->assocresp_qos_map_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
585*4882a593Smuzhiyun 	}
586*4882a593Smuzhiyun 	/* clear mgmt frame ies */
587*4882a593Smuzhiyun 	if (priv->probereq_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
588*4882a593Smuzhiyun 		mask |= MGMT_MASK_PROBE_REQ;
589*4882a593Smuzhiyun 	if (priv->beacon_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
590*4882a593Smuzhiyun 		mask |= MGMT_MASK_BEACON;
591*4882a593Smuzhiyun 	if (priv->proberesp_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
592*4882a593Smuzhiyun 		mask |= MGMT_MASK_PROBE_RESP;
593*4882a593Smuzhiyun 	if (priv->assocresp_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
594*4882a593Smuzhiyun 		mask |= MGMT_MASK_ASSOC_RESP;
595*4882a593Smuzhiyun 	if (priv->proberesp_p2p_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
596*4882a593Smuzhiyun 		mask |= MGMT_MASK_PROBE_RESP;
597*4882a593Smuzhiyun 	if (priv->beacon_vendor_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
598*4882a593Smuzhiyun 		mask |= MGMT_MASK_BEACON;
599*4882a593Smuzhiyun 	if (mask) {
600*4882a593Smuzhiyun 		PRINTM(MCMND, "Clear IES: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
601*4882a593Smuzhiyun 		       priv->beacon_index, priv->probereq_index,
602*4882a593Smuzhiyun 		       priv->proberesp_index, priv->assocresp_index,
603*4882a593Smuzhiyun 		       priv->proberesp_p2p_index, priv->beacon_vendor_index);
604*4882a593Smuzhiyun 		if (woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0,
605*4882a593Smuzhiyun 						NULL, 0, mask, wait_option))
606*4882a593Smuzhiyun 			PRINTM(MERROR, "%s: Clear ies failed, mask=0x%x\n",
607*4882a593Smuzhiyun 			       __func__, mask);
608*4882a593Smuzhiyun 	}
609*4882a593Smuzhiyun 	priv->probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
610*4882a593Smuzhiyun 	priv->beacon_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
611*4882a593Smuzhiyun 	priv->proberesp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
612*4882a593Smuzhiyun 	priv->assocresp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
613*4882a593Smuzhiyun 	priv->proberesp_p2p_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
614*4882a593Smuzhiyun 	priv->beacon_vendor_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
618*4882a593Smuzhiyun /**
619*4882a593Smuzhiyun  * @brief set bss role
620*4882a593Smuzhiyun  *
621*4882a593Smuzhiyun  * @param priv              A pointer to moal private structure
622*4882a593Smuzhiyun  * @param action            Action: set or get
623*4882a593Smuzhiyun  * @param role              A pointer to bss role
624*4882a593Smuzhiyun  *
625*4882a593Smuzhiyun  * @return                  0 -- success, otherwise fail
626*4882a593Smuzhiyun  */
woal_cfg80211_bss_role_cfg(moal_private * priv,t_u16 action,t_u8 * bss_role)627*4882a593Smuzhiyun int woal_cfg80211_bss_role_cfg(moal_private *priv, t_u16 action, t_u8 *bss_role)
628*4882a593Smuzhiyun {
629*4882a593Smuzhiyun 	int ret = 0;
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	ENTER();
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	if (action == MLAN_ACT_SET) {
634*4882a593Smuzhiyun 		/* Reset interface */
635*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
636*4882a593Smuzhiyun 		    woal_reset_intf(priv, MOAL_IOCTL_WAIT, MFALSE)) {
637*4882a593Smuzhiyun 			PRINTM(MERROR, "woal_reset_intf fail\n");
638*4882a593Smuzhiyun 			ret = -EFAULT;
639*4882a593Smuzhiyun 			goto done;
640*4882a593Smuzhiyun 		}
641*4882a593Smuzhiyun 	}
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
644*4882a593Smuzhiyun 	    woal_bss_role_cfg(priv, action, MOAL_IOCTL_WAIT, bss_role)) {
645*4882a593Smuzhiyun 		PRINTM(MERROR, "woal_bss_role_cfg fail\n");
646*4882a593Smuzhiyun 		ret = -EFAULT;
647*4882a593Smuzhiyun 		goto done;
648*4882a593Smuzhiyun 	}
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 	if (action == MLAN_ACT_SET) {
651*4882a593Smuzhiyun 		/* set back the mac address */
652*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
653*4882a593Smuzhiyun 		    woal_request_set_mac_address(priv, MOAL_IOCTL_WAIT)) {
654*4882a593Smuzhiyun 			PRINTM(MERROR, "woal_request_set_mac_address fail\n");
655*4882a593Smuzhiyun 			ret = -EFAULT;
656*4882a593Smuzhiyun 			goto done;
657*4882a593Smuzhiyun 		}
658*4882a593Smuzhiyun 		/* clear the mgmt ies */
659*4882a593Smuzhiyun 		woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
660*4882a593Smuzhiyun 		/* Initialize private structures */
661*4882a593Smuzhiyun 		woal_init_priv(priv, MOAL_IOCTL_WAIT);
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 		/* Enable interfaces */
664*4882a593Smuzhiyun 		netif_device_attach(priv->netdev);
665*4882a593Smuzhiyun 		woal_start_queue(priv->netdev);
666*4882a593Smuzhiyun 	}
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun done:
669*4882a593Smuzhiyun 	LEAVE();
670*4882a593Smuzhiyun 	return ret;
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun #endif
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
675*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
676*4882a593Smuzhiyun /**
677*4882a593Smuzhiyun  *  @brief This function display P2P public action frame type
678*4882a593Smuzhiyun  *
679*4882a593Smuzhiyun  *  @param  buf      A buffer to a management frame
680*4882a593Smuzhiyun  *  @param  len      buffer len
681*4882a593Smuzhiyun  *  @param chan      the channel
682*4882a593Smuzhiyun  *  @param flag      Tx/Rx flag. Tx:flag = 1;Rx:flag = 0;
683*4882a593Smuzhiyun  *
684*4882a593Smuzhiyun  *  @return          N/A
685*4882a593Smuzhiyun  */
woal_cfg80211_display_p2p_actframe(const t_u8 * buf,int len,struct ieee80211_channel * chan,const t_u8 flag)686*4882a593Smuzhiyun void woal_cfg80211_display_p2p_actframe(const t_u8 *buf, int len,
687*4882a593Smuzhiyun 					struct ieee80211_channel *chan,
688*4882a593Smuzhiyun 					const t_u8 flag)
689*4882a593Smuzhiyun {
690*4882a593Smuzhiyun 	const t_u8 p2p_oui[] = {0x50, 0x6f, 0x9a, 0x09};
691*4882a593Smuzhiyun 	t_u8 subtype;
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 	ENTER();
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 	if (!buf || len < (P2P_ACT_FRAME_OUI_SUBTYPE_OFFSET + 1)) {
696*4882a593Smuzhiyun 		LEAVE();
697*4882a593Smuzhiyun 		return;
698*4882a593Smuzhiyun 	}
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun 	if (((struct ieee80211_mgmt *)buf)->u.action.category ==
701*4882a593Smuzhiyun 		    P2P_ACT_FRAME_CATEGORY &&
702*4882a593Smuzhiyun 	    !memcmp(buf + P2P_ACT_FRAME_OUI_OFFSET, p2p_oui, sizeof(p2p_oui))) {
703*4882a593Smuzhiyun 		subtype = *(buf + P2P_ACT_FRAME_OUI_SUBTYPE_OFFSET);
704*4882a593Smuzhiyun 		switch (subtype) {
705*4882a593Smuzhiyun 		case P2P_GO_NEG_REQ:
706*4882a593Smuzhiyun 			PRINTM(MMSG,
707*4882a593Smuzhiyun 			       "wlan: %s P2P Group Owner Negotiation Req Frame, channel=%d\n",
708*4882a593Smuzhiyun 			       (flag) ? "TX" : "RX",
709*4882a593Smuzhiyun 			       (chan) ? chan->hw_value : 0);
710*4882a593Smuzhiyun 			break;
711*4882a593Smuzhiyun 		case P2P_GO_NEG_RSP:
712*4882a593Smuzhiyun 			PRINTM(MMSG,
713*4882a593Smuzhiyun 			       "wlan: %s P2P Group Owner Negotiation Rsp Frame, channel=%d\n",
714*4882a593Smuzhiyun 			       (flag) ? "TX" : "RX",
715*4882a593Smuzhiyun 			       (chan) ? chan->hw_value : 0);
716*4882a593Smuzhiyun 			break;
717*4882a593Smuzhiyun 		case P2P_GO_NEG_CONF:
718*4882a593Smuzhiyun 			PRINTM(MMSG,
719*4882a593Smuzhiyun 			       "wlan: %s P2P Group Owner Negotiation Confirm Frame, channel=%d\n",
720*4882a593Smuzhiyun 			       (flag) ? "TX" : "RX",
721*4882a593Smuzhiyun 			       (chan) ? chan->hw_value : 0);
722*4882a593Smuzhiyun 			break;
723*4882a593Smuzhiyun 		case P2P_INVITE_REQ:
724*4882a593Smuzhiyun 			PRINTM(MMSG,
725*4882a593Smuzhiyun 			       "wlan: %s P2P Invitation Request, channel=%d\n",
726*4882a593Smuzhiyun 			       (flag) ? "TX" : "RX",
727*4882a593Smuzhiyun 			       (chan) ? chan->hw_value : 0);
728*4882a593Smuzhiyun 			break;
729*4882a593Smuzhiyun 		case P2P_INVITE_RSP:
730*4882a593Smuzhiyun 			PRINTM(MMSG,
731*4882a593Smuzhiyun 			       "wlan: %s P2P Invitation Response, channel=%d\n",
732*4882a593Smuzhiyun 			       (flag) ? "TX" : "RX",
733*4882a593Smuzhiyun 			       (chan) ? chan->hw_value : 0);
734*4882a593Smuzhiyun 			break;
735*4882a593Smuzhiyun 		case P2P_DEVDIS_REQ:
736*4882a593Smuzhiyun 			PRINTM(MMSG,
737*4882a593Smuzhiyun 			       "wlan: %s P2P Device Discoverability Request, channel=%d\n",
738*4882a593Smuzhiyun 			       (flag) ? "TX" : "RX",
739*4882a593Smuzhiyun 			       (chan) ? chan->hw_value : 0);
740*4882a593Smuzhiyun 			break;
741*4882a593Smuzhiyun 		case P2P_DEVDIS_RSP:
742*4882a593Smuzhiyun 			PRINTM(MIOCTL,
743*4882a593Smuzhiyun 			       "wlan: %s P2P Device Discoverability Response, channel=%d\n",
744*4882a593Smuzhiyun 			       (flag) ? "TX" : "RX",
745*4882a593Smuzhiyun 			       (chan) ? chan->hw_value : 0);
746*4882a593Smuzhiyun 			break;
747*4882a593Smuzhiyun 		case P2P_PROVDIS_REQ:
748*4882a593Smuzhiyun 			PRINTM(MMSG,
749*4882a593Smuzhiyun 			       "wlan: %s P2P Provision Discovery Request, channel=%d\n",
750*4882a593Smuzhiyun 			       (flag) ? "TX" : "RX",
751*4882a593Smuzhiyun 			       (chan) ? chan->hw_value : 0);
752*4882a593Smuzhiyun 			break;
753*4882a593Smuzhiyun 		case P2P_PROVDIS_RSP:
754*4882a593Smuzhiyun 			PRINTM(MMSG,
755*4882a593Smuzhiyun 			       "wlan: %s P2P Provision Discovery Response, channel=%d\n",
756*4882a593Smuzhiyun 			       (flag) ? "TX" : "RX",
757*4882a593Smuzhiyun 			       (chan) ? chan->hw_value : 0);
758*4882a593Smuzhiyun 			break;
759*4882a593Smuzhiyun 		default:
760*4882a593Smuzhiyun 			PRINTM(MMSG,
761*4882a593Smuzhiyun 			       "wlan: %s Unknown P2P Action Frame, channel=%d, subtype=%d\n",
762*4882a593Smuzhiyun 			       (flag) ? "TX" : "RX",
763*4882a593Smuzhiyun 			       (chan) ? chan->hw_value : 0, subtype);
764*4882a593Smuzhiyun 			break;
765*4882a593Smuzhiyun 		}
766*4882a593Smuzhiyun 	}
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 	LEAVE();
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun /**
772*4882a593Smuzhiyun  * @brief initialize p2p client for wpa_supplicant
773*4882a593Smuzhiyun  *
774*4882a593Smuzhiyun  * @param priv			A pointer to moal private structure
775*4882a593Smuzhiyun  *
776*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
777*4882a593Smuzhiyun  */
woal_cfg80211_init_p2p_client(moal_private * priv)778*4882a593Smuzhiyun int woal_cfg80211_init_p2p_client(moal_private *priv)
779*4882a593Smuzhiyun {
780*4882a593Smuzhiyun 	int ret = MLAN_STATUS_SUCCESS;
781*4882a593Smuzhiyun 	t_u16 wifi_direct_mode = WIFI_DIRECT_MODE_DISABLE;
782*4882a593Smuzhiyun 	t_u8 bss_role;
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 	ENTER();
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	/* bss type check */
787*4882a593Smuzhiyun 	if (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) {
788*4882a593Smuzhiyun 		PRINTM(MERROR, "Unexpected bss type when init p2p client\n");
789*4882a593Smuzhiyun 		ret = -EFAULT;
790*4882a593Smuzhiyun 		goto done;
791*4882a593Smuzhiyun 	}
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 	/* get the bss role */
794*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
795*4882a593Smuzhiyun 	    woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_GET, &bss_role)) {
796*4882a593Smuzhiyun 		ret = -EFAULT;
797*4882a593Smuzhiyun 		goto done;
798*4882a593Smuzhiyun 	}
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun 	if (bss_role != MLAN_BSS_ROLE_STA) {
801*4882a593Smuzhiyun 		bss_role = MLAN_BSS_ROLE_STA;
802*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
803*4882a593Smuzhiyun 		    woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_SET, &bss_role)) {
804*4882a593Smuzhiyun 			ret = -EFAULT;
805*4882a593Smuzhiyun 			goto done;
806*4882a593Smuzhiyun 		}
807*4882a593Smuzhiyun 	}
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun 	wifi_direct_mode = WIFI_DIRECT_MODE_DISABLE;
810*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
811*4882a593Smuzhiyun 	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
812*4882a593Smuzhiyun 		ret = -EFAULT;
813*4882a593Smuzhiyun 		goto done;
814*4882a593Smuzhiyun 	}
815*4882a593Smuzhiyun 
816*4882a593Smuzhiyun 	/* first, init wifi direct to listen mode */
817*4882a593Smuzhiyun 	wifi_direct_mode = WIFI_DIRECT_MODE_LISTEN;
818*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
819*4882a593Smuzhiyun 	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
820*4882a593Smuzhiyun 		ret = -EFAULT;
821*4882a593Smuzhiyun 		goto done;
822*4882a593Smuzhiyun 	}
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun 	/* second, init wifi direct client  */
825*4882a593Smuzhiyun 	wifi_direct_mode = WIFI_DIRECT_MODE_CLIENT;
826*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
827*4882a593Smuzhiyun 	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
828*4882a593Smuzhiyun 		ret = -EFAULT;
829*4882a593Smuzhiyun 		goto done;
830*4882a593Smuzhiyun 	}
831*4882a593Smuzhiyun done:
832*4882a593Smuzhiyun 	LEAVE();
833*4882a593Smuzhiyun 	return ret;
834*4882a593Smuzhiyun }
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun /**
837*4882a593Smuzhiyun  * @brief initialize p2p GO for wpa_supplicant
838*4882a593Smuzhiyun  *
839*4882a593Smuzhiyun  * @param priv			A pointer to moal private structure
840*4882a593Smuzhiyun  *
841*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
842*4882a593Smuzhiyun  */
woal_cfg80211_init_p2p_go(moal_private * priv)843*4882a593Smuzhiyun int woal_cfg80211_init_p2p_go(moal_private *priv)
844*4882a593Smuzhiyun {
845*4882a593Smuzhiyun 	int ret = MLAN_STATUS_SUCCESS;
846*4882a593Smuzhiyun 	t_u16 wifi_direct_mode;
847*4882a593Smuzhiyun 	t_u8 bss_role;
848*4882a593Smuzhiyun 	mlan_ds_wifi_direct_config p2p_config;
849*4882a593Smuzhiyun 	mlan_ds_ps_mgmt ps_mgmt;
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 	ENTER();
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	/* bss type check */
854*4882a593Smuzhiyun 	if (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) {
855*4882a593Smuzhiyun 		PRINTM(MERROR, "Unexpected bss type when init p2p GO\n");
856*4882a593Smuzhiyun 		ret = -EFAULT;
857*4882a593Smuzhiyun 		goto done;
858*4882a593Smuzhiyun 	}
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 	wifi_direct_mode = WIFI_DIRECT_MODE_DISABLE;
861*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
862*4882a593Smuzhiyun 	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
863*4882a593Smuzhiyun 		ret = -EFAULT;
864*4882a593Smuzhiyun 		goto done;
865*4882a593Smuzhiyun 	}
866*4882a593Smuzhiyun 
867*4882a593Smuzhiyun 	/* first, init wifi direct to listen mode */
868*4882a593Smuzhiyun 	wifi_direct_mode = WIFI_DIRECT_MODE_LISTEN;
869*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
870*4882a593Smuzhiyun 	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
871*4882a593Smuzhiyun 		ret = -EFAULT;
872*4882a593Smuzhiyun 		goto done;
873*4882a593Smuzhiyun 	}
874*4882a593Smuzhiyun 
875*4882a593Smuzhiyun 	/* second, init wifi direct to GO mode  */
876*4882a593Smuzhiyun 	wifi_direct_mode = WIFI_DIRECT_MODE_GO;
877*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
878*4882a593Smuzhiyun 	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
879*4882a593Smuzhiyun 		ret = -EFAULT;
880*4882a593Smuzhiyun 		goto done;
881*4882a593Smuzhiyun 	}
882*4882a593Smuzhiyun 
883*4882a593Smuzhiyun 	/* get the bss role, and set it to uAP */
884*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
885*4882a593Smuzhiyun 	    woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_GET, &bss_role)) {
886*4882a593Smuzhiyun 		ret = -EFAULT;
887*4882a593Smuzhiyun 		goto done;
888*4882a593Smuzhiyun 	}
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun 	if (bss_role != MLAN_BSS_ROLE_UAP) {
891*4882a593Smuzhiyun 		bss_role = MLAN_BSS_ROLE_UAP;
892*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
893*4882a593Smuzhiyun 		    woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_SET, &bss_role)) {
894*4882a593Smuzhiyun 			ret = -EFAULT;
895*4882a593Smuzhiyun 			goto done;
896*4882a593Smuzhiyun 		}
897*4882a593Smuzhiyun 	}
898*4882a593Smuzhiyun /* NoA:-- Interval = 100TUs and Duration= 50TUs, count=255*/
899*4882a593Smuzhiyun #define DEF_NOA_COUNT 255
900*4882a593Smuzhiyun 	if (priv->phandle->noa_duration && priv->phandle->card_info->go_noa) {
901*4882a593Smuzhiyun 		memset(&p2p_config, 0, sizeof(p2p_config));
902*4882a593Smuzhiyun 		p2p_config.noa_enable = MTRUE;
903*4882a593Smuzhiyun 		p2p_config.index = 0;
904*4882a593Smuzhiyun 		p2p_config.noa_count = DEF_NOA_COUNT;
905*4882a593Smuzhiyun 		p2p_config.noa_duration = priv->phandle->noa_duration;
906*4882a593Smuzhiyun 		p2p_config.noa_interval = priv->phandle->noa_interval;
907*4882a593Smuzhiyun 		p2p_config.flags = WIFI_DIRECT_NOA;
908*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
909*4882a593Smuzhiyun 		    woal_p2p_config(priv, MLAN_ACT_SET, &p2p_config)) {
910*4882a593Smuzhiyun 			PRINTM(MERROR, "woal_p2p_config fail\n");
911*4882a593Smuzhiyun 			ret = -EFAULT;
912*4882a593Smuzhiyun 			goto done;
913*4882a593Smuzhiyun 		}
914*4882a593Smuzhiyun 
915*4882a593Smuzhiyun 		memset(&ps_mgmt, 0, sizeof(ps_mgmt));
916*4882a593Smuzhiyun 		ps_mgmt.flags = PS_FLAG_PS_MODE;
917*4882a593Smuzhiyun 		ps_mgmt.ps_mode = PS_MODE_INACTIVITY;
918*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
919*4882a593Smuzhiyun 		    woal_set_get_uap_power_mode(priv, MLAN_ACT_SET, &ps_mgmt)) {
920*4882a593Smuzhiyun 			PRINTM(MERROR, "woal_set_get_uap_power_mode fail\n");
921*4882a593Smuzhiyun 			ret = -EFAULT;
922*4882a593Smuzhiyun 			goto done;
923*4882a593Smuzhiyun 		}
924*4882a593Smuzhiyun 		PRINTM(MMSG, "Enable NOA: duration=%d, interval=%d\n",
925*4882a593Smuzhiyun 		       priv->phandle->noa_duration,
926*4882a593Smuzhiyun 		       priv->phandle->noa_interval);
927*4882a593Smuzhiyun 	}
928*4882a593Smuzhiyun done:
929*4882a593Smuzhiyun 	LEAVE();
930*4882a593Smuzhiyun 	return ret;
931*4882a593Smuzhiyun }
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun /**
934*4882a593Smuzhiyun  * @brief reset bss role and wifi direct mode for wpa_supplicant
935*4882a593Smuzhiyun  *
936*4882a593Smuzhiyun  * @param priv			A pointer to moal private structure
937*4882a593Smuzhiyun  *
938*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
939*4882a593Smuzhiyun  */
woal_cfg80211_deinit_p2p(moal_private * priv)940*4882a593Smuzhiyun int woal_cfg80211_deinit_p2p(moal_private *priv)
941*4882a593Smuzhiyun {
942*4882a593Smuzhiyun 	int ret = MLAN_STATUS_SUCCESS;
943*4882a593Smuzhiyun 	t_u16 wifi_direct_mode;
944*4882a593Smuzhiyun 	t_u8 bss_role;
945*4882a593Smuzhiyun 	t_u8 channel_status;
946*4882a593Smuzhiyun 	moal_private *remain_priv = NULL;
947*4882a593Smuzhiyun 	mlan_ds_ps_mgmt ps_mgmt;
948*4882a593Smuzhiyun 
949*4882a593Smuzhiyun 	ENTER();
950*4882a593Smuzhiyun 
951*4882a593Smuzhiyun 	/* bss type check */
952*4882a593Smuzhiyun 	if (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) {
953*4882a593Smuzhiyun 		PRINTM(MERROR, "Unexpected bss type when deinit p2p\n");
954*4882a593Smuzhiyun 		ret = -EFAULT;
955*4882a593Smuzhiyun 		goto done;
956*4882a593Smuzhiyun 	}
957*4882a593Smuzhiyun 	/* unregister mgmt frame from FW */
958*4882a593Smuzhiyun 	if (priv->mgmt_subtype_mask) {
959*4882a593Smuzhiyun 		priv->mgmt_subtype_mask = 0;
960*4882a593Smuzhiyun 		if (woal_reg_rx_mgmt_ind(priv, MLAN_ACT_SET,
961*4882a593Smuzhiyun 					 &priv->mgmt_subtype_mask,
962*4882a593Smuzhiyun 					 MOAL_IOCTL_WAIT)) {
963*4882a593Smuzhiyun 			PRINTM(MERROR,
964*4882a593Smuzhiyun 			       "deinit_p2p: fail to unregister mgmt frame\n");
965*4882a593Smuzhiyun 			ret = -EFAULT;
966*4882a593Smuzhiyun 			goto done;
967*4882a593Smuzhiyun 		}
968*4882a593Smuzhiyun 	}
969*4882a593Smuzhiyun 
970*4882a593Smuzhiyun 	/* cancel previous remain on channel */
971*4882a593Smuzhiyun 	if (priv->phandle->remain_on_channel) {
972*4882a593Smuzhiyun 		remain_priv =
973*4882a593Smuzhiyun 			priv->phandle->priv[priv->phandle->remain_bss_index];
974*4882a593Smuzhiyun 		if (!remain_priv) {
975*4882a593Smuzhiyun 			PRINTM(MERROR,
976*4882a593Smuzhiyun 			       "deinit_p2p: wrong remain_bss_index=%d\n",
977*4882a593Smuzhiyun 			       priv->phandle->remain_bss_index);
978*4882a593Smuzhiyun 			ret = -EFAULT;
979*4882a593Smuzhiyun 			goto done;
980*4882a593Smuzhiyun 		}
981*4882a593Smuzhiyun 		if (woal_cfg80211_remain_on_channel_cfg(
982*4882a593Smuzhiyun 			    remain_priv, MOAL_IOCTL_WAIT, MTRUE,
983*4882a593Smuzhiyun 			    &channel_status, NULL, 0, 0)) {
984*4882a593Smuzhiyun 			PRINTM(MERROR,
985*4882a593Smuzhiyun 			       "deinit_p2p: Fail to cancel remain on channel\n");
986*4882a593Smuzhiyun 			ret = -EFAULT;
987*4882a593Smuzhiyun 			goto done;
988*4882a593Smuzhiyun 		}
989*4882a593Smuzhiyun 		if (priv->phandle->cookie) {
990*4882a593Smuzhiyun 			cfg80211_remain_on_channel_expired(
991*4882a593Smuzhiyun #if KERNEL_VERSION(3, 6, 0) > CFG80211_VERSION_CODE
992*4882a593Smuzhiyun 				remain_priv->netdev,
993*4882a593Smuzhiyun #else
994*4882a593Smuzhiyun 				remain_priv->wdev,
995*4882a593Smuzhiyun #endif
996*4882a593Smuzhiyun 				priv->phandle->cookie, &priv->phandle->chan,
997*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
998*4882a593Smuzhiyun 				priv->phandle->channel_type,
999*4882a593Smuzhiyun #endif
1000*4882a593Smuzhiyun 				GFP_ATOMIC);
1001*4882a593Smuzhiyun 			priv->phandle->cookie = 0;
1002*4882a593Smuzhiyun 		}
1003*4882a593Smuzhiyun 		priv->phandle->remain_on_channel = MFALSE;
1004*4882a593Smuzhiyun 	}
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun 	/* get the bss role */
1007*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
1008*4882a593Smuzhiyun 	    woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_GET, &bss_role)) {
1009*4882a593Smuzhiyun 		ret = -EFAULT;
1010*4882a593Smuzhiyun 		goto done;
1011*4882a593Smuzhiyun 	}
1012*4882a593Smuzhiyun 
1013*4882a593Smuzhiyun 	/* reset bss role */
1014*4882a593Smuzhiyun 	if (bss_role != MLAN_BSS_ROLE_STA) {
1015*4882a593Smuzhiyun 		memset(&ps_mgmt, 0, sizeof(ps_mgmt));
1016*4882a593Smuzhiyun 		ps_mgmt.flags = PS_FLAG_PS_MODE;
1017*4882a593Smuzhiyun 		ps_mgmt.ps_mode = PS_MODE_DISABLE;
1018*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
1019*4882a593Smuzhiyun 		    woal_set_get_uap_power_mode(priv, MLAN_ACT_SET, &ps_mgmt)) {
1020*4882a593Smuzhiyun 			PRINTM(MERROR, "woal_set_get_uap_power_mode fail\n");
1021*4882a593Smuzhiyun 			ret = -EFAULT;
1022*4882a593Smuzhiyun 			goto done;
1023*4882a593Smuzhiyun 		}
1024*4882a593Smuzhiyun 		bss_role = MLAN_BSS_ROLE_STA;
1025*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
1026*4882a593Smuzhiyun 		    woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_SET, &bss_role)) {
1027*4882a593Smuzhiyun 			ret = -EFAULT;
1028*4882a593Smuzhiyun 			goto done;
1029*4882a593Smuzhiyun 		}
1030*4882a593Smuzhiyun 	}
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun 	wifi_direct_mode = WIFI_DIRECT_MODE_DISABLE;
1033*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
1034*4882a593Smuzhiyun 	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
1035*4882a593Smuzhiyun 		ret = -EFAULT;
1036*4882a593Smuzhiyun 		goto done;
1037*4882a593Smuzhiyun 	}
1038*4882a593Smuzhiyun done:
1039*4882a593Smuzhiyun 	LEAVE();
1040*4882a593Smuzhiyun 	return ret;
1041*4882a593Smuzhiyun }
1042*4882a593Smuzhiyun #endif /* KERNEL_VERSION */
1043*4882a593Smuzhiyun #endif /* WIFI_DIRECT_SUPPORT */
1044*4882a593Smuzhiyun 
1045*4882a593Smuzhiyun #ifdef UAP_SUPPORT
1046*4882a593Smuzhiyun /**
1047*4882a593Smuzhiyun  * @brief Request to cancel CAC
1048*4882a593Smuzhiyun  *
1049*4882a593Smuzhiyun  * @param priv         A pointer to moal_private structure
1050*4882a593Smuzhiyun  *
1051*4882a593Smuzhiyun  * @return              N/A */
woal_cancel_cac(moal_private * priv)1052*4882a593Smuzhiyun void woal_cancel_cac(moal_private *priv)
1053*4882a593Smuzhiyun {
1054*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
1055*4882a593Smuzhiyun 	if (priv->phandle->is_cac_timer_set &&
1056*4882a593Smuzhiyun 	    priv->bss_index == priv->phandle->cac_bss_index) {
1057*4882a593Smuzhiyun 		woal_cancel_timer(&priv->phandle->cac_timer);
1058*4882a593Smuzhiyun 		priv->phandle->is_cac_timer_set = MFALSE;
1059*4882a593Smuzhiyun 		/* Make sure Chan Report is cancelled */
1060*4882a593Smuzhiyun 		if (woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT))
1061*4882a593Smuzhiyun 			PRINTM(MERROR, "%s: cancel chan report failed \n",
1062*4882a593Smuzhiyun 			       __func__);
1063*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1064*4882a593Smuzhiyun 		cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel,
1065*4882a593Smuzhiyun 				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
1066*4882a593Smuzhiyun #else
1067*4882a593Smuzhiyun 		cfg80211_cac_event(priv->netdev, NL80211_RADAR_CAC_ABORTED,
1068*4882a593Smuzhiyun 				   GFP_KERNEL);
1069*4882a593Smuzhiyun #endif
1070*4882a593Smuzhiyun 		memset(&priv->phandle->dfs_channel, 0,
1071*4882a593Smuzhiyun 		       sizeof(struct cfg80211_chan_def));
1072*4882a593Smuzhiyun 		priv->phandle->cac_bss_index = 0xff;
1073*4882a593Smuzhiyun 	}
1074*4882a593Smuzhiyun #endif
1075*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1076*4882a593Smuzhiyun 	if (moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
1077*4882a593Smuzhiyun 		woal_cancel_cac_block(priv);
1078*4882a593Smuzhiyun #endif
1079*4882a593Smuzhiyun 	return;
1080*4882a593Smuzhiyun }
1081*4882a593Smuzhiyun #endif
1082*4882a593Smuzhiyun 
1083*4882a593Smuzhiyun /**
1084*4882a593Smuzhiyun  * @brief Request the driver to change the interface type
1085*4882a593Smuzhiyun  *
1086*4882a593Smuzhiyun  * @param wiphy         A pointer to wiphy structure
1087*4882a593Smuzhiyun  * @param dev           A pointer to net_device structure
1088*4882a593Smuzhiyun  * @param type          Virtual interface types
1089*4882a593Smuzhiyun  * @param flags         Flags
1090*4882a593Smuzhiyun  * @param params        A pointer to vif_params structure
1091*4882a593Smuzhiyun  *
1092*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
1093*4882a593Smuzhiyun  */
woal_cfg80211_change_virtual_intf(struct wiphy * wiphy,struct net_device * dev,enum nl80211_iftype type,u32 * flags,struct vif_params * params)1094*4882a593Smuzhiyun int woal_cfg80211_change_virtual_intf(struct wiphy *wiphy,
1095*4882a593Smuzhiyun 				      struct net_device *dev,
1096*4882a593Smuzhiyun 				      enum nl80211_iftype type,
1097*4882a593Smuzhiyun #if KERNEL_VERSION(4, 12, 0) > CFG80211_VERSION_CODE
1098*4882a593Smuzhiyun 				      u32 *flags,
1099*4882a593Smuzhiyun #endif
1100*4882a593Smuzhiyun 				      struct vif_params *params)
1101*4882a593Smuzhiyun {
1102*4882a593Smuzhiyun 	int ret = 0;
1103*4882a593Smuzhiyun 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
1104*4882a593Smuzhiyun 	mlan_ds_bss *bss = NULL;
1105*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
1106*4882a593Smuzhiyun #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1107*4882a593Smuzhiyun 	t_u8 bss_role;
1108*4882a593Smuzhiyun #endif
1109*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
1110*4882a593Smuzhiyun 
1111*4882a593Smuzhiyun 	ENTER();
1112*4882a593Smuzhiyun 
1113*4882a593Smuzhiyun 	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_MONITOR) {
1114*4882a593Smuzhiyun 		ret = -EFAULT;
1115*4882a593Smuzhiyun 		goto done;
1116*4882a593Smuzhiyun 	}
1117*4882a593Smuzhiyun 
1118*4882a593Smuzhiyun 	if (priv->wdev->iftype == type) {
1119*4882a593Smuzhiyun 		PRINTM(MINFO, "Already set to required type\n");
1120*4882a593Smuzhiyun 		goto done;
1121*4882a593Smuzhiyun 	}
1122*4882a593Smuzhiyun #ifdef UAP_SUPPORT
1123*4882a593Smuzhiyun 	/* when AP mode switch to station mode, we use it to cancel pending CAC
1124*4882a593Smuzhiyun 	 */
1125*4882a593Smuzhiyun 	if (priv->wdev->iftype == NL80211_IFTYPE_AP &&
1126*4882a593Smuzhiyun 	    type == NL80211_IFTYPE_STATION) {
1127*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
1128*4882a593Smuzhiyun 		if (priv->phandle->is_cac_timer_set &&
1129*4882a593Smuzhiyun 		    priv->bss_index == priv->phandle->cac_bss_index) {
1130*4882a593Smuzhiyun 			woal_cancel_timer(&priv->phandle->cac_timer);
1131*4882a593Smuzhiyun 			priv->phandle->is_cac_timer_set = MFALSE;
1132*4882a593Smuzhiyun 			/* Make sure Chan Report is cancelled */
1133*4882a593Smuzhiyun 			if (woal_11h_cancel_chan_report_ioctl(priv,
1134*4882a593Smuzhiyun 							      MOAL_IOCTL_WAIT))
1135*4882a593Smuzhiyun 				PRINTM(MERROR,
1136*4882a593Smuzhiyun 				       "%s: cancel chan report failed \n",
1137*4882a593Smuzhiyun 				       __func__);
1138*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1139*4882a593Smuzhiyun 			cfg80211_cac_event(priv->netdev,
1140*4882a593Smuzhiyun 					   &priv->phandle->dfs_channel,
1141*4882a593Smuzhiyun 					   NL80211_RADAR_CAC_ABORTED,
1142*4882a593Smuzhiyun 					   GFP_KERNEL);
1143*4882a593Smuzhiyun #else
1144*4882a593Smuzhiyun 			cfg80211_cac_event(priv->netdev,
1145*4882a593Smuzhiyun 					   NL80211_RADAR_CAC_ABORTED,
1146*4882a593Smuzhiyun 					   GFP_KERNEL);
1147*4882a593Smuzhiyun #endif
1148*4882a593Smuzhiyun 			memset(&priv->phandle->dfs_channel, 0,
1149*4882a593Smuzhiyun 			       sizeof(struct cfg80211_chan_def));
1150*4882a593Smuzhiyun 			priv->phandle->cac_bss_index = 0xff;
1151*4882a593Smuzhiyun 		}
1152*4882a593Smuzhiyun #endif
1153*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1154*4882a593Smuzhiyun 		if (moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
1155*4882a593Smuzhiyun 			woal_cancel_cac_block(priv);
1156*4882a593Smuzhiyun #endif
1157*4882a593Smuzhiyun 	}
1158*4882a593Smuzhiyun 	if ((priv->bss_type == MLAN_BSS_TYPE_UAP) && (priv->bss_index > 0)) {
1159*4882a593Smuzhiyun 		PRINTM(MMSG,
1160*4882a593Smuzhiyun 		       "%s: Skip change virtual intf type on uap: from %d to %d\n",
1161*4882a593Smuzhiyun 		       dev->name, priv->wdev->iftype, type);
1162*4882a593Smuzhiyun 		priv->wdev->iftype = type;
1163*4882a593Smuzhiyun 		goto done;
1164*4882a593Smuzhiyun 	}
1165*4882a593Smuzhiyun #endif
1166*4882a593Smuzhiyun 
1167*4882a593Smuzhiyun 	PRINTM(MIOCTL, "%s: change virturl intf=%d\n", dev->name, type);
1168*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
1169*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
1170*4882a593Smuzhiyun 	/** cancel previous remain on channel to avoid firmware hang */
1171*4882a593Smuzhiyun 	if (priv->phandle->remain_on_channel) {
1172*4882a593Smuzhiyun 		t_u8 channel_status;
1173*4882a593Smuzhiyun 		moal_private *remain_priv = NULL;
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun 		remain_priv =
1176*4882a593Smuzhiyun 			priv->phandle->priv[priv->phandle->remain_bss_index];
1177*4882a593Smuzhiyun 		if (!remain_priv) {
1178*4882a593Smuzhiyun 			PRINTM(MERROR,
1179*4882a593Smuzhiyun 			       "change_virtual_intf:wrong remain_bss_index=%d\n",
1180*4882a593Smuzhiyun 			       priv->phandle->remain_bss_index);
1181*4882a593Smuzhiyun 			ret = -EFAULT;
1182*4882a593Smuzhiyun 			goto done;
1183*4882a593Smuzhiyun 		}
1184*4882a593Smuzhiyun 		if (woal_cfg80211_remain_on_channel_cfg(
1185*4882a593Smuzhiyun 			    remain_priv, MOAL_IOCTL_WAIT, MTRUE,
1186*4882a593Smuzhiyun 			    &channel_status, NULL, 0, 0)) {
1187*4882a593Smuzhiyun 			PRINTM(MERROR,
1188*4882a593Smuzhiyun 			       "change_virtual_intf: Fail to cancel remain on channel\n");
1189*4882a593Smuzhiyun 			ret = -EFAULT;
1190*4882a593Smuzhiyun 			goto done;
1191*4882a593Smuzhiyun 		}
1192*4882a593Smuzhiyun 		if (priv->phandle->cookie) {
1193*4882a593Smuzhiyun 			cfg80211_remain_on_channel_expired(
1194*4882a593Smuzhiyun #if KERNEL_VERSION(3, 6, 0) > CFG80211_VERSION_CODE
1195*4882a593Smuzhiyun 				remain_priv->netdev,
1196*4882a593Smuzhiyun #else
1197*4882a593Smuzhiyun 				remain_priv->wdev,
1198*4882a593Smuzhiyun #endif
1199*4882a593Smuzhiyun 				priv->phandle->cookie, &priv->phandle->chan,
1200*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
1201*4882a593Smuzhiyun 				priv->phandle->channel_type,
1202*4882a593Smuzhiyun #endif
1203*4882a593Smuzhiyun 				GFP_ATOMIC);
1204*4882a593Smuzhiyun 			priv->phandle->cookie = 0;
1205*4882a593Smuzhiyun 		}
1206*4882a593Smuzhiyun 		priv->phandle->remain_on_channel = MFALSE;
1207*4882a593Smuzhiyun 	}
1208*4882a593Smuzhiyun #endif
1209*4882a593Smuzhiyun #endif
1210*4882a593Smuzhiyun 
1211*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
1212*4882a593Smuzhiyun 	if (req == NULL) {
1213*4882a593Smuzhiyun 		ret = -ENOMEM;
1214*4882a593Smuzhiyun 		goto done;
1215*4882a593Smuzhiyun 	}
1216*4882a593Smuzhiyun 
1217*4882a593Smuzhiyun 	bss = (mlan_ds_bss *)req->pbuf;
1218*4882a593Smuzhiyun 	bss->sub_command = MLAN_OID_BSS_MODE;
1219*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_BSS;
1220*4882a593Smuzhiyun 	req->action = MLAN_ACT_SET;
1221*4882a593Smuzhiyun 
1222*4882a593Smuzhiyun 	switch (type) {
1223*4882a593Smuzhiyun 	case NL80211_IFTYPE_STATION:
1224*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
1225*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
1226*4882a593Smuzhiyun 		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT &&
1227*4882a593Smuzhiyun 		    (priv->wdev->iftype == NL80211_IFTYPE_AP ||
1228*4882a593Smuzhiyun 		     priv->wdev->iftype == NL80211_IFTYPE_P2P_GO ||
1229*4882a593Smuzhiyun 		     priv->wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
1230*4882a593Smuzhiyun 			if (priv->phandle->is_go_timer_set) {
1231*4882a593Smuzhiyun 				woal_cancel_timer(&priv->phandle->go_timer);
1232*4882a593Smuzhiyun 				priv->phandle->is_go_timer_set = MFALSE;
1233*4882a593Smuzhiyun 			}
1234*4882a593Smuzhiyun 			/* if we support wifi direct && priv->bss_type ==
1235*4882a593Smuzhiyun 			 * wifi_direct, and currently the interface type is AP
1236*4882a593Smuzhiyun 			 * or GO or client, that means wpa_supplicant deinit()
1237*4882a593Smuzhiyun 			 * wifi direct interface, so we should deinit bss_role
1238*4882a593Smuzhiyun 			 * and wifi direct mode, for other bss_type, we should
1239*4882a593Smuzhiyun 			 * not update bss_role and wifi direct mode
1240*4882a593Smuzhiyun 			 */
1241*4882a593Smuzhiyun 
1242*4882a593Smuzhiyun 			if (MLAN_STATUS_SUCCESS !=
1243*4882a593Smuzhiyun 			    woal_cfg80211_deinit_p2p(priv)) {
1244*4882a593Smuzhiyun 				ret = -EFAULT;
1245*4882a593Smuzhiyun 				goto done;
1246*4882a593Smuzhiyun 			}
1247*4882a593Smuzhiyun 		}
1248*4882a593Smuzhiyun #endif /* KERNEL_VERSION */
1249*4882a593Smuzhiyun #endif /* WIFI_DIRECT_SUPPORT */
1250*4882a593Smuzhiyun #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1251*4882a593Smuzhiyun 		if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
1252*4882a593Smuzhiyun #if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13)
1253*4882a593Smuzhiyun 			woal_cfg80211_del_beacon(wiphy, dev, 0);
1254*4882a593Smuzhiyun #else
1255*4882a593Smuzhiyun 			woal_cfg80211_del_beacon(wiphy, dev);
1256*4882a593Smuzhiyun #endif
1257*4882a593Smuzhiyun 			bss_role = MLAN_BSS_ROLE_STA;
1258*4882a593Smuzhiyun 			woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_SET,
1259*4882a593Smuzhiyun 						   &bss_role);
1260*4882a593Smuzhiyun 			PRINTM(MIOCTL, "set bss role for STA\n");
1261*4882a593Smuzhiyun 		}
1262*4882a593Smuzhiyun #endif
1263*4882a593Smuzhiyun 		bss->param.bss_mode = MLAN_BSS_MODE_INFRA;
1264*4882a593Smuzhiyun 		priv->wdev->iftype = NL80211_IFTYPE_STATION;
1265*4882a593Smuzhiyun 		PRINTM(MINFO, "Setting interface type to managed\n");
1266*4882a593Smuzhiyun 		break;
1267*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
1268*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
1269*4882a593Smuzhiyun 	case NL80211_IFTYPE_P2P_CLIENT:
1270*4882a593Smuzhiyun 		if (priv->phandle->is_go_timer_set) {
1271*4882a593Smuzhiyun 			woal_cancel_timer(&priv->phandle->go_timer);
1272*4882a593Smuzhiyun 			priv->phandle->is_go_timer_set = MFALSE;
1273*4882a593Smuzhiyun 		}
1274*4882a593Smuzhiyun 
1275*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
1276*4882a593Smuzhiyun 		    woal_cfg80211_init_p2p_client(priv)) {
1277*4882a593Smuzhiyun 			ret = -EFAULT;
1278*4882a593Smuzhiyun 			goto done;
1279*4882a593Smuzhiyun 		}
1280*4882a593Smuzhiyun 
1281*4882a593Smuzhiyun 		bss->param.bss_mode = MLAN_BSS_MODE_INFRA;
1282*4882a593Smuzhiyun 		priv->wdev->iftype = NL80211_IFTYPE_P2P_CLIENT;
1283*4882a593Smuzhiyun 		PRINTM(MINFO, "Setting interface type to P2P client\n");
1284*4882a593Smuzhiyun 
1285*4882a593Smuzhiyun 		break;
1286*4882a593Smuzhiyun #endif /* KERNEL_VERSION */
1287*4882a593Smuzhiyun #endif /* WIFI_DIRECT_SUPPORT */
1288*4882a593Smuzhiyun 	case NL80211_IFTYPE_AP:
1289*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
1290*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
1291*4882a593Smuzhiyun 	/* Fall Through */
1292*4882a593Smuzhiyun 	case NL80211_IFTYPE_P2P_GO:
1293*4882a593Smuzhiyun 		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
1294*4882a593Smuzhiyun 			if (MLAN_STATUS_SUCCESS !=
1295*4882a593Smuzhiyun 			    woal_cfg80211_init_p2p_go(priv)) {
1296*4882a593Smuzhiyun 				ret = -EFAULT;
1297*4882a593Smuzhiyun 				goto done;
1298*4882a593Smuzhiyun 			}
1299*4882a593Smuzhiyun 			priv->phandle->is_go_timer_set = MTRUE;
1300*4882a593Smuzhiyun 			woal_mod_timer(&priv->phandle->go_timer,
1301*4882a593Smuzhiyun 				       MOAL_TIMER_10S);
1302*4882a593Smuzhiyun 		}
1303*4882a593Smuzhiyun 		if (type == NL80211_IFTYPE_P2P_GO)
1304*4882a593Smuzhiyun 			priv->wdev->iftype = NL80211_IFTYPE_P2P_GO;
1305*4882a593Smuzhiyun #endif
1306*4882a593Smuzhiyun #endif
1307*4882a593Smuzhiyun #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1308*4882a593Smuzhiyun 		if (priv->bss_type == MLAN_BSS_TYPE_STA) {
1309*4882a593Smuzhiyun #ifdef STA_CFG80211
1310*4882a593Smuzhiyun 			/** cancel pending scan */
1311*4882a593Smuzhiyun 			woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
1312*4882a593Smuzhiyun #endif
1313*4882a593Smuzhiyun 			if (priv->probereq_index !=
1314*4882a593Smuzhiyun 			    MLAN_CUSTOM_IE_AUTO_IDX_MASK)
1315*4882a593Smuzhiyun 				if (woal_cfg80211_mgmt_frame_ie(
1316*4882a593Smuzhiyun 					    priv, NULL, 0, NULL, 0, NULL, 0,
1317*4882a593Smuzhiyun 					    NULL, 0, MGMT_MASK_PROBE_REQ,
1318*4882a593Smuzhiyun 					    MOAL_IOCTL_WAIT))
1319*4882a593Smuzhiyun 					PRINTM(MERROR,
1320*4882a593Smuzhiyun 					       "%s: Clear probe req ie failed\n",
1321*4882a593Smuzhiyun 					       __func__);
1322*4882a593Smuzhiyun 			bss_role = MLAN_BSS_ROLE_UAP;
1323*4882a593Smuzhiyun 			woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_SET,
1324*4882a593Smuzhiyun 						   &bss_role);
1325*4882a593Smuzhiyun 			PRINTM(MIOCTL, "set bss role for AP\n");
1326*4882a593Smuzhiyun 		}
1327*4882a593Smuzhiyun #endif
1328*4882a593Smuzhiyun 		if (type == NL80211_IFTYPE_AP)
1329*4882a593Smuzhiyun 			priv->wdev->iftype = NL80211_IFTYPE_AP;
1330*4882a593Smuzhiyun 		PRINTM(MINFO, "Setting interface type to P2P GO\n");
1331*4882a593Smuzhiyun 
1332*4882a593Smuzhiyun 		/* there is no need for P2P GO to set bss_mode */
1333*4882a593Smuzhiyun 		goto done;
1334*4882a593Smuzhiyun 
1335*4882a593Smuzhiyun 		break;
1336*4882a593Smuzhiyun 
1337*4882a593Smuzhiyun 	case NL80211_IFTYPE_UNSPECIFIED:
1338*4882a593Smuzhiyun 		bss->param.bss_mode = MLAN_BSS_MODE_AUTO;
1339*4882a593Smuzhiyun 		priv->wdev->iftype = NL80211_IFTYPE_STATION;
1340*4882a593Smuzhiyun 		PRINTM(MINFO, "Setting interface type to auto\n");
1341*4882a593Smuzhiyun 		break;
1342*4882a593Smuzhiyun 	default:
1343*4882a593Smuzhiyun 		ret = -EINVAL;
1344*4882a593Smuzhiyun 		break;
1345*4882a593Smuzhiyun 	}
1346*4882a593Smuzhiyun 	if (ret)
1347*4882a593Smuzhiyun 		goto done;
1348*4882a593Smuzhiyun 
1349*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1350*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
1351*4882a593Smuzhiyun 		ret = -EFAULT;
1352*4882a593Smuzhiyun 		goto done;
1353*4882a593Smuzhiyun 	}
1354*4882a593Smuzhiyun 
1355*4882a593Smuzhiyun done:
1356*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
1357*4882a593Smuzhiyun 		kfree(req);
1358*4882a593Smuzhiyun 	LEAVE();
1359*4882a593Smuzhiyun 	return ret;
1360*4882a593Smuzhiyun }
1361*4882a593Smuzhiyun 
1362*4882a593Smuzhiyun /**
1363*4882a593Smuzhiyun  * @brief Request the driver to change the value of fragment
1364*4882a593Smuzhiyun  * threshold or rts threshold or retry limit
1365*4882a593Smuzhiyun  *
1366*4882a593Smuzhiyun  * @param wiphy         A pointer to wiphy structure
1367*4882a593Smuzhiyun  * @param changed       Change flags
1368*4882a593Smuzhiyun  *
1369*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
1370*4882a593Smuzhiyun  */
woal_cfg80211_set_wiphy_params(struct wiphy * wiphy,u32 changed)1371*4882a593Smuzhiyun int woal_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1372*4882a593Smuzhiyun {
1373*4882a593Smuzhiyun 	moal_private *priv = NULL;
1374*4882a593Smuzhiyun 	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
1375*4882a593Smuzhiyun #ifdef UAP_CFG80211
1376*4882a593Smuzhiyun #ifdef UAP_SUPPORT
1377*4882a593Smuzhiyun 	pmlan_uap_bss_param sys_cfg = NULL;
1378*4882a593Smuzhiyun #endif
1379*4882a593Smuzhiyun #endif
1380*4882a593Smuzhiyun 	int frag_thr = wiphy->frag_threshold;
1381*4882a593Smuzhiyun 	int rts_thr = wiphy->rts_threshold;
1382*4882a593Smuzhiyun 	int retry = wiphy->retry_long;
1383*4882a593Smuzhiyun 
1384*4882a593Smuzhiyun 	ENTER();
1385*4882a593Smuzhiyun 
1386*4882a593Smuzhiyun 	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
1387*4882a593Smuzhiyun 	if (!priv) {
1388*4882a593Smuzhiyun 		LEAVE();
1389*4882a593Smuzhiyun 		return -EFAULT;
1390*4882a593Smuzhiyun 	}
1391*4882a593Smuzhiyun 	if (rts_thr == (int)MLAN_FRAG_RTS_DISABLED)
1392*4882a593Smuzhiyun 		rts_thr = MLAN_RTS_MAX_VALUE;
1393*4882a593Smuzhiyun 	if (frag_thr == (int)MLAN_FRAG_RTS_DISABLED)
1394*4882a593Smuzhiyun 		frag_thr = MLAN_FRAG_MAX_VALUE;
1395*4882a593Smuzhiyun 
1396*4882a593Smuzhiyun #ifdef UAP_CFG80211
1397*4882a593Smuzhiyun #ifdef UAP_SUPPORT
1398*4882a593Smuzhiyun 	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
1399*4882a593Smuzhiyun 		sys_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
1400*4882a593Smuzhiyun 		if (!sys_cfg) {
1401*4882a593Smuzhiyun 			PRINTM(MERROR,
1402*4882a593Smuzhiyun 			       "Fail to alloc memory for mlan_uap_bss_param\n");
1403*4882a593Smuzhiyun 			LEAVE();
1404*4882a593Smuzhiyun 			return -EFAULT;
1405*4882a593Smuzhiyun 		}
1406*4882a593Smuzhiyun 		/* Initialize the invalid values so that the correct
1407*4882a593Smuzhiyun 		 * values below are downloaded to firmware
1408*4882a593Smuzhiyun 		 */
1409*4882a593Smuzhiyun 		woal_set_sys_config_invalid_data(sys_cfg);
1410*4882a593Smuzhiyun 		sys_cfg->frag_threshold = frag_thr;
1411*4882a593Smuzhiyun 		sys_cfg->rts_threshold = rts_thr;
1412*4882a593Smuzhiyun 		sys_cfg->retry_limit = retry;
1413*4882a593Smuzhiyun 
1414*4882a593Smuzhiyun 		if ((changed & WIPHY_PARAM_RTS_THRESHOLD) ||
1415*4882a593Smuzhiyun 		    (changed & WIPHY_PARAM_FRAG_THRESHOLD) ||
1416*4882a593Smuzhiyun 		    (changed &
1417*4882a593Smuzhiyun 		     (WIPHY_PARAM_RETRY_LONG | WIPHY_PARAM_RETRY_SHORT))) {
1418*4882a593Smuzhiyun 			if (woal_set_get_sys_config(priv, MLAN_ACT_SET,
1419*4882a593Smuzhiyun 						    MOAL_IOCTL_WAIT, sys_cfg)) {
1420*4882a593Smuzhiyun 				kfree(sys_cfg);
1421*4882a593Smuzhiyun 				goto fail;
1422*4882a593Smuzhiyun 			}
1423*4882a593Smuzhiyun 		}
1424*4882a593Smuzhiyun 		kfree(sys_cfg);
1425*4882a593Smuzhiyun 	}
1426*4882a593Smuzhiyun #endif
1427*4882a593Smuzhiyun #endif
1428*4882a593Smuzhiyun 
1429*4882a593Smuzhiyun #ifdef STA_CFG80211
1430*4882a593Smuzhiyun #ifdef STA_SUPPORT
1431*4882a593Smuzhiyun 	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
1432*4882a593Smuzhiyun 		if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1433*4882a593Smuzhiyun 			if (woal_set_get_rts(priv, MLAN_ACT_SET,
1434*4882a593Smuzhiyun 					     MOAL_IOCTL_WAIT, &rts_thr))
1435*4882a593Smuzhiyun 				goto fail;
1436*4882a593Smuzhiyun 		}
1437*4882a593Smuzhiyun 		if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
1438*4882a593Smuzhiyun 			if (woal_set_get_frag(priv, MLAN_ACT_SET,
1439*4882a593Smuzhiyun 					      MOAL_IOCTL_WAIT, &frag_thr))
1440*4882a593Smuzhiyun 				goto fail;
1441*4882a593Smuzhiyun 		}
1442*4882a593Smuzhiyun 		if (changed &
1443*4882a593Smuzhiyun 		    (WIPHY_PARAM_RETRY_LONG | WIPHY_PARAM_RETRY_SHORT))
1444*4882a593Smuzhiyun 			if (woal_set_get_retry(priv, MLAN_ACT_SET,
1445*4882a593Smuzhiyun 					       MOAL_IOCTL_WAIT, &retry))
1446*4882a593Smuzhiyun 				goto fail;
1447*4882a593Smuzhiyun 	}
1448*4882a593Smuzhiyun #endif
1449*4882a593Smuzhiyun #endif
1450*4882a593Smuzhiyun 	LEAVE();
1451*4882a593Smuzhiyun 	return 0;
1452*4882a593Smuzhiyun 
1453*4882a593Smuzhiyun fail:
1454*4882a593Smuzhiyun 	PRINTM(MERROR, "Failed to change wiphy params %x\n", changed);
1455*4882a593Smuzhiyun 	LEAVE();
1456*4882a593Smuzhiyun 	return -EFAULT;
1457*4882a593Smuzhiyun }
1458*4882a593Smuzhiyun 
1459*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 36) < CFG80211_VERSION_CODE
1460*4882a593Smuzhiyun /**
1461*4882a593Smuzhiyun  * @brief Request the driver to add a key
1462*4882a593Smuzhiyun  *
1463*4882a593Smuzhiyun  * @param wiphy         A pointer to wiphy structure
1464*4882a593Smuzhiyun  * @param netdev        A pointer to net_device structure
1465*4882a593Smuzhiyun  * @param key_index     Key index
1466*4882a593Smuzhiyun  * @param pairwise      Flag to indicate pairwise or group (for kernel > 2.6.36)
1467*4882a593Smuzhiyun  * @param mac_addr      MAC address (NULL for group key)
1468*4882a593Smuzhiyun  * @param params        A pointer to key_params structure
1469*4882a593Smuzhiyun  *
1470*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
1471*4882a593Smuzhiyun  */
1472*4882a593Smuzhiyun #else
1473*4882a593Smuzhiyun /**
1474*4882a593Smuzhiyun  * @brief Request the driver to add a key
1475*4882a593Smuzhiyun  *
1476*4882a593Smuzhiyun  * @param wiphy         A pointer to wiphy structure
1477*4882a593Smuzhiyun  * @param netdev        A pointer to net_device structure
1478*4882a593Smuzhiyun  * @param key_index     Key index
1479*4882a593Smuzhiyun  * @param mac_addr      MAC address (NULL for group key)
1480*4882a593Smuzhiyun  * @param params        A pointer to key_params structure
1481*4882a593Smuzhiyun  *
1482*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
1483*4882a593Smuzhiyun  */
1484*4882a593Smuzhiyun #endif
woal_cfg80211_add_key(struct wiphy * wiphy,struct net_device * netdev,int link_id,t_u8 key_index,bool pairwise,const t_u8 * mac_addr,struct key_params * params)1485*4882a593Smuzhiyun int woal_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
1486*4882a593Smuzhiyun #if (CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || IMX_ANDROID_13)
1487*4882a593Smuzhiyun 			  int link_id,
1488*4882a593Smuzhiyun #endif
1489*4882a593Smuzhiyun 			  t_u8 key_index,
1490*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 36) < CFG80211_VERSION_CODE
1491*4882a593Smuzhiyun 			  bool pairwise,
1492*4882a593Smuzhiyun #endif
1493*4882a593Smuzhiyun 			  const t_u8 *mac_addr, struct key_params *params)
1494*4882a593Smuzhiyun {
1495*4882a593Smuzhiyun 	moal_private *priv = (moal_private *)woal_get_netdev_priv(netdev);
1496*4882a593Smuzhiyun 
1497*4882a593Smuzhiyun 	ENTER();
1498*4882a593Smuzhiyun 	if (priv->ft_pre_connect) {
1499*4882a593Smuzhiyun 		PRINTM(MINFO, "Skip set keys during ft connecting\n");
1500*4882a593Smuzhiyun 		return -EFAULT;
1501*4882a593Smuzhiyun 	}
1502*4882a593Smuzhiyun 
1503*4882a593Smuzhiyun 	/** cancel pending scan */
1504*4882a593Smuzhiyun 	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
1505*4882a593Smuzhiyun 
1506*4882a593Smuzhiyun 	if (woal_cfg80211_set_key(priv, 0, params->cipher, params->key,
1507*4882a593Smuzhiyun 				  params->key_len, params->seq, params->seq_len,
1508*4882a593Smuzhiyun 				  key_index, mac_addr, 0, MOAL_IOCTL_WAIT)) {
1509*4882a593Smuzhiyun 		PRINTM(MERROR, "Error adding the crypto keys\n");
1510*4882a593Smuzhiyun 		LEAVE();
1511*4882a593Smuzhiyun 		return -EFAULT;
1512*4882a593Smuzhiyun 	}
1513*4882a593Smuzhiyun 
1514*4882a593Smuzhiyun 	PRINTM(MINFO, "Crypto keys added\n");
1515*4882a593Smuzhiyun 
1516*4882a593Smuzhiyun 	LEAVE();
1517*4882a593Smuzhiyun 	return 0;
1518*4882a593Smuzhiyun }
1519*4882a593Smuzhiyun 
1520*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 36) < CFG80211_VERSION_CODE
1521*4882a593Smuzhiyun /**
1522*4882a593Smuzhiyun  * @brief Request the driver to delete a key
1523*4882a593Smuzhiyun  *
1524*4882a593Smuzhiyun  * @param wiphy         A pointer to wiphy structure
1525*4882a593Smuzhiyun  * @param netdev        A pointer to net_device structure
1526*4882a593Smuzhiyun  * @param key_index     Key index
1527*4882a593Smuzhiyun  * @param pairwise      Flag to indicate pairwise or group (for kernel > 2.6.36)
1528*4882a593Smuzhiyun  * @param mac_addr      MAC address (NULL for group key)
1529*4882a593Smuzhiyun  *
1530*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
1531*4882a593Smuzhiyun  */
1532*4882a593Smuzhiyun #else
1533*4882a593Smuzhiyun /**
1534*4882a593Smuzhiyun  * @brief Request the driver to delete a key
1535*4882a593Smuzhiyun  *
1536*4882a593Smuzhiyun  * @param wiphy         A pointer to wiphy structure
1537*4882a593Smuzhiyun  * @param netdev        A pointer to net_device structure
1538*4882a593Smuzhiyun  * @param key_index     Key index
1539*4882a593Smuzhiyun  * @param mac_addr      MAC address (NULL for group key)
1540*4882a593Smuzhiyun  *
1541*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
1542*4882a593Smuzhiyun  */
1543*4882a593Smuzhiyun #endif
woal_cfg80211_del_key(struct wiphy * wiphy,struct net_device * netdev,int link_id,t_u8 key_index,bool pairwise,const t_u8 * mac_addr)1544*4882a593Smuzhiyun int woal_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
1545*4882a593Smuzhiyun #if (CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || IMX_ANDROID_13)
1546*4882a593Smuzhiyun 			  int link_id,
1547*4882a593Smuzhiyun #endif
1548*4882a593Smuzhiyun 			  t_u8 key_index,
1549*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 36) < CFG80211_VERSION_CODE
1550*4882a593Smuzhiyun 			  bool pairwise,
1551*4882a593Smuzhiyun #endif
1552*4882a593Smuzhiyun 			  const t_u8 *mac_addr)
1553*4882a593Smuzhiyun {
1554*4882a593Smuzhiyun 	moal_private *priv = (moal_private *)woal_get_netdev_priv(netdev);
1555*4882a593Smuzhiyun 
1556*4882a593Smuzhiyun 	ENTER();
1557*4882a593Smuzhiyun 	if (priv->phandle->driver_status) {
1558*4882a593Smuzhiyun 		PRINTM(MERROR, "Block %s in abnormal driver state\n", __func__);
1559*4882a593Smuzhiyun 		LEAVE();
1560*4882a593Smuzhiyun 		return -EFAULT;
1561*4882a593Smuzhiyun 	}
1562*4882a593Smuzhiyun 	/* del_key will be trigger from cfg80211_rx_mlme_mgmt funtion
1563*4882a593Smuzhiyun 	 * where we receive deauth/disassoicate packet in rx_work
1564*4882a593Smuzhiyun 	 * use MOAL_NO_WAIT to avoid dead lock
1565*4882a593Smuzhiyun 	 */
1566*4882a593Smuzhiyun 	if (MLAN_STATUS_FAILURE ==
1567*4882a593Smuzhiyun 	    woal_cfg80211_set_key(priv, 0, 0, NULL, 0, NULL, 0, key_index,
1568*4882a593Smuzhiyun 				  mac_addr, 1, MOAL_NO_WAIT)) {
1569*4882a593Smuzhiyun 		PRINTM(MERROR, "Error deleting the crypto keys\n");
1570*4882a593Smuzhiyun 		LEAVE();
1571*4882a593Smuzhiyun 		return -EFAULT;
1572*4882a593Smuzhiyun 	}
1573*4882a593Smuzhiyun 
1574*4882a593Smuzhiyun 	PRINTM(MINFO, "Crypto keys deleted\n");
1575*4882a593Smuzhiyun 	LEAVE();
1576*4882a593Smuzhiyun 	return 0;
1577*4882a593Smuzhiyun }
1578*4882a593Smuzhiyun 
1579*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 37) < CFG80211_VERSION_CODE
1580*4882a593Smuzhiyun /**
1581*4882a593Smuzhiyun  * @brief Request to enable WEP key to driver
1582*4882a593Smuzhiyun  *
1583*4882a593Smuzhiyun  * @param wiphy         A pointer to wiphy structure
1584*4882a593Smuzhiyun  * @param netdev        A pointer to net_device structure
1585*4882a593Smuzhiyun  * @param key_index     Key index
1586*4882a593Smuzhiyun  * @param ucast         Unicast flag (for kernel > 2.6.37)
1587*4882a593Smuzhiyun  * @param mcast         Multicast flag (for kernel > 2.6.37)
1588*4882a593Smuzhiyun  *
1589*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
1590*4882a593Smuzhiyun  */
1591*4882a593Smuzhiyun #else
1592*4882a593Smuzhiyun /**
1593*4882a593Smuzhiyun  * @brief Request to enable WEP key to driver
1594*4882a593Smuzhiyun  *
1595*4882a593Smuzhiyun  * @param wiphy         A pointer to wiphy structure
1596*4882a593Smuzhiyun  * @param netdev        A pointer to net_device structure
1597*4882a593Smuzhiyun  * @param key_index     Key index
1598*4882a593Smuzhiyun  *
1599*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
1600*4882a593Smuzhiyun  */
1601*4882a593Smuzhiyun #endif
woal_cfg80211_set_default_key(struct wiphy * wiphy,struct net_device * netdev,int link_id,t_u8 key_index,bool ucast,bool mcast)1602*4882a593Smuzhiyun int woal_cfg80211_set_default_key(struct wiphy *wiphy,
1603*4882a593Smuzhiyun 				  struct net_device *netdev,
1604*4882a593Smuzhiyun #if (CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || IMX_ANDROID_13)
1605*4882a593Smuzhiyun 				  int link_id,
1606*4882a593Smuzhiyun #endif
1607*4882a593Smuzhiyun 				  t_u8 key_index
1608*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 37) < CFG80211_VERSION_CODE
1609*4882a593Smuzhiyun 				  ,
1610*4882a593Smuzhiyun 				  bool ucast, bool mcast
1611*4882a593Smuzhiyun #endif
1612*4882a593Smuzhiyun )
1613*4882a593Smuzhiyun {
1614*4882a593Smuzhiyun 	int ret = 0;
1615*4882a593Smuzhiyun 	moal_private *priv = (moal_private *)woal_get_netdev_priv(netdev);
1616*4882a593Smuzhiyun 	mlan_bss_info bss_info;
1617*4882a593Smuzhiyun 
1618*4882a593Smuzhiyun 	ENTER();
1619*4882a593Smuzhiyun 	memset(&bss_info, 0, sizeof(mlan_bss_info));
1620*4882a593Smuzhiyun 	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
1621*4882a593Smuzhiyun 		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
1622*4882a593Smuzhiyun 		if (!bss_info.wep_status) {
1623*4882a593Smuzhiyun 			LEAVE();
1624*4882a593Smuzhiyun 			return ret;
1625*4882a593Smuzhiyun 		}
1626*4882a593Smuzhiyun 	}
1627*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
1628*4882a593Smuzhiyun 	    woal_cfg80211_set_wep_keys(priv, NULL, 0, key_index,
1629*4882a593Smuzhiyun 				       MOAL_IOCTL_WAIT)) {
1630*4882a593Smuzhiyun 		ret = -EFAULT;
1631*4882a593Smuzhiyun 	}
1632*4882a593Smuzhiyun 	LEAVE();
1633*4882a593Smuzhiyun 	return ret;
1634*4882a593Smuzhiyun }
1635*4882a593Smuzhiyun 
1636*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 30) <= CFG80211_VERSION_CODE
woal_cfg80211_set_default_mgmt_key(struct wiphy * wiphy,struct net_device * netdev,int link_id,t_u8 key_index)1637*4882a593Smuzhiyun int woal_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,
1638*4882a593Smuzhiyun 				       struct net_device *netdev,
1639*4882a593Smuzhiyun #if (CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || IMX_ANDROID_13)
1640*4882a593Smuzhiyun 				       int link_id,
1641*4882a593Smuzhiyun #endif
1642*4882a593Smuzhiyun 				       t_u8 key_index)
1643*4882a593Smuzhiyun {
1644*4882a593Smuzhiyun 	PRINTM(MINFO, "set default mgmt key, key index=%d\n", key_index);
1645*4882a593Smuzhiyun 
1646*4882a593Smuzhiyun 	return 0;
1647*4882a593Smuzhiyun }
1648*4882a593Smuzhiyun #endif
1649*4882a593Smuzhiyun 
1650*4882a593Smuzhiyun #if KERNEL_VERSION(5, 10, 0) <= CFG80211_VERSION_CODE
woal_cfg80211_set_default_beacon_key(struct wiphy * wiphy,struct net_device * netdev,int link_id,t_u8 key_index)1651*4882a593Smuzhiyun int woal_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
1652*4882a593Smuzhiyun 					 struct net_device *netdev,
1653*4882a593Smuzhiyun #if (CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || IMX_ANDROID_13)
1654*4882a593Smuzhiyun 					 int link_id,
1655*4882a593Smuzhiyun #endif
1656*4882a593Smuzhiyun 					 t_u8 key_index)
1657*4882a593Smuzhiyun {
1658*4882a593Smuzhiyun 	PRINTM(MINFO, "set default beacon key, key index=%d\n", key_index);
1659*4882a593Smuzhiyun 
1660*4882a593Smuzhiyun 	return 0;
1661*4882a593Smuzhiyun }
1662*4882a593Smuzhiyun #endif
1663*4882a593Smuzhiyun 
1664*4882a593Smuzhiyun #if KERNEL_VERSION(3, 1, 0) <= CFG80211_VERSION_CODE
1665*4882a593Smuzhiyun /**
1666*4882a593Smuzhiyun  *  @brief  Set GTK rekey data to driver
1667*4882a593Smuzhiyun  *
1668*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
1669*4882a593Smuzhiyun  *  @param gtk_rekey     A pointer to mlan_ds_misc_gtk_rekey_data structure
1670*4882a593Smuzhiyun  *  @param action           MLAN_ACT_SET or MLAN_ACT_GET
1671*4882a593Smuzhiyun  *
1672*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
1673*4882a593Smuzhiyun  */
woal_set_rekey_data(moal_private * priv,mlan_ds_misc_gtk_rekey_data * gtk_rekey,t_u8 action,t_u8 wait_option)1674*4882a593Smuzhiyun mlan_status woal_set_rekey_data(moal_private *priv,
1675*4882a593Smuzhiyun 				mlan_ds_misc_gtk_rekey_data *gtk_rekey,
1676*4882a593Smuzhiyun 				t_u8 action, t_u8 wait_option)
1677*4882a593Smuzhiyun {
1678*4882a593Smuzhiyun 	mlan_ioctl_req *req;
1679*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc_cfg;
1680*4882a593Smuzhiyun 	mlan_status status;
1681*4882a593Smuzhiyun 
1682*4882a593Smuzhiyun 	ENTER();
1683*4882a593Smuzhiyun 
1684*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1685*4882a593Smuzhiyun 
1686*4882a593Smuzhiyun 	if (req == NULL) {
1687*4882a593Smuzhiyun 		LEAVE();
1688*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
1689*4882a593Smuzhiyun 	} else {
1690*4882a593Smuzhiyun 		misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
1691*4882a593Smuzhiyun 		misc_cfg->sub_command = MLAN_OID_MISC_GTK_REKEY_OFFLOAD;
1692*4882a593Smuzhiyun 		req->req_id = MLAN_IOCTL_MISC_CFG;
1693*4882a593Smuzhiyun 
1694*4882a593Smuzhiyun 		req->action = action;
1695*4882a593Smuzhiyun 		if (action == MLAN_ACT_SET)
1696*4882a593Smuzhiyun 			moal_memcpy_ext(priv->phandle,
1697*4882a593Smuzhiyun 					&misc_cfg->param.gtk_rekey, gtk_rekey,
1698*4882a593Smuzhiyun 					sizeof(mlan_ds_misc_gtk_rekey_data),
1699*4882a593Smuzhiyun 					sizeof(mlan_ds_misc_gtk_rekey_data));
1700*4882a593Smuzhiyun 
1701*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, wait_option);
1702*4882a593Smuzhiyun 		if (status != MLAN_STATUS_PENDING)
1703*4882a593Smuzhiyun 			kfree(req);
1704*4882a593Smuzhiyun 	}
1705*4882a593Smuzhiyun 
1706*4882a593Smuzhiyun 	LEAVE();
1707*4882a593Smuzhiyun 	return status;
1708*4882a593Smuzhiyun }
1709*4882a593Smuzhiyun 
1710*4882a593Smuzhiyun /**
1711*4882a593Smuzhiyun  * @brief Give the data necessary for GTK rekeying to the driver
1712*4882a593Smuzhiyun  *
1713*4882a593Smuzhiyun  * @param wiphy         A pointer to wiphy structure
1714*4882a593Smuzhiyun  * @param dev           A pointer to net_device structure
1715*4882a593Smuzhiyun  * @param data        A pointer to cfg80211_gtk_rekey_data structure
1716*4882a593Smuzhiyun  *
1717*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
1718*4882a593Smuzhiyun  */
woal_cfg80211_set_rekey_data(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_gtk_rekey_data * data)1719*4882a593Smuzhiyun int woal_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
1720*4882a593Smuzhiyun 				 struct cfg80211_gtk_rekey_data *data)
1721*4882a593Smuzhiyun {
1722*4882a593Smuzhiyun 	int ret = 0;
1723*4882a593Smuzhiyun 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
1724*4882a593Smuzhiyun 	mlan_ds_misc_gtk_rekey_data rekey;
1725*4882a593Smuzhiyun 	mlan_fw_info fw_info;
1726*4882a593Smuzhiyun 
1727*4882a593Smuzhiyun 	ENTER();
1728*4882a593Smuzhiyun 
1729*4882a593Smuzhiyun 	if (priv->phandle->params.gtk_rekey_offload ==
1730*4882a593Smuzhiyun 	    GTK_REKEY_OFFLOAD_DISABLE) {
1731*4882a593Smuzhiyun 		PRINTM(MMSG, "%s return: gtk_rekey_offload is DISABLE\n",
1732*4882a593Smuzhiyun 		       __func__);
1733*4882a593Smuzhiyun 		LEAVE();
1734*4882a593Smuzhiyun 		return ret;
1735*4882a593Smuzhiyun 	}
1736*4882a593Smuzhiyun 
1737*4882a593Smuzhiyun 	memset(&fw_info, 0, sizeof(mlan_fw_info));
1738*4882a593Smuzhiyun 	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
1739*4882a593Smuzhiyun 	if (!fw_info.fw_supplicant_support) {
1740*4882a593Smuzhiyun 		LEAVE();
1741*4882a593Smuzhiyun 		return -1;
1742*4882a593Smuzhiyun 	}
1743*4882a593Smuzhiyun 
1744*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle, rekey.kek, data->kek, MLAN_KEK_LEN,
1745*4882a593Smuzhiyun 			MLAN_KEK_LEN);
1746*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle, rekey.kck, data->kck, MLAN_KCK_LEN,
1747*4882a593Smuzhiyun 			MLAN_KCK_LEN);
1748*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle, rekey.replay_ctr, data->replay_ctr,
1749*4882a593Smuzhiyun 			MLAN_REPLAY_CTR_LEN, MLAN_REPLAY_CTR_LEN);
1750*4882a593Smuzhiyun 
1751*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle, &priv->gtk_rekey_data, &rekey,
1752*4882a593Smuzhiyun 			sizeof(mlan_ds_misc_gtk_rekey_data),
1753*4882a593Smuzhiyun 			sizeof(mlan_ds_misc_gtk_rekey_data));
1754*4882a593Smuzhiyun 	if (priv->phandle->params.gtk_rekey_offload ==
1755*4882a593Smuzhiyun 	    GTK_REKEY_OFFLOAD_SUSPEND) {
1756*4882a593Smuzhiyun 		priv->gtk_data_ready = MTRUE;
1757*4882a593Smuzhiyun 		LEAVE();
1758*4882a593Smuzhiyun 		return ret;
1759*4882a593Smuzhiyun 	}
1760*4882a593Smuzhiyun 
1761*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
1762*4882a593Smuzhiyun 	    woal_set_rekey_data(priv, &rekey, MLAN_ACT_SET, MOAL_IOCTL_WAIT)) {
1763*4882a593Smuzhiyun 		ret = -EFAULT;
1764*4882a593Smuzhiyun 	}
1765*4882a593Smuzhiyun 
1766*4882a593Smuzhiyun 	LEAVE();
1767*4882a593Smuzhiyun 	return ret;
1768*4882a593Smuzhiyun }
1769*4882a593Smuzhiyun #endif
1770*4882a593Smuzhiyun 
1771*4882a593Smuzhiyun #ifdef STA_SUPPORT
1772*4882a593Smuzhiyun /* Opportunistic Key Caching APIs functions support
1773*4882a593Smuzhiyun  *
1774*4882a593Smuzhiyun  * this function get pmksa entry list in private structure
1775*4882a593Smuzhiyun  * @param priv         A pointer to moal_private structure
1776*4882a593Smuzhiyun  * @param bssid        A pointer to bssid
1777*4882a593Smuzhiyun  * @return             pointer to target entry or NULL
1778*4882a593Smuzhiyun  */
woal_get_pmksa_entry(moal_private * priv,const u8 * bssid)1779*4882a593Smuzhiyun struct pmksa_entry *woal_get_pmksa_entry(moal_private *priv, const u8 *bssid)
1780*4882a593Smuzhiyun {
1781*4882a593Smuzhiyun 	struct pmksa_entry *entry = NULL;
1782*4882a593Smuzhiyun 	unsigned long flags;
1783*4882a593Smuzhiyun 
1784*4882a593Smuzhiyun 	if (!priv || priv->bss_type != MLAN_BSS_TYPE_STA) {
1785*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid interface structure\n");
1786*4882a593Smuzhiyun 		return NULL;
1787*4882a593Smuzhiyun 	}
1788*4882a593Smuzhiyun 
1789*4882a593Smuzhiyun 	spin_lock_irqsave(&priv->pmksa_list_lock, flags);
1790*4882a593Smuzhiyun 	list_for_each_entry (entry, &priv->pmksa_cache_list, link) {
1791*4882a593Smuzhiyun 		if (!memcmp(entry->bssid, bssid, ETH_ALEN)) {
1792*4882a593Smuzhiyun 			spin_unlock_irqrestore(&priv->pmksa_list_lock, flags);
1793*4882a593Smuzhiyun 			return entry;
1794*4882a593Smuzhiyun 		}
1795*4882a593Smuzhiyun 	}
1796*4882a593Smuzhiyun 	spin_unlock_irqrestore(&priv->pmksa_list_lock, flags);
1797*4882a593Smuzhiyun 
1798*4882a593Smuzhiyun 	return NULL;
1799*4882a593Smuzhiyun }
1800*4882a593Smuzhiyun 
1801*4882a593Smuzhiyun /**
1802*4882a593Smuzhiyun  * This function flush pmksa entry list in private structure
1803*4882a593Smuzhiyun  * @param priv         A pointer to moal_private structure
1804*4882a593Smuzhiyun  * @return             success of failure
1805*4882a593Smuzhiyun  */
woal_flush_pmksa_list(moal_private * priv)1806*4882a593Smuzhiyun int woal_flush_pmksa_list(moal_private *priv)
1807*4882a593Smuzhiyun {
1808*4882a593Smuzhiyun 	struct pmksa_entry *entry, *tmp;
1809*4882a593Smuzhiyun 	unsigned long flags;
1810*4882a593Smuzhiyun 
1811*4882a593Smuzhiyun 	if (!priv || priv->bss_type != MLAN_BSS_TYPE_STA) {
1812*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid interface structure\n");
1813*4882a593Smuzhiyun 		return -EFAULT;
1814*4882a593Smuzhiyun 	}
1815*4882a593Smuzhiyun 
1816*4882a593Smuzhiyun 	spin_lock_irqsave(&priv->pmksa_list_lock, flags);
1817*4882a593Smuzhiyun 	list_for_each_entry_safe (entry, tmp, &priv->pmksa_cache_list, link) {
1818*4882a593Smuzhiyun 		list_del(&entry->link);
1819*4882a593Smuzhiyun 		kfree(entry);
1820*4882a593Smuzhiyun 	}
1821*4882a593Smuzhiyun 	INIT_LIST_HEAD(&priv->pmksa_cache_list);
1822*4882a593Smuzhiyun 	spin_unlock_irqrestore(&priv->pmksa_list_lock, flags);
1823*4882a593Smuzhiyun 
1824*4882a593Smuzhiyun 	return 0;
1825*4882a593Smuzhiyun }
1826*4882a593Smuzhiyun 
1827*4882a593Smuzhiyun /**
1828*4882a593Smuzhiyun  *  This function add new pmksa entry to list
1829*4882a593Smuzhiyun  *  @param wiphy        A pointer to struct wiphy
1830*4882a593Smuzhiyun  *  @param dev          A pointer to net_device structure
1831*4882a593Smuzhiyun  *  @param pmksa        A pointer to cfg80211_pmksa structure
1832*4882a593Smuzhiyun  *  @return             success of failure
1833*4882a593Smuzhiyun  */
woal_cfg80211_set_pmksa(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_pmksa * pmksa)1834*4882a593Smuzhiyun int woal_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
1835*4882a593Smuzhiyun 			    struct cfg80211_pmksa *pmksa)
1836*4882a593Smuzhiyun {
1837*4882a593Smuzhiyun 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
1838*4882a593Smuzhiyun 	struct pmksa_entry *entry = NULL;
1839*4882a593Smuzhiyun 	unsigned long flags;
1840*4882a593Smuzhiyun 	int ret = 0;
1841*4882a593Smuzhiyun 
1842*4882a593Smuzhiyun 	ENTER();
1843*4882a593Smuzhiyun 
1844*4882a593Smuzhiyun 	if (!priv || priv->bss_type != MLAN_BSS_TYPE_STA) {
1845*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid interface structure\n");
1846*4882a593Smuzhiyun 		ret = -1;
1847*4882a593Smuzhiyun 		goto done;
1848*4882a593Smuzhiyun 	}
1849*4882a593Smuzhiyun 
1850*4882a593Smuzhiyun 	PRINTM(MIOCTL, "Set pmksa entry: bssid=" MACSTR "\n",
1851*4882a593Smuzhiyun 	       MAC2STR(pmksa->bssid));
1852*4882a593Smuzhiyun 	entry = woal_get_pmksa_entry(priv, pmksa->bssid);
1853*4882a593Smuzhiyun 	if (!entry) {
1854*4882a593Smuzhiyun 		entry = kzalloc(sizeof(struct pmksa_entry), GFP_ATOMIC);
1855*4882a593Smuzhiyun 		if (!entry) {
1856*4882a593Smuzhiyun 			PRINTM(MERROR, "Fail to allocate pmksa entry\n");
1857*4882a593Smuzhiyun 			goto done;
1858*4882a593Smuzhiyun 		}
1859*4882a593Smuzhiyun 		INIT_LIST_HEAD(&entry->link);
1860*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, entry->bssid, pmksa->bssid,
1861*4882a593Smuzhiyun 				ETH_ALEN, ETH_ALEN);
1862*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, entry->pmkid, pmksa->pmkid,
1863*4882a593Smuzhiyun 				PMKID_LEN, PMKID_LEN);
1864*4882a593Smuzhiyun 		spin_lock_irqsave(&priv->pmksa_list_lock, flags);
1865*4882a593Smuzhiyun 		list_add_tail(&entry->link, &priv->pmksa_cache_list);
1866*4882a593Smuzhiyun 		spin_unlock_irqrestore(&priv->pmksa_list_lock, flags);
1867*4882a593Smuzhiyun 	} else {
1868*4882a593Smuzhiyun 		/** pmkid is differnt from previous value? */
1869*4882a593Smuzhiyun 		memset(entry->pmkid, 0, PMKID_LEN);
1870*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, entry->pmkid, pmksa->pmkid,
1871*4882a593Smuzhiyun 				PMKID_LEN, PMKID_LEN);
1872*4882a593Smuzhiyun 	}
1873*4882a593Smuzhiyun 
1874*4882a593Smuzhiyun 	/** Check if current roaming is going and received target pmkid */
1875*4882a593Smuzhiyun 	if (priv->wait_target_ap_pmkid) {
1876*4882a593Smuzhiyun 		struct cfg80211_connect_params *param = &priv->sme_current;
1877*4882a593Smuzhiyun 
1878*4882a593Smuzhiyun 		if (param && !memcmp(pmksa->bssid, param->bssid, ETH_ALEN)) {
1879*4882a593Smuzhiyun 			PRINTM(MIOCTL,
1880*4882a593Smuzhiyun 			       "Current roaming target bssid=" MACSTR "\n",
1881*4882a593Smuzhiyun 			       MAC2STR(param->bssid));
1882*4882a593Smuzhiyun 			priv->target_ap_pmksa = entry;
1883*4882a593Smuzhiyun 			priv->wait_target_ap_pmkid = MFALSE;
1884*4882a593Smuzhiyun 			wake_up_interruptible(&priv->okc_wait_q);
1885*4882a593Smuzhiyun 		}
1886*4882a593Smuzhiyun 	}
1887*4882a593Smuzhiyun 
1888*4882a593Smuzhiyun done:
1889*4882a593Smuzhiyun 	LEAVE();
1890*4882a593Smuzhiyun 	return ret;
1891*4882a593Smuzhiyun }
1892*4882a593Smuzhiyun 
1893*4882a593Smuzhiyun /**
1894*4882a593Smuzhiyun  *  This function delete pmksa entry
1895*4882a593Smuzhiyun  *  @param wiphy        A pointer to struct wiphy
1896*4882a593Smuzhiyun  *  @param dev          A pointer to net_device structure
1897*4882a593Smuzhiyun  *  @param pmksa        A pointer to cfg80211_pmksa structure
1898*4882a593Smuzhiyun  *  @return             success of failure
1899*4882a593Smuzhiyun  */
woal_cfg80211_del_pmksa(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_pmksa * pmksa)1900*4882a593Smuzhiyun int woal_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
1901*4882a593Smuzhiyun 			    struct cfg80211_pmksa *pmksa)
1902*4882a593Smuzhiyun {
1903*4882a593Smuzhiyun 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
1904*4882a593Smuzhiyun 	struct pmksa_entry *entry, *tmp;
1905*4882a593Smuzhiyun 	unsigned long flags;
1906*4882a593Smuzhiyun 
1907*4882a593Smuzhiyun 	ENTER();
1908*4882a593Smuzhiyun 
1909*4882a593Smuzhiyun 	if (!priv || priv->bss_type != MLAN_BSS_TYPE_STA) {
1910*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid interface structure\n");
1911*4882a593Smuzhiyun 		LEAVE();
1912*4882a593Smuzhiyun 		return -1;
1913*4882a593Smuzhiyun 	}
1914*4882a593Smuzhiyun 
1915*4882a593Smuzhiyun 	PRINTM(MIOCTL, "Delete pmksa: bssid=" MACSTR "\n",
1916*4882a593Smuzhiyun 	       MAC2STR(pmksa->bssid));
1917*4882a593Smuzhiyun 	spin_lock_irqsave(&priv->pmksa_list_lock, flags);
1918*4882a593Smuzhiyun 	list_for_each_entry_safe (entry, tmp, &priv->pmksa_cache_list, link) {
1919*4882a593Smuzhiyun 		if (!memcmp(entry->bssid, pmksa->bssid, ETH_ALEN)) {
1920*4882a593Smuzhiyun 			list_del(&entry->link);
1921*4882a593Smuzhiyun 			kfree(entry);
1922*4882a593Smuzhiyun 		}
1923*4882a593Smuzhiyun 	}
1924*4882a593Smuzhiyun 	spin_unlock_irqrestore(&priv->pmksa_list_lock, flags);
1925*4882a593Smuzhiyun 
1926*4882a593Smuzhiyun 	LEAVE();
1927*4882a593Smuzhiyun 	return 0;
1928*4882a593Smuzhiyun }
1929*4882a593Smuzhiyun 
1930*4882a593Smuzhiyun /**
1931*4882a593Smuzhiyun  *  This function flush pmksa entry list
1932*4882a593Smuzhiyun  *  @param wiphy        A pointer to struct wiphy
1933*4882a593Smuzhiyun  *  @param dev          A pointer to net_device structure
1934*4882a593Smuzhiyun  *  @return             success of failure
1935*4882a593Smuzhiyun  */
woal_cfg80211_flush_pmksa(struct wiphy * wiphy,struct net_device * dev)1936*4882a593Smuzhiyun int woal_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
1937*4882a593Smuzhiyun {
1938*4882a593Smuzhiyun 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
1939*4882a593Smuzhiyun 
1940*4882a593Smuzhiyun 	if (!priv || priv->bss_type != MLAN_BSS_TYPE_STA)
1941*4882a593Smuzhiyun 		return -1;
1942*4882a593Smuzhiyun 
1943*4882a593Smuzhiyun 	PRINTM(MIOCTL, "Flush pmksa list.\n");
1944*4882a593Smuzhiyun 	return woal_flush_pmksa_list(priv);
1945*4882a593Smuzhiyun }
1946*4882a593Smuzhiyun #endif
1947*4882a593Smuzhiyun 
1948*4882a593Smuzhiyun #if KERNEL_VERSION(3, 5, 0) > CFG80211_VERSION_CODE
1949*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 34) < CFG80211_VERSION_CODE
1950*4882a593Smuzhiyun /**
1951*4882a593Smuzhiyun  * @brief Request the driver to change the channel
1952*4882a593Smuzhiyun  *
1953*4882a593Smuzhiyun  * @param wiphy           A pointer to wiphy structure
1954*4882a593Smuzhiyun  * @param dev             A pointer to net_device structure
1955*4882a593Smuzhiyun  * @param chan            A pointer to ieee80211_channel structure
1956*4882a593Smuzhiyun  * @param channel_type    Channel type of nl80211_channel_type
1957*4882a593Smuzhiyun  *
1958*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
1959*4882a593Smuzhiyun  */
1960*4882a593Smuzhiyun #else
1961*4882a593Smuzhiyun /**
1962*4882a593Smuzhiyun  * @brief Request the driver to change the channel
1963*4882a593Smuzhiyun  *
1964*4882a593Smuzhiyun  * @param wiphy           A pointer to wiphy structure
1965*4882a593Smuzhiyun  * @param chan            A pointer to ieee80211_channel structure
1966*4882a593Smuzhiyun  * @param channel_type    Channel type of nl80211_channel_type
1967*4882a593Smuzhiyun  *
1968*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
1969*4882a593Smuzhiyun  */
1970*4882a593Smuzhiyun #endif
woal_cfg80211_set_channel(struct wiphy * wiphy,struct net_device * dev,struct ieee80211_channel * chan,enum nl80211_channel_type channel_type)1971*4882a593Smuzhiyun int woal_cfg80211_set_channel(struct wiphy *wiphy,
1972*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 34) < CFG80211_VERSION_CODE
1973*4882a593Smuzhiyun 			      struct net_device *dev,
1974*4882a593Smuzhiyun #endif
1975*4882a593Smuzhiyun 			      struct ieee80211_channel *chan,
1976*4882a593Smuzhiyun 			      enum nl80211_channel_type channel_type)
1977*4882a593Smuzhiyun {
1978*4882a593Smuzhiyun 	int ret = 0;
1979*4882a593Smuzhiyun 	moal_private *priv = NULL;
1980*4882a593Smuzhiyun 
1981*4882a593Smuzhiyun 	ENTER();
1982*4882a593Smuzhiyun 
1983*4882a593Smuzhiyun #if KERNEL_VERSION(3, 5, 0) > CFG80211_VERSION_CODE
1984*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 34) < CFG80211_VERSION_CODE
1985*4882a593Smuzhiyun 	if (dev)
1986*4882a593Smuzhiyun 		priv = woal_get_netdev_priv(dev);
1987*4882a593Smuzhiyun #endif
1988*4882a593Smuzhiyun #endif
1989*4882a593Smuzhiyun 	if (!priv) {
1990*4882a593Smuzhiyun 		moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
1991*4882a593Smuzhiyun 
1992*4882a593Smuzhiyun 		if (handle)
1993*4882a593Smuzhiyun 			priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
1994*4882a593Smuzhiyun 	}
1995*4882a593Smuzhiyun 	if (priv) {
1996*4882a593Smuzhiyun #ifdef STA_CFG80211
1997*4882a593Smuzhiyun #ifdef STA_SUPPORT
1998*4882a593Smuzhiyun 		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
1999*4882a593Smuzhiyun 			if (priv->media_connected == MTRUE) {
2000*4882a593Smuzhiyun 				PRINTM(MERROR,
2001*4882a593Smuzhiyun 				       "This configuration is valid only when station is not connected\n");
2002*4882a593Smuzhiyun 				LEAVE();
2003*4882a593Smuzhiyun 				return -EINVAL;
2004*4882a593Smuzhiyun 			}
2005*4882a593Smuzhiyun 			ret = woal_set_rf_channel(priv, chan, channel_type,
2006*4882a593Smuzhiyun 						  MOAL_IOCTL_WAIT);
2007*4882a593Smuzhiyun 		}
2008*4882a593Smuzhiyun #endif
2009*4882a593Smuzhiyun #endif
2010*4882a593Smuzhiyun 		priv->channel =
2011*4882a593Smuzhiyun 			ieee80211_frequency_to_channel(chan->center_freq);
2012*4882a593Smuzhiyun 	}
2013*4882a593Smuzhiyun 	/* set monitor channel support */
2014*4882a593Smuzhiyun 
2015*4882a593Smuzhiyun 	LEAVE();
2016*4882a593Smuzhiyun 	return ret;
2017*4882a593Smuzhiyun }
2018*4882a593Smuzhiyun #endif
2019*4882a593Smuzhiyun 
2020*4882a593Smuzhiyun #if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE
woal_is_pattern_supported(struct cfg80211_pkt_pattern * pat,t_u8 * byte_seq,t_u8 max_byte_seq)2021*4882a593Smuzhiyun static bool woal_is_pattern_supported(struct cfg80211_pkt_pattern *pat,
2022*4882a593Smuzhiyun 				      t_u8 *byte_seq, t_u8 max_byte_seq)
2023*4882a593Smuzhiyun {
2024*4882a593Smuzhiyun 	int j, k, valid_byte_cnt = 0;
2025*4882a593Smuzhiyun 	bool dont_care_byte = false;
2026*4882a593Smuzhiyun 
2027*4882a593Smuzhiyun 	for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) {
2028*4882a593Smuzhiyun 		for (k = 0; k < 8; k++) {
2029*4882a593Smuzhiyun 			if (pat->mask[j] & 1 << k) {
2030*4882a593Smuzhiyun 				moal_memcpy_ext(NULL, byte_seq + valid_byte_cnt,
2031*4882a593Smuzhiyun 						&pat->pattern[j * 8 + k], 1,
2032*4882a593Smuzhiyun 						(t_u32)max_byte_seq -
2033*4882a593Smuzhiyun 							(t_u32)valid_byte_cnt);
2034*4882a593Smuzhiyun 				valid_byte_cnt++;
2035*4882a593Smuzhiyun 				if (dont_care_byte)
2036*4882a593Smuzhiyun 					return false;
2037*4882a593Smuzhiyun 			} else {
2038*4882a593Smuzhiyun 				if (valid_byte_cnt)
2039*4882a593Smuzhiyun 					dont_care_byte = true;
2040*4882a593Smuzhiyun 			}
2041*4882a593Smuzhiyun 
2042*4882a593Smuzhiyun 			if (valid_byte_cnt > max_byte_seq)
2043*4882a593Smuzhiyun 				return false;
2044*4882a593Smuzhiyun 		}
2045*4882a593Smuzhiyun 	}
2046*4882a593Smuzhiyun 
2047*4882a593Smuzhiyun 	byte_seq[max_byte_seq] = valid_byte_cnt;
2048*4882a593Smuzhiyun 
2049*4882a593Smuzhiyun 	return true;
2050*4882a593Smuzhiyun }
2051*4882a593Smuzhiyun 
woal_get_coalesce_pkt_type(t_u8 * byte_seq)2052*4882a593Smuzhiyun static int woal_get_coalesce_pkt_type(t_u8 *byte_seq)
2053*4882a593Smuzhiyun {
2054*4882a593Smuzhiyun 	const t_u8 ipv4_mc_mac[] = {0x33, 0x33};
2055*4882a593Smuzhiyun 	const t_u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
2056*4882a593Smuzhiyun 	const t_u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff};
2057*4882a593Smuzhiyun 
2058*4882a593Smuzhiyun 	if ((byte_seq[0] & 0x01) && (byte_seq[COALESCE_MAX_BYTESEQ] == 1))
2059*4882a593Smuzhiyun 		return PACKET_TYPE_UNICAST;
2060*4882a593Smuzhiyun 	else if (!memcmp(byte_seq, bc_mac, 4))
2061*4882a593Smuzhiyun 		return PACKET_TYPE_BROADCAST;
2062*4882a593Smuzhiyun 	else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
2063*4882a593Smuzhiyun 		  byte_seq[COALESCE_MAX_BYTESEQ] == 2) ||
2064*4882a593Smuzhiyun 		 (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
2065*4882a593Smuzhiyun 		  byte_seq[COALESCE_MAX_BYTESEQ] == 3))
2066*4882a593Smuzhiyun 		return PACKET_TYPE_MULTICAST;
2067*4882a593Smuzhiyun 
2068*4882a593Smuzhiyun 	return 0;
2069*4882a593Smuzhiyun }
2070*4882a593Smuzhiyun 
woal_fill_coalesce_rule_info(struct cfg80211_coalesce_rules * crule,struct coalesce_rule * mrule)2071*4882a593Smuzhiyun static int woal_fill_coalesce_rule_info(struct cfg80211_coalesce_rules *crule,
2072*4882a593Smuzhiyun 					struct coalesce_rule *mrule)
2073*4882a593Smuzhiyun {
2074*4882a593Smuzhiyun 	t_u8 byte_seq[COALESCE_MAX_BYTESEQ + 1];
2075*4882a593Smuzhiyun 	struct filt_field_param *param;
2076*4882a593Smuzhiyun 	int i;
2077*4882a593Smuzhiyun 
2078*4882a593Smuzhiyun 	mrule->max_coalescing_delay = crule->delay;
2079*4882a593Smuzhiyun 
2080*4882a593Smuzhiyun 	param = mrule->params;
2081*4882a593Smuzhiyun 
2082*4882a593Smuzhiyun 	for (i = 0; i < crule->n_patterns; i++) {
2083*4882a593Smuzhiyun 		memset(byte_seq, 0, sizeof(byte_seq));
2084*4882a593Smuzhiyun 		if (!woal_is_pattern_supported(&crule->patterns[i], byte_seq,
2085*4882a593Smuzhiyun 					       COALESCE_MAX_BYTESEQ)) {
2086*4882a593Smuzhiyun 			PRINTM(MERROR, "Pattern not supported\n");
2087*4882a593Smuzhiyun 			return -EOPNOTSUPP;
2088*4882a593Smuzhiyun 		}
2089*4882a593Smuzhiyun 
2090*4882a593Smuzhiyun 		if (!crule->patterns[i].pkt_offset) {
2091*4882a593Smuzhiyun 			u8 pkt_type;
2092*4882a593Smuzhiyun 
2093*4882a593Smuzhiyun 			pkt_type = woal_get_coalesce_pkt_type(byte_seq);
2094*4882a593Smuzhiyun 			if (pkt_type && mrule->pkt_type) {
2095*4882a593Smuzhiyun 				PRINTM(MERROR,
2096*4882a593Smuzhiyun 				       "Multiple packet types not allowed\n");
2097*4882a593Smuzhiyun 				return -EOPNOTSUPP;
2098*4882a593Smuzhiyun 			} else if (pkt_type) {
2099*4882a593Smuzhiyun 				mrule->pkt_type = pkt_type;
2100*4882a593Smuzhiyun 				continue;
2101*4882a593Smuzhiyun 			}
2102*4882a593Smuzhiyun 		}
2103*4882a593Smuzhiyun 
2104*4882a593Smuzhiyun 		if (crule->condition == NL80211_COALESCE_CONDITION_MATCH)
2105*4882a593Smuzhiyun 			param->operation = RECV_FILTER_MATCH_TYPE_EQ;
2106*4882a593Smuzhiyun 		else
2107*4882a593Smuzhiyun 			param->operation = RECV_FILTER_MATCH_TYPE_NE;
2108*4882a593Smuzhiyun 
2109*4882a593Smuzhiyun 		param->operand_len = byte_seq[COALESCE_MAX_BYTESEQ];
2110*4882a593Smuzhiyun 		moal_memcpy_ext(NULL, param->operand_byte_stream, byte_seq,
2111*4882a593Smuzhiyun 				param->operand_len, COALESCE_MAX_BYTESEQ);
2112*4882a593Smuzhiyun 		param->offset = crule->patterns[i].pkt_offset;
2113*4882a593Smuzhiyun 		param++;
2114*4882a593Smuzhiyun 
2115*4882a593Smuzhiyun 		mrule->num_of_fields++;
2116*4882a593Smuzhiyun 	}
2117*4882a593Smuzhiyun 
2118*4882a593Smuzhiyun 	if (!mrule->pkt_type) {
2119*4882a593Smuzhiyun 		PRINTM(MERROR, "Packet type can not be determined\n");
2120*4882a593Smuzhiyun 		return -EOPNOTSUPP;
2121*4882a593Smuzhiyun 	}
2122*4882a593Smuzhiyun 
2123*4882a593Smuzhiyun 	return 0;
2124*4882a593Smuzhiyun }
2125*4882a593Smuzhiyun 
2126*4882a593Smuzhiyun /**
2127*4882a593Smuzhiyun  *  @brief Set coalesce parameter
2128*4882a593Smuzhiyun  *
2129*4882a593Smuzhiyun  *  @param priv             A pointer to moal_private structure
2130*4882a593Smuzhiyun  *  @param action           MLAN_ACT_SET or MLAN_ACT_GET
2131*4882a593Smuzhiyun  *  @param coalesce_cfg     A pointer to coalesce structure
2132*4882a593Smuzhiyun  *
2133*4882a593Smuzhiyun  *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2134*4882a593Smuzhiyun  */
woal_set_coalesce(moal_private * priv,t_u16 action,mlan_ds_coalesce_cfg * coalesce_cfg)2135*4882a593Smuzhiyun static mlan_status woal_set_coalesce(moal_private *priv, t_u16 action,
2136*4882a593Smuzhiyun 				     mlan_ds_coalesce_cfg *coalesce_cfg)
2137*4882a593Smuzhiyun {
2138*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2139*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc_cfg = NULL;
2140*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
2141*4882a593Smuzhiyun 
2142*4882a593Smuzhiyun 	ENTER();
2143*4882a593Smuzhiyun 
2144*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2145*4882a593Smuzhiyun 	if (req == NULL) {
2146*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
2147*4882a593Smuzhiyun 		goto done;
2148*4882a593Smuzhiyun 	}
2149*4882a593Smuzhiyun 
2150*4882a593Smuzhiyun 	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
2151*4882a593Smuzhiyun 	misc_cfg->sub_command = MLAN_OID_MISC_COALESCE_CFG;
2152*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_MISC_CFG;
2153*4882a593Smuzhiyun 	req->action = action;
2154*4882a593Smuzhiyun 
2155*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle, &misc_cfg->param.coalesce_cfg,
2156*4882a593Smuzhiyun 			coalesce_cfg, sizeof(mlan_ds_coalesce_cfg),
2157*4882a593Smuzhiyun 			sizeof(mlan_ds_coalesce_cfg));
2158*4882a593Smuzhiyun 
2159*4882a593Smuzhiyun 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2160*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS)
2161*4882a593Smuzhiyun 		goto done;
2162*4882a593Smuzhiyun 
2163*4882a593Smuzhiyun done:
2164*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_PENDING)
2165*4882a593Smuzhiyun 		kfree(req);
2166*4882a593Smuzhiyun 	LEAVE();
2167*4882a593Smuzhiyun 	return ret;
2168*4882a593Smuzhiyun }
2169*4882a593Smuzhiyun 
2170*4882a593Smuzhiyun /**
2171*4882a593Smuzhiyun  * @brief Request the driver to set the coalesce
2172*4882a593Smuzhiyun  *
2173*4882a593Smuzhiyun  * @param wiphy           A pointer to wiphy structure
2174*4882a593Smuzhiyun  * @param coalesce        A pointer to cfg80211_coalesce structure
2175*4882a593Smuzhiyun  *
2176*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
2177*4882a593Smuzhiyun  */
woal_cfg80211_set_coalesce(struct wiphy * wiphy,struct cfg80211_coalesce * coalesce)2178*4882a593Smuzhiyun int woal_cfg80211_set_coalesce(struct wiphy *wiphy,
2179*4882a593Smuzhiyun 			       struct cfg80211_coalesce *coalesce)
2180*4882a593Smuzhiyun {
2181*4882a593Smuzhiyun 	int ret = 0;
2182*4882a593Smuzhiyun 	int i;
2183*4882a593Smuzhiyun 	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
2184*4882a593Smuzhiyun 	moal_private *priv = NULL;
2185*4882a593Smuzhiyun 	mlan_ds_coalesce_cfg coalesce_cfg;
2186*4882a593Smuzhiyun 
2187*4882a593Smuzhiyun 	ENTER();
2188*4882a593Smuzhiyun 
2189*4882a593Smuzhiyun 	if (!handle) {
2190*4882a593Smuzhiyun 		PRINTM(MFATAL, "Unable to get handle\n");
2191*4882a593Smuzhiyun 		ret = -EINVAL;
2192*4882a593Smuzhiyun 		goto done;
2193*4882a593Smuzhiyun 	}
2194*4882a593Smuzhiyun 	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
2195*4882a593Smuzhiyun 	if (!priv) {
2196*4882a593Smuzhiyun 		ret = -EINVAL;
2197*4882a593Smuzhiyun 		goto done;
2198*4882a593Smuzhiyun 	}
2199*4882a593Smuzhiyun 
2200*4882a593Smuzhiyun 	memset(&coalesce_cfg, 0, sizeof(coalesce_cfg));
2201*4882a593Smuzhiyun 	if (!coalesce) {
2202*4882a593Smuzhiyun 		PRINTM(MMSG, "Disable coalesce and reset all previous rules\n");
2203*4882a593Smuzhiyun 	} else {
2204*4882a593Smuzhiyun 		coalesce_cfg.num_of_rules = coalesce->n_rules;
2205*4882a593Smuzhiyun 		for (i = 0; i < coalesce->n_rules; i++) {
2206*4882a593Smuzhiyun 			ret = woal_fill_coalesce_rule_info(
2207*4882a593Smuzhiyun 				&coalesce->rules[i], &coalesce_cfg.rule[i]);
2208*4882a593Smuzhiyun 			if (ret) {
2209*4882a593Smuzhiyun 				PRINTM(MERROR,
2210*4882a593Smuzhiyun 				       "Recheck the patterns provided for rule %d\n",
2211*4882a593Smuzhiyun 				       i + 1);
2212*4882a593Smuzhiyun 				return ret;
2213*4882a593Smuzhiyun 			}
2214*4882a593Smuzhiyun 		}
2215*4882a593Smuzhiyun 	}
2216*4882a593Smuzhiyun 
2217*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
2218*4882a593Smuzhiyun 	    woal_set_coalesce(priv, MLAN_ACT_SET, &coalesce_cfg)) {
2219*4882a593Smuzhiyun 		PRINTM(MERROR, "wlan: Fail to set coalesce\n");
2220*4882a593Smuzhiyun 		ret = -EFAULT;
2221*4882a593Smuzhiyun 	}
2222*4882a593Smuzhiyun 
2223*4882a593Smuzhiyun done:
2224*4882a593Smuzhiyun 	LEAVE();
2225*4882a593Smuzhiyun 	return ret;
2226*4882a593Smuzhiyun }
2227*4882a593Smuzhiyun #endif
2228*4882a593Smuzhiyun 
2229*4882a593Smuzhiyun /**
2230*4882a593Smuzhiyun  * @brief Request the driver to set the bitrate
2231*4882a593Smuzhiyun  *
2232*4882a593Smuzhiyun  * @param wiphy           A pointer to wiphy structure
2233*4882a593Smuzhiyun  * @param dev             A pointer to net_device structure
2234*4882a593Smuzhiyun  * @param peer            A pointer to peer address
2235*4882a593Smuzhiyun  * @param mask            A pointer to cfg80211_bitrate_mask structure
2236*4882a593Smuzhiyun  *
2237*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
2238*4882a593Smuzhiyun  */
woal_cfg80211_set_bitrate_mask(struct wiphy * wiphy,struct net_device * dev,unsigned int link_id,const u8 * peer,const struct cfg80211_bitrate_mask * mask)2239*4882a593Smuzhiyun int woal_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
2240*4882a593Smuzhiyun #if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13)
2241*4882a593Smuzhiyun 				   unsigned int link_id,
2242*4882a593Smuzhiyun #endif
2243*4882a593Smuzhiyun 				   const u8 *peer,
2244*4882a593Smuzhiyun 				   const struct cfg80211_bitrate_mask *mask)
2245*4882a593Smuzhiyun {
2246*4882a593Smuzhiyun 	int ret = 0;
2247*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
2248*4882a593Smuzhiyun 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2249*4882a593Smuzhiyun 	mlan_bss_info bss_info;
2250*4882a593Smuzhiyun 	enum ieee80211_band band;
2251*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
2252*4882a593Smuzhiyun 	mlan_ds_rate *rate = NULL;
2253*4882a593Smuzhiyun 	mlan_rate_cfg_t *rate_cfg = NULL;
2254*4882a593Smuzhiyun 
2255*4882a593Smuzhiyun 	ENTER();
2256*4882a593Smuzhiyun 
2257*4882a593Smuzhiyun 	if (priv->media_connected == MFALSE) {
2258*4882a593Smuzhiyun 		PRINTM(MERROR, "Can not set data rate in disconnected state\n");
2259*4882a593Smuzhiyun 		ret = -EINVAL;
2260*4882a593Smuzhiyun 		goto done;
2261*4882a593Smuzhiyun 	}
2262*4882a593Smuzhiyun 
2263*4882a593Smuzhiyun 	status = woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
2264*4882a593Smuzhiyun 	if (status)
2265*4882a593Smuzhiyun 		goto done;
2266*4882a593Smuzhiyun 	band = woal_band_cfg_to_ieee_band(bss_info.bss_band);
2267*4882a593Smuzhiyun 
2268*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
2269*4882a593Smuzhiyun 	if (req == NULL) {
2270*4882a593Smuzhiyun 		ret = -ENOMEM;
2271*4882a593Smuzhiyun 		goto done;
2272*4882a593Smuzhiyun 	}
2273*4882a593Smuzhiyun 	rate = (mlan_ds_rate *)req->pbuf;
2274*4882a593Smuzhiyun 	rate_cfg = &rate->param.rate_cfg;
2275*4882a593Smuzhiyun 	rate->sub_command = MLAN_OID_RATE_CFG;
2276*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_RATE;
2277*4882a593Smuzhiyun 	req->action = MLAN_ACT_SET;
2278*4882a593Smuzhiyun 	rate_cfg->rate_type = MLAN_RATE_BITMAP;
2279*4882a593Smuzhiyun 
2280*4882a593Smuzhiyun 	/* Fill HR/DSSS rates. */
2281*4882a593Smuzhiyun 	if (band == IEEE80211_BAND_2GHZ)
2282*4882a593Smuzhiyun 		rate_cfg->bitmap_rates[0] = mask->control[band].legacy & 0x000f;
2283*4882a593Smuzhiyun 
2284*4882a593Smuzhiyun 	/* Fill OFDM rates */
2285*4882a593Smuzhiyun 	if (band == IEEE80211_BAND_2GHZ)
2286*4882a593Smuzhiyun 		rate_cfg->bitmap_rates[1] =
2287*4882a593Smuzhiyun 			(mask->control[band].legacy & 0x0ff0) >> 4;
2288*4882a593Smuzhiyun 	else
2289*4882a593Smuzhiyun 		rate_cfg->bitmap_rates[1] = mask->control[band].legacy;
2290*4882a593Smuzhiyun 
2291*4882a593Smuzhiyun #if KERNEL_VERSION(3, 4, 0) <= CFG80211_VERSION_CODE
2292*4882a593Smuzhiyun 		/* Fill MCS rates */
2293*4882a593Smuzhiyun #if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
2294*4882a593Smuzhiyun 	rate_cfg->bitmap_rates[2] = mask->control[band].ht_mcs[0];
2295*4882a593Smuzhiyun #else
2296*4882a593Smuzhiyun 	rate_cfg->bitmap_rates[2] = mask->control[band].mcs[0];
2297*4882a593Smuzhiyun #endif
2298*4882a593Smuzhiyun #if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
2299*4882a593Smuzhiyun 	rate_cfg->bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8;
2300*4882a593Smuzhiyun #else
2301*4882a593Smuzhiyun 	rate_cfg->bitmap_rates[2] |= mask->control[band].mcs[1] << 8;
2302*4882a593Smuzhiyun #endif
2303*4882a593Smuzhiyun #endif
2304*4882a593Smuzhiyun 
2305*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2306*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
2307*4882a593Smuzhiyun 		ret = -EFAULT;
2308*4882a593Smuzhiyun 		goto done;
2309*4882a593Smuzhiyun 	}
2310*4882a593Smuzhiyun 
2311*4882a593Smuzhiyun done:
2312*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
2313*4882a593Smuzhiyun 		kfree(req);
2314*4882a593Smuzhiyun 	LEAVE();
2315*4882a593Smuzhiyun 	return ret;
2316*4882a593Smuzhiyun }
2317*4882a593Smuzhiyun 
2318*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 38) <= CFG80211_VERSION_CODE
2319*4882a593Smuzhiyun /**
2320*4882a593Smuzhiyun  * @brief Request the driver to get antenna configuration
2321*4882a593Smuzhiyun  *
2322*4882a593Smuzhiyun  * @param wiphy           A pointer to wiphy structure
2323*4882a593Smuzhiyun  * @param tx_ant          Bitmaps of allowed antennas to use for TX
2324*4882a593Smuzhiyun  * @param rx_ant          Bitmaps of allowed antennas to use for RX
2325*4882a593Smuzhiyun  *
2326*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
2327*4882a593Smuzhiyun  */
woal_cfg80211_get_antenna(struct wiphy * wiphy,u32 * tx_ant,u32 * rx_ant)2328*4882a593Smuzhiyun int woal_cfg80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant)
2329*4882a593Smuzhiyun {
2330*4882a593Smuzhiyun 	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
2331*4882a593Smuzhiyun 	moal_private *priv = NULL;
2332*4882a593Smuzhiyun 	mlan_ds_radio_cfg *radio = NULL;
2333*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
2334*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
2335*4882a593Smuzhiyun 	int ret = 0;
2336*4882a593Smuzhiyun 
2337*4882a593Smuzhiyun 	ENTER();
2338*4882a593Smuzhiyun 
2339*4882a593Smuzhiyun 	if (!handle) {
2340*4882a593Smuzhiyun 		PRINTM(MFATAL, "Unable to get handle\n");
2341*4882a593Smuzhiyun 		ret = -EINVAL;
2342*4882a593Smuzhiyun 		goto done;
2343*4882a593Smuzhiyun 	}
2344*4882a593Smuzhiyun 	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
2345*4882a593Smuzhiyun 	if (!priv) {
2346*4882a593Smuzhiyun 		ret = -EINVAL;
2347*4882a593Smuzhiyun 		goto done;
2348*4882a593Smuzhiyun 	}
2349*4882a593Smuzhiyun 
2350*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
2351*4882a593Smuzhiyun 	if (req == NULL) {
2352*4882a593Smuzhiyun 		ret = -ENOMEM;
2353*4882a593Smuzhiyun 		goto done;
2354*4882a593Smuzhiyun 	}
2355*4882a593Smuzhiyun 
2356*4882a593Smuzhiyun 	radio = (mlan_ds_radio_cfg *)req->pbuf;
2357*4882a593Smuzhiyun 	radio->sub_command = MLAN_OID_ANT_CFG;
2358*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_RADIO_CFG;
2359*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
2360*4882a593Smuzhiyun 
2361*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2362*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
2363*4882a593Smuzhiyun 		ret = -EFAULT;
2364*4882a593Smuzhiyun 		goto done;
2365*4882a593Smuzhiyun 	}
2366*4882a593Smuzhiyun 
2367*4882a593Smuzhiyun 	if (handle->feature_control & FEATURE_CTRL_STREAM_2X2) {
2368*4882a593Smuzhiyun 		*tx_ant = radio->param.ant_cfg.tx_antenna;
2369*4882a593Smuzhiyun 		*rx_ant = radio->param.ant_cfg.rx_antenna;
2370*4882a593Smuzhiyun 	} else {
2371*4882a593Smuzhiyun 		*tx_ant = radio->param.ant_cfg_1x1.antenna;
2372*4882a593Smuzhiyun 		*rx_ant = radio->param.ant_cfg_1x1.antenna;
2373*4882a593Smuzhiyun 	}
2374*4882a593Smuzhiyun 
2375*4882a593Smuzhiyun done:
2376*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
2377*4882a593Smuzhiyun 		kfree(req);
2378*4882a593Smuzhiyun 	/* Driver must return -EINVAL to cfg80211 */
2379*4882a593Smuzhiyun 	if (ret)
2380*4882a593Smuzhiyun 		ret = -EINVAL;
2381*4882a593Smuzhiyun 	LEAVE();
2382*4882a593Smuzhiyun 	return ret;
2383*4882a593Smuzhiyun }
2384*4882a593Smuzhiyun 
2385*4882a593Smuzhiyun /**
2386*4882a593Smuzhiyun  * @brief Request the driver to set antenna configuration
2387*4882a593Smuzhiyun  *
2388*4882a593Smuzhiyun  * @param wiphy           A pointer to wiphy structure
2389*4882a593Smuzhiyun  * @param tx_ant          Bitmaps of allowed antennas to use for TX
2390*4882a593Smuzhiyun  * @param rx_ant          Bitmaps of allowed antennas to use for RX
2391*4882a593Smuzhiyun  *
2392*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
2393*4882a593Smuzhiyun  */
woal_cfg80211_set_antenna(struct wiphy * wiphy,u32 tx_ant,u32 rx_ant)2394*4882a593Smuzhiyun int woal_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
2395*4882a593Smuzhiyun {
2396*4882a593Smuzhiyun 	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
2397*4882a593Smuzhiyun 	moal_private *priv = NULL;
2398*4882a593Smuzhiyun 	mlan_ds_radio_cfg *radio = NULL;
2399*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
2400*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
2401*4882a593Smuzhiyun 	int ret = 0;
2402*4882a593Smuzhiyun 
2403*4882a593Smuzhiyun 	ENTER();
2404*4882a593Smuzhiyun 
2405*4882a593Smuzhiyun 	if (!handle) {
2406*4882a593Smuzhiyun 		PRINTM(MFATAL, "Unable to get handle\n");
2407*4882a593Smuzhiyun 		ret = -EINVAL;
2408*4882a593Smuzhiyun 		goto done;
2409*4882a593Smuzhiyun 	}
2410*4882a593Smuzhiyun 	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
2411*4882a593Smuzhiyun 	if (!priv) {
2412*4882a593Smuzhiyun 		ret = -EINVAL;
2413*4882a593Smuzhiyun 		goto done;
2414*4882a593Smuzhiyun 	}
2415*4882a593Smuzhiyun 
2416*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
2417*4882a593Smuzhiyun 	if (req == NULL) {
2418*4882a593Smuzhiyun 		ret = -ENOMEM;
2419*4882a593Smuzhiyun 		goto done;
2420*4882a593Smuzhiyun 	}
2421*4882a593Smuzhiyun 	radio = (mlan_ds_radio_cfg *)req->pbuf;
2422*4882a593Smuzhiyun 	radio->sub_command = MLAN_OID_ANT_CFG;
2423*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_RADIO_CFG;
2424*4882a593Smuzhiyun 	req->action = MLAN_ACT_SET;
2425*4882a593Smuzhiyun 	if (handle->feature_control & FEATURE_CTRL_STREAM_2X2) {
2426*4882a593Smuzhiyun 		radio->param.ant_cfg.tx_antenna = tx_ant;
2427*4882a593Smuzhiyun 		radio->param.ant_cfg.rx_antenna = rx_ant;
2428*4882a593Smuzhiyun 	} else {
2429*4882a593Smuzhiyun 		radio->param.ant_cfg_1x1.antenna = tx_ant;
2430*4882a593Smuzhiyun 	}
2431*4882a593Smuzhiyun 
2432*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2433*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
2434*4882a593Smuzhiyun 		ret = -EFAULT;
2435*4882a593Smuzhiyun 		goto done;
2436*4882a593Smuzhiyun 	}
2437*4882a593Smuzhiyun 
2438*4882a593Smuzhiyun done:
2439*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
2440*4882a593Smuzhiyun 		kfree(req);
2441*4882a593Smuzhiyun 	/* Driver must return -EINVAL to cfg80211 */
2442*4882a593Smuzhiyun 	if (ret)
2443*4882a593Smuzhiyun 		ret = -EINVAL;
2444*4882a593Smuzhiyun 	LEAVE();
2445*4882a593Smuzhiyun 	return ret;
2446*4882a593Smuzhiyun }
2447*4882a593Smuzhiyun #endif
2448*4882a593Smuzhiyun /**
2449*4882a593Smuzhiyun  * @brief register/unregister mgmt frame forwarding
2450*4882a593Smuzhiyun  *
2451*4882a593Smuzhiyun  * @param priv             A pointer to moal_private structure
2452*4882a593Smuzhiyun  * @param frame_type      Bit mask for mgmt frame type
2453*4882a593Smuzhiyun  * @param reg             Register or unregister
2454*4882a593Smuzhiyun  *
2455*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
2456*4882a593Smuzhiyun  */
woal_mgmt_frame_register(moal_private * priv,u16 frame_type,bool reg)2457*4882a593Smuzhiyun void woal_mgmt_frame_register(moal_private *priv, u16 frame_type, bool reg)
2458*4882a593Smuzhiyun {
2459*4882a593Smuzhiyun 	t_u32 mgmt_subtype_mask = 0x0;
2460*4882a593Smuzhiyun 	t_u32 last_mgmt_subtype_mask = priv->mgmt_subtype_mask;
2461*4882a593Smuzhiyun 
2462*4882a593Smuzhiyun 	ENTER();
2463*4882a593Smuzhiyun 
2464*4882a593Smuzhiyun #ifdef SDIO_SUSPEND_RESUME
2465*4882a593Smuzhiyun 	if (priv->phandle->shutdown_hs_in_process) {
2466*4882a593Smuzhiyun 		LEAVE();
2467*4882a593Smuzhiyun 		return;
2468*4882a593Smuzhiyun 	}
2469*4882a593Smuzhiyun #endif
2470*4882a593Smuzhiyun 
2471*4882a593Smuzhiyun 	if (reg == MTRUE) {
2472*4882a593Smuzhiyun 		/* set mgmt_subtype_mask based on origin value */
2473*4882a593Smuzhiyun 		mgmt_subtype_mask =
2474*4882a593Smuzhiyun 			last_mgmt_subtype_mask | BIT(frame_type >> 4);
2475*4882a593Smuzhiyun 	} else {
2476*4882a593Smuzhiyun 		/* clear mgmt_subtype_mask */
2477*4882a593Smuzhiyun 		mgmt_subtype_mask =
2478*4882a593Smuzhiyun 			last_mgmt_subtype_mask & ~BIT(frame_type >> 4);
2479*4882a593Smuzhiyun 	}
2480*4882a593Smuzhiyun 	PRINTM(MIOCTL,
2481*4882a593Smuzhiyun 	       "%s: frame_type=0x%x mgmt_subtype_mask=0x%x last_mgmt_subtype_mask=0x%x\n",
2482*4882a593Smuzhiyun 	       priv->netdev->name, frame_type, mgmt_subtype_mask,
2483*4882a593Smuzhiyun 	       last_mgmt_subtype_mask);
2484*4882a593Smuzhiyun 	if (mgmt_subtype_mask != last_mgmt_subtype_mask) {
2485*4882a593Smuzhiyun 		last_mgmt_subtype_mask = mgmt_subtype_mask;
2486*4882a593Smuzhiyun 		/* Notify driver that a mgmt frame type was registered.
2487*4882a593Smuzhiyun 		 * Note that this callback may not sleep, and cannot run
2488*4882a593Smuzhiyun 		 * concurrently with itself.
2489*4882a593Smuzhiyun 		 */
2490*4882a593Smuzhiyun 		woal_reg_rx_mgmt_ind(priv, MLAN_ACT_SET, &mgmt_subtype_mask,
2491*4882a593Smuzhiyun 				     MOAL_NO_WAIT);
2492*4882a593Smuzhiyun 		priv->mgmt_subtype_mask = last_mgmt_subtype_mask;
2493*4882a593Smuzhiyun 	}
2494*4882a593Smuzhiyun 
2495*4882a593Smuzhiyun 	LEAVE();
2496*4882a593Smuzhiyun }
2497*4882a593Smuzhiyun #if KERNEL_VERSION(3, 6, 0) > CFG80211_VERSION_CODE
2498*4882a593Smuzhiyun /**
2499*4882a593Smuzhiyun  * @brief register/unregister mgmt frame forwarding
2500*4882a593Smuzhiyun  *
2501*4882a593Smuzhiyun  * @param wiphy           A pointer to wiphy structure
2502*4882a593Smuzhiyun  * @param dev             A pointer to net_device structure
2503*4882a593Smuzhiyun  * @param frame_type      Bit mask for mgmt frame type
2504*4882a593Smuzhiyun  * @param reg             Register or unregister
2505*4882a593Smuzhiyun  *
2506*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
2507*4882a593Smuzhiyun  */
woal_cfg80211_mgmt_frame_register(struct wiphy * wiphy,struct net_device * dev,u16 frame_type,bool reg)2508*4882a593Smuzhiyun void woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
2509*4882a593Smuzhiyun 				       struct net_device *dev, u16 frame_type,
2510*4882a593Smuzhiyun 				       bool reg)
2511*4882a593Smuzhiyun #else
2512*4882a593Smuzhiyun #if KERNEL_VERSION(5, 8, 0) <= CFG80211_VERSION_CODE
2513*4882a593Smuzhiyun void woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
2514*4882a593Smuzhiyun 				       struct wireless_dev *wdev,
2515*4882a593Smuzhiyun 				       struct mgmt_frame_regs *upd)
2516*4882a593Smuzhiyun #else
2517*4882a593Smuzhiyun /**
2518*4882a593Smuzhiyun  * @brief register/unregister mgmt frame forwarding
2519*4882a593Smuzhiyun  *
2520*4882a593Smuzhiyun  * @param wiphy           A pointer to wiphy structure
2521*4882a593Smuzhiyun  * @param wdev            A pointer to wireless_dev structure
2522*4882a593Smuzhiyun  * @param frame_type      Bit mask for mgmt frame type
2523*4882a593Smuzhiyun  * @param reg             Register or unregister
2524*4882a593Smuzhiyun  *
2525*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
2526*4882a593Smuzhiyun  */
2527*4882a593Smuzhiyun void woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
2528*4882a593Smuzhiyun 				       struct wireless_dev *wdev,
2529*4882a593Smuzhiyun 				       u16 frame_type, bool reg)
2530*4882a593Smuzhiyun #endif
2531*4882a593Smuzhiyun #endif
2532*4882a593Smuzhiyun {
2533*4882a593Smuzhiyun #if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
2534*4882a593Smuzhiyun 	struct net_device *dev = wdev->netdev;
2535*4882a593Smuzhiyun #endif
2536*4882a593Smuzhiyun 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2537*4882a593Smuzhiyun 
2538*4882a593Smuzhiyun 	ENTER();
2539*4882a593Smuzhiyun 
2540*4882a593Smuzhiyun #if KERNEL_VERSION(5, 8, 0) <= CFG80211_VERSION_CODE
2541*4882a593Smuzhiyun 	if ((upd->interface_stypes & BIT(IEEE80211_STYPE_AUTH >> 4))
2542*4882a593Smuzhiyun 	    /** Supplicant 2.8 always register auth, FW will handle auth when
2543*4882a593Smuzhiyun 	     *  host_mlme=0
2544*4882a593Smuzhiyun 	     */
2545*4882a593Smuzhiyun 	    && !moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
2546*4882a593Smuzhiyun 		upd->interface_stypes &= ~BIT(IEEE80211_STYPE_AUTH >> 4);
2547*4882a593Smuzhiyun 
2548*4882a593Smuzhiyun 	if (priv->mgmt_subtype_mask != upd->interface_stypes) {
2549*4882a593Smuzhiyun 		priv->mgmt_subtype_mask = upd->interface_stypes;
2550*4882a593Smuzhiyun 		woal_reg_rx_mgmt_ind(priv, MLAN_ACT_SET, &upd->interface_stypes,
2551*4882a593Smuzhiyun 				     MOAL_NO_WAIT);
2552*4882a593Smuzhiyun 	}
2553*4882a593Smuzhiyun #else
2554*4882a593Smuzhiyun 	if (frame_type == IEEE80211_STYPE_AUTH
2555*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
2556*4882a593Smuzhiyun 	    /** Supplicant 2.8 always register auth, FW will handle auth when
2557*4882a593Smuzhiyun 	     *  host_mlme=0
2558*4882a593Smuzhiyun 	     */
2559*4882a593Smuzhiyun 	    && !moal_extflg_isset(priv->phandle, EXT_HOST_MLME)
2560*4882a593Smuzhiyun #endif
2561*4882a593Smuzhiyun 	) {
2562*4882a593Smuzhiyun 		LEAVE();
2563*4882a593Smuzhiyun 		return;
2564*4882a593Smuzhiyun 	}
2565*4882a593Smuzhiyun 	woal_mgmt_frame_register(priv, frame_type, reg);
2566*4882a593Smuzhiyun #endif
2567*4882a593Smuzhiyun 	LEAVE();
2568*4882a593Smuzhiyun }
2569*4882a593Smuzhiyun 
2570*4882a593Smuzhiyun #ifdef UAP_CFG80211
2571*4882a593Smuzhiyun #if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE
2572*4882a593Smuzhiyun /*
2573*4882a593Smuzhiyun  * @brief  prepare and send WOAL_EVENT_CANCEL_CHANRPT
2574*4882a593Smuzhiyun  *
2575*4882a593Smuzhiyun  * @param priv           A pointer moal_private structure
2576*4882a593Smuzhiyun  *
2577*4882a593Smuzhiyun  * @return          N/A
2578*4882a593Smuzhiyun  */
woal_cancel_chanrpt_event(moal_private * priv)2579*4882a593Smuzhiyun void woal_cancel_chanrpt_event(moal_private *priv)
2580*4882a593Smuzhiyun {
2581*4882a593Smuzhiyun 	struct woal_event *evt;
2582*4882a593Smuzhiyun 	unsigned long flags;
2583*4882a593Smuzhiyun 	moal_handle *handle = priv->phandle;
2584*4882a593Smuzhiyun 
2585*4882a593Smuzhiyun 	evt = kzalloc(sizeof(struct woal_event), GFP_ATOMIC);
2586*4882a593Smuzhiyun 	if (!evt) {
2587*4882a593Smuzhiyun 		PRINTM(MERROR, "Fail to alloc memory for deauth event\n");
2588*4882a593Smuzhiyun 		LEAVE();
2589*4882a593Smuzhiyun 		return;
2590*4882a593Smuzhiyun 	}
2591*4882a593Smuzhiyun 	evt->priv = priv;
2592*4882a593Smuzhiyun 	evt->type = WOAL_EVENT_CANCEL_CHANRPT;
2593*4882a593Smuzhiyun 	INIT_LIST_HEAD(&evt->link);
2594*4882a593Smuzhiyun 	spin_lock_irqsave(&handle->evt_lock, flags);
2595*4882a593Smuzhiyun 	list_add_tail(&evt->link, &handle->evt_queue);
2596*4882a593Smuzhiyun 	spin_unlock_irqrestore(&handle->evt_lock, flags);
2597*4882a593Smuzhiyun 	queue_work(handle->evt_workqueue, &handle->evt_work);
2598*4882a593Smuzhiyun }
2599*4882a593Smuzhiyun #endif
2600*4882a593Smuzhiyun #endif
2601*4882a593Smuzhiyun 
2602*4882a593Smuzhiyun #if KERNEL_VERSION(3, 2, 0) <= CFG80211_VERSION_CODE
2603*4882a593Smuzhiyun #if KERNEL_VERSION(3, 3, 0) <= CFG80211_VERSION_CODE
2604*4882a593Smuzhiyun #if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
2605*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
2606*4882a593Smuzhiyun #if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
2607*4882a593Smuzhiyun /**
2608*4882a593Smuzhiyun  * @brief tx mgmt frame
2609*4882a593Smuzhiyun  *
2610*4882a593Smuzhiyun  * @param wiphy                 A pointer to wiphy structure
2611*4882a593Smuzhiyun  * @param wdev                  A pointer to wireless_dev structure
2612*4882a593Smuzhiyun  * @param params                A pointer to cfg80211_mgmt_tx_params structure
2613*4882a593Smuzhiyun  * @param cookie                A pointer to frame cookie
2614*4882a593Smuzhiyun  *
2615*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
2616*4882a593Smuzhiyun  */
2617*4882a593Smuzhiyun #else
2618*4882a593Smuzhiyun /**
2619*4882a593Smuzhiyun  * @brief tx mgmt frame
2620*4882a593Smuzhiyun  *
2621*4882a593Smuzhiyun  * @param wiphy                 A pointer to wiphy structure
2622*4882a593Smuzhiyun  * @param wdev                  A pointer to wireless_dev structure
2623*4882a593Smuzhiyun  * @param chan                  A pointer to ieee80211_channel structure
2624*4882a593Smuzhiyun  * @param offchan               Off channel or not
2625*4882a593Smuzhiyun  * @param wait                  Duration to wait
2626*4882a593Smuzhiyun  * @param buf                   Frame buffer
2627*4882a593Smuzhiyun  * @param len                   Frame length
2628*4882a593Smuzhiyun  * @param no_cck                No CCK check
2629*4882a593Smuzhiyun  * @param dont_wait_for_ack     Do not wait for ACK
2630*4882a593Smuzhiyun  * @param cookie                A pointer to frame cookie
2631*4882a593Smuzhiyun  *
2632*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
2633*4882a593Smuzhiyun  */
2634*4882a593Smuzhiyun #endif
2635*4882a593Smuzhiyun #else
2636*4882a593Smuzhiyun /**
2637*4882a593Smuzhiyun  * @brief tx mgmt frame
2638*4882a593Smuzhiyun  *
2639*4882a593Smuzhiyun  * @param wiphy                 A pointer to wiphy structure
2640*4882a593Smuzhiyun  * @param wdev                  A pointer to wireless_dev structure
2641*4882a593Smuzhiyun  * @param chan                  A pointer to ieee80211_channel structure
2642*4882a593Smuzhiyun  * @param offchan               Off channel or not
2643*4882a593Smuzhiyun  * @param channel_type          Channel type
2644*4882a593Smuzhiyun  * @param channel_type_valid    Is channel type valid or not
2645*4882a593Smuzhiyun  * @param wait                  Duration to wait
2646*4882a593Smuzhiyun  * @param buf                   Frame buffer
2647*4882a593Smuzhiyun  * @param len                   Frame length
2648*4882a593Smuzhiyun  * @param no_cck                No CCK check
2649*4882a593Smuzhiyun  * @param dont_wait_for_ack     Do not wait for ACK
2650*4882a593Smuzhiyun  * @param cookie                A pointer to frame cookie
2651*4882a593Smuzhiyun  *
2652*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
2653*4882a593Smuzhiyun  */
2654*4882a593Smuzhiyun #endif
2655*4882a593Smuzhiyun #else
2656*4882a593Smuzhiyun /**
2657*4882a593Smuzhiyun  * @brief tx mgmt frame
2658*4882a593Smuzhiyun  *
2659*4882a593Smuzhiyun  * @param wiphy                 A pointer to wiphy structure
2660*4882a593Smuzhiyun  * @param dev                   A pointer to net_device structure
2661*4882a593Smuzhiyun  * @param chan                  A pointer to ieee80211_channel structure
2662*4882a593Smuzhiyun  * @param offchan               Off channel or not
2663*4882a593Smuzhiyun  * @param channel_type          Channel type
2664*4882a593Smuzhiyun  * @param channel_type_valid    Is channel type valid or not
2665*4882a593Smuzhiyun  * @param wait                  Duration to wait
2666*4882a593Smuzhiyun  * @param buf                   Frame buffer
2667*4882a593Smuzhiyun  * @param len                   Frame length
2668*4882a593Smuzhiyun  * @param no_cck                No CCK check
2669*4882a593Smuzhiyun  * @param dont_wait_for_ack     Do not wait for ACK
2670*4882a593Smuzhiyun  * @param cookie                A pointer to frame cookie
2671*4882a593Smuzhiyun  *
2672*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
2673*4882a593Smuzhiyun  */
2674*4882a593Smuzhiyun #endif
2675*4882a593Smuzhiyun #else
2676*4882a593Smuzhiyun /**
2677*4882a593Smuzhiyun  * @brief tx mgmt frame
2678*4882a593Smuzhiyun  *
2679*4882a593Smuzhiyun  * @param wiphy                 A pointer to wiphy structure
2680*4882a593Smuzhiyun  * @param dev                   A pointer to net_device structure
2681*4882a593Smuzhiyun  * @param chan                  A pointer to ieee80211_channel structure
2682*4882a593Smuzhiyun  * @param offchan               Off channel or not
2683*4882a593Smuzhiyun  * @param channel_type          Channel type
2684*4882a593Smuzhiyun  * @param channel_type_valid    Is channel type valid or not
2685*4882a593Smuzhiyun  * @param wait                  Duration to wait
2686*4882a593Smuzhiyun  * @param buf                   Frame buffer
2687*4882a593Smuzhiyun  * @param len                   Frame length
2688*4882a593Smuzhiyun  * @param no_cck                No CCK check
2689*4882a593Smuzhiyun  * @param cookie                A pointer to frame cookie
2690*4882a593Smuzhiyun  *
2691*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
2692*4882a593Smuzhiyun  */
2693*4882a593Smuzhiyun #endif
2694*4882a593Smuzhiyun #else
2695*4882a593Smuzhiyun /**
2696*4882a593Smuzhiyun  * @brief tx mgmt frame
2697*4882a593Smuzhiyun  *
2698*4882a593Smuzhiyun  * @param wiphy                 A pointer to wiphy structure
2699*4882a593Smuzhiyun  * @param dev                   A pointer to net_device structure
2700*4882a593Smuzhiyun  * @param chan                  A pointer to ieee80211_channel structure
2701*4882a593Smuzhiyun  * @param offchan               Off channel or not
2702*4882a593Smuzhiyun  * @param channel_type          Channel type
2703*4882a593Smuzhiyun  * @param channel_type_valid    Is channel type valid or not
2704*4882a593Smuzhiyun  * @param wait                  Duration to wait
2705*4882a593Smuzhiyun  * @param buf                   Frame buffer
2706*4882a593Smuzhiyun  * @param len                   Frame length
2707*4882a593Smuzhiyun  * @param cookie                A pointer to frame cookie
2708*4882a593Smuzhiyun  *
2709*4882a593Smuzhiyun  * @return                0 -- success, otherwise fail
2710*4882a593Smuzhiyun  */
2711*4882a593Smuzhiyun #endif
woal_cfg80211_mgmt_tx(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_mgmt_tx_params * params,u64 * cookie)2712*4882a593Smuzhiyun int woal_cfg80211_mgmt_tx(struct wiphy *wiphy,
2713*4882a593Smuzhiyun #if KERNEL_VERSION(3, 6, 0) > CFG80211_VERSION_CODE
2714*4882a593Smuzhiyun 			  struct net_device *dev,
2715*4882a593Smuzhiyun #else
2716*4882a593Smuzhiyun 			  struct wireless_dev *wdev,
2717*4882a593Smuzhiyun #endif
2718*4882a593Smuzhiyun #if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
2719*4882a593Smuzhiyun 			  struct cfg80211_mgmt_tx_params *params,
2720*4882a593Smuzhiyun #else
2721*4882a593Smuzhiyun 			  struct ieee80211_channel *chan, bool offchan,
2722*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
2723*4882a593Smuzhiyun 			  enum nl80211_channel_type channel_type,
2724*4882a593Smuzhiyun 			  bool channel_type_valid,
2725*4882a593Smuzhiyun #endif
2726*4882a593Smuzhiyun 			  unsigned int wait, const u8 *buf, size_t len,
2727*4882a593Smuzhiyun #if KERNEL_VERSION(3, 2, 0) <= CFG80211_VERSION_CODE
2728*4882a593Smuzhiyun 			  bool no_cck,
2729*4882a593Smuzhiyun #endif
2730*4882a593Smuzhiyun #if KERNEL_VERSION(3, 3, 0) <= CFG80211_VERSION_CODE
2731*4882a593Smuzhiyun 			  bool dont_wait_for_ack,
2732*4882a593Smuzhiyun #endif
2733*4882a593Smuzhiyun #endif
2734*4882a593Smuzhiyun 			  u64 *cookie)
2735*4882a593Smuzhiyun {
2736*4882a593Smuzhiyun #if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
2737*4882a593Smuzhiyun 	struct net_device *dev = wdev->netdev;
2738*4882a593Smuzhiyun #endif
2739*4882a593Smuzhiyun #if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
2740*4882a593Smuzhiyun 	struct ieee80211_channel *chan = params->chan;
2741*4882a593Smuzhiyun 	unsigned int wait = params->wait;
2742*4882a593Smuzhiyun 	const u8 *buf = params->buf;
2743*4882a593Smuzhiyun 	size_t len = params->len;
2744*4882a593Smuzhiyun #endif
2745*4882a593Smuzhiyun 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2746*4882a593Smuzhiyun 	int ret = 0;
2747*4882a593Smuzhiyun 	pmlan_buffer pmbuf = NULL;
2748*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
2749*4882a593Smuzhiyun 	t_u16 packet_len = 0;
2750*4882a593Smuzhiyun 	t_u8 addr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2751*4882a593Smuzhiyun 	t_u32 pkt_type;
2752*4882a593Smuzhiyun 	t_u32 tx_control;
2753*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 39) <= CFG80211_VERSION_CODE
2754*4882a593Smuzhiyun 	t_u8 channel_status;
2755*4882a593Smuzhiyun 	t_u32 duration;
2756*4882a593Smuzhiyun 	moal_private *remain_priv = NULL;
2757*4882a593Smuzhiyun #endif
2758*4882a593Smuzhiyun 
2759*4882a593Smuzhiyun 	unsigned long flags;
2760*4882a593Smuzhiyun 	struct sk_buff *skb = NULL;
2761*4882a593Smuzhiyun 	struct tx_status_info *tx_info = NULL;
2762*4882a593Smuzhiyun 	t_u32 remain_len = 0;
2763*4882a593Smuzhiyun 	t_u16 fc, type, stype;
2764*4882a593Smuzhiyun 
2765*4882a593Smuzhiyun 	ENTER();
2766*4882a593Smuzhiyun 
2767*4882a593Smuzhiyun 	if (buf == NULL || len == 0) {
2768*4882a593Smuzhiyun 		PRINTM(MERROR, "%s: corrupt data\n", __func__);
2769*4882a593Smuzhiyun 		LEAVE();
2770*4882a593Smuzhiyun 		return -EFAULT;
2771*4882a593Smuzhiyun 	}
2772*4882a593Smuzhiyun 
2773*4882a593Smuzhiyun 	/* If the packet is probe response, that means we are in listen phase,
2774*4882a593Smuzhiyun 	 * so we should not call remain_on_channel_cfg because
2775*4882a593Smuzhiyun 	 * remain_on_channl already handled it. If the packet if action, that
2776*4882a593Smuzhiyun 	 * means we are in PD/GO negotiation, so we should call
2777*4882a593Smuzhiyun 	 * remain_on_channel_cfg in order to receive action frame from peer
2778*4882a593Smuzhiyun 	 * device
2779*4882a593Smuzhiyun 	 */
2780*4882a593Smuzhiyun 	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
2781*4882a593Smuzhiyun 		if (ieee80211_is_probe_resp(
2782*4882a593Smuzhiyun 			    ((struct ieee80211_mgmt *)buf)->frame_control)) {
2783*4882a593Smuzhiyun 			PRINTM(MIOCTL, "Skip send probe_resp in GO/UAP mode\n");
2784*4882a593Smuzhiyun 			goto done;
2785*4882a593Smuzhiyun 		}
2786*4882a593Smuzhiyun 		fc = le16_to_cpu(((struct ieee80211_mgmt *)buf)->frame_control);
2787*4882a593Smuzhiyun 		type = fc & IEEE80211_FCTL_FTYPE;
2788*4882a593Smuzhiyun 		stype = fc & IEEE80211_FCTL_STYPE;
2789*4882a593Smuzhiyun 		if (type == IEEE80211_FTYPE_MGMT) {
2790*4882a593Smuzhiyun 			switch (stype) {
2791*4882a593Smuzhiyun 			case IEEE80211_STYPE_AUTH:
2792*4882a593Smuzhiyun 				PRINTM(MMSG, "wlan: HostMlme %s send Auth\n",
2793*4882a593Smuzhiyun 				       priv->netdev->name);
2794*4882a593Smuzhiyun 				break;
2795*4882a593Smuzhiyun 			case IEEE80211_STYPE_DEAUTH:
2796*4882a593Smuzhiyun 			case IEEE80211_STYPE_DISASSOC:
2797*4882a593Smuzhiyun #ifdef UAP_SUPPORT
2798*4882a593Smuzhiyun 				if (!priv->bss_started) {
2799*4882a593Smuzhiyun 					PRINTM(MCMND,
2800*4882a593Smuzhiyun 					       "Drop deauth packet before AP started\n");
2801*4882a593Smuzhiyun 					woal_cancel_cac(priv);
2802*4882a593Smuzhiyun 					goto done;
2803*4882a593Smuzhiyun 				}
2804*4882a593Smuzhiyun #endif
2805*4882a593Smuzhiyun 				PRINTM(MMSG,
2806*4882a593Smuzhiyun 				       "wlan: HostMlme %s send deauth/disassoc\n",
2807*4882a593Smuzhiyun 				       priv->netdev->name);
2808*4882a593Smuzhiyun 
2809*4882a593Smuzhiyun 				break;
2810*4882a593Smuzhiyun 			case IEEE80211_STYPE_ASSOC_RESP:
2811*4882a593Smuzhiyun 			case IEEE80211_STYPE_REASSOC_RESP:
2812*4882a593Smuzhiyun 				PRINTM(MMSG,
2813*4882a593Smuzhiyun 				       "wlan: HostMlme %s send assoc/reassoc resp\n",
2814*4882a593Smuzhiyun 				       priv->netdev->name);
2815*4882a593Smuzhiyun 				break;
2816*4882a593Smuzhiyun 			default:
2817*4882a593Smuzhiyun 				break;
2818*4882a593Smuzhiyun 			}
2819*4882a593Smuzhiyun 		}
2820*4882a593Smuzhiyun 	}
2821*4882a593Smuzhiyun 
2822*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 39) <= CFG80211_VERSION_CODE
2823*4882a593Smuzhiyun 	if ((ieee80211_is_action(((struct ieee80211_mgmt *)buf)->frame_control))
2824*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
2825*4882a593Smuzhiyun 	    || moal_extflg_isset(priv->phandle, EXT_HOST_MLME)
2826*4882a593Smuzhiyun #endif
2827*4882a593Smuzhiyun 	) {
2828*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
2829*4882a593Smuzhiyun 		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
2830*4882a593Smuzhiyun 			woal_cfg80211_display_p2p_actframe(buf, len, chan,
2831*4882a593Smuzhiyun 							   MTRUE);
2832*4882a593Smuzhiyun 		if (priv->phandle->is_go_timer_set) {
2833*4882a593Smuzhiyun 			woal_cancel_timer(&priv->phandle->go_timer);
2834*4882a593Smuzhiyun 			priv->phandle->is_go_timer_set = MFALSE;
2835*4882a593Smuzhiyun 		}
2836*4882a593Smuzhiyun #endif
2837*4882a593Smuzhiyun 		if (priv->phandle->is_remain_timer_set) {
2838*4882a593Smuzhiyun 			woal_cancel_timer(&priv->phandle->remain_timer);
2839*4882a593Smuzhiyun 			woal_remain_timer_func(priv->phandle);
2840*4882a593Smuzhiyun 		}
2841*4882a593Smuzhiyun 		/* With sd8777 We have difficulty to receive response packet in
2842*4882a593Smuzhiyun 		 * 500ms
2843*4882a593Smuzhiyun 		 */
2844*4882a593Smuzhiyun #define MGMT_TX_DEFAULT_WAIT_TIME 1500
2845*4882a593Smuzhiyun 		if (priv->phandle->remain_on_channel)
2846*4882a593Smuzhiyun 			remain_priv =
2847*4882a593Smuzhiyun 				priv->phandle
2848*4882a593Smuzhiyun 					->priv[priv->phandle->remain_bss_index];
2849*4882a593Smuzhiyun 		/** cancel previous remain on channel */
2850*4882a593Smuzhiyun 		if (priv->phandle->remain_on_channel && remain_priv) {
2851*4882a593Smuzhiyun 			if (woal_cfg80211_remain_on_channel_cfg(
2852*4882a593Smuzhiyun 				    remain_priv, MOAL_IOCTL_WAIT, MTRUE,
2853*4882a593Smuzhiyun 				    &channel_status, NULL, 0, 0))
2854*4882a593Smuzhiyun 				PRINTM(MERROR,
2855*4882a593Smuzhiyun 				       "mgmt_tx:Fail to cancel remain on channel\n");
2856*4882a593Smuzhiyun 			if (priv->phandle->cookie) {
2857*4882a593Smuzhiyun 				cfg80211_remain_on_channel_expired(
2858*4882a593Smuzhiyun #if KERNEL_VERSION(3, 6, 0) > CFG80211_VERSION_CODE
2859*4882a593Smuzhiyun 					remain_priv->netdev,
2860*4882a593Smuzhiyun #else
2861*4882a593Smuzhiyun 					remain_priv->wdev,
2862*4882a593Smuzhiyun #endif
2863*4882a593Smuzhiyun 					priv->phandle->cookie,
2864*4882a593Smuzhiyun 					&priv->phandle->chan,
2865*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
2866*4882a593Smuzhiyun 					priv->phandle->channel_type,
2867*4882a593Smuzhiyun #endif
2868*4882a593Smuzhiyun 					GFP_ATOMIC);
2869*4882a593Smuzhiyun 				priv->phandle->cookie = 0;
2870*4882a593Smuzhiyun 			}
2871*4882a593Smuzhiyun 			priv->phandle->remain_on_channel = MFALSE;
2872*4882a593Smuzhiyun 		}
2873*4882a593Smuzhiyun #ifdef STA_CFG80211
2874*4882a593Smuzhiyun 		/** cancel pending scan */
2875*4882a593Smuzhiyun 		woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
2876*4882a593Smuzhiyun #endif
2877*4882a593Smuzhiyun 
2878*4882a593Smuzhiyun 		if (chan && priv->bss_type != MLAN_BSS_ROLE_UAP) {
2879*4882a593Smuzhiyun 			duration = (wait > MGMT_TX_DEFAULT_WAIT_TIME) ?
2880*4882a593Smuzhiyun 					   wait :
2881*4882a593Smuzhiyun 					   MGMT_TX_DEFAULT_WAIT_TIME;
2882*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
2883*4882a593Smuzhiyun 			if (channel_type_valid)
2884*4882a593Smuzhiyun 				ret = woal_cfg80211_remain_on_channel_cfg(
2885*4882a593Smuzhiyun 					priv, MOAL_IOCTL_WAIT, MFALSE,
2886*4882a593Smuzhiyun 					&channel_status, chan, channel_type,
2887*4882a593Smuzhiyun 					duration);
2888*4882a593Smuzhiyun 			else
2889*4882a593Smuzhiyun #endif
2890*4882a593Smuzhiyun 				ret = woal_cfg80211_remain_on_channel_cfg(
2891*4882a593Smuzhiyun 					priv, MOAL_IOCTL_WAIT, MFALSE,
2892*4882a593Smuzhiyun 					&channel_status, chan, 0, duration);
2893*4882a593Smuzhiyun 			if (ret) {
2894*4882a593Smuzhiyun 				/* Return fail will cause p2p connection fail
2895*4882a593Smuzhiyun 				 */
2896*4882a593Smuzhiyun 				woal_sched_timeout(2);
2897*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
2898*4882a593Smuzhiyun 				if (channel_type_valid)
2899*4882a593Smuzhiyun 					ret = woal_cfg80211_remain_on_channel_cfg(
2900*4882a593Smuzhiyun 						priv, MOAL_IOCTL_WAIT, MFALSE,
2901*4882a593Smuzhiyun 						&channel_status, chan,
2902*4882a593Smuzhiyun 						channel_type, duration);
2903*4882a593Smuzhiyun 				else
2904*4882a593Smuzhiyun #endif
2905*4882a593Smuzhiyun 					ret = woal_cfg80211_remain_on_channel_cfg(
2906*4882a593Smuzhiyun 						priv, MOAL_IOCTL_WAIT, MFALSE,
2907*4882a593Smuzhiyun 						&channel_status, chan, 0,
2908*4882a593Smuzhiyun 						duration);
2909*4882a593Smuzhiyun 				PRINTM(MERROR,
2910*4882a593Smuzhiyun 				       "Try configure remain on channel again, ret=%d\n",
2911*4882a593Smuzhiyun 				       ret);
2912*4882a593Smuzhiyun 				ret = 0;
2913*4882a593Smuzhiyun 			} else {
2914*4882a593Smuzhiyun 				priv->phandle->remain_on_channel = MTRUE;
2915*4882a593Smuzhiyun 				priv->phandle->remain_bss_index =
2916*4882a593Smuzhiyun 					priv->bss_index;
2917*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
2918*4882a593Smuzhiyun 				priv->phandle->channel_type = channel_type;
2919*4882a593Smuzhiyun #endif
2920*4882a593Smuzhiyun 				moal_memcpy_ext(
2921*4882a593Smuzhiyun 					priv->phandle, &priv->phandle->chan,
2922*4882a593Smuzhiyun 					chan, sizeof(struct ieee80211_channel),
2923*4882a593Smuzhiyun 					sizeof(struct ieee80211_channel));
2924*4882a593Smuzhiyun 				PRINTM(MIOCTL,
2925*4882a593Smuzhiyun 				       "%s: Mgmt Tx: Set remain channel=%d duration=%d\n",
2926*4882a593Smuzhiyun 				       dev->name,
2927*4882a593Smuzhiyun 				       ieee80211_frequency_to_channel(
2928*4882a593Smuzhiyun 					       chan->center_freq),
2929*4882a593Smuzhiyun 				       duration);
2930*4882a593Smuzhiyun 			}
2931*4882a593Smuzhiyun 		}
2932*4882a593Smuzhiyun 	}
2933*4882a593Smuzhiyun #endif
2934*4882a593Smuzhiyun 
2935*4882a593Smuzhiyun 	/* pkt_type + tx_control */
2936*4882a593Smuzhiyun #define HEADER_SIZE 8
2937*4882a593Smuzhiyun 	packet_len = (t_u16)len + MLAN_MAC_ADDR_LENGTH;
2938*4882a593Smuzhiyun 	pmbuf = woal_alloc_mlan_buffer(priv->phandle,
2939*4882a593Smuzhiyun 				       MLAN_MIN_DATA_HEADER_LEN + HEADER_SIZE +
2940*4882a593Smuzhiyun 					       packet_len + sizeof(packet_len));
2941*4882a593Smuzhiyun 	if (!pmbuf) {
2942*4882a593Smuzhiyun 		PRINTM(MERROR, "Fail to allocate mlan_buffer\n");
2943*4882a593Smuzhiyun 		ret = -ENOMEM;
2944*4882a593Smuzhiyun 		goto done;
2945*4882a593Smuzhiyun 	}
2946*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) > LINUX_VERSION_CODE
2947*4882a593Smuzhiyun 	*cookie = random32() | 1;
2948*4882a593Smuzhiyun #else
2949*4882a593Smuzhiyun #if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE
2950*4882a593Smuzhiyun 	*cookie = prandom_u32() | 1;
2951*4882a593Smuzhiyun #else
2952*4882a593Smuzhiyun 	*cookie = get_random_u32() | 1;
2953*4882a593Smuzhiyun #endif
2954*4882a593Smuzhiyun #endif
2955*4882a593Smuzhiyun 	pmbuf->data_offset = MLAN_MIN_DATA_HEADER_LEN;
2956*4882a593Smuzhiyun 	pkt_type = MRVL_PKT_TYPE_MGMT_FRAME;
2957*4882a593Smuzhiyun 	tx_control = 0;
2958*4882a593Smuzhiyun 	remain_len = HEADER_SIZE + packet_len + sizeof(packet_len);
2959*4882a593Smuzhiyun 	/* Add pkt_type and tx_control */
2960*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle, pmbuf->pbuf + pmbuf->data_offset,
2961*4882a593Smuzhiyun 			&pkt_type, sizeof(pkt_type), remain_len);
2962*4882a593Smuzhiyun 	remain_len -= sizeof(pkt_type);
2963*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle,
2964*4882a593Smuzhiyun 			pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
2965*4882a593Smuzhiyun 			&tx_control, sizeof(tx_control), remain_len);
2966*4882a593Smuzhiyun 	remain_len -= sizeof(tx_control);
2967*4882a593Smuzhiyun 	/* frmctl + durationid + addr1 + addr2 + addr3 + seqctl */
2968*4882a593Smuzhiyun #define PACKET_ADDR4_POS (2 + 2 + 6 + 6 + 6 + 2)
2969*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle,
2970*4882a593Smuzhiyun 			pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE,
2971*4882a593Smuzhiyun 			&packet_len, sizeof(packet_len), remain_len);
2972*4882a593Smuzhiyun 	remain_len -= sizeof(packet_len);
2973*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle,
2974*4882a593Smuzhiyun 			pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE +
2975*4882a593Smuzhiyun 				sizeof(packet_len),
2976*4882a593Smuzhiyun 			buf, PACKET_ADDR4_POS, remain_len);
2977*4882a593Smuzhiyun 	remain_len -= PACKET_ADDR4_POS;
2978*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle,
2979*4882a593Smuzhiyun 			pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE +
2980*4882a593Smuzhiyun 				sizeof(packet_len) + PACKET_ADDR4_POS,
2981*4882a593Smuzhiyun 			addr, MLAN_MAC_ADDR_LENGTH, remain_len);
2982*4882a593Smuzhiyun 	remain_len -= MLAN_MAC_ADDR_LENGTH;
2983*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle,
2984*4882a593Smuzhiyun 			pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE +
2985*4882a593Smuzhiyun 				sizeof(packet_len) + PACKET_ADDR4_POS +
2986*4882a593Smuzhiyun 				MLAN_MAC_ADDR_LENGTH,
2987*4882a593Smuzhiyun 			buf + PACKET_ADDR4_POS, len - PACKET_ADDR4_POS,
2988*4882a593Smuzhiyun 			remain_len);
2989*4882a593Smuzhiyun 
2990*4882a593Smuzhiyun 	pmbuf->data_len = HEADER_SIZE + packet_len + sizeof(packet_len);
2991*4882a593Smuzhiyun 	pmbuf->buf_type = MLAN_BUF_TYPE_RAW_DATA;
2992*4882a593Smuzhiyun 	pmbuf->bss_index = priv->bss_index;
2993*4882a593Smuzhiyun 	if ((ieee80211_is_action(((struct ieee80211_mgmt *)buf)->frame_control))
2994*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
2995*4882a593Smuzhiyun 	    || moal_extflg_isset(priv->phandle, EXT_HOST_MLME)
2996*4882a593Smuzhiyun #endif
2997*4882a593Smuzhiyun 	) {
2998*4882a593Smuzhiyun 		pmbuf->flags = MLAN_BUF_FLAG_TX_STATUS;
2999*4882a593Smuzhiyun 		if (!priv->tx_seq_num)
3000*4882a593Smuzhiyun 			priv->tx_seq_num++;
3001*4882a593Smuzhiyun 		pmbuf->tx_seq_num = priv->tx_seq_num++;
3002*4882a593Smuzhiyun 		tx_info = kzalloc(sizeof(struct tx_status_info), GFP_ATOMIC);
3003*4882a593Smuzhiyun 		if (tx_info) {
3004*4882a593Smuzhiyun 			skb = alloc_skb(len, GFP_ATOMIC);
3005*4882a593Smuzhiyun 			if (skb) {
3006*4882a593Smuzhiyun 				moal_memcpy_ext(priv->phandle, skb->data, buf,
3007*4882a593Smuzhiyun 						len, len);
3008*4882a593Smuzhiyun 				skb_put(skb, len);
3009*4882a593Smuzhiyun 				spin_lock_irqsave(&priv->tx_stat_lock, flags);
3010*4882a593Smuzhiyun 				tx_info->tx_cookie = *cookie;
3011*4882a593Smuzhiyun 				tx_info->tx_skb = skb;
3012*4882a593Smuzhiyun 				tx_info->tx_seq_num = pmbuf->tx_seq_num;
3013*4882a593Smuzhiyun 				if ((priv->bss_role == MLAN_BSS_ROLE_UAP) &&
3014*4882a593Smuzhiyun 				    (priv->phandle->remain_on_channel && !wait))
3015*4882a593Smuzhiyun 					tx_info->cancel_remain_on_channel =
3016*4882a593Smuzhiyun 						MTRUE;
3017*4882a593Smuzhiyun 				INIT_LIST_HEAD(&tx_info->link);
3018*4882a593Smuzhiyun 				list_add_tail(&tx_info->link,
3019*4882a593Smuzhiyun 					      &priv->tx_stat_queue);
3020*4882a593Smuzhiyun 				spin_unlock_irqrestore(&priv->tx_stat_lock,
3021*4882a593Smuzhiyun 						       flags);
3022*4882a593Smuzhiyun 			} else {
3023*4882a593Smuzhiyun 				kfree(tx_info);
3024*4882a593Smuzhiyun 				tx_info = NULL;
3025*4882a593Smuzhiyun 			}
3026*4882a593Smuzhiyun 		}
3027*4882a593Smuzhiyun 	}
3028*4882a593Smuzhiyun 
3029*4882a593Smuzhiyun 	status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
3030*4882a593Smuzhiyun 
3031*4882a593Smuzhiyun 	switch (status) {
3032*4882a593Smuzhiyun 	case MLAN_STATUS_PENDING:
3033*4882a593Smuzhiyun 		atomic_inc(&priv->phandle->tx_pending);
3034*4882a593Smuzhiyun 		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
3035*4882a593Smuzhiyun 
3036*4882a593Smuzhiyun 		/* Delay 30ms to guarantee the packet has been already tx'ed,
3037*4882a593Smuzhiyun 		 * because if we call cfg80211_mgmt_tx_status() immediately,
3038*4882a593Smuzhiyun 		 * then wpa_supplicant will call cancel_remain_on_channel(),
3039*4882a593Smuzhiyun 		 * which may affect the mgmt frame tx. Meanwhile it is only
3040*4882a593Smuzhiyun 		 * necessary for P2P action handshake to wait 30ms.
3041*4882a593Smuzhiyun 		 */
3042*4882a593Smuzhiyun 		if ((ieee80211_is_action(
3043*4882a593Smuzhiyun 			    ((struct ieee80211_mgmt *)buf)->frame_control))
3044*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
3045*4882a593Smuzhiyun 		    || moal_extflg_isset(priv->phandle, EXT_HOST_MLME)
3046*4882a593Smuzhiyun #endif
3047*4882a593Smuzhiyun 		) {
3048*4882a593Smuzhiyun 			if (tx_info)
3049*4882a593Smuzhiyun 				break;
3050*4882a593Smuzhiyun 			else
3051*4882a593Smuzhiyun 				woal_sched_timeout(30);
3052*4882a593Smuzhiyun 		}
3053*4882a593Smuzhiyun 		/* Notify the mgmt tx status */
3054*4882a593Smuzhiyun #if KERNEL_VERSION(2, 6, 37) <= CFG80211_VERSION_CODE
3055*4882a593Smuzhiyun #if KERNEL_VERSION(3, 6, 0) > CFG80211_VERSION_CODE
3056*4882a593Smuzhiyun 		cfg80211_mgmt_tx_status(dev, *cookie, buf, len, true,
3057*4882a593Smuzhiyun 					GFP_ATOMIC);
3058*4882a593Smuzhiyun #else
3059*4882a593Smuzhiyun 		cfg80211_mgmt_tx_status(priv->wdev, *cookie, buf, len, true,
3060*4882a593Smuzhiyun 					GFP_ATOMIC);
3061*4882a593Smuzhiyun #endif
3062*4882a593Smuzhiyun #endif
3063*4882a593Smuzhiyun 		break;
3064*4882a593Smuzhiyun 	case MLAN_STATUS_SUCCESS:
3065*4882a593Smuzhiyun 		woal_free_mlan_buffer(priv->phandle, pmbuf);
3066*4882a593Smuzhiyun 		break;
3067*4882a593Smuzhiyun 	case MLAN_STATUS_FAILURE:
3068*4882a593Smuzhiyun 	default:
3069*4882a593Smuzhiyun 		woal_free_mlan_buffer(priv->phandle, pmbuf);
3070*4882a593Smuzhiyun 		ret = -EFAULT;
3071*4882a593Smuzhiyun 		break;
3072*4882a593Smuzhiyun 	}
3073*4882a593Smuzhiyun 
3074*4882a593Smuzhiyun done:
3075*4882a593Smuzhiyun 
3076*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING) {
3077*4882a593Smuzhiyun 		if (tx_info)
3078*4882a593Smuzhiyun 			woal_remove_tx_info(priv, tx_info->tx_seq_num);
3079*4882a593Smuzhiyun 	}
3080*4882a593Smuzhiyun 
3081*4882a593Smuzhiyun 	LEAVE();
3082*4882a593Smuzhiyun 	return ret;
3083*4882a593Smuzhiyun }
3084*4882a593Smuzhiyun 
3085*4882a593Smuzhiyun /**
3086*4882a593Smuzhiyun  * @brief Add custom ie to mgmt frames.
3087*4882a593Smuzhiyun  *
3088*4882a593Smuzhiyun  * @param priv                  A pointer to moal private structure
3089*4882a593Smuzhiyun  * @param beacon_ies_data       Beacon ie
3090*4882a593Smuzhiyun  * @param beacon_index          The index for beacon when auto index
3091*4882a593Smuzhiyun  * @param proberesp_ies_data    Probe resp ie
3092*4882a593Smuzhiyun  * @param proberesp_index       The index for probe resp when auto index
3093*4882a593Smuzhiyun  * @param assocresp_ies_data    Assoc resp ie
3094*4882a593Smuzhiyun  * @param assocresp_index       The index for assoc resp when auto index
3095*4882a593Smuzhiyun  * @param probereq_ies_data     Probe req ie
3096*4882a593Smuzhiyun  * @param probereq_index        The index for probe req when auto index
3097*4882a593Smuzhiyun  * @param wait_option           wait option
3098*4882a593Smuzhiyun  *
3099*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
3100*4882a593Smuzhiyun  */
3101*4882a593Smuzhiyun static mlan_status
woal_cfg80211_custom_ie(moal_private * priv,custom_ie * beacon_ies_data,t_u16 * beacon_index,custom_ie * proberesp_ies_data,t_u16 * proberesp_index,custom_ie * assocresp_ies_data,t_u16 * assocresp_index,custom_ie * probereq_ies_data,t_u16 * probereq_index,t_u8 wait_option)3102*4882a593Smuzhiyun woal_cfg80211_custom_ie(moal_private *priv, custom_ie *beacon_ies_data,
3103*4882a593Smuzhiyun 			t_u16 *beacon_index, custom_ie *proberesp_ies_data,
3104*4882a593Smuzhiyun 			t_u16 *proberesp_index, custom_ie *assocresp_ies_data,
3105*4882a593Smuzhiyun 			t_u16 *assocresp_index, custom_ie *probereq_ies_data,
3106*4882a593Smuzhiyun 			t_u16 *probereq_index, t_u8 wait_option)
3107*4882a593Smuzhiyun {
3108*4882a593Smuzhiyun 	mlan_ioctl_req *ioctl_req = NULL;
3109*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = NULL;
3110*4882a593Smuzhiyun 	mlan_ds_misc_custom_ie *pcustom_ie = NULL;
3111*4882a593Smuzhiyun 	t_u8 *pos = NULL;
3112*4882a593Smuzhiyun 	t_u16 len = 0;
3113*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
3114*4882a593Smuzhiyun 	t_u32 remain_len = 0;
3115*4882a593Smuzhiyun 
3116*4882a593Smuzhiyun 	ENTER();
3117*4882a593Smuzhiyun 
3118*4882a593Smuzhiyun 	pcustom_ie = kzalloc(sizeof(mlan_ds_misc_custom_ie), GFP_KERNEL);
3119*4882a593Smuzhiyun 	if (!pcustom_ie) {
3120*4882a593Smuzhiyun 		PRINTM(MERROR, "Fail to allocate custome_ie\n");
3121*4882a593Smuzhiyun 		status = MLAN_STATUS_FAILURE;
3122*4882a593Smuzhiyun 		goto done;
3123*4882a593Smuzhiyun 	}
3124*4882a593Smuzhiyun 
3125*4882a593Smuzhiyun 	pcustom_ie->type = TLV_TYPE_MGMT_IE;
3126*4882a593Smuzhiyun 
3127*4882a593Smuzhiyun 	pos = (t_u8 *)pcustom_ie->ie_data_list;
3128*4882a593Smuzhiyun 	remain_len = sizeof(pcustom_ie->ie_data_list);
3129*4882a593Smuzhiyun 	if (beacon_ies_data) {
3130*4882a593Smuzhiyun 		len = sizeof(*beacon_ies_data) - MAX_IE_SIZE +
3131*4882a593Smuzhiyun 		      beacon_ies_data->ie_length;
3132*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, pos, beacon_ies_data, len,
3133*4882a593Smuzhiyun 				remain_len);
3134*4882a593Smuzhiyun 		pos += len;
3135*4882a593Smuzhiyun 		remain_len -= len;
3136*4882a593Smuzhiyun 		pcustom_ie->len += len;
3137*4882a593Smuzhiyun 	}
3138*4882a593Smuzhiyun 
3139*4882a593Smuzhiyun 	if (proberesp_ies_data) {
3140*4882a593Smuzhiyun 		len = sizeof(*proberesp_ies_data) - MAX_IE_SIZE +
3141*4882a593Smuzhiyun 		      proberesp_ies_data->ie_length;
3142*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, pos, proberesp_ies_data, len,
3143*4882a593Smuzhiyun 				remain_len);
3144*4882a593Smuzhiyun 		pos += len;
3145*4882a593Smuzhiyun 		remain_len -= len;
3146*4882a593Smuzhiyun 		pcustom_ie->len += len;
3147*4882a593Smuzhiyun 	}
3148*4882a593Smuzhiyun 
3149*4882a593Smuzhiyun 	if (assocresp_ies_data) {
3150*4882a593Smuzhiyun 		len = sizeof(*assocresp_ies_data) - MAX_IE_SIZE +
3151*4882a593Smuzhiyun 		      assocresp_ies_data->ie_length;
3152*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, pos, assocresp_ies_data, len,
3153*4882a593Smuzhiyun 				remain_len);
3154*4882a593Smuzhiyun 		pos += len;
3155*4882a593Smuzhiyun 		remain_len -= len;
3156*4882a593Smuzhiyun 		pcustom_ie->len += len;
3157*4882a593Smuzhiyun 	}
3158*4882a593Smuzhiyun 
3159*4882a593Smuzhiyun 	if (probereq_ies_data) {
3160*4882a593Smuzhiyun 		len = sizeof(*probereq_ies_data) - MAX_IE_SIZE +
3161*4882a593Smuzhiyun 		      probereq_ies_data->ie_length;
3162*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, pos, probereq_ies_data, len,
3163*4882a593Smuzhiyun 				remain_len);
3164*4882a593Smuzhiyun 		pos += len;
3165*4882a593Smuzhiyun 		remain_len -= len;
3166*4882a593Smuzhiyun 		pcustom_ie->len += len;
3167*4882a593Smuzhiyun 	}
3168*4882a593Smuzhiyun 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3169*4882a593Smuzhiyun 	if (ioctl_req == NULL) {
3170*4882a593Smuzhiyun 		PRINTM(MERROR, "Fail to allocate ioctl_req\n");
3171*4882a593Smuzhiyun 		status = MLAN_STATUS_FAILURE;
3172*4882a593Smuzhiyun 		goto done;
3173*4882a593Smuzhiyun 	}
3174*4882a593Smuzhiyun 
3175*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
3176*4882a593Smuzhiyun 	misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
3177*4882a593Smuzhiyun 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
3178*4882a593Smuzhiyun 	ioctl_req->action = MLAN_ACT_SET;
3179*4882a593Smuzhiyun 
3180*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle, &misc->param.cust_ie, pcustom_ie,
3181*4882a593Smuzhiyun 			sizeof(mlan_ds_misc_custom_ie),
3182*4882a593Smuzhiyun 			sizeof(mlan_ds_misc_custom_ie));
3183*4882a593Smuzhiyun 
3184*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, ioctl_req, wait_option);
3185*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS)
3186*4882a593Smuzhiyun 		goto done;
3187*4882a593Smuzhiyun 
3188*4882a593Smuzhiyun 	/* get the assigned index */
3189*4882a593Smuzhiyun 	pos = (t_u8 *)(&misc->param.cust_ie.ie_data_list[0].ie_index);
3190*4882a593Smuzhiyun 	if (beacon_ies_data && beacon_ies_data->ie_length &&
3191*4882a593Smuzhiyun 	    beacon_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
3192*4882a593Smuzhiyun 		/* save beacon ie index after auto-indexing */
3193*4882a593Smuzhiyun 		*beacon_index = misc->param.cust_ie.ie_data_list[0].ie_index;
3194*4882a593Smuzhiyun 		len = sizeof(*beacon_ies_data) - MAX_IE_SIZE +
3195*4882a593Smuzhiyun 		      beacon_ies_data->ie_length;
3196*4882a593Smuzhiyun 		pos += len;
3197*4882a593Smuzhiyun 	}
3198*4882a593Smuzhiyun 
3199*4882a593Smuzhiyun 	if (proberesp_ies_data && proberesp_ies_data->ie_length &&
3200*4882a593Smuzhiyun 	    proberesp_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
3201*4882a593Smuzhiyun 		/* save probe resp ie index after auto-indexing */
3202*4882a593Smuzhiyun 		*proberesp_index = *((t_u16 *)pos);
3203*4882a593Smuzhiyun 		len = sizeof(*proberesp_ies_data) - MAX_IE_SIZE +
3204*4882a593Smuzhiyun 		      proberesp_ies_data->ie_length;
3205*4882a593Smuzhiyun 		pos += len;
3206*4882a593Smuzhiyun 	}
3207*4882a593Smuzhiyun 
3208*4882a593Smuzhiyun 	if (assocresp_ies_data && assocresp_ies_data->ie_length &&
3209*4882a593Smuzhiyun 	    assocresp_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
3210*4882a593Smuzhiyun 		/* save assoc resp ie index after auto-indexing */
3211*4882a593Smuzhiyun 		*assocresp_index = *((t_u16 *)pos);
3212*4882a593Smuzhiyun 		len = sizeof(*assocresp_ies_data) - MAX_IE_SIZE +
3213*4882a593Smuzhiyun 		      assocresp_ies_data->ie_length;
3214*4882a593Smuzhiyun 		pos += len;
3215*4882a593Smuzhiyun 	}
3216*4882a593Smuzhiyun 	if (probereq_ies_data && probereq_ies_data->ie_length &&
3217*4882a593Smuzhiyun 	    probereq_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
3218*4882a593Smuzhiyun 		/* save probe resp ie index after auto-indexing */
3219*4882a593Smuzhiyun 		*probereq_index = *((t_u16 *)pos);
3220*4882a593Smuzhiyun 		len = sizeof(*probereq_ies_data) - MAX_IE_SIZE +
3221*4882a593Smuzhiyun 		      probereq_ies_data->ie_length;
3222*4882a593Smuzhiyun 		pos += len;
3223*4882a593Smuzhiyun 	}
3224*4882a593Smuzhiyun 	// TODO why we check status_code at end
3225*4882a593Smuzhiyun 	if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL)
3226*4882a593Smuzhiyun 		status = MLAN_STATUS_FAILURE;
3227*4882a593Smuzhiyun 
3228*4882a593Smuzhiyun done:
3229*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
3230*4882a593Smuzhiyun 		kfree(ioctl_req);
3231*4882a593Smuzhiyun 	kfree(pcustom_ie);
3232*4882a593Smuzhiyun 	LEAVE();
3233*4882a593Smuzhiyun 	return status;
3234*4882a593Smuzhiyun }
3235*4882a593Smuzhiyun 
3236*4882a593Smuzhiyun #if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
3237*4882a593Smuzhiyun /**
3238*4882a593Smuzhiyun  * @brief set Qos map
3239*4882a593Smuzhiyun  *
3240*4882a593Smuzhiyun  * @param wiphy         A pointer to wiphy structure
3241*4882a593Smuzhiyun  * @param dev           A pointer to net_device structure
3242*4882a593Smuzhiyun  * @param qos_map       A pointer to cfg80211_qos_map structure
3243*4882a593Smuzhiyun  *
3244*4882a593Smuzhiyun  *
3245*4882a593Smuzhiyun  * @return              0 -- success, otherwise fail
3246*4882a593Smuzhiyun  */
woal_cfg80211_set_qos_map(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_qos_map * qos_map)3247*4882a593Smuzhiyun int woal_cfg80211_set_qos_map(struct wiphy *wiphy, struct net_device *dev,
3248*4882a593Smuzhiyun 			      struct cfg80211_qos_map *qos_map)
3249*4882a593Smuzhiyun {
3250*4882a593Smuzhiyun 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
3251*4882a593Smuzhiyun 	int i, j, ret = 0;
3252*4882a593Smuzhiyun 
3253*4882a593Smuzhiyun 	ENTER();
3254*4882a593Smuzhiyun 	/**clear dscp map*/
3255*4882a593Smuzhiyun 	if (!qos_map) {
3256*4882a593Smuzhiyun 		memset(priv->dscp_map, 0xFF, sizeof(priv->dscp_map));
3257*4882a593Smuzhiyun 		goto done;
3258*4882a593Smuzhiyun 	}
3259*4882a593Smuzhiyun 
3260*4882a593Smuzhiyun 	/**update dscp map*/
3261*4882a593Smuzhiyun 	for (i = 0; i < MAX_NUM_TID; i++) {
3262*4882a593Smuzhiyun 		PRINTM(MINFO, "TID %d: dscp_low=%d, dscp_high=%d\n", i,
3263*4882a593Smuzhiyun 		       qos_map->up[i].low, qos_map->up[i].high);
3264*4882a593Smuzhiyun 		if (qos_map->up[i].low != 0xff && qos_map->up[i].high != 0xff &&
3265*4882a593Smuzhiyun 		    qos_map->up[i].high <= 63) {
3266*4882a593Smuzhiyun 			for (j = qos_map->up[i].low; j <= qos_map->up[i].high;
3267*4882a593Smuzhiyun 			     j++)
3268*4882a593Smuzhiyun 				priv->dscp_map[j] = i;
3269*4882a593Smuzhiyun 		}
3270*4882a593Smuzhiyun 	}
3271*4882a593Smuzhiyun 
3272*4882a593Smuzhiyun 	for (i = 0; i < qos_map->num_des; i++) {
3273*4882a593Smuzhiyun 		if ((qos_map->dscp_exception[i].dscp <= 63) &&
3274*4882a593Smuzhiyun 		    (qos_map->dscp_exception[i].up <= 7)) {
3275*4882a593Smuzhiyun 			PRINTM(MINFO, "dscp excpt: value=%d priority=%d\n",
3276*4882a593Smuzhiyun 			       qos_map->dscp_exception[i].dscp,
3277*4882a593Smuzhiyun 			       qos_map->dscp_exception[i].up);
3278*4882a593Smuzhiyun 			priv->dscp_map[qos_map->dscp_exception[i].dscp] =
3279*4882a593Smuzhiyun 				qos_map->dscp_exception[i].up;
3280*4882a593Smuzhiyun 		}
3281*4882a593Smuzhiyun 	}
3282*4882a593Smuzhiyun 
3283*4882a593Smuzhiyun 	/**UAP update (re)associate response*/
3284*4882a593Smuzhiyun 	if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
3285*4882a593Smuzhiyun 		IEEEtypes_Generic_t qos_map_ie;
3286*4882a593Smuzhiyun 		t_u16 qos_map_ies_len;
3287*4882a593Smuzhiyun 
3288*4882a593Smuzhiyun 		qos_map_ie.ieee_hdr.element_id = QOS_MAPPING;
3289*4882a593Smuzhiyun 		qos_map_ie.ieee_hdr.len =
3290*4882a593Smuzhiyun 			2 * qos_map->num_des + sizeof(qos_map->up);
3291*4882a593Smuzhiyun 		qos_map_ies_len =
3292*4882a593Smuzhiyun 			qos_map_ie.ieee_hdr.len + sizeof(qos_map_ie.ieee_hdr);
3293*4882a593Smuzhiyun 
3294*4882a593Smuzhiyun 		if (qos_map_ies_len > sizeof(qos_map_ie.data)) {
3295*4882a593Smuzhiyun 			PRINTM(MERROR,
3296*4882a593Smuzhiyun 			       "QoS MAP IE size exceeds the buffer len\n");
3297*4882a593Smuzhiyun 			goto done;
3298*4882a593Smuzhiyun 		}
3299*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, qos_map_ie.data,
3300*4882a593Smuzhiyun 				(t_u8 *)qos_map->dscp_exception,
3301*4882a593Smuzhiyun 				2 * qos_map->num_des, sizeof(qos_map_ie.data));
3302*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle,
3303*4882a593Smuzhiyun 				&qos_map_ie.data[2 * qos_map->num_des],
3304*4882a593Smuzhiyun 				(t_u8 *)qos_map->up, sizeof(qos_map->up),
3305*4882a593Smuzhiyun 				sizeof(qos_map_ie.data) - 2 * qos_map->num_des);
3306*4882a593Smuzhiyun 
3307*4882a593Smuzhiyun 		/* set the assoc response ies */
3308*4882a593Smuzhiyun 		ret = woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0,
3309*4882a593Smuzhiyun 						  (t_u8 *)&qos_map_ie,
3310*4882a593Smuzhiyun 						  qos_map_ies_len, NULL, 0,
3311*4882a593Smuzhiyun 						  MGMT_MASK_ASSOC_RESP_QOS_MAP,
3312*4882a593Smuzhiyun 						  MOAL_IOCTL_WAIT);
3313*4882a593Smuzhiyun 		if (ret) {
3314*4882a593Smuzhiyun 			PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n");
3315*4882a593Smuzhiyun 			goto done;
3316*4882a593Smuzhiyun 		}
3317*4882a593Smuzhiyun 	}
3318*4882a593Smuzhiyun 
3319*4882a593Smuzhiyun done:
3320*4882a593Smuzhiyun 	LEAVE();
3321*4882a593Smuzhiyun 	return ret;
3322*4882a593Smuzhiyun }
3323*4882a593Smuzhiyun #endif
3324*4882a593Smuzhiyun 
3325*4882a593Smuzhiyun /**
3326*4882a593Smuzhiyun  * @brief get specific ie
3327*4882a593Smuzhiyun  *
3328*4882a593Smuzhiyun  * @param ie              Pointer to IEs
3329*4882a593Smuzhiyun  * @param len             Total length of ie
3330*4882a593Smuzhiyun  * @param ie_out          Pointer to out IE buf
3331*4882a593Smuzhiyun  * @param ie_out_len    Total length of ie_out
3332*4882a593Smuzhiyun  * @param mask            IE mask
3333*4882a593Smuzhiyun  *
3334*4882a593Smuzhiyun  * @return                out IE length
3335*4882a593Smuzhiyun  */
woal_get_specific_ie(const t_u8 * ie,int len,t_u8 * ie_out,t_u32 ie_out_len,t_u16 mask)3336*4882a593Smuzhiyun static t_u16 woal_get_specific_ie(const t_u8 *ie, int len, t_u8 *ie_out,
3337*4882a593Smuzhiyun 				  t_u32 ie_out_len, t_u16 mask)
3338*4882a593Smuzhiyun {
3339*4882a593Smuzhiyun 	int left_len = len;
3340*4882a593Smuzhiyun 	const t_u8 *pos = ie;
3341*4882a593Smuzhiyun 	int length;
3342*4882a593Smuzhiyun 	t_u8 id = 0;
3343*4882a593Smuzhiyun 	t_u16 out_len = 0;
3344*4882a593Smuzhiyun 	IEEEtypes_VendorSpecific_t *pvendor_ie = NULL;
3345*4882a593Smuzhiyun 	const u8 wps_oui[4] = {0x00, 0x50, 0xf2, 0x04};
3346*4882a593Smuzhiyun 	const u8 p2p_oui[4] = {0x50, 0x6f, 0x9a, 0x09};
3347*4882a593Smuzhiyun 	const u8 wfd_oui[4] = {0x50, 0x6f, 0x9a, 0x0a};
3348*4882a593Smuzhiyun 	const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
3349*4882a593Smuzhiyun 
3350*4882a593Smuzhiyun 	ENTER();
3351*4882a593Smuzhiyun 	while (left_len >= 2) {
3352*4882a593Smuzhiyun 		length = *(pos + 1);
3353*4882a593Smuzhiyun 		id = *pos;
3354*4882a593Smuzhiyun 		if ((length + 2) > left_len)
3355*4882a593Smuzhiyun 			break;
3356*4882a593Smuzhiyun 		if (id == VENDOR_SPECIFIC_221) {
3357*4882a593Smuzhiyun 			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pos;
3358*4882a593Smuzhiyun 			if (!memcmp(pvendor_ie->vend_hdr.oui, wmm_oui,
3359*4882a593Smuzhiyun 				    sizeof(pvendor_ie->vend_hdr.oui)) &&
3360*4882a593Smuzhiyun 			    pvendor_ie->vend_hdr.oui_type == wmm_oui[3]) {
3361*4882a593Smuzhiyun 				PRINTM(MIOCTL, "find WMM IE\n");
3362*4882a593Smuzhiyun 			} else if (!memcmp(pvendor_ie->vend_hdr.oui, p2p_oui,
3363*4882a593Smuzhiyun 					   sizeof(pvendor_ie->vend_hdr.oui)) &&
3364*4882a593Smuzhiyun 				   pvendor_ie->vend_hdr.oui_type ==
3365*4882a593Smuzhiyun 					   p2p_oui[3]) {
3366*4882a593Smuzhiyun 				if (mask & IE_MASK_P2P) {
3367*4882a593Smuzhiyun 					/** only get first p2p ie here */
3368*4882a593Smuzhiyun 					moal_memcpy_ext(NULL, ie_out + out_len,
3369*4882a593Smuzhiyun 							pos, length + 2,
3370*4882a593Smuzhiyun 							ie_out_len - out_len);
3371*4882a593Smuzhiyun 					out_len += length + 2;
3372*4882a593Smuzhiyun 					break;
3373*4882a593Smuzhiyun 				}
3374*4882a593Smuzhiyun 			} else if (!memcmp(pvendor_ie->vend_hdr.oui, wps_oui,
3375*4882a593Smuzhiyun 					   sizeof(pvendor_ie->vend_hdr.oui)) &&
3376*4882a593Smuzhiyun 				   pvendor_ie->vend_hdr.oui_type ==
3377*4882a593Smuzhiyun 					   wps_oui[3]) {
3378*4882a593Smuzhiyun 				if (mask & IE_MASK_WPS) {
3379*4882a593Smuzhiyun 					if ((out_len + length + 2) <
3380*4882a593Smuzhiyun 					    (int)ie_out_len) {
3381*4882a593Smuzhiyun 						moal_memcpy_ext(
3382*4882a593Smuzhiyun 							NULL, ie_out + out_len,
3383*4882a593Smuzhiyun 							pos, length + 2,
3384*4882a593Smuzhiyun 							ie_out_len - out_len);
3385*4882a593Smuzhiyun 						out_len += length + 2;
3386*4882a593Smuzhiyun 					} else {
3387*4882a593Smuzhiyun 						PRINTM(MERROR,
3388*4882a593Smuzhiyun 						       "get_specific_ie: IE too big, fail copy WPS IE\n");
3389*4882a593Smuzhiyun 						break;
3390*4882a593Smuzhiyun 					}
3391*4882a593Smuzhiyun 				}
3392*4882a593Smuzhiyun 			} else if (!memcmp(pvendor_ie->vend_hdr.oui, wfd_oui,
3393*4882a593Smuzhiyun 					   sizeof(pvendor_ie->vend_hdr.oui)) &&
3394*4882a593Smuzhiyun 				   pvendor_ie->vend_hdr.oui_type ==
3395*4882a593Smuzhiyun 					   wfd_oui[3]) {
3396*4882a593Smuzhiyun 				if (mask & IE_MASK_WFD) {
3397*4882a593Smuzhiyun 					if ((out_len + length + 2) <
3398*4882a593Smuzhiyun 					    (int)ie_out_len) {
3399*4882a593Smuzhiyun 						moal_memcpy_ext(
3400*4882a593Smuzhiyun 							NULL, ie_out + out_len,
3401*4882a593Smuzhiyun 							pos, length + 2,
3402*4882a593Smuzhiyun 							ie_out_len - out_len);
3403*4882a593Smuzhiyun 						out_len += length + 2;
3404*4882a593Smuzhiyun 					} else {
3405*4882a593Smuzhiyun 						PRINTM(MERROR,
3406*4882a593Smuzhiyun 						       "get_specific_ie: IE too big, fail copy WFD IE\n");
3407*4882a593Smuzhiyun 						break;
3408*4882a593Smuzhiyun 					}
3409*4882a593Smuzhiyun 				}
3410*4882a593Smuzhiyun 			} else if (mask & IE_MASK_VENDOR) {
3411*4882a593Smuzhiyun 				if ((out_len + length + 2) < (int)ie_out_len) {
3412*4882a593Smuzhiyun 					moal_memcpy_ext(NULL, ie_out + out_len,
3413*4882a593Smuzhiyun 							pos, length + 2,
3414*4882a593Smuzhiyun 							ie_out_len - out_len);
3415*4882a593Smuzhiyun 					out_len += length + 2;
3416*4882a593Smuzhiyun 				} else {
3417*4882a593Smuzhiyun 					PRINTM(MERROR,
3418*4882a593Smuzhiyun 					       "get_specific_ie:IE too big, fail copy VENDOR IE\n");
3419*4882a593Smuzhiyun 					break;
3420*4882a593Smuzhiyun 				}
3421*4882a593Smuzhiyun 			}
3422*4882a593Smuzhiyun 		}
3423*4882a593Smuzhiyun 		pos += (length + 2);
3424*4882a593Smuzhiyun 		left_len -= (length + 2);
3425*4882a593Smuzhiyun 	}
3426*4882a593Smuzhiyun 	LEAVE();
3427*4882a593Smuzhiyun 	return out_len;
3428*4882a593Smuzhiyun }
3429*4882a593Smuzhiyun 
3430*4882a593Smuzhiyun /**
3431*4882a593Smuzhiyun  * @brief Find specific IE from IE buffer
3432*4882a593Smuzhiyun  *
3433*4882a593Smuzhiyun  * @param ie              Pointer to IEs
3434*4882a593Smuzhiyun  * @param len             Total length of ie
3435*4882a593Smuzhiyun  * @param spec_ie         Pointer to specific IE buffer
3436*4882a593Smuzhiyun  * @param spec_len        Total length of specific IE
3437*4882a593Smuzhiyun  *
3438*4882a593Smuzhiyun  * @return                out IE length
3439*4882a593Smuzhiyun  */
woal_find_ie(const t_u8 * ie,int len,const t_u8 * spec_ie,int spec_len)3440*4882a593Smuzhiyun static t_u8 woal_find_ie(const t_u8 *ie, int len, const t_u8 *spec_ie,
3441*4882a593Smuzhiyun 			 int spec_len)
3442*4882a593Smuzhiyun {
3443*4882a593Smuzhiyun 	int left_len = len;
3444*4882a593Smuzhiyun 	const t_u8 *pos = ie;
3445*4882a593Smuzhiyun 	int length;
3446*4882a593Smuzhiyun 
3447*4882a593Smuzhiyun 	while (left_len >= 2) {
3448*4882a593Smuzhiyun 		length = *(pos + 1);
3449*4882a593Smuzhiyun 		if ((length + 2) > left_len)
3450*4882a593Smuzhiyun 			break;
3451*4882a593Smuzhiyun 		if ((length + 2) == spec_len) {
3452*4882a593Smuzhiyun 			if (!memcmp(pos, spec_ie, spec_len))
3453*4882a593Smuzhiyun 				return MTRUE;
3454*4882a593Smuzhiyun 		}
3455*4882a593Smuzhiyun 		pos += (length + 2);
3456*4882a593Smuzhiyun 		left_len -= (length + 2);
3457*4882a593Smuzhiyun 	}
3458*4882a593Smuzhiyun 	return MFALSE;
3459*4882a593Smuzhiyun }
3460*4882a593Smuzhiyun 
3461*4882a593Smuzhiyun /**
3462*4882a593Smuzhiyun  * @brief Filter specific IE in ie buf
3463*4882a593Smuzhiyun  *
3464*4882a593Smuzhiyun  * @param priv            pointer to moal private structure
3465*4882a593Smuzhiyun  * @param ie              Pointer to IEs
3466*4882a593Smuzhiyun  * @param len             Total length of ie
3467*4882a593Smuzhiyun  * @param ie_out		  Pointer to out IE buf
3468*4882a593Smuzhiyun  * @param ie_out_len      Total length of ie_out
3469*4882a593Smuzhiyun  * @param wps_flag	      flag for wps/p2p
3470*4882a593Smuzhiyun  * @param dup_ie          Pointer to duplicate ie
3471*4882a593Smuzhiyun  * @param dup_ie_len	  duplicate IE len
3472*4882a593Smuzhiyun  *
3473*4882a593Smuzhiyun  * @return                out IE length
3474*4882a593Smuzhiyun  */
woal_filter_beacon_ies(moal_private * priv,const t_u8 * ie,int len,t_u8 * ie_out,t_u32 ie_out_len,t_u16 wps_flag,const t_u8 * dup_ie,int dup_ie_len)3475*4882a593Smuzhiyun static t_u16 woal_filter_beacon_ies(moal_private *priv, const t_u8 *ie, int len,
3476*4882a593Smuzhiyun 				    t_u8 *ie_out, t_u32 ie_out_len,
3477*4882a593Smuzhiyun 				    t_u16 wps_flag, const t_u8 *dup_ie,
3478*4882a593Smuzhiyun 				    int dup_ie_len)
3479*4882a593Smuzhiyun {
3480*4882a593Smuzhiyun 	int left_len = len;
3481*4882a593Smuzhiyun 	const t_u8 *pos = ie;
3482*4882a593Smuzhiyun 	int length;
3483*4882a593Smuzhiyun 	t_u8 id = 0;
3484*4882a593Smuzhiyun 	t_u16 out_len = 0;
3485*4882a593Smuzhiyun 	IEEEtypes_VendorSpecific_t *pvendor_ie = NULL;
3486*4882a593Smuzhiyun 	const u8 wps_oui[4] = {0x00, 0x50, 0xf2, 0x04};
3487*4882a593Smuzhiyun 	const u8 p2p_oui[4] = {0x50, 0x6f, 0x9a, 0x09};
3488*4882a593Smuzhiyun 	const u8 wfd_oui[4] = {0x50, 0x6f, 0x9a, 0x0a};
3489*4882a593Smuzhiyun 	const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
3490*4882a593Smuzhiyun 	t_u8 find_p2p_ie = MFALSE;
3491*4882a593Smuzhiyun 	t_u8 enable_11d = MFALSE;
3492*4882a593Smuzhiyun 	t_u8 ext_id = 0;
3493*4882a593Smuzhiyun 	int ie_len;
3494*4882a593Smuzhiyun 
3495*4882a593Smuzhiyun 	/* ERP_INFO/EXTENDED_SUPPORT_RATES/HT_CAPABILITY/HT_OPERATION/WMM
3496*4882a593Smuzhiyun 	 * and WPS/P2P/WFD IE will be fileter out
3497*4882a593Smuzhiyun 	 */
3498*4882a593Smuzhiyun 	while (left_len >= 2) {
3499*4882a593Smuzhiyun 		length = *(pos + 1);
3500*4882a593Smuzhiyun 		id = *pos;
3501*4882a593Smuzhiyun 		if ((length + 2) > left_len)
3502*4882a593Smuzhiyun 			break;
3503*4882a593Smuzhiyun 		if (dup_ie && dup_ie_len &&
3504*4882a593Smuzhiyun 		    woal_find_ie(dup_ie, dup_ie_len, pos, length + 2)) {
3505*4882a593Smuzhiyun 			PRINTM(MIOCTL, "skip duplicate IE\n");
3506*4882a593Smuzhiyun 			pos += (length + 2);
3507*4882a593Smuzhiyun 			left_len -= (length + 2);
3508*4882a593Smuzhiyun 			continue;
3509*4882a593Smuzhiyun 		}
3510*4882a593Smuzhiyun 		switch (id) {
3511*4882a593Smuzhiyun 		case COUNTRY_INFO:
3512*4882a593Smuzhiyun 			enable_11d = MTRUE;
3513*4882a593Smuzhiyun 			if ((out_len + length + 2) < (int)ie_out_len) {
3514*4882a593Smuzhiyun 				moal_memcpy_ext(priv->phandle, ie_out + out_len,
3515*4882a593Smuzhiyun 						pos, length + 2,
3516*4882a593Smuzhiyun 						ie_out_len - out_len);
3517*4882a593Smuzhiyun 				out_len += length + 2;
3518*4882a593Smuzhiyun 			} else {
3519*4882a593Smuzhiyun 				PRINTM(MERROR,
3520*4882a593Smuzhiyun 				       "IE too big, fail copy COUNTRY INFO IE\n");
3521*4882a593Smuzhiyun 			}
3522*4882a593Smuzhiyun 			break;
3523*4882a593Smuzhiyun 		case HT_CAPABILITY:
3524*4882a593Smuzhiyun 		case HT_OPERATION:
3525*4882a593Smuzhiyun 		case VHT_CAPABILITY:
3526*4882a593Smuzhiyun 		case VHT_OPERATION:
3527*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
3528*4882a593Smuzhiyun 			if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME)) {
3529*4882a593Smuzhiyun 				if ((out_len + length + 2) < (int)ie_out_len) {
3530*4882a593Smuzhiyun 					moal_memcpy_ext(priv->phandle,
3531*4882a593Smuzhiyun 							ie_out + out_len, pos,
3532*4882a593Smuzhiyun 							length + 2,
3533*4882a593Smuzhiyun 							ie_out_len - out_len);
3534*4882a593Smuzhiyun 					out_len += length + 2;
3535*4882a593Smuzhiyun 				} else {
3536*4882a593Smuzhiyun 					PRINTM(MERROR,
3537*4882a593Smuzhiyun 					       "IE too big, fail copy COUNTRY INFO IE\n");
3538*4882a593Smuzhiyun 				}
3539*4882a593Smuzhiyun 			}
3540*4882a593Smuzhiyun #endif
3541*4882a593Smuzhiyun 			break;
3542*4882a593Smuzhiyun 		case EXTENDED_SUPPORTED_RATES:
3543*4882a593Smuzhiyun 		case WLAN_EID_ERP_INFO:
3544*4882a593Smuzhiyun 		/* Fall Through */
3545*4882a593Smuzhiyun 		case REGULATORY_CLASS:
3546*4882a593Smuzhiyun 		/* Fall Through */
3547*4882a593Smuzhiyun 		case OVERLAPBSSSCANPARAM:
3548*4882a593Smuzhiyun 		/* Fall Through */
3549*4882a593Smuzhiyun 		case WAPI_IE:
3550*4882a593Smuzhiyun 			break;
3551*4882a593Smuzhiyun 		case EXTENSION:
3552*4882a593Smuzhiyun 			ext_id = *(pos + 2);
3553*4882a593Smuzhiyun 			if ((ext_id == HE_CAPABILITY || ext_id == HE_OPERATION)
3554*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
3555*4882a593Smuzhiyun 			    && !moal_extflg_isset(priv->phandle, EXT_HOST_MLME)
3556*4882a593Smuzhiyun #endif
3557*4882a593Smuzhiyun 			)
3558*4882a593Smuzhiyun 				break;
3559*4882a593Smuzhiyun 			else {
3560*4882a593Smuzhiyun #ifdef UAP_SUPPORT
3561*4882a593Smuzhiyun #if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 20, 0)
3562*4882a593Smuzhiyun 				if (ext_id == HE_CAPABILITY) {
3563*4882a593Smuzhiyun 					mlan_ds_11ax_he_cfg he_cfg;
3564*4882a593Smuzhiyun 					IEEEtypes_HECap_t *hecap_ie;
3565*4882a593Smuzhiyun 
3566*4882a593Smuzhiyun 					if (priv->channel <= 14)
3567*4882a593Smuzhiyun 						he_cfg.band = MBIT(0);
3568*4882a593Smuzhiyun 					else
3569*4882a593Smuzhiyun 						he_cfg.band = MBIT(1);
3570*4882a593Smuzhiyun 
3571*4882a593Smuzhiyun 					PRINTM(MCMND,
3572*4882a593Smuzhiyun 					       "Retrieve 11ax cfg by channel=%d band=%d\n",
3573*4882a593Smuzhiyun 					       priv->channel, he_cfg.band);
3574*4882a593Smuzhiyun 
3575*4882a593Smuzhiyun 					if (0 == woal_11ax_cfg(priv,
3576*4882a593Smuzhiyun 							       MLAN_ACT_GET,
3577*4882a593Smuzhiyun 							       &he_cfg)) {
3578*4882a593Smuzhiyun 						hecap_ie = (IEEEtypes_HECap_t
3579*4882a593Smuzhiyun 								    *)&he_cfg
3580*4882a593Smuzhiyun 								   .he_cap.len;
3581*4882a593Smuzhiyun 
3582*4882a593Smuzhiyun 						hecap_ie->ieee_hdr.len =
3583*4882a593Smuzhiyun 							he_cfg.he_cap.len;
3584*4882a593Smuzhiyun 						hecap_ie->ieee_hdr.element_id =
3585*4882a593Smuzhiyun 							he_cfg.he_cap.id;
3586*4882a593Smuzhiyun 
3587*4882a593Smuzhiyun 						moal_memcpy_ext(
3588*4882a593Smuzhiyun 							priv->phandle,
3589*4882a593Smuzhiyun 							ie_out + out_len,
3590*4882a593Smuzhiyun 							hecap_ie,
3591*4882a593Smuzhiyun 							hecap_ie->ieee_hdr.len +
3592*4882a593Smuzhiyun 								2,
3593*4882a593Smuzhiyun 							ie_out_len - out_len);
3594*4882a593Smuzhiyun 
3595*4882a593Smuzhiyun 						out_len +=
3596*4882a593Smuzhiyun 							hecap_ie->ieee_hdr.len +
3597*4882a593Smuzhiyun 							2;
3598*4882a593Smuzhiyun 					} else {
3599*4882a593Smuzhiyun 						PRINTM(MERROR,
3600*4882a593Smuzhiyun 						       "Fail to get 11ax he_cap parameters\n");
3601*4882a593Smuzhiyun 					}
3602*4882a593Smuzhiyun 				} else
3603*4882a593Smuzhiyun #endif
3604*4882a593Smuzhiyun #endif
3605*4882a593Smuzhiyun 				{
3606*4882a593Smuzhiyun 					if ((out_len + length + 2) <
3607*4882a593Smuzhiyun 					    (int)ie_out_len) {
3608*4882a593Smuzhiyun 						moal_memcpy_ext(
3609*4882a593Smuzhiyun 							priv->phandle,
3610*4882a593Smuzhiyun 							ie_out + out_len, pos,
3611*4882a593Smuzhiyun 							length + 2,
3612*4882a593Smuzhiyun 							ie_out_len - out_len);
3613*4882a593Smuzhiyun 						out_len += length + 2;
3614*4882a593Smuzhiyun 					} else {
3615*4882a593Smuzhiyun 						PRINTM(MERROR,
3616*4882a593Smuzhiyun 						       "IE too big, fail copy EXTENSION IE\n");
3617*4882a593Smuzhiyun 					}
3618*4882a593Smuzhiyun 				}
3619*4882a593Smuzhiyun 				break;
3620*4882a593Smuzhiyun 			}
3621*4882a593Smuzhiyun 		case EXT_CAPABILITY:
3622*4882a593Smuzhiyun 			/* filter out EXTCAP */
3623*4882a593Smuzhiyun 			if (wps_flag & IE_MASK_EXTCAP) {
3624*4882a593Smuzhiyun 				ie_len = length + 2;
3625*4882a593Smuzhiyun 				if (MLAN_STATUS_SUCCESS !=
3626*4882a593Smuzhiyun 				    woal_set_get_gen_ie(priv, MLAN_ACT_SET,
3627*4882a593Smuzhiyun 							(t_u8 *)pos, &ie_len,
3628*4882a593Smuzhiyun 							MOAL_IOCTL_WAIT))
3629*4882a593Smuzhiyun 					PRINTM(MERROR,
3630*4882a593Smuzhiyun 					       "Fail to set EXTCAP IE\n");
3631*4882a593Smuzhiyun 				break;
3632*4882a593Smuzhiyun 			}
3633*4882a593Smuzhiyun 			if ((out_len + length + 2) < (int)ie_out_len) {
3634*4882a593Smuzhiyun 				moal_memcpy_ext(priv->phandle, ie_out + out_len,
3635*4882a593Smuzhiyun 						pos, length + 2,
3636*4882a593Smuzhiyun 						ie_out_len - out_len);
3637*4882a593Smuzhiyun 				out_len += length + 2;
3638*4882a593Smuzhiyun 			} else {
3639*4882a593Smuzhiyun 				PRINTM(MERROR,
3640*4882a593Smuzhiyun 				       "IE too big, fail copy EXTCAP IE\n");
3641*4882a593Smuzhiyun 			}
3642*4882a593Smuzhiyun 			break;
3643*4882a593Smuzhiyun 		case VENDOR_SPECIFIC_221:
3644*4882a593Smuzhiyun 			/* filter out wmm ie */
3645*4882a593Smuzhiyun 			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pos;
3646*4882a593Smuzhiyun 			if (!memcmp(pvendor_ie->vend_hdr.oui, wmm_oui,
3647*4882a593Smuzhiyun 				    sizeof(pvendor_ie->vend_hdr.oui)) &&
3648*4882a593Smuzhiyun 			    pvendor_ie->vend_hdr.oui_type == wmm_oui[3]) {
3649*4882a593Smuzhiyun 				break;
3650*4882a593Smuzhiyun 			}
3651*4882a593Smuzhiyun 			/* filter out wps ie */
3652*4882a593Smuzhiyun 			else if (!memcmp(pvendor_ie->vend_hdr.oui, wps_oui,
3653*4882a593Smuzhiyun 					 sizeof(pvendor_ie->vend_hdr.oui)) &&
3654*4882a593Smuzhiyun 				 pvendor_ie->vend_hdr.oui_type == wps_oui[3]) {
3655*4882a593Smuzhiyun 				if (wps_flag & IE_MASK_WPS)
3656*4882a593Smuzhiyun 					break;
3657*4882a593Smuzhiyun 			}
3658*4882a593Smuzhiyun 			/* filter out first p2p ie */
3659*4882a593Smuzhiyun 			else if (!memcmp(pvendor_ie->vend_hdr.oui, p2p_oui,
3660*4882a593Smuzhiyun 					 sizeof(pvendor_ie->vend_hdr.oui)) &&
3661*4882a593Smuzhiyun 				 pvendor_ie->vend_hdr.oui_type == p2p_oui[3]) {
3662*4882a593Smuzhiyun 				if (!find_p2p_ie && (wps_flag & IE_MASK_P2P)) {
3663*4882a593Smuzhiyun 					find_p2p_ie = MTRUE;
3664*4882a593Smuzhiyun 					break;
3665*4882a593Smuzhiyun 				}
3666*4882a593Smuzhiyun 			}
3667*4882a593Smuzhiyun 			/* filter out wfd ie */
3668*4882a593Smuzhiyun 			else if (!memcmp(pvendor_ie->vend_hdr.oui, wfd_oui,
3669*4882a593Smuzhiyun 					 sizeof(pvendor_ie->vend_hdr.oui)) &&
3670*4882a593Smuzhiyun 				 pvendor_ie->vend_hdr.oui_type == wfd_oui[3]) {
3671*4882a593Smuzhiyun 				if (wps_flag & IE_MASK_WFD)
3672*4882a593Smuzhiyun 					break;
3673*4882a593Smuzhiyun 			} else if (wps_flag & IE_MASK_VENDOR) {
3674*4882a593Smuzhiyun 				// filter out vendor IE
3675*4882a593Smuzhiyun 				break;
3676*4882a593Smuzhiyun 			}
3677*4882a593Smuzhiyun 			if ((out_len + length + 2) < (int)ie_out_len) {
3678*4882a593Smuzhiyun 				moal_memcpy_ext(priv->phandle, ie_out + out_len,
3679*4882a593Smuzhiyun 						pos, length + 2,
3680*4882a593Smuzhiyun 						ie_out_len - out_len);
3681*4882a593Smuzhiyun 				out_len += length + 2;
3682*4882a593Smuzhiyun 			} else {
3683*4882a593Smuzhiyun 				PRINTM(MERROR,
3684*4882a593Smuzhiyun 				       "IE too big, fail copy VENDOR_SPECIFIC_221 IE\n");
3685*4882a593Smuzhiyun 			}
3686*4882a593Smuzhiyun 			break;
3687*4882a593Smuzhiyun 		default:
3688*4882a593Smuzhiyun 			if ((out_len + length + 2) < (int)ie_out_len) {
3689*4882a593Smuzhiyun 				moal_memcpy_ext(priv->phandle, ie_out + out_len,
3690*4882a593Smuzhiyun 						pos, length + 2,
3691*4882a593Smuzhiyun 						ie_out_len - out_len);
3692*4882a593Smuzhiyun 				out_len += length + 2;
3693*4882a593Smuzhiyun 			} else {
3694*4882a593Smuzhiyun 				PRINTM(MERROR, "IE too big, fail copy %d IE\n",
3695*4882a593Smuzhiyun 				       id);
3696*4882a593Smuzhiyun 			}
3697*4882a593Smuzhiyun 			break;
3698*4882a593Smuzhiyun 		}
3699*4882a593Smuzhiyun 		pos += (length + 2);
3700*4882a593Smuzhiyun 		left_len -= (length + 2);
3701*4882a593Smuzhiyun 	}
3702*4882a593Smuzhiyun 
3703*4882a593Smuzhiyun #ifdef UAP_SUPPORT
3704*4882a593Smuzhiyun 	if (enable_11d && !priv->bss_started) {
3705*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
3706*4882a593Smuzhiyun 		    woal_set_11d(priv, MOAL_IOCTL_WAIT, MTRUE)) {
3707*4882a593Smuzhiyun 			PRINTM(MERROR, "woal_set_11d fail\n");
3708*4882a593Smuzhiyun 		}
3709*4882a593Smuzhiyun 	}
3710*4882a593Smuzhiyun #endif
3711*4882a593Smuzhiyun 	return out_len;
3712*4882a593Smuzhiyun }
3713*4882a593Smuzhiyun 
3714*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
3715*4882a593Smuzhiyun /**
3716*4882a593Smuzhiyun  * @brief Check if selected_registrar_on in wps_ie
3717*4882a593Smuzhiyun  *
3718*4882a593Smuzhiyun  * @param ie              Pointer to IEs
3719*4882a593Smuzhiyun  * @param len             Total length of ie
3720*4882a593Smuzhiyun  *
3721*4882a593Smuzhiyun  * @return                MTRUE/MFALSE
3722*4882a593Smuzhiyun  */
is_selected_registrar_on(const t_u8 * ie,int len)3723*4882a593Smuzhiyun static t_u8 is_selected_registrar_on(const t_u8 *ie, int len)
3724*4882a593Smuzhiyun {
3725*4882a593Smuzhiyun #define WPS_IE_FIX_LEN 6
3726*4882a593Smuzhiyun #define TLV_ID_SELECTED_REGISTRAR 0x1041
3727*4882a593Smuzhiyun 	int left_len = len - WPS_IE_FIX_LEN;
3728*4882a593Smuzhiyun 
3729*4882a593Smuzhiyun 	TLV_Generic_t *tlv = (TLV_Generic_t *)(ie + WPS_IE_FIX_LEN);
3730*4882a593Smuzhiyun 	u16 tlv_type, tlv_len;
3731*4882a593Smuzhiyun 	u8 *pos = NULL;
3732*4882a593Smuzhiyun 
3733*4882a593Smuzhiyun 	while (left_len > (int)sizeof(TLV_Generic_t)) {
3734*4882a593Smuzhiyun 		tlv_type = ntohs((__force __be16)tlv->type);
3735*4882a593Smuzhiyun 		tlv_len = ntohs((__force __be16)tlv->len);
3736*4882a593Smuzhiyun 		if (tlv_type == TLV_ID_SELECTED_REGISTRAR) {
3737*4882a593Smuzhiyun 			PRINTM(MIOCTL, "Selected Registrar found !");
3738*4882a593Smuzhiyun 			pos = (u8 *)tlv + sizeof(TLV_Generic_t);
3739*4882a593Smuzhiyun 			if (*pos == 1)
3740*4882a593Smuzhiyun 				return MTRUE;
3741*4882a593Smuzhiyun 			else
3742*4882a593Smuzhiyun 				return MFALSE;
3743*4882a593Smuzhiyun 		}
3744*4882a593Smuzhiyun 		tlv = (TLV_Generic_t *)((u8 *)tlv + tlv_len +
3745*4882a593Smuzhiyun 					sizeof(TLV_Generic_t));
3746*4882a593Smuzhiyun 		left_len -= tlv_len + sizeof(TLV_Generic_t);
3747*4882a593Smuzhiyun 	}
3748*4882a593Smuzhiyun 	return MFALSE;
3749*4882a593Smuzhiyun }
3750*4882a593Smuzhiyun 
3751*4882a593Smuzhiyun /**
3752*4882a593Smuzhiyun  * @brief Check if selected_registrar_on in ies
3753*4882a593Smuzhiyun  *
3754*4882a593Smuzhiyun  * @param ie              Pointer to IEs
3755*4882a593Smuzhiyun  * @param len             Total length of ie
3756*4882a593Smuzhiyun  *
3757*4882a593Smuzhiyun  *
3758*4882a593Smuzhiyun  * @return                MTRUE/MFALSE
3759*4882a593Smuzhiyun  */
woal_is_selected_registrar_on(const t_u8 * ie,int len)3760*4882a593Smuzhiyun static t_u16 woal_is_selected_registrar_on(const t_u8 *ie, int len)
3761*4882a593Smuzhiyun {
3762*4882a593Smuzhiyun 	int left_len = len;
3763*4882a593Smuzhiyun 	const t_u8 *pos = ie;
3764*4882a593Smuzhiyun 	int length;
3765*4882a593Smuzhiyun 	t_u8 id = 0;
3766*4882a593Smuzhiyun 	IEEEtypes_VendorSpecific_t *pvendor_ie = NULL;
3767*4882a593Smuzhiyun 	const u8 wps_oui[4] = {0x00, 0x50, 0xf2, 0x04};
3768*4882a593Smuzhiyun 
3769*4882a593Smuzhiyun 	while (left_len >= 2) {
3770*4882a593Smuzhiyun 		length = *(pos + 1);
3771*4882a593Smuzhiyun 		id = *pos;
3772*4882a593Smuzhiyun 		if ((length + 2) > left_len)
3773*4882a593Smuzhiyun 			break;
3774*4882a593Smuzhiyun 		switch (id) {
3775*4882a593Smuzhiyun 		case VENDOR_SPECIFIC_221:
3776*4882a593Smuzhiyun 			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pos;
3777*4882a593Smuzhiyun 			if (!memcmp(pvendor_ie->vend_hdr.oui, wps_oui,
3778*4882a593Smuzhiyun 				    sizeof(pvendor_ie->vend_hdr.oui)) &&
3779*4882a593Smuzhiyun 			    pvendor_ie->vend_hdr.oui_type == wps_oui[3]) {
3780*4882a593Smuzhiyun 				PRINTM(MIOCTL, "Find WPS ie\n");
3781*4882a593Smuzhiyun 				return is_selected_registrar_on(pos,
3782*4882a593Smuzhiyun 								length + 2);
3783*4882a593Smuzhiyun 			}
3784*4882a593Smuzhiyun 			break;
3785*4882a593Smuzhiyun 		default:
3786*4882a593Smuzhiyun 			break;
3787*4882a593Smuzhiyun 		}
3788*4882a593Smuzhiyun 		pos += (length + 2);
3789*4882a593Smuzhiyun 		left_len -= (length + 2);
3790*4882a593Smuzhiyun 	}
3791*4882a593Smuzhiyun 	return MFALSE;
3792*4882a593Smuzhiyun }
3793*4882a593Smuzhiyun #endif
3794*4882a593Smuzhiyun 
3795*4882a593Smuzhiyun /**
3796*4882a593Smuzhiyun  * @brief config AP or GO for mgmt frame ies.
3797*4882a593Smuzhiyun  *
3798*4882a593Smuzhiyun  * @param priv                  A pointer to moal private structure
3799*4882a593Smuzhiyun  * @param beacon_ies            A pointer to beacon ies
3800*4882a593Smuzhiyun  * @param beacon_ies_len        Beacon ies length
3801*4882a593Smuzhiyun  * @param proberesp_ies         A pointer to probe resp ies
3802*4882a593Smuzhiyun  * @param proberesp_ies_len     Probe resp ies length
3803*4882a593Smuzhiyun  * @param assocresp_ies         A pointer to probe resp ies
3804*4882a593Smuzhiyun  * @param assocresp_ies_len     Assoc resp ies length
3805*4882a593Smuzhiyun  * @param probereq_ies          A pointer to probe req ies
3806*4882a593Smuzhiyun  * @param probereq_ies_len      Probe req ies length *
3807*4882a593Smuzhiyun  * @param mask					Mgmt frame mask
3808*4882a593Smuzhiyun  * @param wait_option           wait_option
3809*4882a593Smuzhiyun  *
3810*4882a593Smuzhiyun  * @return                      0 -- success, otherwise fail
3811*4882a593Smuzhiyun  */
woal_cfg80211_mgmt_frame_ie(moal_private * priv,const t_u8 * beacon_ies,size_t beacon_ies_len,const t_u8 * proberesp_ies,size_t proberesp_ies_len,const t_u8 * assocresp_ies,size_t assocresp_ies_len,const t_u8 * probereq_ies,size_t probereq_ies_len,t_u16 mask,t_u8 wait_option)3812*4882a593Smuzhiyun int woal_cfg80211_mgmt_frame_ie(
3813*4882a593Smuzhiyun 	moal_private *priv, const t_u8 *beacon_ies, size_t beacon_ies_len,
3814*4882a593Smuzhiyun 	const t_u8 *proberesp_ies, size_t proberesp_ies_len,
3815*4882a593Smuzhiyun 	const t_u8 *assocresp_ies, size_t assocresp_ies_len,
3816*4882a593Smuzhiyun 	const t_u8 *probereq_ies, size_t probereq_ies_len, t_u16 mask,
3817*4882a593Smuzhiyun 	t_u8 wait_option)
3818*4882a593Smuzhiyun {
3819*4882a593Smuzhiyun 	int ret = 0;
3820*4882a593Smuzhiyun 	t_u8 *pos = NULL;
3821*4882a593Smuzhiyun 	custom_ie *beacon_ies_data = NULL;
3822*4882a593Smuzhiyun 	custom_ie *proberesp_ies_data = NULL;
3823*4882a593Smuzhiyun 	custom_ie *assocresp_ies_data = NULL;
3824*4882a593Smuzhiyun 	custom_ie *probereq_ies_data = NULL;
3825*4882a593Smuzhiyun 
3826*4882a593Smuzhiyun 	/* static variables for mgmt frame ie auto-indexing */
3827*4882a593Smuzhiyun 	t_u16 beacon_index = priv->beacon_index;
3828*4882a593Smuzhiyun 	t_u16 proberesp_index = priv->proberesp_index;
3829*4882a593Smuzhiyun 	t_u16 assocresp_index = priv->assocresp_index;
3830*4882a593Smuzhiyun 	t_u16 probereq_index = priv->probereq_index;
3831*4882a593Smuzhiyun 	t_u16 beacon_wps_index = priv->beacon_wps_index;
3832*4882a593Smuzhiyun 	t_u16 proberesp_p2p_index = priv->proberesp_p2p_index;
3833*4882a593Smuzhiyun 	t_u16 assocrep_qos_map_index = priv->assocresp_qos_map_index;
3834*4882a593Smuzhiyun 	t_u16 beacon_vendor_index = priv->beacon_vendor_index;
3835*4882a593Smuzhiyun 
3836*4882a593Smuzhiyun 	ENTER();
3837*4882a593Smuzhiyun 
3838*4882a593Smuzhiyun 	/* we need remove vendor IE from beacon extra IE, vendor IE will be
3839*4882a593Smuzhiyun 	 * configure through proberesp_vendor_index
3840*4882a593Smuzhiyun 	 */
3841*4882a593Smuzhiyun 	if (mask & MGMT_MASK_BEACON_WPS_P2P) {
3842*4882a593Smuzhiyun 		beacon_ies_data = kzalloc(sizeof(custom_ie), GFP_KERNEL);
3843*4882a593Smuzhiyun 		if (!beacon_ies_data) {
3844*4882a593Smuzhiyun 			ret = -ENOMEM;
3845*4882a593Smuzhiyun 			goto done;
3846*4882a593Smuzhiyun 		}
3847*4882a593Smuzhiyun 		if (beacon_ies && beacon_ies_len) {
3848*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
3849*4882a593Smuzhiyun 			if (woal_is_selected_registrar_on(beacon_ies,
3850*4882a593Smuzhiyun 							  beacon_ies_len)) {
3851*4882a593Smuzhiyun 				PRINTM(MIOCTL, "selected_registrar is on\n");
3852*4882a593Smuzhiyun 				priv->phandle->is_go_timer_set = MTRUE;
3853*4882a593Smuzhiyun 				woal_mod_timer(&priv->phandle->go_timer,
3854*4882a593Smuzhiyun 					       MOAL_TIMER_10S);
3855*4882a593Smuzhiyun 			} else
3856*4882a593Smuzhiyun 				PRINTM(MIOCTL, "selected_registrar is off\n");
3857*4882a593Smuzhiyun #endif
3858*4882a593Smuzhiyun 			beacon_ies_data->ie_index = beacon_wps_index;
3859*4882a593Smuzhiyun 			beacon_ies_data->mgmt_subtype_mask = MGMT_MASK_BEACON;
3860*4882a593Smuzhiyun 			beacon_ies_data->ie_length = woal_filter_beacon_ies(
3861*4882a593Smuzhiyun 				priv, beacon_ies, beacon_ies_len,
3862*4882a593Smuzhiyun 				beacon_ies_data->ie_buffer, MAX_IE_SIZE,
3863*4882a593Smuzhiyun 				IE_MASK_VENDOR, NULL, 0);
3864*4882a593Smuzhiyun 			DBG_HEXDUMP(MCMD_D, "beacon extra ie",
3865*4882a593Smuzhiyun 				    beacon_ies_data->ie_buffer,
3866*4882a593Smuzhiyun 				    beacon_ies_data->ie_length);
3867*4882a593Smuzhiyun 		} else {
3868*4882a593Smuzhiyun 			/* clear the beacon wps ies */
3869*4882a593Smuzhiyun 			if (beacon_wps_index > MAX_MGMT_IE_INDEX) {
3870*4882a593Smuzhiyun 				PRINTM(MERROR,
3871*4882a593Smuzhiyun 				       "Invalid beacon wps index for mgmt frame ie.\n");
3872*4882a593Smuzhiyun 				ret = -EFAULT;
3873*4882a593Smuzhiyun 				goto done;
3874*4882a593Smuzhiyun 			}
3875*4882a593Smuzhiyun 
3876*4882a593Smuzhiyun 			beacon_ies_data->ie_index = beacon_wps_index;
3877*4882a593Smuzhiyun 			beacon_ies_data->mgmt_subtype_mask =
3878*4882a593Smuzhiyun 				MLAN_CUSTOM_IE_DELETE_MASK;
3879*4882a593Smuzhiyun 			beacon_ies_data->ie_length = 0;
3880*4882a593Smuzhiyun 			beacon_wps_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
3881*4882a593Smuzhiyun 		}
3882*4882a593Smuzhiyun 		if ((beacon_ies && beacon_ies_len &&
3883*4882a593Smuzhiyun 		     beacon_ies_data->ie_length) ||
3884*4882a593Smuzhiyun 		    (beacon_ies_data->mgmt_subtype_mask ==
3885*4882a593Smuzhiyun 		     MLAN_CUSTOM_IE_DELETE_MASK)) {
3886*4882a593Smuzhiyun 			if (MLAN_STATUS_FAILURE ==
3887*4882a593Smuzhiyun 			    woal_cfg80211_custom_ie(
3888*4882a593Smuzhiyun 				    priv, beacon_ies_data, &beacon_wps_index,
3889*4882a593Smuzhiyun 				    proberesp_ies_data, &proberesp_index,
3890*4882a593Smuzhiyun 				    assocresp_ies_data, &assocresp_index,
3891*4882a593Smuzhiyun 				    probereq_ies_data, &probereq_index,
3892*4882a593Smuzhiyun 				    wait_option)) {
3893*4882a593Smuzhiyun 				PRINTM(MERROR, "Fail to set beacon wps IE\n");
3894*4882a593Smuzhiyun 				ret = -EFAULT;
3895*4882a593Smuzhiyun 			}
3896*4882a593Smuzhiyun 			priv->beacon_wps_index = beacon_wps_index;
3897*4882a593Smuzhiyun 			PRINTM(MCMND, "beacon_wps_index=0x%x len=%d\n",
3898*4882a593Smuzhiyun 			       beacon_wps_index, beacon_ies_data->ie_length);
3899*4882a593Smuzhiyun 			goto done;
3900*4882a593Smuzhiyun 		}
3901*4882a593Smuzhiyun 		kfree(beacon_ies_data); // Further allocation of beacon_ies_data
3902*4882a593Smuzhiyun 					// is happening, so need to free here.
3903*4882a593Smuzhiyun 		beacon_ies_data = NULL;
3904*4882a593Smuzhiyun 	}
3905*4882a593Smuzhiyun 
3906*4882a593Smuzhiyun 	if (mask & MGMT_MASK_ASSOC_RESP_QOS_MAP) {
3907*4882a593Smuzhiyun 		assocresp_ies_data = kzalloc(sizeof(custom_ie), GFP_KERNEL);
3908*4882a593Smuzhiyun 		if (!assocresp_ies_data) {
3909*4882a593Smuzhiyun 			ret = -ENOMEM;
3910*4882a593Smuzhiyun 			goto done;
3911*4882a593Smuzhiyun 		}
3912*4882a593Smuzhiyun 		if (assocresp_ies && assocresp_ies_len) {
3913*4882a593Smuzhiyun 			/* set the assoc response qos map ies */
3914*4882a593Smuzhiyun 			assocresp_ies_data->ie_index = assocrep_qos_map_index;
3915*4882a593Smuzhiyun 			assocresp_ies_data->mgmt_subtype_mask =
3916*4882a593Smuzhiyun 				MGMT_MASK_ASSOC_RESP;
3917*4882a593Smuzhiyun 			if (MLAN_CUSTOM_IE_AUTO_IDX_MASK ==
3918*4882a593Smuzhiyun 			    assocrep_qos_map_index)
3919*4882a593Smuzhiyun 				assocresp_ies_data->mgmt_subtype_mask |=
3920*4882a593Smuzhiyun 					MLAN_CUSTOM_IE_NEW_MASK;
3921*4882a593Smuzhiyun 			if (assocresp_ies_len > MAX_IE_SIZE) {
3922*4882a593Smuzhiyun 				PRINTM(MERROR,
3923*4882a593Smuzhiyun 				       "IE too big: assocresp_ies_len=%d\n",
3924*4882a593Smuzhiyun 				       (int)assocresp_ies_len);
3925*4882a593Smuzhiyun 				ret = -EFAULT;
3926*4882a593Smuzhiyun 				goto done;
3927*4882a593Smuzhiyun 			}
3928*4882a593Smuzhiyun 			assocresp_ies_data->ie_length = assocresp_ies_len;
3929*4882a593Smuzhiyun 			pos = assocresp_ies_data->ie_buffer;
3930*4882a593Smuzhiyun 			moal_memcpy_ext(priv->phandle, pos, assocresp_ies,
3931*4882a593Smuzhiyun 					assocresp_ies_len, MAX_IE_SIZE);
3932*4882a593Smuzhiyun 			DBG_HEXDUMP(MCMD_D, "Qos Map",
3933*4882a593Smuzhiyun 				    assocresp_ies_data->ie_buffer,
3934*4882a593Smuzhiyun 				    assocresp_ies_data->ie_length);
3935*4882a593Smuzhiyun 		} else {
3936*4882a593Smuzhiyun 			/* clear the assoc response qos map ie */
3937*4882a593Smuzhiyun 			if (assocrep_qos_map_index > MAX_MGMT_IE_INDEX) {
3938*4882a593Smuzhiyun 				PRINTM(MERROR,
3939*4882a593Smuzhiyun 				       "Invalid Qos map index for mgmt frame ie.\n");
3940*4882a593Smuzhiyun 				ret = -EFAULT;
3941*4882a593Smuzhiyun 				goto done;
3942*4882a593Smuzhiyun 			}
3943*4882a593Smuzhiyun 
3944*4882a593Smuzhiyun 			assocresp_ies_data->ie_index = assocrep_qos_map_index;
3945*4882a593Smuzhiyun 			assocresp_ies_data->mgmt_subtype_mask =
3946*4882a593Smuzhiyun 				MLAN_CUSTOM_IE_DELETE_MASK;
3947*4882a593Smuzhiyun 			assocresp_ies_data->ie_length = 0;
3948*4882a593Smuzhiyun 			assocrep_qos_map_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
3949*4882a593Smuzhiyun 		}
3950*4882a593Smuzhiyun 		if (MLAN_STATUS_FAILURE ==
3951*4882a593Smuzhiyun 		    woal_cfg80211_custom_ie(priv, NULL, &beacon_wps_index, NULL,
3952*4882a593Smuzhiyun 					    &proberesp_index,
3953*4882a593Smuzhiyun 					    assocresp_ies_data,
3954*4882a593Smuzhiyun 					    &assocrep_qos_map_index, NULL,
3955*4882a593Smuzhiyun 					    &probereq_index, wait_option)) {
3956*4882a593Smuzhiyun 			PRINTM(MERROR, "Fail to set Qos map IE\n");
3957*4882a593Smuzhiyun 			ret = -EFAULT;
3958*4882a593Smuzhiyun 		}
3959*4882a593Smuzhiyun 		priv->assocresp_qos_map_index = assocrep_qos_map_index;
3960*4882a593Smuzhiyun 		PRINTM(MCMND, "qos map ie index=0x%x len=%d\n",
3961*4882a593Smuzhiyun 		       assocrep_qos_map_index, assocresp_ies_data->ie_length);
3962*4882a593Smuzhiyun 		goto done;
3963*4882a593Smuzhiyun 	}
3964*4882a593Smuzhiyun 
3965*4882a593Smuzhiyun 	if (mask & MGMT_MASK_BEACON) {
3966*4882a593Smuzhiyun 		beacon_ies_data = kzalloc(sizeof(custom_ie), GFP_KERNEL);
3967*4882a593Smuzhiyun 		if (!beacon_ies_data) {
3968*4882a593Smuzhiyun 			ret = -ENOMEM;
3969*4882a593Smuzhiyun 			goto done;
3970*4882a593Smuzhiyun 		}
3971*4882a593Smuzhiyun 	}
3972*4882a593Smuzhiyun 
3973*4882a593Smuzhiyun 	if (mask & MGMT_MASK_PROBE_RESP) {
3974*4882a593Smuzhiyun 		/** set or clear proberesp ie */
3975*4882a593Smuzhiyun 		if (proberesp_ies_len ||
3976*4882a593Smuzhiyun 		    (!proberesp_ies_len && !beacon_ies_len)) {
3977*4882a593Smuzhiyun 			proberesp_ies_data =
3978*4882a593Smuzhiyun 				kzalloc(sizeof(custom_ie), GFP_KERNEL);
3979*4882a593Smuzhiyun 			if (!proberesp_ies_data) {
3980*4882a593Smuzhiyun 				ret = -ENOMEM;
3981*4882a593Smuzhiyun 				goto done;
3982*4882a593Smuzhiyun 			}
3983*4882a593Smuzhiyun 		}
3984*4882a593Smuzhiyun 	}
3985*4882a593Smuzhiyun 
3986*4882a593Smuzhiyun 	if (mask & MGMT_MASK_ASSOC_RESP) {
3987*4882a593Smuzhiyun 		/** set or clear assocresp ie */
3988*4882a593Smuzhiyun 		if (assocresp_ies_len ||
3989*4882a593Smuzhiyun 		    (!assocresp_ies_len && !beacon_ies_len)) {
3990*4882a593Smuzhiyun 			assocresp_ies_data =
3991*4882a593Smuzhiyun 				kzalloc(sizeof(custom_ie), GFP_KERNEL);
3992*4882a593Smuzhiyun 			if (!assocresp_ies_data) {
3993*4882a593Smuzhiyun 				ret = -ENOMEM;
3994*4882a593Smuzhiyun 				goto done;
3995*4882a593Smuzhiyun 			}
3996*4882a593Smuzhiyun 		}
3997*4882a593Smuzhiyun 	}
3998*4882a593Smuzhiyun 	if (mask & MGMT_MASK_PROBE_REQ) {
3999*4882a593Smuzhiyun 		probereq_ies_data = kzalloc(sizeof(custom_ie), GFP_KERNEL);
4000*4882a593Smuzhiyun 		if (!probereq_ies_data) {
4001*4882a593Smuzhiyun 			ret = -ENOMEM;
4002*4882a593Smuzhiyun 			goto done;
4003*4882a593Smuzhiyun 		}
4004*4882a593Smuzhiyun 	}
4005*4882a593Smuzhiyun 
4006*4882a593Smuzhiyun 	if (beacon_ies_data) {
4007*4882a593Smuzhiyun 		if (beacon_ies && beacon_ies_len) {
4008*4882a593Smuzhiyun 			/* set the probe response/beacon vendor ies which
4009*4882a593Smuzhiyun 			 * includes wpa IE
4010*4882a593Smuzhiyun 			 */
4011*4882a593Smuzhiyun 			beacon_ies_data->ie_index = beacon_vendor_index;
4012*4882a593Smuzhiyun 			beacon_ies_data->mgmt_subtype_mask =
4013*4882a593Smuzhiyun 				MGMT_MASK_PROBE_RESP | MGMT_MASK_BEACON;
4014*4882a593Smuzhiyun 			if (beacon_vendor_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK)
4015*4882a593Smuzhiyun 				beacon_ies_data->mgmt_subtype_mask |=
4016*4882a593Smuzhiyun 					MLAN_CUSTOM_IE_NEW_MASK;
4017*4882a593Smuzhiyun 			beacon_ies_data->ie_length =
4018*4882a593Smuzhiyun 				woal_get_specific_ie(beacon_ies, beacon_ies_len,
4019*4882a593Smuzhiyun 						     beacon_ies_data->ie_buffer,
4020*4882a593Smuzhiyun 						     MAX_IE_SIZE,
4021*4882a593Smuzhiyun 						     IE_MASK_VENDOR);
4022*4882a593Smuzhiyun 			DBG_HEXDUMP(MCMD_D, "beacon vendor IE",
4023*4882a593Smuzhiyun 				    beacon_ies_data->ie_buffer,
4024*4882a593Smuzhiyun 				    beacon_ies_data->ie_length);
4025*4882a593Smuzhiyun 		}
4026*4882a593Smuzhiyun 		if (beacon_vendor_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK &&
4027*4882a593Smuzhiyun 		    !beacon_ies_data->ie_length) {
4028*4882a593Smuzhiyun 			/* clear the beacon vendor ies */
4029*4882a593Smuzhiyun 			if (beacon_vendor_index > MAX_MGMT_IE_INDEX) {
4030*4882a593Smuzhiyun 				PRINTM(MERROR,
4031*4882a593Smuzhiyun 				       "Invalid beacon_vendor_index for mgmt frame ie.\n");
4032*4882a593Smuzhiyun 				ret = -EFAULT;
4033*4882a593Smuzhiyun 				goto done;
4034*4882a593Smuzhiyun 			}
4035*4882a593Smuzhiyun 			beacon_ies_data->ie_index = beacon_vendor_index;
4036*4882a593Smuzhiyun 			beacon_ies_data->mgmt_subtype_mask =
4037*4882a593Smuzhiyun 				MLAN_CUSTOM_IE_DELETE_MASK;
4038*4882a593Smuzhiyun 			beacon_ies_data->ie_length = 0;
4039*4882a593Smuzhiyun 			beacon_vendor_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
4040*4882a593Smuzhiyun 		}
4041*4882a593Smuzhiyun 		if ((beacon_ies && beacon_ies_len &&
4042*4882a593Smuzhiyun 		     beacon_ies_data->ie_length) ||
4043*4882a593Smuzhiyun 		    (beacon_ies_data->mgmt_subtype_mask ==
4044*4882a593Smuzhiyun 		     MLAN_CUSTOM_IE_DELETE_MASK)) {
4045*4882a593Smuzhiyun 			if (MLAN_STATUS_FAILURE ==
4046*4882a593Smuzhiyun 			    woal_cfg80211_custom_ie(
4047*4882a593Smuzhiyun 				    priv, beacon_ies_data, &beacon_vendor_index,
4048*4882a593Smuzhiyun 				    NULL, &proberesp_index, NULL,
4049*4882a593Smuzhiyun 				    &assocresp_index, NULL, &probereq_index,
4050*4882a593Smuzhiyun 				    wait_option)) {
4051*4882a593Smuzhiyun 				PRINTM(MERROR,
4052*4882a593Smuzhiyun 				       "Fail to set beacon vendor IE\n");
4053*4882a593Smuzhiyun 				ret = -EFAULT;
4054*4882a593Smuzhiyun 				goto done;
4055*4882a593Smuzhiyun 			}
4056*4882a593Smuzhiyun 			priv->beacon_vendor_index = beacon_vendor_index;
4057*4882a593Smuzhiyun 			PRINTM(MCMND, "beacon_vendor=0x%x len=%d\n",
4058*4882a593Smuzhiyun 			       beacon_vendor_index, beacon_ies_data->ie_length);
4059*4882a593Smuzhiyun 		}
4060*4882a593Smuzhiyun 		memset(beacon_ies_data, 0x00, sizeof(custom_ie));
4061*4882a593Smuzhiyun 		if (beacon_ies && beacon_ies_len) {
4062*4882a593Smuzhiyun 			/* set the beacon ies */
4063*4882a593Smuzhiyun 			/* we need remove vendor IE from beacon tail, vendor/wpa
4064*4882a593Smuzhiyun 			 * IE will be configure through beacon_vendor_index
4065*4882a593Smuzhiyun 			 */
4066*4882a593Smuzhiyun 			beacon_ies_data->ie_index = beacon_index;
4067*4882a593Smuzhiyun 			beacon_ies_data->mgmt_subtype_mask =
4068*4882a593Smuzhiyun 				MGMT_MASK_BEACON | MGMT_MASK_ASSOC_RESP |
4069*4882a593Smuzhiyun 				MGMT_MASK_PROBE_RESP;
4070*4882a593Smuzhiyun 			beacon_ies_data->ie_length = woal_filter_beacon_ies(
4071*4882a593Smuzhiyun 				priv, beacon_ies, beacon_ies_len,
4072*4882a593Smuzhiyun 				beacon_ies_data->ie_buffer, MAX_IE_SIZE,
4073*4882a593Smuzhiyun 				IE_MASK_WPS | IE_MASK_WFD | IE_MASK_P2P |
4074*4882a593Smuzhiyun 					IE_MASK_VENDOR,
4075*4882a593Smuzhiyun 				proberesp_ies, proberesp_ies_len);
4076*4882a593Smuzhiyun 			if (beacon_ies_data->ie_length)
4077*4882a593Smuzhiyun 				DBG_HEXDUMP(MCMD_D, "beacon ie",
4078*4882a593Smuzhiyun 					    beacon_ies_data->ie_buffer,
4079*4882a593Smuzhiyun 					    beacon_ies_data->ie_length);
4080*4882a593Smuzhiyun 			else {
4081*4882a593Smuzhiyun 				kfree(beacon_ies_data);
4082*4882a593Smuzhiyun 				beacon_ies_data = NULL;
4083*4882a593Smuzhiyun 			}
4084*4882a593Smuzhiyun 		} else {
4085*4882a593Smuzhiyun 			/* clear the beacon ies */
4086*4882a593Smuzhiyun 			if (beacon_index > MAX_MGMT_IE_INDEX) {
4087*4882a593Smuzhiyun 				PRINTM(MINFO,
4088*4882a593Smuzhiyun 				       "Invalid beacon index for mgmt frame ie.\n");
4089*4882a593Smuzhiyun 				ret = -EFAULT;
4090*4882a593Smuzhiyun 				goto done;
4091*4882a593Smuzhiyun 			}
4092*4882a593Smuzhiyun 
4093*4882a593Smuzhiyun 			beacon_ies_data->ie_index = beacon_index;
4094*4882a593Smuzhiyun 			beacon_ies_data->mgmt_subtype_mask =
4095*4882a593Smuzhiyun 				MLAN_CUSTOM_IE_DELETE_MASK;
4096*4882a593Smuzhiyun 			beacon_ies_data->ie_length = 0;
4097*4882a593Smuzhiyun 			beacon_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
4098*4882a593Smuzhiyun 		}
4099*4882a593Smuzhiyun 	}
4100*4882a593Smuzhiyun 
4101*4882a593Smuzhiyun 	if (proberesp_ies_data) {
4102*4882a593Smuzhiyun 		proberesp_ies_data->mgmt_subtype_mask = 0xff;
4103*4882a593Smuzhiyun 		if (proberesp_ies && proberesp_ies_len) {
4104*4882a593Smuzhiyun 			/* set the probe response p2p ies */
4105*4882a593Smuzhiyun 			proberesp_ies_data->ie_index = proberesp_p2p_index;
4106*4882a593Smuzhiyun 			proberesp_ies_data->mgmt_subtype_mask =
4107*4882a593Smuzhiyun 				MGMT_MASK_PROBE_RESP;
4108*4882a593Smuzhiyun 			proberesp_ies_data->ie_length = woal_get_specific_ie(
4109*4882a593Smuzhiyun 				proberesp_ies, proberesp_ies_len,
4110*4882a593Smuzhiyun 				proberesp_ies_data->ie_buffer, MAX_IE_SIZE,
4111*4882a593Smuzhiyun 				IE_MASK_P2P);
4112*4882a593Smuzhiyun 			DBG_HEXDUMP(MCMD_D, "proberesp p2p ie",
4113*4882a593Smuzhiyun 				    proberesp_ies_data->ie_buffer,
4114*4882a593Smuzhiyun 				    proberesp_ies_data->ie_length);
4115*4882a593Smuzhiyun 		} else if (proberesp_p2p_index !=
4116*4882a593Smuzhiyun 			   MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
4117*4882a593Smuzhiyun 			/* clear the probe response p2p ies */
4118*4882a593Smuzhiyun 			if (proberesp_p2p_index > MAX_MGMT_IE_INDEX) {
4119*4882a593Smuzhiyun 				PRINTM(MERROR,
4120*4882a593Smuzhiyun 				       "Invalid proberesp_p2p_index for mgmt frame ie.\n");
4121*4882a593Smuzhiyun 				ret = -EFAULT;
4122*4882a593Smuzhiyun 				goto done;
4123*4882a593Smuzhiyun 			}
4124*4882a593Smuzhiyun 			proberesp_ies_data->ie_index = proberesp_p2p_index;
4125*4882a593Smuzhiyun 			proberesp_ies_data->mgmt_subtype_mask =
4126*4882a593Smuzhiyun 				MLAN_CUSTOM_IE_DELETE_MASK;
4127*4882a593Smuzhiyun 			proberesp_ies_data->ie_length = 0;
4128*4882a593Smuzhiyun 			proberesp_p2p_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
4129*4882a593Smuzhiyun 		}
4130*4882a593Smuzhiyun 		if ((proberesp_ies && proberesp_ies_len &&
4131*4882a593Smuzhiyun 		     proberesp_ies_data->ie_length) ||
4132*4882a593Smuzhiyun 		    (proberesp_ies_data->mgmt_subtype_mask ==
4133*4882a593Smuzhiyun 		     MLAN_CUSTOM_IE_DELETE_MASK)) {
4134*4882a593Smuzhiyun 			if (MLAN_STATUS_FAILURE ==
4135*4882a593Smuzhiyun 			    woal_cfg80211_custom_ie(
4136*4882a593Smuzhiyun 				    priv, NULL, &beacon_index,
4137*4882a593Smuzhiyun 				    proberesp_ies_data, &proberesp_p2p_index,
4138*4882a593Smuzhiyun 				    NULL, &assocresp_index, NULL,
4139*4882a593Smuzhiyun 				    &probereq_index, wait_option)) {
4140*4882a593Smuzhiyun 				PRINTM(MERROR,
4141*4882a593Smuzhiyun 				       "Fail to set proberesp p2p IE\n");
4142*4882a593Smuzhiyun 				ret = -EFAULT;
4143*4882a593Smuzhiyun 				goto done;
4144*4882a593Smuzhiyun 			}
4145*4882a593Smuzhiyun 			priv->proberesp_p2p_index = proberesp_p2p_index;
4146*4882a593Smuzhiyun 			PRINTM(MCMND, "proberesp_p2p=0x%x len=%d\n",
4147*4882a593Smuzhiyun 			       proberesp_p2p_index,
4148*4882a593Smuzhiyun 			       proberesp_ies_data->ie_length);
4149*4882a593Smuzhiyun 		}
4150*4882a593Smuzhiyun 		memset(proberesp_ies_data, 0x00, sizeof(custom_ie));
4151*4882a593Smuzhiyun 		if (proberesp_ies && proberesp_ies_len) {
4152*4882a593Smuzhiyun 			/* set the probe response ies */
4153*4882a593Smuzhiyun 			proberesp_ies_data->ie_index = proberesp_index;
4154*4882a593Smuzhiyun 			proberesp_ies_data->mgmt_subtype_mask =
4155*4882a593Smuzhiyun 				MGMT_MASK_PROBE_RESP;
4156*4882a593Smuzhiyun 			if (proberesp_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK)
4157*4882a593Smuzhiyun 				proberesp_ies_data->mgmt_subtype_mask |=
4158*4882a593Smuzhiyun 					MLAN_CUSTOM_IE_NEW_MASK;
4159*4882a593Smuzhiyun 			proberesp_ies_data->ie_length = woal_filter_beacon_ies(
4160*4882a593Smuzhiyun 				priv, proberesp_ies, proberesp_ies_len,
4161*4882a593Smuzhiyun 				proberesp_ies_data->ie_buffer, MAX_IE_SIZE,
4162*4882a593Smuzhiyun 				IE_MASK_P2P | IE_MASK_VENDOR, NULL, 0);
4163*4882a593Smuzhiyun 			if (proberesp_ies_data->ie_length) {
4164*4882a593Smuzhiyun 				DBG_HEXDUMP(MCMD_D, "proberesp ie",
4165*4882a593Smuzhiyun 					    proberesp_ies_data->ie_buffer,
4166*4882a593Smuzhiyun 					    proberesp_ies_data->ie_length);
4167*4882a593Smuzhiyun 			} else {
4168*4882a593Smuzhiyun 				kfree(proberesp_ies_data);
4169*4882a593Smuzhiyun 				proberesp_ies_data = NULL;
4170*4882a593Smuzhiyun 			}
4171*4882a593Smuzhiyun 		} else {
4172*4882a593Smuzhiyun 			/* clear the probe response ies */
4173*4882a593Smuzhiyun 			if (proberesp_index > MAX_MGMT_IE_INDEX) {
4174*4882a593Smuzhiyun 				PRINTM(MERROR,
4175*4882a593Smuzhiyun 				       "Invalid probe resp index for mgmt frame ie.\n");
4176*4882a593Smuzhiyun 				ret = -EFAULT;
4177*4882a593Smuzhiyun 				goto done;
4178*4882a593Smuzhiyun 			}
4179*4882a593Smuzhiyun 			proberesp_ies_data->ie_index = proberesp_index;
4180*4882a593Smuzhiyun 			proberesp_ies_data->mgmt_subtype_mask =
4181*4882a593Smuzhiyun 				MLAN_CUSTOM_IE_DELETE_MASK;
4182*4882a593Smuzhiyun 			proberesp_ies_data->ie_length = 0;
4183*4882a593Smuzhiyun 			proberesp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
4184*4882a593Smuzhiyun 		}
4185*4882a593Smuzhiyun 	}
4186*4882a593Smuzhiyun 	if (assocresp_ies_data) {
4187*4882a593Smuzhiyun 		if (assocresp_ies && assocresp_ies_len) {
4188*4882a593Smuzhiyun 			/* set the assoc response ies */
4189*4882a593Smuzhiyun 			assocresp_ies_data->ie_index = assocresp_index;
4190*4882a593Smuzhiyun 			assocresp_ies_data->mgmt_subtype_mask =
4191*4882a593Smuzhiyun 				MGMT_MASK_ASSOC_RESP;
4192*4882a593Smuzhiyun 			if (assocresp_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK)
4193*4882a593Smuzhiyun 				assocresp_ies_data->mgmt_subtype_mask |=
4194*4882a593Smuzhiyun 					MLAN_CUSTOM_IE_NEW_MASK;
4195*4882a593Smuzhiyun 			if (assocresp_ies_len > MAX_IE_SIZE) {
4196*4882a593Smuzhiyun 				PRINTM(MERROR,
4197*4882a593Smuzhiyun 				       "IE too big, assocresp_ies_len=%d\n",
4198*4882a593Smuzhiyun 				       (int)assocresp_ies_len);
4199*4882a593Smuzhiyun 				ret = -EFAULT;
4200*4882a593Smuzhiyun 				goto done;
4201*4882a593Smuzhiyun 			}
4202*4882a593Smuzhiyun 			assocresp_ies_data->ie_length = assocresp_ies_len;
4203*4882a593Smuzhiyun 			pos = assocresp_ies_data->ie_buffer;
4204*4882a593Smuzhiyun 			moal_memcpy_ext(priv->phandle, pos, assocresp_ies,
4205*4882a593Smuzhiyun 					assocresp_ies_len, MAX_IE_SIZE);
4206*4882a593Smuzhiyun 			DBG_HEXDUMP(MCMD_D, "assocresp ie",
4207*4882a593Smuzhiyun 				    assocresp_ies_data->ie_buffer,
4208*4882a593Smuzhiyun 				    assocresp_ies_data->ie_length);
4209*4882a593Smuzhiyun 		} else {
4210*4882a593Smuzhiyun 			/* clear the assoc response ies */
4211*4882a593Smuzhiyun 			if (assocresp_index > MAX_MGMT_IE_INDEX) {
4212*4882a593Smuzhiyun 				PRINTM(MERROR,
4213*4882a593Smuzhiyun 				       "Invalid assoc resp index for mgmt frame ie.\n");
4214*4882a593Smuzhiyun 				ret = -EFAULT;
4215*4882a593Smuzhiyun 				goto done;
4216*4882a593Smuzhiyun 			}
4217*4882a593Smuzhiyun 
4218*4882a593Smuzhiyun 			assocresp_ies_data->ie_index = assocresp_index;
4219*4882a593Smuzhiyun 			assocresp_ies_data->mgmt_subtype_mask =
4220*4882a593Smuzhiyun 				MLAN_CUSTOM_IE_DELETE_MASK;
4221*4882a593Smuzhiyun 			assocresp_ies_data->ie_length = 0;
4222*4882a593Smuzhiyun 			assocresp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
4223*4882a593Smuzhiyun 		}
4224*4882a593Smuzhiyun 	}
4225*4882a593Smuzhiyun 
4226*4882a593Smuzhiyun 	if (probereq_ies_data) {
4227*4882a593Smuzhiyun 		if (probereq_ies && probereq_ies_len) {
4228*4882a593Smuzhiyun 			/* set the probe req ies */
4229*4882a593Smuzhiyun 			probereq_ies_data->ie_index = probereq_index;
4230*4882a593Smuzhiyun 			probereq_ies_data->mgmt_subtype_mask =
4231*4882a593Smuzhiyun 				MGMT_MASK_PROBE_REQ;
4232*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
4233*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
4234*4882a593Smuzhiyun 			if (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) {
4235*4882a593Smuzhiyun 				/* filter out P2P/WFD ie/EXT_CAP ie */
4236*4882a593Smuzhiyun 				probereq_ies_data->ie_length =
4237*4882a593Smuzhiyun 					woal_filter_beacon_ies(
4238*4882a593Smuzhiyun 						priv, probereq_ies,
4239*4882a593Smuzhiyun 						probereq_ies_len,
4240*4882a593Smuzhiyun 						probereq_ies_data->ie_buffer,
4241*4882a593Smuzhiyun 						MAX_IE_SIZE,
4242*4882a593Smuzhiyun 						IE_MASK_P2P | IE_MASK_WFD |
4243*4882a593Smuzhiyun 							IE_MASK_EXTCAP,
4244*4882a593Smuzhiyun 						NULL, 0);
4245*4882a593Smuzhiyun 			} else {
4246*4882a593Smuzhiyun #endif /* KERNEL_VERSION */
4247*4882a593Smuzhiyun #endif /* WIFI_DIRECT_SUPPORT */
4248*4882a593Smuzhiyun 				if (probereq_ies_len > MAX_IE_SIZE) {
4249*4882a593Smuzhiyun 					PRINTM(MERROR,
4250*4882a593Smuzhiyun 					       "IE too big, probereq_ies_len=%d\n",
4251*4882a593Smuzhiyun 					       (int)probereq_ies_len);
4252*4882a593Smuzhiyun 					ret = -EFAULT;
4253*4882a593Smuzhiyun 					goto done;
4254*4882a593Smuzhiyun 				}
4255*4882a593Smuzhiyun 				probereq_ies_data->ie_length = probereq_ies_len;
4256*4882a593Smuzhiyun 				pos = probereq_ies_data->ie_buffer;
4257*4882a593Smuzhiyun 				moal_memcpy_ext(priv->phandle, pos,
4258*4882a593Smuzhiyun 						probereq_ies, probereq_ies_len,
4259*4882a593Smuzhiyun 						MAX_IE_SIZE);
4260*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
4261*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
4262*4882a593Smuzhiyun 			}
4263*4882a593Smuzhiyun #endif /* KERNEL_VERSION */
4264*4882a593Smuzhiyun #endif /* WIFI_DIRECT_SUPPORT */
4265*4882a593Smuzhiyun 			if (probereq_ies_data->ie_length)
4266*4882a593Smuzhiyun 				DBG_HEXDUMP(MCMD_D, "probereq ie",
4267*4882a593Smuzhiyun 					    probereq_ies_data->ie_buffer,
4268*4882a593Smuzhiyun 					    probereq_ies_data->ie_length);
4269*4882a593Smuzhiyun 			else {
4270*4882a593Smuzhiyun 				kfree(probereq_ies_data);
4271*4882a593Smuzhiyun 				probereq_ies_data = NULL;
4272*4882a593Smuzhiyun 			}
4273*4882a593Smuzhiyun 		} else {
4274*4882a593Smuzhiyun 			/* clear the probe req ies */
4275*4882a593Smuzhiyun 			if (probereq_index > MAX_MGMT_IE_INDEX) {
4276*4882a593Smuzhiyun 				PRINTM(MERROR,
4277*4882a593Smuzhiyun 				       "Invalid probe req index for mgmt frame ie.\n");
4278*4882a593Smuzhiyun 				ret = -EFAULT;
4279*4882a593Smuzhiyun 				goto done;
4280*4882a593Smuzhiyun 			}
4281*4882a593Smuzhiyun 			probereq_ies_data->ie_index = probereq_index;
4282*4882a593Smuzhiyun 			probereq_ies_data->mgmt_subtype_mask =
4283*4882a593Smuzhiyun 				MLAN_CUSTOM_IE_DELETE_MASK;
4284*4882a593Smuzhiyun 			probereq_ies_data->ie_length = 0;
4285*4882a593Smuzhiyun 			probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
4286*4882a593Smuzhiyun 		}
4287*4882a593Smuzhiyun 	}
4288*4882a593Smuzhiyun 
4289*4882a593Smuzhiyun 	if (beacon_ies_data || proberesp_ies_data || assocresp_ies_data ||
4290*4882a593Smuzhiyun 	    probereq_ies_data) {
4291*4882a593Smuzhiyun 		if (MLAN_STATUS_FAILURE ==
4292*4882a593Smuzhiyun 		    woal_cfg80211_custom_ie(
4293*4882a593Smuzhiyun 			    priv, beacon_ies_data, &beacon_index,
4294*4882a593Smuzhiyun 			    proberesp_ies_data, &proberesp_index,
4295*4882a593Smuzhiyun 			    assocresp_ies_data, &assocresp_index,
4296*4882a593Smuzhiyun 			    probereq_ies_data, &probereq_index, wait_option)) {
4297*4882a593Smuzhiyun 			PRINTM(MERROR,
4298*4882a593Smuzhiyun 			       "Fail to set beacon proberesp assoc probereq IES\n");
4299*4882a593Smuzhiyun 			ret = -EFAULT;
4300*4882a593Smuzhiyun 			goto done;
4301*4882a593Smuzhiyun 		}
4302*4882a593Smuzhiyun 	}
4303*4882a593Smuzhiyun 	if (beacon_ies_data) {
4304*4882a593Smuzhiyun 		priv->beacon_index = beacon_index;
4305*4882a593Smuzhiyun 		PRINTM(MCMND, "beacon ie length = %d\n",
4306*4882a593Smuzhiyun 		       beacon_ies_data->ie_length);
4307*4882a593Smuzhiyun 	}
4308*4882a593Smuzhiyun 	if (assocresp_ies_data) {
4309*4882a593Smuzhiyun 		priv->assocresp_index = assocresp_index;
4310*4882a593Smuzhiyun 		PRINTM(MCMND, "assocresp ie length = %d\n",
4311*4882a593Smuzhiyun 		       assocresp_ies_data->ie_length);
4312*4882a593Smuzhiyun 	}
4313*4882a593Smuzhiyun 	if (proberesp_ies_data) {
4314*4882a593Smuzhiyun 		priv->proberesp_index = proberesp_index;
4315*4882a593Smuzhiyun 		PRINTM(MCMND, "proberesp ie length = %d\n",
4316*4882a593Smuzhiyun 		       proberesp_ies_data->ie_length);
4317*4882a593Smuzhiyun 	}
4318*4882a593Smuzhiyun 	if (probereq_ies_data) {
4319*4882a593Smuzhiyun 		priv->probereq_index = probereq_index;
4320*4882a593Smuzhiyun 		PRINTM(MCMND, "probereq ie length = %d\n",
4321*4882a593Smuzhiyun 		       probereq_ies_data->ie_length);
4322*4882a593Smuzhiyun 	}
4323*4882a593Smuzhiyun 	PRINTM(MCMND, "beacon=%x assocresp=%x proberesp=%x probereq=%x\n",
4324*4882a593Smuzhiyun 	       beacon_index, assocresp_index, proberesp_index, probereq_index);
4325*4882a593Smuzhiyun done:
4326*4882a593Smuzhiyun 	kfree(beacon_ies_data);
4327*4882a593Smuzhiyun 	kfree(proberesp_ies_data);
4328*4882a593Smuzhiyun 	kfree(assocresp_ies_data);
4329*4882a593Smuzhiyun 	kfree(probereq_ies_data);
4330*4882a593Smuzhiyun 
4331*4882a593Smuzhiyun 	LEAVE();
4332*4882a593Smuzhiyun 
4333*4882a593Smuzhiyun 	return ret;
4334*4882a593Smuzhiyun }
4335*4882a593Smuzhiyun 
4336*4882a593Smuzhiyun /**
4337*4882a593Smuzhiyun  *  @brief Sets up the ieee80211_supported band
4338*4882a593Smuzhiyun  *  *
4339*4882a593Smuzhiyun  *  @param ht_info      A pointer to ieee80211_sta_ht_cap structure
4340*4882a593Smuzhiyun  *  @param dev_cap      Device capability information
4341*4882a593Smuzhiyun  *  @param mcs_set      Device MCS sets
4342*4882a593Smuzhiyun  *
4343*4882a593Smuzhiyun  *  @return             N/A
4344*4882a593Smuzhiyun  */
woal_setup_wiphy_bands(t_u8 ieee_band)4345*4882a593Smuzhiyun struct ieee80211_supported_band *woal_setup_wiphy_bands(t_u8 ieee_band)
4346*4882a593Smuzhiyun {
4347*4882a593Smuzhiyun 	struct ieee80211_supported_band *band = NULL;
4348*4882a593Smuzhiyun 	switch (ieee_band) {
4349*4882a593Smuzhiyun 	case IEEE80211_BAND_5GHZ:
4350*4882a593Smuzhiyun 		band = kmemdup(&cfg80211_band_5ghz,
4351*4882a593Smuzhiyun 			       sizeof(struct ieee80211_supported_band),
4352*4882a593Smuzhiyun 			       GFP_KERNEL);
4353*4882a593Smuzhiyun 		if (!band) {
4354*4882a593Smuzhiyun 			PRINTM(MERROR, "No memory for 5g band\n");
4355*4882a593Smuzhiyun 			break;
4356*4882a593Smuzhiyun 		}
4357*4882a593Smuzhiyun 		band->channels =
4358*4882a593Smuzhiyun 			kmemdup(&cfg80211_channels_5ghz,
4359*4882a593Smuzhiyun 				sizeof(cfg80211_channels_5ghz), GFP_KERNEL);
4360*4882a593Smuzhiyun 		if (!band->channels) {
4361*4882a593Smuzhiyun 			PRINTM(MERROR, "No memory for 5g band->channel\n");
4362*4882a593Smuzhiyun 			kfree(band);
4363*4882a593Smuzhiyun 			band = NULL;
4364*4882a593Smuzhiyun 			break;
4365*4882a593Smuzhiyun 		}
4366*4882a593Smuzhiyun 		band->n_channels = ARRAY_SIZE(cfg80211_channels_5ghz);
4367*4882a593Smuzhiyun 		break;
4368*4882a593Smuzhiyun 	case IEEE80211_BAND_2GHZ:
4369*4882a593Smuzhiyun 	default:
4370*4882a593Smuzhiyun 		band = kmemdup(&cfg80211_band_2ghz,
4371*4882a593Smuzhiyun 			       sizeof(struct ieee80211_supported_band),
4372*4882a593Smuzhiyun 			       GFP_KERNEL);
4373*4882a593Smuzhiyun 		if (!band) {
4374*4882a593Smuzhiyun 			PRINTM(MERROR, "No memory for 2g band\n");
4375*4882a593Smuzhiyun 			break;
4376*4882a593Smuzhiyun 		}
4377*4882a593Smuzhiyun 		band->channels =
4378*4882a593Smuzhiyun 			kmemdup(&cfg80211_channels_2ghz,
4379*4882a593Smuzhiyun 				sizeof(cfg80211_channels_2ghz), GFP_KERNEL);
4380*4882a593Smuzhiyun 		if (!band->channels) {
4381*4882a593Smuzhiyun 			PRINTM(MERROR, "No memory for 2g band->channel\n");
4382*4882a593Smuzhiyun 			kfree(band);
4383*4882a593Smuzhiyun 			band = NULL;
4384*4882a593Smuzhiyun 			break;
4385*4882a593Smuzhiyun 		}
4386*4882a593Smuzhiyun 		band->n_channels = ARRAY_SIZE(cfg80211_channels_2ghz);
4387*4882a593Smuzhiyun 		break;
4388*4882a593Smuzhiyun 	}
4389*4882a593Smuzhiyun 	return band;
4390*4882a593Smuzhiyun }
4391*4882a593Smuzhiyun 
4392*4882a593Smuzhiyun /**
4393*4882a593Smuzhiyun  *  @brief Sets up the CFG802.11 specific HT capability fields
4394*4882a593Smuzhiyun  *  with default values
4395*4882a593Smuzhiyun  *
4396*4882a593Smuzhiyun  *  @param ht_info      A pointer to ieee80211_sta_ht_cap structure
4397*4882a593Smuzhiyun  *  @param dev_cap      Device capability information
4398*4882a593Smuzhiyun  *  @param mcs_set      Device MCS sets
4399*4882a593Smuzhiyun  *
4400*4882a593Smuzhiyun  *  @return             N/A
4401*4882a593Smuzhiyun  */
woal_cfg80211_setup_ht_cap(struct ieee80211_sta_ht_cap * ht_info,t_u32 dev_cap,t_u8 * mcs_set)4402*4882a593Smuzhiyun void woal_cfg80211_setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info,
4403*4882a593Smuzhiyun 				t_u32 dev_cap, t_u8 *mcs_set)
4404*4882a593Smuzhiyun {
4405*4882a593Smuzhiyun 	ENTER();
4406*4882a593Smuzhiyun 
4407*4882a593Smuzhiyun 	ht_info->ht_supported = true;
4408*4882a593Smuzhiyun 	ht_info->ampdu_factor = 0x3;
4409*4882a593Smuzhiyun 	ht_info->ampdu_density = 0;
4410*4882a593Smuzhiyun 
4411*4882a593Smuzhiyun 	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
4412*4882a593Smuzhiyun 	ht_info->cap = 0;
4413*4882a593Smuzhiyun 	if (mcs_set)
4414*4882a593Smuzhiyun 		moal_memcpy_ext(NULL, ht_info->mcs.rx_mask, mcs_set,
4415*4882a593Smuzhiyun 				sizeof(ht_info->mcs.rx_mask),
4416*4882a593Smuzhiyun 				sizeof(ht_info->mcs.rx_mask));
4417*4882a593Smuzhiyun 	if (dev_cap & MBIT(8)) /* 40Mhz intolarance enabled */
4418*4882a593Smuzhiyun 		ht_info->cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT;
4419*4882a593Smuzhiyun 	if (dev_cap & MBIT(17)) /* Channel width 20/40Mhz support */
4420*4882a593Smuzhiyun 		ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
4421*4882a593Smuzhiyun 	if ((dev_cap >> 20) & 0x03) /* Delayed ACK supported */
4422*4882a593Smuzhiyun 		ht_info->cap |= IEEE80211_HT_CAP_DELAY_BA;
4423*4882a593Smuzhiyun 	if (dev_cap & MBIT(22)) /* Rx LDPC supported */
4424*4882a593Smuzhiyun 		ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
4425*4882a593Smuzhiyun 	if (dev_cap & MBIT(23)) /* Short GI @ 20Mhz supported */
4426*4882a593Smuzhiyun 		ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
4427*4882a593Smuzhiyun 	if (dev_cap & MBIT(24)) /* Short GI @ 40Mhz supported */
4428*4882a593Smuzhiyun 		ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
4429*4882a593Smuzhiyun 	if (dev_cap & MBIT(25)) /* Tx STBC supported */
4430*4882a593Smuzhiyun 		ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
4431*4882a593Smuzhiyun 	if (dev_cap & MBIT(26)) /* Rx STBC supported */
4432*4882a593Smuzhiyun 		ht_info->cap |= IEEE80211_HT_CAP_RX_STBC;
4433*4882a593Smuzhiyun 	if (dev_cap & MBIT(27)) /* MIMO PS supported */
4434*4882a593Smuzhiyun 		ht_info->cap |= 0; /* WLAN_HT_CAP_SM_PS_STATIC */
4435*4882a593Smuzhiyun 	else /* Disable HT SM PS */
4436*4882a593Smuzhiyun 		ht_info->cap |= IEEE80211_HT_CAP_SM_PS;
4437*4882a593Smuzhiyun 	if (dev_cap & MBIT(29)) /* Green field supported */
4438*4882a593Smuzhiyun 		ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
4439*4882a593Smuzhiyun 	if (dev_cap & MBIT(31)) /* MAX AMSDU supported */
4440*4882a593Smuzhiyun 		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
4441*4882a593Smuzhiyun 	/* DSSS/CCK in 40Mhz supported*/
4442*4882a593Smuzhiyun 	ht_info->cap |= IEEE80211_HT_CAP_DSSSCCK40;
4443*4882a593Smuzhiyun 	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
4444*4882a593Smuzhiyun 
4445*4882a593Smuzhiyun 	LEAVE();
4446*4882a593Smuzhiyun }
4447*4882a593Smuzhiyun 
4448*4882a593Smuzhiyun #if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
4449*4882a593Smuzhiyun /**
4450*4882a593Smuzhiyun  *  @brief Sets up the CFG802.11 specific VHT capability fields
4451*4882a593Smuzhiyun  *  with default values
4452*4882a593Smuzhiyun  *
4453*4882a593Smuzhiyun  * @param priv         A pointer to moal private structure
4454*4882a593Smuzhiyun  *  @param vht_cap      A pointer to ieee80211_sta_vht_cap structure
4455*4882a593Smuzhiyun  *
4456*4882a593Smuzhiyun  *  @return             N/A
4457*4882a593Smuzhiyun  */
woal_cfg80211_setup_vht_cap(moal_private * priv,struct ieee80211_sta_vht_cap * vht_cap)4458*4882a593Smuzhiyun void woal_cfg80211_setup_vht_cap(moal_private *priv,
4459*4882a593Smuzhiyun 				 struct ieee80211_sta_vht_cap *vht_cap)
4460*4882a593Smuzhiyun {
4461*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
4462*4882a593Smuzhiyun 	mlan_ds_11ac_cfg *cfg_11ac = NULL;
4463*4882a593Smuzhiyun 	mlan_status status;
4464*4882a593Smuzhiyun 
4465*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ac_cfg));
4466*4882a593Smuzhiyun 	if (req == NULL) {
4467*4882a593Smuzhiyun 		status = MLAN_STATUS_FAILURE;
4468*4882a593Smuzhiyun 		PRINTM(MERROR, "Fail to allocate buf for setup vht_cap\n");
4469*4882a593Smuzhiyun 		goto done;
4470*4882a593Smuzhiyun 	}
4471*4882a593Smuzhiyun 	cfg_11ac = (mlan_ds_11ac_cfg *)req->pbuf;
4472*4882a593Smuzhiyun 	cfg_11ac->sub_command = MLAN_OID_11AC_VHT_CFG;
4473*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11AC_CFG;
4474*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
4475*4882a593Smuzhiyun 	cfg_11ac->param.vht_cfg.band = BAND_SELECT_A;
4476*4882a593Smuzhiyun 	cfg_11ac->param.vht_cfg.txrx = MLAN_RADIO_RX;
4477*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4478*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
4479*4882a593Smuzhiyun 		PRINTM(MERROR, "Fail to get vht_cfg\n");
4480*4882a593Smuzhiyun 		goto done;
4481*4882a593Smuzhiyun 	}
4482*4882a593Smuzhiyun 	vht_cap->vht_supported = true;
4483*4882a593Smuzhiyun 	vht_cap->cap = cfg_11ac->param.vht_cfg.vht_cap_info;
4484*4882a593Smuzhiyun 	vht_cap->vht_mcs.rx_mcs_map =
4485*4882a593Smuzhiyun 		(__force __le16)cfg_11ac->param.vht_cfg.vht_rx_mcs;
4486*4882a593Smuzhiyun 	vht_cap->vht_mcs.rx_highest =
4487*4882a593Smuzhiyun 		(__force __le16)cfg_11ac->param.vht_cfg.vht_rx_max_rate;
4488*4882a593Smuzhiyun 	vht_cap->vht_mcs.tx_mcs_map =
4489*4882a593Smuzhiyun 		(__force __le16)cfg_11ac->param.vht_cfg.vht_tx_mcs;
4490*4882a593Smuzhiyun 	vht_cap->vht_mcs.tx_highest =
4491*4882a593Smuzhiyun 		(__force __le16)cfg_11ac->param.vht_cfg.vht_tx_max_rate;
4492*4882a593Smuzhiyun 	PRINTM(MCMND,
4493*4882a593Smuzhiyun 	       "vht_cap=0x%x rx_mcs_map=0x%x rx_max=0x%x tx_mcs_map=0x%x tx_max=0x%x\n",
4494*4882a593Smuzhiyun 	       vht_cap->cap, vht_cap->vht_mcs.rx_mcs_map,
4495*4882a593Smuzhiyun 	       vht_cap->vht_mcs.rx_highest, vht_cap->vht_mcs.tx_mcs_map,
4496*4882a593Smuzhiyun 	       vht_cap->vht_mcs.tx_highest);
4497*4882a593Smuzhiyun done:
4498*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
4499*4882a593Smuzhiyun 		kfree(req);
4500*4882a593Smuzhiyun 	LEAVE();
4501*4882a593Smuzhiyun }
4502*4882a593Smuzhiyun #endif
4503*4882a593Smuzhiyun 
4504*4882a593Smuzhiyun #if KERNEL_VERSION(4, 20, 0) <= CFG80211_VERSION_CODE
4505*4882a593Smuzhiyun /*
4506*4882a593Smuzhiyun ===============
4507*4882a593Smuzhiyun 11AX CAP for uAP
4508*4882a593Smuzhiyun ===============
4509*4882a593Smuzhiyun Note: bits not mentioned below are set to 0.
4510*4882a593Smuzhiyun 
4511*4882a593Smuzhiyun 5G
4512*4882a593Smuzhiyun ===
4513*4882a593Smuzhiyun HE MAC Cap:
4514*4882a593Smuzhiyun Bit0:  1  (+HTC HE Support)
4515*4882a593Smuzhiyun Bit25: 1  (OM Control Support. But uAP does not support
4516*4882a593Smuzhiyun 	   Tx OM received from the STA, as it does not support UL OFDMA)
4517*4882a593Smuzhiyun 
4518*4882a593Smuzhiyun HE PHY Cap:
4519*4882a593Smuzhiyun Bit1-7: 0x2 (Supported Channel Width Set.
4520*4882a593Smuzhiyun 	     Note it would be changed after 80+80 MHz is supported)
4521*4882a593Smuzhiyun Bit8-11: 0x3 (Punctured Preamble Rx.
4522*4882a593Smuzhiyun 	      Note: it would be changed after 80+80 MHz is supported)
4523*4882a593Smuzhiyun Bit12: 0x0 (Device Class)
4524*4882a593Smuzhiyun Bit13: 0x1 (LDPC coding in Payload)
4525*4882a593Smuzhiyun Bit17: 0x1 (NDP with 4xHE-LTF+3.2usGI)
4526*4882a593Smuzhiyun Bit18: 0x1 (STBC Tx <= 80 MHz)
4527*4882a593Smuzhiyun Bit19: 0x1 (STBC Rx <= 80 MHz)
4528*4882a593Smuzhiyun Bit20: 0x1 (Doppler Tx)
4529*4882a593Smuzhiyun Bit21: 0x1 (Doppler Rx)
4530*4882a593Smuzhiyun Bit27-28: 0x1 (DCM Max Constellation Rx)
4531*4882a593Smuzhiyun Bit31: 0x1 (SU Beamformer)
4532*4882a593Smuzhiyun Bit32: 0x1 (SU BeamFormee)
4533*4882a593Smuzhiyun Bit34-36: 0x7 (Beamformee STS <= 80 MHz)
4534*4882a593Smuzhiyun Bit40-42: 0x1 (Number of Sounding Dimentions <= 80 MHz)
4535*4882a593Smuzhiyun Bit53: 0x1 (Partial Bandwidth Extended Range)
4536*4882a593Smuzhiyun Bit55: 0x1 (PPE Threshold Present.
4537*4882a593Smuzhiyun 	    Note: PPE threshold may have some changes later)
4538*4882a593Smuzhiyun Bit58: 0x1 (HE SU PPDU and HE MU PPDU with 4xHE-LTF+0.8usGI)
4539*4882a593Smuzhiyun Bit59-61: 0x1 (Max Nc)
4540*4882a593Smuzhiyun Bit75: 0x1 (Rx 1024-QAM Support < 242-tone RU)
4541*4882a593Smuzhiyun */
4542*4882a593Smuzhiyun 
4543*4882a593Smuzhiyun #define UAP_HE_MAC_CAP0_MASK 0x00
4544*4882a593Smuzhiyun #define UAP_HE_MAC_CAP1_MASK 0x00
4545*4882a593Smuzhiyun #define UAP_HE_MAC_CAP2_MASK 0x00
4546*4882a593Smuzhiyun #define UAP_HE_MAC_CAP3_MASK 0x02
4547*4882a593Smuzhiyun #define UAP_HE_MAC_CAP4_MASK 0x00
4548*4882a593Smuzhiyun #define UAP_HE_MAC_CAP5_MASK 0x00
4549*4882a593Smuzhiyun #define UAP_HE_PHY_CAP0_MASK 0x04
4550*4882a593Smuzhiyun #define UAP_HE_PHY_CAP1_MASK 0x23
4551*4882a593Smuzhiyun #define UAP_HE_PHY_CAP2_MASK 0x3E
4552*4882a593Smuzhiyun #define UAP_HE_PHY_CAP3_MASK 0x88
4553*4882a593Smuzhiyun #define UAP_HE_PHY_CAP4_MASK 0x1D
4554*4882a593Smuzhiyun #define UAP_HE_PHY_CAP5_MASK 0x01
4555*4882a593Smuzhiyun #define UAP_HE_PHY_CAP6_MASK 0xA0
4556*4882a593Smuzhiyun #define UAP_HE_PHY_CAP7_MASK 0x0C
4557*4882a593Smuzhiyun #define UAP_HE_PHY_CAP8_MASK 0x00
4558*4882a593Smuzhiyun #define UAP_HE_PHY_CAP9_MASK 0x08
4559*4882a593Smuzhiyun #define UAP_HE_PHY_CAP10_MASK 0x00
4560*4882a593Smuzhiyun 
4561*4882a593Smuzhiyun /*
4562*4882a593Smuzhiyun 2G
4563*4882a593Smuzhiyun ===
4564*4882a593Smuzhiyun HE MAC Cap:
4565*4882a593Smuzhiyun Bit0:   1  (+HTC HE Support)
4566*4882a593Smuzhiyun Bit25: 1  (OM Control Support. Note: uAP does not support
4567*4882a593Smuzhiyun 	Tx OM received from the STA, as it does not support UL OFDMA)
4568*4882a593Smuzhiyun 
4569*4882a593Smuzhiyun HE PHY Cap:
4570*4882a593Smuzhiyun Bit1-7: 0x1 (Supported Channel Width Set)
4571*4882a593Smuzhiyun Bit8-11: 0x0 (Punctured Preamble Rx)
4572*4882a593Smuzhiyun Bit12: 0x0 (Device Class)
4573*4882a593Smuzhiyun Bit13: 0x1 (LDPC coding in Payload)
4574*4882a593Smuzhiyun Bit17: 0x1 (NDP with 4xLTF+3.2usGI)
4575*4882a593Smuzhiyun Bit18: 0x1 (STBC Tx <= 80 MHz)
4576*4882a593Smuzhiyun Bit19: 0x1 (STBC Rx <= 80 MHz)
4577*4882a593Smuzhiyun Bit20: 0x1 (Doppler Tx)
4578*4882a593Smuzhiyun Bit21: 0x1 (Doppler Rx)
4579*4882a593Smuzhiyun Bit27-28: 0x1 (DCM Max Constellation Rx)
4580*4882a593Smuzhiyun Bit31: 0x1 (SU Beamformer)
4581*4882a593Smuzhiyun Bit32: 0x1 (SU BeamFormee)
4582*4882a593Smuzhiyun Bit34-36: 0x7 (Beamformee STS <= 80 MHz)
4583*4882a593Smuzhiyun Bit40-42: 0x1 (Number of Sounding Dimentions <= 80 MHz)
4584*4882a593Smuzhiyun Bit53: 0x1 (Partial Bandwidth Extended Range)
4585*4882a593Smuzhiyun Bit55: 0x1 (PPE Threshold Present.
4586*4882a593Smuzhiyun 	    Note: PPE threshold may have some changes later)
4587*4882a593Smuzhiyun Bit58: 0x1 (HE SU PPDU and HE MU PPDU with 4xHE-LTF+0.8usGI)
4588*4882a593Smuzhiyun Bit59-61: 0x1 (Max Nc)
4589*4882a593Smuzhiyun Bit75: 0x1 (Rx 1024-QAM Support < 242-tone RU)
4590*4882a593Smuzhiyun */
4591*4882a593Smuzhiyun #define UAP_HE_2G_MAC_CAP0_MASK 0x00
4592*4882a593Smuzhiyun #define UAP_HE_2G_MAC_CAP1_MASK 0x00
4593*4882a593Smuzhiyun #define UAP_HE_2G_MAC_CAP2_MASK 0x00
4594*4882a593Smuzhiyun #define UAP_HE_2G_MAC_CAP3_MASK 0x02
4595*4882a593Smuzhiyun #define UAP_HE_2G_MAC_CAP4_MASK 0x00
4596*4882a593Smuzhiyun #define UAP_HE_2G_MAC_CAP5_MASK 0x00
4597*4882a593Smuzhiyun #define UAP_HE_2G_PHY_CAP0_MASK 0x02
4598*4882a593Smuzhiyun #define UAP_HE_2G_PHY_CAP1_MASK 0x20
4599*4882a593Smuzhiyun #define UAP_HE_2G_PHY_CAP2_MASK 0x3E
4600*4882a593Smuzhiyun #define UAP_HE_2G_PHY_CAP3_MASK 0x88
4601*4882a593Smuzhiyun #define UAP_HE_2G_PHY_CAP4_MASK 0x1D
4602*4882a593Smuzhiyun #define UAP_HE_2G_PHY_CAP5_MASK 0x01
4603*4882a593Smuzhiyun #define UAP_HE_2G_PHY_CAP6_MASK 0xA0
4604*4882a593Smuzhiyun #define UAP_HE_2G_PHY_CAP7_MASK 0x0C
4605*4882a593Smuzhiyun #define UAP_HE_2G_PHY_CAP8_MASK 0x00
4606*4882a593Smuzhiyun #define UAP_HE_2G_PHY_CAP9_MASK 0x08
4607*4882a593Smuzhiyun #define UAP_HE_2G_PHY_CAP10_MASK 0x00
4608*4882a593Smuzhiyun 
4609*4882a593Smuzhiyun /**
4610*4882a593Smuzhiyun  *  @brief update 11ax ie for AP mode *
4611*4882a593Smuzhiyun  *  @param band     channel band
4612*4882a593Smuzhiyun  *  @hecap_ie       a pointer to mlan_ds_11ax_he_capa
4613*4882a593Smuzhiyun  *
4614*4882a593Smuzhiyun  *  @return         0--success, otherwise failure
4615*4882a593Smuzhiyun  */
woal_uap_update_11ax_ie(t_u8 band,mlan_ds_11ax_he_capa * hecap_ie)4616*4882a593Smuzhiyun static void woal_uap_update_11ax_ie(t_u8 band, mlan_ds_11ax_he_capa *hecap_ie)
4617*4882a593Smuzhiyun {
4618*4882a593Smuzhiyun 	if (band == BAND_5GHZ) {
4619*4882a593Smuzhiyun 		hecap_ie->he_mac_cap[0] &= UAP_HE_MAC_CAP0_MASK;
4620*4882a593Smuzhiyun 		hecap_ie->he_mac_cap[1] &= UAP_HE_MAC_CAP1_MASK;
4621*4882a593Smuzhiyun 		hecap_ie->he_mac_cap[2] &= UAP_HE_MAC_CAP2_MASK;
4622*4882a593Smuzhiyun 		hecap_ie->he_mac_cap[3] &= UAP_HE_MAC_CAP3_MASK;
4623*4882a593Smuzhiyun 		hecap_ie->he_mac_cap[4] &= UAP_HE_MAC_CAP4_MASK;
4624*4882a593Smuzhiyun 		hecap_ie->he_mac_cap[5] &= UAP_HE_MAC_CAP5_MASK;
4625*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[0] &= UAP_HE_PHY_CAP0_MASK;
4626*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[1] &= UAP_HE_PHY_CAP1_MASK;
4627*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[2] &= UAP_HE_PHY_CAP2_MASK;
4628*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[3] &= UAP_HE_PHY_CAP3_MASK;
4629*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[4] &= UAP_HE_PHY_CAP4_MASK;
4630*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[5] &= UAP_HE_PHY_CAP5_MASK;
4631*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[6] &= UAP_HE_PHY_CAP6_MASK;
4632*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[7] &= UAP_HE_PHY_CAP7_MASK;
4633*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[8] &= UAP_HE_PHY_CAP8_MASK;
4634*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[9] &= UAP_HE_PHY_CAP9_MASK;
4635*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[10] &= UAP_HE_PHY_CAP10_MASK;
4636*4882a593Smuzhiyun 	} else {
4637*4882a593Smuzhiyun 		hecap_ie->he_mac_cap[0] &= UAP_HE_2G_MAC_CAP0_MASK;
4638*4882a593Smuzhiyun 		hecap_ie->he_mac_cap[1] &= UAP_HE_2G_MAC_CAP1_MASK;
4639*4882a593Smuzhiyun 		hecap_ie->he_mac_cap[2] &= UAP_HE_2G_MAC_CAP2_MASK;
4640*4882a593Smuzhiyun 		hecap_ie->he_mac_cap[3] &= UAP_HE_2G_MAC_CAP3_MASK;
4641*4882a593Smuzhiyun 		hecap_ie->he_mac_cap[4] &= UAP_HE_2G_MAC_CAP4_MASK;
4642*4882a593Smuzhiyun 		hecap_ie->he_mac_cap[5] &= UAP_HE_2G_MAC_CAP5_MASK;
4643*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[0] &= UAP_HE_2G_PHY_CAP0_MASK;
4644*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[1] &= UAP_HE_2G_PHY_CAP1_MASK;
4645*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[2] &= UAP_HE_2G_PHY_CAP2_MASK;
4646*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[3] &= UAP_HE_2G_PHY_CAP3_MASK;
4647*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[4] &= UAP_HE_2G_PHY_CAP4_MASK;
4648*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[5] &= UAP_HE_2G_PHY_CAP5_MASK;
4649*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[6] &= UAP_HE_2G_PHY_CAP6_MASK;
4650*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[7] &= UAP_HE_2G_PHY_CAP7_MASK;
4651*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[8] &= UAP_HE_2G_PHY_CAP8_MASK;
4652*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[9] &= UAP_HE_2G_PHY_CAP9_MASK;
4653*4882a593Smuzhiyun 		hecap_ie->he_phy_cap[10] &= UAP_HE_2G_PHY_CAP10_MASK;
4654*4882a593Smuzhiyun 	}
4655*4882a593Smuzhiyun 	return;
4656*4882a593Smuzhiyun }
4657*4882a593Smuzhiyun 
4658*4882a593Smuzhiyun /**
4659*4882a593Smuzhiyun  *  @brief Sets up the CFG802.11 specific HE capability fields *  with default
4660*4882a593Smuzhiyun  * values
4661*4882a593Smuzhiyun  *
4662*4882a593Smuzhiyun  *  @param priv         A pointer to moal private structure
4663*4882a593Smuzhiyun  *  @param iftype_data  A pointer to ieee80211_sband_iftype_data structure
4664*4882a593Smuzhiyun  *
4665*4882a593Smuzhiyun  *  @return             N/A
4666*4882a593Smuzhiyun  */
woal_cfg80211_setup_he_cap(moal_private * priv,struct ieee80211_supported_band * band)4667*4882a593Smuzhiyun void woal_cfg80211_setup_he_cap(moal_private *priv,
4668*4882a593Smuzhiyun 				struct ieee80211_supported_band *band)
4669*4882a593Smuzhiyun {
4670*4882a593Smuzhiyun 	mlan_fw_info fw_info;
4671*4882a593Smuzhiyun 	struct ieee80211_sband_iftype_data *iftype_data = NULL;
4672*4882a593Smuzhiyun 	t_u8 extra_mcs_size = 0;
4673*4882a593Smuzhiyun 	int ppe_threshold_len = 0;
4674*4882a593Smuzhiyun 	mlan_ds_11ax_he_capa *phe_cap = NULL;
4675*4882a593Smuzhiyun 	t_u8 hw_hecap_len;
4676*4882a593Smuzhiyun 
4677*4882a593Smuzhiyun 	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
4678*4882a593Smuzhiyun 	if (band->band == NL80211_BAND_5GHZ) {
4679*4882a593Smuzhiyun 		phe_cap = (mlan_ds_11ax_he_capa *)fw_info.hw_he_cap;
4680*4882a593Smuzhiyun 		hw_hecap_len = fw_info.hw_hecap_len;
4681*4882a593Smuzhiyun 		woal_uap_update_11ax_ie(BAND_5GHZ, phe_cap);
4682*4882a593Smuzhiyun 	} else {
4683*4882a593Smuzhiyun 		phe_cap = (mlan_ds_11ax_he_capa *)fw_info.hw_2g_he_cap;
4684*4882a593Smuzhiyun 		hw_hecap_len = fw_info.hw_2g_hecap_len;
4685*4882a593Smuzhiyun 		woal_uap_update_11ax_ie(BAND_2GHZ, phe_cap);
4686*4882a593Smuzhiyun 	}
4687*4882a593Smuzhiyun 
4688*4882a593Smuzhiyun 	if (!hw_hecap_len)
4689*4882a593Smuzhiyun 		return;
4690*4882a593Smuzhiyun 	DBG_HEXDUMP(MCMD_D, "Setup HECAP", (u8 *)phe_cap, hw_hecap_len);
4691*4882a593Smuzhiyun 	iftype_data =
4692*4882a593Smuzhiyun 		kmalloc(sizeof(struct ieee80211_sband_iftype_data), GFP_KERNEL);
4693*4882a593Smuzhiyun 	if (!iftype_data) {
4694*4882a593Smuzhiyun 		PRINTM(MERROR, "Fail to allocate iftype data\n");
4695*4882a593Smuzhiyun 		goto done;
4696*4882a593Smuzhiyun 	}
4697*4882a593Smuzhiyun 	memset(iftype_data, 0, sizeof(struct ieee80211_sband_iftype_data));
4698*4882a593Smuzhiyun 	iftype_data->types_mask =
4699*4882a593Smuzhiyun 		MBIT(NL80211_IFTYPE_STATION) | MBIT(NL80211_IFTYPE_AP) |
4700*4882a593Smuzhiyun 		MBIT(NL80211_IFTYPE_P2P_CLIENT) | MBIT(NL80211_IFTYPE_P2P_GO);
4701*4882a593Smuzhiyun 	iftype_data->he_cap.has_he = true;
4702*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle,
4703*4882a593Smuzhiyun 			iftype_data->he_cap.he_cap_elem.mac_cap_info,
4704*4882a593Smuzhiyun 			phe_cap->he_mac_cap, sizeof(phe_cap->he_mac_cap),
4705*4882a593Smuzhiyun 			sizeof(iftype_data->he_cap.he_cap_elem.mac_cap_info));
4706*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle,
4707*4882a593Smuzhiyun 			iftype_data->he_cap.he_cap_elem.phy_cap_info,
4708*4882a593Smuzhiyun 			phe_cap->he_phy_cap, sizeof(phe_cap->he_phy_cap),
4709*4882a593Smuzhiyun 			sizeof(iftype_data->he_cap.he_cap_elem.phy_cap_info));
4710*4882a593Smuzhiyun 	memset(&iftype_data->he_cap.he_mcs_nss_supp, 0xff,
4711*4882a593Smuzhiyun 	       sizeof(struct ieee80211_he_mcs_nss_supp));
4712*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle, &iftype_data->he_cap.he_mcs_nss_supp,
4713*4882a593Smuzhiyun 			phe_cap->he_txrx_mcs_support,
4714*4882a593Smuzhiyun 			sizeof(phe_cap->he_txrx_mcs_support),
4715*4882a593Smuzhiyun 			sizeof(struct ieee80211_he_mcs_nss_supp));
4716*4882a593Smuzhiyun 	// Support 160Mhz
4717*4882a593Smuzhiyun 	if (phe_cap->he_phy_cap[0] & MBIT(3))
4718*4882a593Smuzhiyun 		extra_mcs_size += 4;
4719*4882a593Smuzhiyun 
4720*4882a593Smuzhiyun 	// Support 80+80
4721*4882a593Smuzhiyun 	if (phe_cap->he_phy_cap[0] & MBIT(4))
4722*4882a593Smuzhiyun 		extra_mcs_size += 4;
4723*4882a593Smuzhiyun 	if (extra_mcs_size)
4724*4882a593Smuzhiyun 		moal_memcpy_ext(
4725*4882a593Smuzhiyun 			priv->phandle,
4726*4882a593Smuzhiyun 			(t_u8 *)&iftype_data->he_cap.he_mcs_nss_supp.rx_mcs_160,
4727*4882a593Smuzhiyun 			phe_cap->val, extra_mcs_size,
4728*4882a593Smuzhiyun 			sizeof(struct ieee80211_he_mcs_nss_supp) - 4);
4729*4882a593Smuzhiyun 
4730*4882a593Smuzhiyun #define HE_CAP_FIX_SIZE 22
4731*4882a593Smuzhiyun 	// Support PPE threshold
4732*4882a593Smuzhiyun 	ppe_threshold_len = phe_cap->len - HE_CAP_FIX_SIZE - extra_mcs_size;
4733*4882a593Smuzhiyun 	if (phe_cap->he_phy_cap[6] & MBIT(7) && ppe_threshold_len) {
4734*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, iftype_data->he_cap.ppe_thres,
4735*4882a593Smuzhiyun 				&phe_cap->val[extra_mcs_size],
4736*4882a593Smuzhiyun 				ppe_threshold_len,
4737*4882a593Smuzhiyun 				sizeof(iftype_data->he_cap.ppe_thres));
4738*4882a593Smuzhiyun 	} else {
4739*4882a593Smuzhiyun 		iftype_data->he_cap.he_cap_elem.phy_cap_info[6] &= ~MBIT(7);
4740*4882a593Smuzhiyun 		PRINTM(MCMND, "Clear PPE threshold 0x%x\n",
4741*4882a593Smuzhiyun 		       iftype_data->he_cap.he_cap_elem.phy_cap_info[7]);
4742*4882a593Smuzhiyun 	}
4743*4882a593Smuzhiyun 	band->n_iftype_data = 1;
4744*4882a593Smuzhiyun 	band->iftype_data = iftype_data;
4745*4882a593Smuzhiyun done:
4746*4882a593Smuzhiyun 	LEAVE();
4747*4882a593Smuzhiyun }
4748*4882a593Smuzhiyun 
4749*4882a593Smuzhiyun #endif
4750*4882a593Smuzhiyun 
4751*4882a593Smuzhiyun /**
4752*4882a593Smuzhiyun  *  @brief free iftype_data
4753*4882a593Smuzhiyun  *
4754*4882a593Smuzhiyun  *  @param wiphy        A pointer to struct wiphy
4755*4882a593Smuzhiyun  *
4756*4882a593Smuzhiyun  *
4757*4882a593Smuzhiyun  *  @return             N/A
4758*4882a593Smuzhiyun  */
woal_cfg80211_free_bands(struct wiphy * wiphy)4759*4882a593Smuzhiyun void woal_cfg80211_free_bands(struct wiphy *wiphy)
4760*4882a593Smuzhiyun {
4761*4882a593Smuzhiyun 	t_u8 band;
4762*4882a593Smuzhiyun 
4763*4882a593Smuzhiyun 	for (band = NL80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; ++band) {
4764*4882a593Smuzhiyun 		if (!wiphy->bands[band])
4765*4882a593Smuzhiyun 			continue;
4766*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
4767*4882a593Smuzhiyun 		if (wiphy->bands[band]->iftype_data) {
4768*4882a593Smuzhiyun 			kfree(wiphy->bands[band]->iftype_data);
4769*4882a593Smuzhiyun 			wiphy->bands[band]->n_iftype_data = 0;
4770*4882a593Smuzhiyun 		}
4771*4882a593Smuzhiyun #endif
4772*4882a593Smuzhiyun 		kfree(wiphy->bands[band]->channels);
4773*4882a593Smuzhiyun 		kfree(wiphy->bands[band]);
4774*4882a593Smuzhiyun 		wiphy->bands[band] = NULL;
4775*4882a593Smuzhiyun 	}
4776*4882a593Smuzhiyun }
4777*4882a593Smuzhiyun 
4778*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
4779*4882a593Smuzhiyun /*
4780*4882a593Smuzhiyun  * @brief  prepare and send fake deauth packet to cfg80211 to
4781*4882a593Smuzhiyun  *         notify wpa_supplicant about disconnection
4782*4882a593Smuzhiyun  *	       <host_mlme, wiphy suspend case>
4783*4882a593Smuzhiyun  *
4784*4882a593Smuzhiyun  * @param priv           A pointer moal_private structure
4785*4882a593Smuzhiyun  * @param reason_code    disconnect reason code
4786*4882a593Smuzhiyun  *
4787*4882a593Smuzhiyun  * @return          N/A
4788*4882a593Smuzhiyun  */
woal_deauth_event(moal_private * priv,int reason_code)4789*4882a593Smuzhiyun void woal_deauth_event(moal_private *priv, int reason_code)
4790*4882a593Smuzhiyun {
4791*4882a593Smuzhiyun 	struct woal_event *evt;
4792*4882a593Smuzhiyun 	unsigned long flags;
4793*4882a593Smuzhiyun 	moal_handle *handle = priv->phandle;
4794*4882a593Smuzhiyun 
4795*4882a593Smuzhiyun 	evt = kzalloc(sizeof(struct woal_event), GFP_ATOMIC);
4796*4882a593Smuzhiyun 	if (!evt) {
4797*4882a593Smuzhiyun 		PRINTM(MERROR, "Fail to alloc memory for deauth event\n");
4798*4882a593Smuzhiyun 		LEAVE();
4799*4882a593Smuzhiyun 		return;
4800*4882a593Smuzhiyun 	}
4801*4882a593Smuzhiyun 	evt->priv = priv;
4802*4882a593Smuzhiyun 	evt->type = WOAL_EVENT_DEAUTH;
4803*4882a593Smuzhiyun 	evt->reason_code = reason_code;
4804*4882a593Smuzhiyun 	INIT_LIST_HEAD(&evt->link);
4805*4882a593Smuzhiyun 	spin_lock_irqsave(&handle->evt_lock, flags);
4806*4882a593Smuzhiyun 	list_add_tail(&evt->link, &handle->evt_queue);
4807*4882a593Smuzhiyun 	spin_unlock_irqrestore(&handle->evt_lock, flags);
4808*4882a593Smuzhiyun 	queue_work(handle->evt_workqueue, &handle->evt_work);
4809*4882a593Smuzhiyun }
4810*4882a593Smuzhiyun #endif
4811*4882a593Smuzhiyun 
4812*4882a593Smuzhiyun #ifdef STA_CFG80211
4813*4882a593Smuzhiyun #if KERNEL_VERSION(3, 2, 0) <= CFG80211_VERSION_CODE
4814*4882a593Smuzhiyun /**
4815*4882a593Smuzhiyun  * @brief   prepare woal_bgscan_stop event
4816*4882a593Smuzhiyun  *
4817*4882a593Smuzhiyun  * @param priv          A pointer moal_private structure
4818*4882a593Smuzhiyun  * @param pchan_info    A pointer to chan_band structure
4819*4882a593Smuzhiyun  *
4820*4882a593Smuzhiyun  * @return          N/A
4821*4882a593Smuzhiyun  */
woal_bgscan_stop_event(moal_private * priv)4822*4882a593Smuzhiyun void woal_bgscan_stop_event(moal_private *priv)
4823*4882a593Smuzhiyun {
4824*4882a593Smuzhiyun 	struct woal_event *evt;
4825*4882a593Smuzhiyun 	unsigned long flags;
4826*4882a593Smuzhiyun 	moal_handle *handle = priv->phandle;
4827*4882a593Smuzhiyun 
4828*4882a593Smuzhiyun 	evt = kzalloc(sizeof(struct woal_event), GFP_ATOMIC);
4829*4882a593Smuzhiyun 	if (evt) {
4830*4882a593Smuzhiyun 		evt->priv = priv;
4831*4882a593Smuzhiyun 		evt->type = WOAL_EVENT_BGSCAN_STOP;
4832*4882a593Smuzhiyun 		INIT_LIST_HEAD(&evt->link);
4833*4882a593Smuzhiyun 		spin_lock_irqsave(&handle->evt_lock, flags);
4834*4882a593Smuzhiyun 		list_add_tail(&evt->link, &handle->evt_queue);
4835*4882a593Smuzhiyun 		spin_unlock_irqrestore(&handle->evt_lock, flags);
4836*4882a593Smuzhiyun 		queue_work(handle->evt_workqueue, &handle->evt_work);
4837*4882a593Smuzhiyun 	}
4838*4882a593Smuzhiyun }
4839*4882a593Smuzhiyun 
4840*4882a593Smuzhiyun /**
4841*4882a593Smuzhiyun  * @brief Notify cfg80211 schedule scan stopped
4842*4882a593Smuzhiyun  *
4843*4882a593Smuzhiyun  * @param priv          A pointer moal_private structure
4844*4882a593Smuzhiyun  *
4845*4882a593Smuzhiyun  * @return          N/A
4846*4882a593Smuzhiyun  */
woal_cfg80211_notify_sched_scan_stop(moal_private * priv)4847*4882a593Smuzhiyun void woal_cfg80211_notify_sched_scan_stop(moal_private *priv)
4848*4882a593Smuzhiyun {
4849*4882a593Smuzhiyun 	cfg80211_sched_scan_stopped(priv->wdev->wiphy
4850*4882a593Smuzhiyun #if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE
4851*4882a593Smuzhiyun 				    ,
4852*4882a593Smuzhiyun 				    0
4853*4882a593Smuzhiyun #endif
4854*4882a593Smuzhiyun 	);
4855*4882a593Smuzhiyun 	priv->sched_scanning = MFALSE;
4856*4882a593Smuzhiyun 	PRINTM(MEVENT, "Notify sched scan stopped\n");
4857*4882a593Smuzhiyun }
4858*4882a593Smuzhiyun 
4859*4882a593Smuzhiyun /**
4860*4882a593Smuzhiyun  * @brief report sched_scan result to kernel
4861*4882a593Smuzhiyun  *
4862*4882a593Smuzhiyun  * @param priv          A pointer moal_private structure
4863*4882a593Smuzhiyun  *
4864*4882a593Smuzhiyun  * @return          N/A
4865*4882a593Smuzhiyun  */
woal_report_sched_scan_result(moal_private * priv)4866*4882a593Smuzhiyun void woal_report_sched_scan_result(moal_private *priv)
4867*4882a593Smuzhiyun {
4868*4882a593Smuzhiyun 	cfg80211_sched_scan_results(priv->wdev->wiphy
4869*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
4870*4882a593Smuzhiyun 				    ,
4871*4882a593Smuzhiyun 				    priv->bg_scan_reqid
4872*4882a593Smuzhiyun #endif
4873*4882a593Smuzhiyun 	);
4874*4882a593Smuzhiyun }
4875*4882a593Smuzhiyun #endif
4876*4882a593Smuzhiyun #endif
4877*4882a593Smuzhiyun 
4878*4882a593Smuzhiyun #if KERNEL_VERSION(3, 5, 0) <= CFG80211_VERSION_CODE
4879*4882a593Smuzhiyun /**
4880*4882a593Smuzhiyun  * @brief   Handle woal_channel_switch event
4881*4882a593Smuzhiyun  *
4882*4882a593Smuzhiyun  * @param priv          A pointer moal_private structure
4883*4882a593Smuzhiyun  * @param pchan_info    A pointer to chan_band structure
4884*4882a593Smuzhiyun  *
4885*4882a593Smuzhiyun  * @return          N/A
4886*4882a593Smuzhiyun  */
woal_channel_switch_event(moal_private * priv,chan_band_info * pchan_info)4887*4882a593Smuzhiyun void woal_channel_switch_event(moal_private *priv, chan_band_info *pchan_info)
4888*4882a593Smuzhiyun {
4889*4882a593Smuzhiyun 	struct woal_event *evt;
4890*4882a593Smuzhiyun 	unsigned long flags;
4891*4882a593Smuzhiyun 	moal_handle *handle = priv->phandle;
4892*4882a593Smuzhiyun 
4893*4882a593Smuzhiyun 	evt = kzalloc(sizeof(struct woal_event), GFP_ATOMIC);
4894*4882a593Smuzhiyun 	if (evt) {
4895*4882a593Smuzhiyun 		evt->priv = priv;
4896*4882a593Smuzhiyun 		evt->type = WOAL_EVENT_CHAN_SWITCH;
4897*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, &evt->chan_info, pchan_info,
4898*4882a593Smuzhiyun 				sizeof(chan_band_info), sizeof(chan_band_info));
4899*4882a593Smuzhiyun 		INIT_LIST_HEAD(&evt->link);
4900*4882a593Smuzhiyun 		spin_lock_irqsave(&handle->evt_lock, flags);
4901*4882a593Smuzhiyun 		list_add_tail(&evt->link, &handle->evt_queue);
4902*4882a593Smuzhiyun 		spin_unlock_irqrestore(&handle->evt_lock, flags);
4903*4882a593Smuzhiyun 		queue_work(handle->evt_workqueue, &handle->evt_work);
4904*4882a593Smuzhiyun 	}
4905*4882a593Smuzhiyun }
4906*4882a593Smuzhiyun 
4907*4882a593Smuzhiyun /**
4908*4882a593Smuzhiyun  * @brief Notify cfg80211 supplicant channel changed
4909*4882a593Smuzhiyun  *
4910*4882a593Smuzhiyun  * @param priv          A pointer moal_private structure
4911*4882a593Smuzhiyun  * @param pchan_info    A pointer to chan_band structure
4912*4882a593Smuzhiyun  *
4913*4882a593Smuzhiyun  * @return          N/A
4914*4882a593Smuzhiyun  */
woal_cfg80211_notify_channel(moal_private * priv,chan_band_info * pchan_info)4915*4882a593Smuzhiyun void woal_cfg80211_notify_channel(moal_private *priv,
4916*4882a593Smuzhiyun 				  chan_band_info *pchan_info)
4917*4882a593Smuzhiyun {
4918*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
4919*4882a593Smuzhiyun 	struct cfg80211_chan_def chandef;
4920*4882a593Smuzhiyun #else
4921*4882a593Smuzhiyun #if KERNEL_VERSION(3, 5, 0) <= CFG80211_VERSION_CODE
4922*4882a593Smuzhiyun 	enum nl80211_channel_type type;
4923*4882a593Smuzhiyun 	enum ieee80211_band band;
4924*4882a593Smuzhiyun 	int freq = 0;
4925*4882a593Smuzhiyun #endif
4926*4882a593Smuzhiyun #endif
4927*4882a593Smuzhiyun 	ENTER();
4928*4882a593Smuzhiyun 
4929*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
4930*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS ==
4931*4882a593Smuzhiyun 	    woal_chandef_create(priv, &chandef, pchan_info)) {
4932*4882a593Smuzhiyun #if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
4933*4882a593Smuzhiyun 		mutex_lock(&priv->wdev->mtx);
4934*4882a593Smuzhiyun #endif
4935*4882a593Smuzhiyun #if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13)
4936*4882a593Smuzhiyun 		cfg80211_ch_switch_notify(priv->netdev, &chandef, 0);
4937*4882a593Smuzhiyun #else
4938*4882a593Smuzhiyun 		cfg80211_ch_switch_notify(priv->netdev, &chandef);
4939*4882a593Smuzhiyun #endif
4940*4882a593Smuzhiyun #if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
4941*4882a593Smuzhiyun 		mutex_unlock(&priv->wdev->mtx);
4942*4882a593Smuzhiyun #endif
4943*4882a593Smuzhiyun 		priv->channel = pchan_info->channel;
4944*4882a593Smuzhiyun #ifdef UAP_CFG80211
4945*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, &priv->chan, &chandef,
4946*4882a593Smuzhiyun 				sizeof(struct cfg80211_chan_def),
4947*4882a593Smuzhiyun 				sizeof(struct cfg80211_chan_def));
4948*4882a593Smuzhiyun #endif
4949*4882a593Smuzhiyun 	}
4950*4882a593Smuzhiyun #else
4951*4882a593Smuzhiyun #if KERNEL_VERSION(3, 5, 0) <= CFG80211_VERSION_CODE
4952*4882a593Smuzhiyun 	if (pchan_info->bandcfg.chanBand == BAND_2GHZ)
4953*4882a593Smuzhiyun 		band = IEEE80211_BAND_2GHZ;
4954*4882a593Smuzhiyun 	else if (pchan_info->bandcfg.chanBand == BAND_5GHZ)
4955*4882a593Smuzhiyun 		band = IEEE80211_BAND_5GHZ;
4956*4882a593Smuzhiyun 	else {
4957*4882a593Smuzhiyun 		LEAVE();
4958*4882a593Smuzhiyun 		return;
4959*4882a593Smuzhiyun 	}
4960*4882a593Smuzhiyun 	priv->channel = pchan_info->channel;
4961*4882a593Smuzhiyun 	freq = ieee80211_channel_to_frequency(pchan_info->channel, band);
4962*4882a593Smuzhiyun 	switch (pchan_info->bandcfg.chanWidth) {
4963*4882a593Smuzhiyun 	case CHAN_BW_20MHZ:
4964*4882a593Smuzhiyun 		if (pchan_info->is_11n_enabled)
4965*4882a593Smuzhiyun 			type = NL80211_CHAN_HT20;
4966*4882a593Smuzhiyun 		else
4967*4882a593Smuzhiyun 			type = NL80211_CHAN_NO_HT;
4968*4882a593Smuzhiyun 		break;
4969*4882a593Smuzhiyun 	default:
4970*4882a593Smuzhiyun 		if (pchan_info->bandcfg.chan2Offset == SEC_CHAN_ABOVE)
4971*4882a593Smuzhiyun 			type = NL80211_CHAN_HT40PLUS;
4972*4882a593Smuzhiyun 		else if (pchan_info->bandcfg.chan2Offset == SEC_CHAN_BELOW)
4973*4882a593Smuzhiyun 			type = NL80211_CHAN_HT40MINUS;
4974*4882a593Smuzhiyun 		else
4975*4882a593Smuzhiyun 			type = NL80211_CHAN_HT20;
4976*4882a593Smuzhiyun 		break;
4977*4882a593Smuzhiyun 	}
4978*4882a593Smuzhiyun 	cfg80211_ch_switch_notify(priv->netdev, freq, type);
4979*4882a593Smuzhiyun #endif
4980*4882a593Smuzhiyun #endif
4981*4882a593Smuzhiyun 	LEAVE();
4982*4882a593Smuzhiyun }
4983*4882a593Smuzhiyun #endif
4984*4882a593Smuzhiyun 
4985*4882a593Smuzhiyun #if defined(UAP_CFG80211) || defined(STA_CFG80211)
4986*4882a593Smuzhiyun /**
4987*4882a593Smuzhiyun  * @brief Notify cfg80211 supplicant ant cfg changed
4988*4882a593Smuzhiyun  *
4989*4882a593Smuzhiyun  * @param priv          A pointer moal_private structure
4990*4882a593Smuzhiyun  * @param wiphy         A pointer structure wiphy
4991*4882a593Smuzhiyun  * @param radio         A pointer to radio cfg structure
4992*4882a593Smuzhiyun  *
4993*4882a593Smuzhiyun  * @return              N/A
4994*4882a593Smuzhiyun  */
woal_cfg80211_notify_antcfg(moal_private * priv,struct wiphy * wiphy,mlan_ds_radio_cfg * radio)4995*4882a593Smuzhiyun void woal_cfg80211_notify_antcfg(moal_private *priv, struct wiphy *wiphy,
4996*4882a593Smuzhiyun 				 mlan_ds_radio_cfg *radio)
4997*4882a593Smuzhiyun {
4998*4882a593Smuzhiyun 	if (IS_STA_OR_UAP_CFG80211(priv->phandle->params.cfg80211_wext) &&
4999*4882a593Smuzhiyun 	    wiphy) {
5000*4882a593Smuzhiyun 		if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
5001*4882a593Smuzhiyun 			struct ieee80211_supported_band *bands =
5002*4882a593Smuzhiyun 				wiphy->bands[IEEE80211_BAND_2GHZ];
5003*4882a593Smuzhiyun 
5004*4882a593Smuzhiyun 			if (((radio->param.ant_cfg.tx_antenna & 0xFF) != 3 &&
5005*4882a593Smuzhiyun 			     (radio->param.ant_cfg.tx_antenna & 0xFF) != 0) ||
5006*4882a593Smuzhiyun 			    ((radio->param.ant_cfg.rx_antenna & 0xFF) != 3 &&
5007*4882a593Smuzhiyun 			     (radio->param.ant_cfg.rx_antenna & 0xFF) != 0)) {
5008*4882a593Smuzhiyun 				bands->ht_cap.mcs.rx_mask[1] = 0;
5009*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
5010*4882a593Smuzhiyun 				if (bands->n_iftype_data &&
5011*4882a593Smuzhiyun 				    bands->iftype_data &&
5012*4882a593Smuzhiyun 				    bands->iftype_data->he_cap.has_he) {
5013*4882a593Smuzhiyun 					t_u16 mcs_nss[2];
5014*4882a593Smuzhiyun 
5015*4882a593Smuzhiyun 					mcs_nss[0] = bands->iftype_data->he_cap
5016*4882a593Smuzhiyun 							     .he_mcs_nss_supp
5017*4882a593Smuzhiyun 							     .rx_mcs_80;
5018*4882a593Smuzhiyun 					mcs_nss[1] = mcs_nss[0] |= 0x0c;
5019*4882a593Smuzhiyun 					moal_memcpy_ext(
5020*4882a593Smuzhiyun 						priv->phandle,
5021*4882a593Smuzhiyun 						(t_void *)&bands->iftype_data
5022*4882a593Smuzhiyun 							->he_cap.he_mcs_nss_supp
5023*4882a593Smuzhiyun 							.rx_mcs_80,
5024*4882a593Smuzhiyun 						(t_void *)&mcs_nss,
5025*4882a593Smuzhiyun 						sizeof(mcs_nss),
5026*4882a593Smuzhiyun 						sizeof(bands->iftype_data->he_cap
5027*4882a593Smuzhiyun 							       .he_mcs_nss_supp));
5028*4882a593Smuzhiyun 				}
5029*4882a593Smuzhiyun #endif
5030*4882a593Smuzhiyun 			} else if ((radio->param.ant_cfg.tx_antenna & 0xFF) ==
5031*4882a593Smuzhiyun 					   3 ||
5032*4882a593Smuzhiyun 				   (radio->param.ant_cfg.rx_antenna & 0xFF) ==
5033*4882a593Smuzhiyun 					   3) {
5034*4882a593Smuzhiyun 				bands->ht_cap.mcs.rx_mask[1] = 0xff;
5035*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
5036*4882a593Smuzhiyun 				if (bands->n_iftype_data &&
5037*4882a593Smuzhiyun 				    bands->iftype_data &&
5038*4882a593Smuzhiyun 				    bands->iftype_data->he_cap.has_he) {
5039*4882a593Smuzhiyun 					t_u16 mcs_nss[2];
5040*4882a593Smuzhiyun 
5041*4882a593Smuzhiyun 					mcs_nss[0] = bands->iftype_data->he_cap
5042*4882a593Smuzhiyun 							     .he_mcs_nss_supp
5043*4882a593Smuzhiyun 							     .rx_mcs_80;
5044*4882a593Smuzhiyun 					mcs_nss[1] = mcs_nss[0] =
5045*4882a593Smuzhiyun 						(mcs_nss[0] & ~0x0c) |
5046*4882a593Smuzhiyun 						((mcs_nss[0] & 0x3) << 2);
5047*4882a593Smuzhiyun 
5048*4882a593Smuzhiyun 					moal_memcpy_ext(
5049*4882a593Smuzhiyun 						priv->phandle,
5050*4882a593Smuzhiyun 						(t_void *)&bands->iftype_data
5051*4882a593Smuzhiyun 							->he_cap.he_mcs_nss_supp
5052*4882a593Smuzhiyun 							.rx_mcs_80,
5053*4882a593Smuzhiyun 						(t_void *)&mcs_nss,
5054*4882a593Smuzhiyun 						sizeof(mcs_nss),
5055*4882a593Smuzhiyun 						sizeof(bands->iftype_data->he_cap
5056*4882a593Smuzhiyun 							       .he_mcs_nss_supp));
5057*4882a593Smuzhiyun 				}
5058*4882a593Smuzhiyun #endif
5059*4882a593Smuzhiyun 			}
5060*4882a593Smuzhiyun 		}
5061*4882a593Smuzhiyun 
5062*4882a593Smuzhiyun 		if (wiphy->bands[IEEE80211_BAND_5GHZ]) {
5063*4882a593Smuzhiyun 			struct ieee80211_supported_band *bands =
5064*4882a593Smuzhiyun 				wiphy->bands[IEEE80211_BAND_5GHZ];
5065*4882a593Smuzhiyun 
5066*4882a593Smuzhiyun 			if (((radio->param.ant_cfg.tx_antenna & 0xFF00) !=
5067*4882a593Smuzhiyun 				     0x300 &&
5068*4882a593Smuzhiyun 			     (radio->param.ant_cfg.tx_antenna & 0xFF00) != 0) ||
5069*4882a593Smuzhiyun 			    ((radio->param.ant_cfg.rx_antenna & 0xFF00) !=
5070*4882a593Smuzhiyun 				     0x300 &&
5071*4882a593Smuzhiyun 			     (radio->param.ant_cfg.rx_antenna & 0xFF00) != 0)) {
5072*4882a593Smuzhiyun 				bands->ht_cap.mcs.rx_mask[1] = 0;
5073*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
5074*4882a593Smuzhiyun 				bands->vht_cap.vht_mcs.rx_mcs_map =
5075*4882a593Smuzhiyun 					(__force __le16)0xfffe;
5076*4882a593Smuzhiyun 				bands->vht_cap.vht_mcs.tx_mcs_map =
5077*4882a593Smuzhiyun 					(__force __le16)0xfffe;
5078*4882a593Smuzhiyun 				bands->vht_cap.vht_mcs.rx_highest =
5079*4882a593Smuzhiyun 					(__force __le16)0x186;
5080*4882a593Smuzhiyun 				bands->vht_cap.vht_mcs.tx_highest =
5081*4882a593Smuzhiyun 					(__force __le16)0x186;
5082*4882a593Smuzhiyun #endif
5083*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
5084*4882a593Smuzhiyun 				if (bands->n_iftype_data &&
5085*4882a593Smuzhiyun 				    bands->iftype_data &&
5086*4882a593Smuzhiyun 				    bands->iftype_data->he_cap.has_he) {
5087*4882a593Smuzhiyun 					t_u16 mcs_nss[2];
5088*4882a593Smuzhiyun 
5089*4882a593Smuzhiyun 					mcs_nss[0] = bands->iftype_data->he_cap
5090*4882a593Smuzhiyun 							     .he_mcs_nss_supp
5091*4882a593Smuzhiyun 							     .rx_mcs_80;
5092*4882a593Smuzhiyun 					mcs_nss[1] = mcs_nss[0] |= 0x0c;
5093*4882a593Smuzhiyun 					moal_memcpy_ext(
5094*4882a593Smuzhiyun 						priv->phandle,
5095*4882a593Smuzhiyun 						(t_void *)&bands->iftype_data
5096*4882a593Smuzhiyun 							->he_cap.he_mcs_nss_supp
5097*4882a593Smuzhiyun 							.rx_mcs_80,
5098*4882a593Smuzhiyun 						(t_void *)&mcs_nss,
5099*4882a593Smuzhiyun 						sizeof(mcs_nss),
5100*4882a593Smuzhiyun 						sizeof(bands->iftype_data->he_cap
5101*4882a593Smuzhiyun 							       .he_mcs_nss_supp));
5102*4882a593Smuzhiyun 				}
5103*4882a593Smuzhiyun #endif
5104*4882a593Smuzhiyun 			} else if ((radio->param.ant_cfg.tx_antenna & 0xFF00) ==
5105*4882a593Smuzhiyun 					   0x300 ||
5106*4882a593Smuzhiyun 				   (radio->param.ant_cfg.rx_antenna & 0xFF00) ==
5107*4882a593Smuzhiyun 					   0x300) {
5108*4882a593Smuzhiyun 				bands->ht_cap.mcs.rx_mask[1] = 0xff;
5109*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
5110*4882a593Smuzhiyun 				bands->vht_cap.vht_mcs.rx_mcs_map =
5111*4882a593Smuzhiyun 					(__force __le16)0xfffa;
5112*4882a593Smuzhiyun 				bands->vht_cap.vht_mcs.tx_mcs_map =
5113*4882a593Smuzhiyun 					(__force __le16)0xfffa;
5114*4882a593Smuzhiyun 				bands->vht_cap.vht_mcs.rx_highest =
5115*4882a593Smuzhiyun 					(__force __le16)0x30c;
5116*4882a593Smuzhiyun 				bands->vht_cap.vht_mcs.tx_highest =
5117*4882a593Smuzhiyun 					(__force __le16)0x30c;
5118*4882a593Smuzhiyun #endif
5119*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
5120*4882a593Smuzhiyun 				if (bands->n_iftype_data &&
5121*4882a593Smuzhiyun 				    bands->iftype_data &&
5122*4882a593Smuzhiyun 				    bands->iftype_data->he_cap.has_he) {
5123*4882a593Smuzhiyun 					t_u16 mcs_nss[2];
5124*4882a593Smuzhiyun 
5125*4882a593Smuzhiyun 					mcs_nss[0] = bands->iftype_data->he_cap
5126*4882a593Smuzhiyun 							     .he_mcs_nss_supp
5127*4882a593Smuzhiyun 							     .rx_mcs_80;
5128*4882a593Smuzhiyun 					mcs_nss[1] = mcs_nss[0] =
5129*4882a593Smuzhiyun 						(mcs_nss[0] & ~0x0c) |
5130*4882a593Smuzhiyun 						((mcs_nss[0] & 0x3) << 2);
5131*4882a593Smuzhiyun 
5132*4882a593Smuzhiyun 					moal_memcpy_ext(
5133*4882a593Smuzhiyun 						priv->phandle,
5134*4882a593Smuzhiyun 						(t_void *)&bands->iftype_data
5135*4882a593Smuzhiyun 							->he_cap.he_mcs_nss_supp
5136*4882a593Smuzhiyun 							.rx_mcs_80,
5137*4882a593Smuzhiyun 						(t_void *)&mcs_nss,
5138*4882a593Smuzhiyun 						sizeof(mcs_nss),
5139*4882a593Smuzhiyun 						sizeof(bands->iftype_data->he_cap
5140*4882a593Smuzhiyun 							       .he_mcs_nss_supp));
5141*4882a593Smuzhiyun 				}
5142*4882a593Smuzhiyun #endif
5143*4882a593Smuzhiyun 			}
5144*4882a593Smuzhiyun 		}
5145*4882a593Smuzhiyun 	}
5146*4882a593Smuzhiyun }
5147*4882a593Smuzhiyun #endif
5148*4882a593Smuzhiyun 
5149*4882a593Smuzhiyun #if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
5150*4882a593Smuzhiyun /**
5151*4882a593Smuzhiyun  * @brief create cfg80211_chan_def structure based on chan_band info
5152*4882a593Smuzhiyun  *
5153*4882a593Smuzhiyun  * @param priv          A pointer moal_private structure
5154*4882a593Smuzhiyun  * @param chandef       A pointer to cfg80211_chan_def structure
5155*4882a593Smuzhiyun  * @param pchan_info    A pointer to chan_band_info structure
5156*4882a593Smuzhiyun  *
5157*4882a593Smuzhiyun  * @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
5158*4882a593Smuzhiyun  */
woal_chandef_create(moal_private * priv,struct cfg80211_chan_def * chandef,chan_band_info * pchan_info)5159*4882a593Smuzhiyun mlan_status woal_chandef_create(moal_private *priv,
5160*4882a593Smuzhiyun 				struct cfg80211_chan_def *chandef,
5161*4882a593Smuzhiyun 				chan_band_info *pchan_info)
5162*4882a593Smuzhiyun {
5163*4882a593Smuzhiyun 	enum ieee80211_band band = IEEE80211_BAND_2GHZ;
5164*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
5165*4882a593Smuzhiyun 
5166*4882a593Smuzhiyun 	ENTER();
5167*4882a593Smuzhiyun 	memset(chandef, 0, sizeof(struct cfg80211_chan_def));
5168*4882a593Smuzhiyun 	chandef->center_freq2 = 0;
5169*4882a593Smuzhiyun 	if (pchan_info->bandcfg.chanBand == BAND_2GHZ)
5170*4882a593Smuzhiyun 		band = IEEE80211_BAND_2GHZ;
5171*4882a593Smuzhiyun 	else if (pchan_info->bandcfg.chanBand == BAND_5GHZ)
5172*4882a593Smuzhiyun 		band = IEEE80211_BAND_5GHZ;
5173*4882a593Smuzhiyun 	chandef->chan = ieee80211_get_channel(
5174*4882a593Smuzhiyun 		priv->wdev->wiphy,
5175*4882a593Smuzhiyun 		ieee80211_channel_to_frequency(pchan_info->channel, band));
5176*4882a593Smuzhiyun 	if (chandef->chan == NULL) {
5177*4882a593Smuzhiyun 		PRINTM(MERROR,
5178*4882a593Smuzhiyun 		       "Fail on ieee80211_get_channel, channel=%d, band=%d\n",
5179*4882a593Smuzhiyun 		       pchan_info->channel, band);
5180*4882a593Smuzhiyun 		status = MLAN_STATUS_FAILURE;
5181*4882a593Smuzhiyun 		goto done;
5182*4882a593Smuzhiyun 	}
5183*4882a593Smuzhiyun 	switch (pchan_info->bandcfg.chanWidth) {
5184*4882a593Smuzhiyun 	case CHAN_BW_20MHZ:
5185*4882a593Smuzhiyun 		if (pchan_info->is_11n_enabled)
5186*4882a593Smuzhiyun 			chandef->width = NL80211_CHAN_WIDTH_20;
5187*4882a593Smuzhiyun 		else
5188*4882a593Smuzhiyun 			chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
5189*4882a593Smuzhiyun 		chandef->center_freq1 = chandef->chan->center_freq;
5190*4882a593Smuzhiyun 		break;
5191*4882a593Smuzhiyun 	case CHAN_BW_40MHZ:
5192*4882a593Smuzhiyun 		chandef->width = NL80211_CHAN_WIDTH_40;
5193*4882a593Smuzhiyun 		if (pchan_info->bandcfg.chan2Offset == SEC_CHAN_ABOVE)
5194*4882a593Smuzhiyun 			chandef->center_freq1 = chandef->chan->center_freq + 10;
5195*4882a593Smuzhiyun 		else if (pchan_info->bandcfg.chan2Offset == SEC_CHAN_BELOW)
5196*4882a593Smuzhiyun 			chandef->center_freq1 = chandef->chan->center_freq - 10;
5197*4882a593Smuzhiyun 		break;
5198*4882a593Smuzhiyun 	case CHAN_BW_80MHZ:
5199*4882a593Smuzhiyun 		chandef->width = NL80211_CHAN_WIDTH_80;
5200*4882a593Smuzhiyun 		chandef->center_freq1 = ieee80211_channel_to_frequency(
5201*4882a593Smuzhiyun 			pchan_info->center_chan, band);
5202*4882a593Smuzhiyun 		break;
5203*4882a593Smuzhiyun 	default:
5204*4882a593Smuzhiyun 		break;
5205*4882a593Smuzhiyun 	}
5206*4882a593Smuzhiyun done:
5207*4882a593Smuzhiyun 	LEAVE();
5208*4882a593Smuzhiyun 	return status;
5209*4882a593Smuzhiyun }
5210*4882a593Smuzhiyun #endif
5211*4882a593Smuzhiyun 
5212*4882a593Smuzhiyun /**
5213*4882a593Smuzhiyun  * @brief Set given radar channel dfs_state to AVAILABLE
5214*4882a593Smuzhiyun  *
5215*4882a593Smuzhiyun  * @param wiphy           A pointer to struct wiphy
5216*4882a593Smuzhiyun  *
5217*4882a593Smuzhiyun  * @return                N/A
5218*4882a593Smuzhiyun  */
woal_clear_wiphy_dfs_state(struct wiphy * wiphy)5219*4882a593Smuzhiyun void woal_clear_wiphy_dfs_state(struct wiphy *wiphy)
5220*4882a593Smuzhiyun {
5221*4882a593Smuzhiyun 	struct ieee80211_supported_band *sband;
5222*4882a593Smuzhiyun 	int i;
5223*4882a593Smuzhiyun 
5224*4882a593Smuzhiyun 	ENTER();
5225*4882a593Smuzhiyun 	if (!wiphy) {
5226*4882a593Smuzhiyun 		LEAVE();
5227*4882a593Smuzhiyun 		return;
5228*4882a593Smuzhiyun 	}
5229*4882a593Smuzhiyun 	sband = wiphy->bands[NL80211_BAND_5GHZ];
5230*4882a593Smuzhiyun 
5231*4882a593Smuzhiyun 	if (!sband) {
5232*4882a593Smuzhiyun 		LEAVE();
5233*4882a593Smuzhiyun 		return;
5234*4882a593Smuzhiyun 	}
5235*4882a593Smuzhiyun 
5236*4882a593Smuzhiyun 	for (i = 0; i < sband->n_channels; i++) {
5237*4882a593Smuzhiyun 		if (sband->channels[i].flags & IEEE80211_CHAN_RADAR) {
5238*4882a593Smuzhiyun #if CFG80211_VERSION_CODE > KERNEL_VERSION(3, 8, 13)
5239*4882a593Smuzhiyun 			if (sband->channels[i].dfs_state ==
5240*4882a593Smuzhiyun 			    NL80211_DFS_UNAVAILABLE) {
5241*4882a593Smuzhiyun 				sband->channels[i].dfs_state =
5242*4882a593Smuzhiyun 					NL80211_DFS_USABLE;
5243*4882a593Smuzhiyun 				sband->channels[i].dfs_state_entered = jiffies;
5244*4882a593Smuzhiyun 			}
5245*4882a593Smuzhiyun #endif
5246*4882a593Smuzhiyun 		}
5247*4882a593Smuzhiyun 	}
5248*4882a593Smuzhiyun 	LEAVE();
5249*4882a593Smuzhiyun }
5250*4882a593Smuzhiyun 
5251*4882a593Smuzhiyun /**
5252*4882a593Smuzhiyun  * @brief Set given radar channel dfs_state to AVAILABLE
5253*4882a593Smuzhiyun  *
5254*4882a593Smuzhiyun  * @param wiphy           A pointer to struct wiphy
5255*4882a593Smuzhiyun  * @param ch_dfs_state    A pointer to struct mlan_ds_11h_chan_dfs_state
5256*4882a593Smuzhiyun  *
5257*4882a593Smuzhiyun  * @return                N/A
5258*4882a593Smuzhiyun  */
woal_get_wiphy_chan_dfs_state(struct wiphy * wiphy,mlan_ds_11h_chan_dfs_state * ch_dfs_state)5259*4882a593Smuzhiyun int woal_get_wiphy_chan_dfs_state(struct wiphy *wiphy,
5260*4882a593Smuzhiyun 				  mlan_ds_11h_chan_dfs_state *ch_dfs_state)
5261*4882a593Smuzhiyun {
5262*4882a593Smuzhiyun 	struct ieee80211_supported_band *sband;
5263*4882a593Smuzhiyun 	int i;
5264*4882a593Smuzhiyun 	int ret = -1;
5265*4882a593Smuzhiyun 	t_u8 channel = ch_dfs_state->channel;
5266*4882a593Smuzhiyun 
5267*4882a593Smuzhiyun 	ENTER();
5268*4882a593Smuzhiyun 	if (!wiphy) {
5269*4882a593Smuzhiyun 		LEAVE();
5270*4882a593Smuzhiyun 		return ret;
5271*4882a593Smuzhiyun 	}
5272*4882a593Smuzhiyun 	sband = wiphy->bands[NL80211_BAND_5GHZ];
5273*4882a593Smuzhiyun 
5274*4882a593Smuzhiyun 	if (!sband) {
5275*4882a593Smuzhiyun 		LEAVE();
5276*4882a593Smuzhiyun 		return ret;
5277*4882a593Smuzhiyun 	}
5278*4882a593Smuzhiyun 	ch_dfs_state->dfs_required = MFALSE;
5279*4882a593Smuzhiyun 	for (i = 0; i < sband->n_channels; i++) {
5280*4882a593Smuzhiyun 		if (sband->channels[i].hw_value == channel) {
5281*4882a593Smuzhiyun 			if (sband->channels[i].flags & IEEE80211_CHAN_RADAR) {
5282*4882a593Smuzhiyun #if CFG80211_VERSION_CODE > KERNEL_VERSION(3, 8, 13)
5283*4882a593Smuzhiyun 				ch_dfs_state->dfs_state =
5284*4882a593Smuzhiyun 					(dfs_state_t)sband->channels[i]
5285*4882a593Smuzhiyun 						.dfs_state;
5286*4882a593Smuzhiyun 				ch_dfs_state->dfs_required = MTRUE;
5287*4882a593Smuzhiyun #endif
5288*4882a593Smuzhiyun 			}
5289*4882a593Smuzhiyun 			ret = 0;
5290*4882a593Smuzhiyun 			break;
5291*4882a593Smuzhiyun 		}
5292*4882a593Smuzhiyun 	}
5293*4882a593Smuzhiyun 	LEAVE();
5294*4882a593Smuzhiyun 	return ret;
5295*4882a593Smuzhiyun }
5296*4882a593Smuzhiyun 
5297*4882a593Smuzhiyun /**
5298*4882a593Smuzhiyun  * @brief Set given radar channel dfs_state to AVAILABLE
5299*4882a593Smuzhiyun  *
5300*4882a593Smuzhiyun  * @param wiphy           A pointer to struct wiphy
5301*4882a593Smuzhiyun  * @param channel         given radar channel
5302*4882a593Smuzhiyun  * @param dfs_state       dfs_state
5303*4882a593Smuzhiyun  *
5304*4882a593Smuzhiyun  * @return                N/A
5305*4882a593Smuzhiyun  */
woal_update_wiphy_chan_dfs_state(struct wiphy * wiphy,t_u8 channel,t_u8 dfs_state)5306*4882a593Smuzhiyun static void woal_update_wiphy_chan_dfs_state(struct wiphy *wiphy, t_u8 channel,
5307*4882a593Smuzhiyun 					     t_u8 dfs_state)
5308*4882a593Smuzhiyun {
5309*4882a593Smuzhiyun 	struct ieee80211_supported_band *sband;
5310*4882a593Smuzhiyun 	int i;
5311*4882a593Smuzhiyun 
5312*4882a593Smuzhiyun 	ENTER();
5313*4882a593Smuzhiyun 	if (!wiphy) {
5314*4882a593Smuzhiyun 		LEAVE();
5315*4882a593Smuzhiyun 		return;
5316*4882a593Smuzhiyun 	}
5317*4882a593Smuzhiyun 	sband = wiphy->bands[NL80211_BAND_5GHZ];
5318*4882a593Smuzhiyun 
5319*4882a593Smuzhiyun 	if (!sband) {
5320*4882a593Smuzhiyun 		LEAVE();
5321*4882a593Smuzhiyun 		return;
5322*4882a593Smuzhiyun 	}
5323*4882a593Smuzhiyun 
5324*4882a593Smuzhiyun 	for (i = 0; i < sband->n_channels; i++) {
5325*4882a593Smuzhiyun 		if (sband->channels[i].flags & IEEE80211_CHAN_RADAR) {
5326*4882a593Smuzhiyun 			if (sband->channels[i].hw_value == channel) {
5327*4882a593Smuzhiyun #if CFG80211_VERSION_CODE > KERNEL_VERSION(3, 8, 13)
5328*4882a593Smuzhiyun 				sband->channels[i].dfs_state = dfs_state;
5329*4882a593Smuzhiyun 				sband->channels[i].dfs_state_entered = jiffies;
5330*4882a593Smuzhiyun #endif
5331*4882a593Smuzhiyun 				break;
5332*4882a593Smuzhiyun 			}
5333*4882a593Smuzhiyun 		}
5334*4882a593Smuzhiyun 	}
5335*4882a593Smuzhiyun #if CFG80211_VERSION_CODE > KERNEL_VERSION(3, 8, 13)
5336*4882a593Smuzhiyun 	if (i < sband->n_channels)
5337*4882a593Smuzhiyun 		PRINTM(MCMD_D, "DFS: Set channel %d dfs_state: %d\n", channel,
5338*4882a593Smuzhiyun 		       sband->channels[i].dfs_state);
5339*4882a593Smuzhiyun #endif
5340*4882a593Smuzhiyun 	LEAVE();
5341*4882a593Smuzhiyun }
5342*4882a593Smuzhiyun /**
5343*4882a593Smuzhiyun  * @brief Set given radar channel dfs_state
5344*4882a593Smuzhiyun  *
5345*4882a593Smuzhiyun  * @param wiphy           A pointer to wiphy structure
5346*4882a593Smuzhiyun  * @param channel         given radar channel
5347*4882a593Smuzhiyun  * @param dfs_state       dfs_state
5348*4882a593Smuzhiyun  *
5349*4882a593Smuzhiyun  * @return                N/A
5350*4882a593Smuzhiyun  */
woal_update_wiphy_channel_dfs_state(struct wiphy * wiphy,t_u8 channel,t_u8 dfs_state)5351*4882a593Smuzhiyun static void woal_update_wiphy_channel_dfs_state(struct wiphy *wiphy,
5352*4882a593Smuzhiyun 						t_u8 channel, t_u8 dfs_state)
5353*4882a593Smuzhiyun {
5354*4882a593Smuzhiyun 	if (!wiphy) {
5355*4882a593Smuzhiyun 		LEAVE();
5356*4882a593Smuzhiyun 		return;
5357*4882a593Smuzhiyun 	}
5358*4882a593Smuzhiyun 	woal_update_wiphy_chan_dfs_state(wiphy, channel, dfs_state);
5359*4882a593Smuzhiyun }
5360*4882a593Smuzhiyun 
5361*4882a593Smuzhiyun /**
5362*4882a593Smuzhiyun  * @brief update channel dfs state to all wiphy
5363*4882a593Smuzhiyun  *
5364*4882a593Smuzhiyun  * @param channel         given radar channel
5365*4882a593Smuzhiyun  * @param dfs_state       dfs_state
5366*4882a593Smuzhiyun  *
5367*4882a593Smuzhiyun  * @return                N/A
5368*4882a593Smuzhiyun  */
woal_update_channel_dfs_state(t_u8 channel,t_u8 dfs_state)5369*4882a593Smuzhiyun void woal_update_channel_dfs_state(t_u8 channel, t_u8 dfs_state)
5370*4882a593Smuzhiyun {
5371*4882a593Smuzhiyun 	int index;
5372*4882a593Smuzhiyun 	for (index = 0; index < MAX_MLAN_ADAPTER; index++) {
5373*4882a593Smuzhiyun 		if (m_handle[index] && m_handle[index]->wiphy)
5374*4882a593Smuzhiyun 			woal_update_wiphy_channel_dfs_state(
5375*4882a593Smuzhiyun 				m_handle[index]->wiphy, channel, dfs_state);
5376*4882a593Smuzhiyun 	}
5377*4882a593Smuzhiyun }
5378