blob: 94ccdb8df235e904df767e973fa17fb82794bac8 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Abhishek Singhef6f38c2018-12-20 13:51:29 +05302 * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019/**
20 * DOC: wlan_hdd_cfg80211.c
21 *
22 * WLAN Host Device Driver cfg80211 APIs implementation
23 *
24 */
25
26#include <linux/version.h>
27#include <linux/module.h>
28#include <linux/kernel.h>
29#include <linux/init.h>
30#include <linux/etherdevice.h>
31#include <linux/wireless.h>
Dustin Browna09acf42018-11-08 12:32:26 +053032#include "osif_sync.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080033#include <wlan_hdd_includes.h>
34#include <net/arp.h>
35#include <net/cfg80211.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080036#include <wlan_hdd_wowl.h>
37#include <ani_global.h>
38#include "sir_params.h"
39#include "dot11f.h"
40#include "wlan_hdd_assoc.h"
41#include "wlan_hdd_wext.h"
42#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070043#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080044#include "wlan_hdd_p2p.h"
45#include "wlan_hdd_cfg80211.h"
46#include "wlan_hdd_hostapd.h"
47#include "wlan_hdd_softap_tx_rx.h"
48#include "wlan_hdd_main.h"
49#include "wlan_hdd_power.h"
50#include "wlan_hdd_trace.h"
Dustin Brownd4241942018-02-26 12:51:37 -080051#include "qdf_str.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053052#include "qdf_trace.h"
Dustin Brownd4241942018-02-26 12:51:37 -080053#include "qdf_types.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080054#include "cds_utils.h"
55#include "cds_sched.h"
56#include "wlan_hdd_scan.h"
57#include <qc_sap_ioctl.h>
58#include "wlan_hdd_tdls.h"
59#include "wlan_hdd_wmm.h"
60#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053061#include "wma.h"
Arif Hussain1f58cbb2019-03-14 17:06:56 -070062#include "wma_twt.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080063#include "wlan_hdd_misc.h"
64#include "wlan_hdd_nan.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080065#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053066#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053067#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053068#include "pld_common.h"
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070069#include "wmi_unified_param.h"
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070070
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080071#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080072#include <wlan_cfg80211_scan.h>
Ryan Hsuc8b27a42018-01-02 13:57:56 -080073#include <wlan_cfg80211_ftm.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080074
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080075#include "wlan_hdd_ext_scan.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080076
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077#include "wlan_hdd_stats.h"
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080078#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080079#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080080#include "qwlan_version.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081
82#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070083#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080084
Ravi Joshideb5a8d2015-11-09 19:11:43 -080085#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053086#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070087#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070088#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053089#include "wlan_hdd_disa.h"
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070090#include "wlan_osif_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080091#include "wlan_hdd_he.h"
Nachiket Kukade177b5b02018-05-22 20:52:17 +053092#ifdef FEATURE_WLAN_APF
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053093#include "wlan_hdd_apf.h"
Nachiket Kukade177b5b02018-05-22 20:52:17 +053094#endif
Qun Zhangef655622019-02-25 10:48:10 +080095#include "wlan_hdd_fw_state.h"
stonez2d686482019-03-12 14:54:26 +080096#include "wlan_hdd_mpta_helper.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -080097
Leo Changfdb45c32016-10-28 11:09:23 -070098#include <cdp_txrx_cmn.h>
99#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800100#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530101#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800102#include "os_if_wifi_pos.h"
Ajit Pal Singh90a45a42017-04-18 18:53:46 +0530103#include "wlan_utility.h"
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -0700104#include "wlan_reg_ucfg_api.h"
Naveen Rawatd2657be2017-10-10 14:31:23 -0700105#include "wifi_pos_api.h"
Sandeep Puligilla063a4342018-01-10 02:50:14 -0800106#include "wlan_hdd_spectralscan.h"
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +0530107#include "wlan_ipa_ucfg_api.h"
Naveen Rawate8b1b822018-01-30 09:46:16 -0800108#include <wlan_cfg80211_mc_cp_stats.h>
Yu Wang157d1472018-03-09 16:05:01 +0800109#include <wlan_cp_stats_mc_ucfg_api.h>
Wu Gaobdb7f272018-07-05 19:33:26 +0800110#include "wlan_tdls_cfg_api.h"
Qiwei Caie689a262018-07-26 15:50:22 +0800111#include <wlan_hdd_bss_transition.h>
112#include <wlan_hdd_concurrency_matrix.h>
113#include <wlan_hdd_p2p_listen_offload.h>
114#include <wlan_hdd_rssi_monitor.h>
115#include <wlan_hdd_sap_cond_chan_switch.h>
116#include <wlan_hdd_station_info.h>
117#include <wlan_hdd_tx_power.h>
118#include <wlan_hdd_active_tos.h>
119#include <wlan_hdd_sar_limits.h>
120#include <wlan_hdd_ota_test.h>
Krunal Soni5e3f9622018-09-26 16:35:50 -0700121#include "wlan_policy_mgr_ucfg.h"
Arunk Khandavalli99716d12018-11-14 15:02:02 +0530122#include "wlan_mlme_ucfg_api.h"
123#include "wlan_mlme_public_struct.h"
Harprit Chhabadae8155d32018-08-22 16:19:34 -0700124#include "wlan_extscan_ucfg_api.h"
Wu Gao93816212018-08-31 16:49:54 +0800125#include "wlan_mlme_ucfg_api.h"
Wu Gao66454f12018-09-26 19:55:41 +0800126#include "wlan_pmo_cfg.h"
127#include "cfg_ucfg_api.h"
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +0530128
Harprit Chhabada6c641ba2018-06-28 14:45:10 -0700129#include "wlan_crypto_global_api.h"
130#include "wlan_nl_to_crypto_params.h"
131#include "wlan_crypto_global_def.h"
jitiphil377bcc12018-10-05 19:46:08 +0530132#include "cdp_txrx_cfg.h"
Min Liu8c5d99e2018-09-10 17:18:44 +0800133#include "wlan_hdd_object_manager.h"
Nachiket Kukade089b9832018-12-12 16:38:17 +0530134#include "nan_ucfg_api.h"
Manikandan Mohand350c192018-11-29 14:01:12 -0800135#include "wlan_fwol_ucfg_api.h"
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -0700136#include "wlan_cfg80211_crypto.h"
Paul Zhang37185672019-05-14 11:20:14 +0800137#include "wlan_cfg80211_interop_issues_ap.h"
gaurank kathpalia97c070b2019-01-07 17:23:06 +0530138#include "wlan_scan_ucfg_api.h"
Jiani Liua5f17222019-03-04 16:22:33 +0800139#include "wlan_hdd_coex_config.h"
Abhinav Kumardbbfd2c2019-05-07 12:22:06 +0530140#include "wlan_hdd_bcn_recv.h"
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +0530141#include "wlan_blm_ucfg_api.h"
guangde4853c402019-05-06 15:54:04 +0800142#include "wlan_hdd_hw_capability.h"
Paul Zhangda2970b2019-06-23 18:16:38 +0800143#include "wlan_hdd_oemdata.h"
Paul Zhangc9dbaee2019-06-23 22:07:31 +0800144#include "os_if_fwol.h"
Harprit Chhabada6c641ba2018-06-28 14:45:10 -0700145
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800146#define g_mode_rates_size (12)
147#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148
149/*
150 * Android CTS verifier needs atleast this much wait time (in msec)
151 */
152#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
153
154/*
155 * Refer @tCfgProtection structure for definition of the bit map.
156 * below value is obtained by setting the following bit-fields.
157 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
158 */
159#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
160
161#define HDD2GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700162 .band = HDD_NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163 .center_freq = (freq), \
164 .hw_value = (chan), \
165 .flags = (flag), \
166 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800167 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168}
169
170#define HDD5GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700171 .band = HDD_NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800172 .center_freq = (freq), \
173 .hw_value = (chan), \
174 .flags = (flag), \
175 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800176 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177}
178
179#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
180 { \
181 .bitrate = rate, \
182 .hw_value = rate_id, \
183 .flags = flag, \
184 }
185
Agrawal Ashish65634612016-08-18 13:24:32 +0530186#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
187 mode <= DFS_MODE_DEPRIORITIZE))
Mohit Khannaceb97782017-04-05 16:27:08 -0700188/*
189 * Number of DPTRACE records to dump when a cfg80211 disconnect with reason
190 * WLAN_REASON_DEAUTH_LEAVING DEAUTH is received from user-space.
191 */
192#define WLAN_DEAUTH_DPTRACE_DUMP_COUNT 100
Mukul Sharma05504ac2017-06-08 12:35:53 +0530193#ifndef WLAN_CIPHER_SUITE_GCMP
194#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
195#endif
196#ifndef WLAN_CIPHER_SUITE_GCMP_256
197#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09
198#endif
Mohit Khannaceb97782017-04-05 16:27:08 -0700199
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +0530200static const u32 hdd_gcmp_cipher_suits[] = {
201 WLAN_CIPHER_SUITE_GCMP,
202 WLAN_CIPHER_SUITE_GCMP_256,
203};
204
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800205static const u32 hdd_cipher_suites[] = {
206 WLAN_CIPHER_SUITE_WEP40,
207 WLAN_CIPHER_SUITE_WEP104,
208 WLAN_CIPHER_SUITE_TKIP,
209#ifdef FEATURE_WLAN_ESE
210#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
211#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
212 WLAN_CIPHER_SUITE_BTK,
213 WLAN_CIPHER_SUITE_KRK,
214 WLAN_CIPHER_SUITE_CCMP,
215#else
216 WLAN_CIPHER_SUITE_CCMP,
217#endif
218#ifdef FEATURE_WLAN_WAPI
219 WLAN_CIPHER_SUITE_SMS4,
220#endif
221#ifdef WLAN_FEATURE_11W
222 WLAN_CIPHER_SUITE_AES_CMAC,
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +0530223#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
224 WLAN_CIPHER_SUITE_BIP_GMAC_128,
225 WLAN_CIPHER_SUITE_BIP_GMAC_256,
226#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800227#endif
228};
229
Abhishek Singhf512bf32016-05-04 16:47:46 +0530230static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231 HDD2GHZCHAN(2412, 1, 0),
232 HDD2GHZCHAN(2417, 2, 0),
233 HDD2GHZCHAN(2422, 3, 0),
234 HDD2GHZCHAN(2427, 4, 0),
235 HDD2GHZCHAN(2432, 5, 0),
236 HDD2GHZCHAN(2437, 6, 0),
237 HDD2GHZCHAN(2442, 7, 0),
238 HDD2GHZCHAN(2447, 8, 0),
239 HDD2GHZCHAN(2452, 9, 0),
240 HDD2GHZCHAN(2457, 10, 0),
241 HDD2GHZCHAN(2462, 11, 0),
242 HDD2GHZCHAN(2467, 12, 0),
243 HDD2GHZCHAN(2472, 13, 0),
244 HDD2GHZCHAN(2484, 14, 0),
245};
246
Abhishek Singhf512bf32016-05-04 16:47:46 +0530247static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800248 HDD5GHZCHAN(5180, 36, 0),
249 HDD5GHZCHAN(5200, 40, 0),
250 HDD5GHZCHAN(5220, 44, 0),
251 HDD5GHZCHAN(5240, 48, 0),
252 HDD5GHZCHAN(5260, 52, 0),
253 HDD5GHZCHAN(5280, 56, 0),
254 HDD5GHZCHAN(5300, 60, 0),
255 HDD5GHZCHAN(5320, 64, 0),
256 HDD5GHZCHAN(5500, 100, 0),
257 HDD5GHZCHAN(5520, 104, 0),
258 HDD5GHZCHAN(5540, 108, 0),
259 HDD5GHZCHAN(5560, 112, 0),
260 HDD5GHZCHAN(5580, 116, 0),
261 HDD5GHZCHAN(5600, 120, 0),
262 HDD5GHZCHAN(5620, 124, 0),
263 HDD5GHZCHAN(5640, 128, 0),
264 HDD5GHZCHAN(5660, 132, 0),
265 HDD5GHZCHAN(5680, 136, 0),
266 HDD5GHZCHAN(5700, 140, 0),
267 HDD5GHZCHAN(5720, 144, 0),
268 HDD5GHZCHAN(5745, 149, 0),
269 HDD5GHZCHAN(5765, 153, 0),
270 HDD5GHZCHAN(5785, 157, 0),
271 HDD5GHZCHAN(5805, 161, 0),
272 HDD5GHZCHAN(5825, 165, 0),
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +0530273};
274
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -0700275#ifdef WLAN_FEATURE_DSRC
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +0530276static const struct ieee80211_channel hdd_channels_dot11p[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800277 HDD5GHZCHAN(5852, 170, 0),
278 HDD5GHZCHAN(5855, 171, 0),
279 HDD5GHZCHAN(5860, 172, 0),
280 HDD5GHZCHAN(5865, 173, 0),
281 HDD5GHZCHAN(5870, 174, 0),
282 HDD5GHZCHAN(5875, 175, 0),
283 HDD5GHZCHAN(5880, 176, 0),
284 HDD5GHZCHAN(5885, 177, 0),
285 HDD5GHZCHAN(5890, 178, 0),
286 HDD5GHZCHAN(5895, 179, 0),
287 HDD5GHZCHAN(5900, 180, 0),
288 HDD5GHZCHAN(5905, 181, 0),
289 HDD5GHZCHAN(5910, 182, 0),
290 HDD5GHZCHAN(5915, 183, 0),
291 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292};
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -0700293#else
294static const struct ieee80211_channel hdd_etsi13_srd_ch[] = {
295 HDD5GHZCHAN(5845, 169, 0),
296 HDD5GHZCHAN(5865, 173, 0),
297};
298#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800299
Qun Zhang043635a2019-02-27 15:19:29 +0800300#define band_2_ghz_channels_size sizeof(hdd_channels_2_4_ghz)
301
302#ifdef WLAN_FEATURE_DSRC
303#define band_5_ghz_chanenls_size (sizeof(hdd_channels_5_ghz) + \
304 sizeof(hdd_channels_dot11p))
305#else
306#define band_5_ghz_chanenls_size (sizeof(hdd_channels_5_ghz) + \
307 sizeof(hdd_etsi13_srd_ch))
308#endif
309
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800310static struct ieee80211_rate g_mode_rates[] = {
311 HDD_G_MODE_RATETAB(10, 0x1, 0),
312 HDD_G_MODE_RATETAB(20, 0x2, 0),
313 HDD_G_MODE_RATETAB(55, 0x4, 0),
314 HDD_G_MODE_RATETAB(110, 0x8, 0),
315 HDD_G_MODE_RATETAB(60, 0x10, 0),
316 HDD_G_MODE_RATETAB(90, 0x20, 0),
317 HDD_G_MODE_RATETAB(120, 0x40, 0),
318 HDD_G_MODE_RATETAB(180, 0x80, 0),
319 HDD_G_MODE_RATETAB(240, 0x100, 0),
320 HDD_G_MODE_RATETAB(360, 0x200, 0),
321 HDD_G_MODE_RATETAB(480, 0x400, 0),
322 HDD_G_MODE_RATETAB(540, 0x800, 0),
323};
324
325static struct ieee80211_rate a_mode_rates[] = {
326 HDD_G_MODE_RATETAB(60, 0x10, 0),
327 HDD_G_MODE_RATETAB(90, 0x20, 0),
328 HDD_G_MODE_RATETAB(120, 0x40, 0),
329 HDD_G_MODE_RATETAB(180, 0x80, 0),
330 HDD_G_MODE_RATETAB(240, 0x100, 0),
331 HDD_G_MODE_RATETAB(360, 0x200, 0),
332 HDD_G_MODE_RATETAB(480, 0x400, 0),
333 HDD_G_MODE_RATETAB(540, 0x800, 0),
334};
335
336static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530337 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800338 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700339 .band = HDD_NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800340 .bitrates = g_mode_rates,
341 .n_bitrates = g_mode_rates_size,
342 .ht_cap.ht_supported = 1,
343 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
344 | IEEE80211_HT_CAP_GRN_FLD
345 | IEEE80211_HT_CAP_DSSSCCK40
346 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
347 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
348 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
349 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
350 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
351 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
352 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
353};
354
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800355static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530356 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800357 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700358 .band = HDD_NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800359 .bitrates = a_mode_rates,
360 .n_bitrates = a_mode_rates_size,
361 .ht_cap.ht_supported = 1,
362 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
363 | IEEE80211_HT_CAP_GRN_FLD
364 | IEEE80211_HT_CAP_DSSSCCK40
365 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
366 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
367 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
368 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
369 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
370 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
371 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
372 .vht_cap.vht_supported = 1,
373};
374
375/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800376 * TX/RX direction for each kind of interface
377 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800378static const struct ieee80211_txrx_stypes
379 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
380 [NL80211_IFTYPE_STATION] = {
381 .tx = 0xffff,
382 .rx = BIT(SIR_MAC_MGMT_ACTION) |
Padma, Santhosh Kumar1ccc1332017-09-13 17:39:01 +0530383 BIT(SIR_MAC_MGMT_PROBE_REQ) |
384 BIT(SIR_MAC_MGMT_AUTH),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800385 },
386 [NL80211_IFTYPE_AP] = {
387 .tx = 0xffff,
388 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
389 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
390 BIT(SIR_MAC_MGMT_PROBE_REQ) |
391 BIT(SIR_MAC_MGMT_DISASSOC) |
392 BIT(SIR_MAC_MGMT_AUTH) |
393 BIT(SIR_MAC_MGMT_DEAUTH) |
394 BIT(SIR_MAC_MGMT_ACTION),
395 },
396 [NL80211_IFTYPE_ADHOC] = {
397 .tx = 0xffff,
398 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
399 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
400 BIT(SIR_MAC_MGMT_PROBE_REQ) |
401 BIT(SIR_MAC_MGMT_DISASSOC) |
402 BIT(SIR_MAC_MGMT_AUTH) |
403 BIT(SIR_MAC_MGMT_DEAUTH) |
404 BIT(SIR_MAC_MGMT_ACTION),
405 },
406 [NL80211_IFTYPE_P2P_CLIENT] = {
407 .tx = 0xffff,
408 .rx = BIT(SIR_MAC_MGMT_ACTION) |
409 BIT(SIR_MAC_MGMT_PROBE_REQ),
410 },
411 [NL80211_IFTYPE_P2P_GO] = {
412 /* This is also same as for SoftAP */
413 .tx = 0xffff,
414 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
415 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
416 BIT(SIR_MAC_MGMT_PROBE_REQ) |
417 BIT(SIR_MAC_MGMT_DISASSOC) |
418 BIT(SIR_MAC_MGMT_AUTH) |
419 BIT(SIR_MAC_MGMT_DEAUTH) |
420 BIT(SIR_MAC_MGMT_ACTION),
421 },
422};
423
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800424/* Interface limits and combinations registered by the driver */
425
426/* STA ( + STA ) combination */
427static const struct ieee80211_iface_limit
428 wlan_hdd_sta_iface_limit[] = {
429 {
430 .max = 3, /* p2p0 is a STA as well */
431 .types = BIT(NL80211_IFTYPE_STATION),
432 },
433};
434
435/* ADHOC (IBSS) limit */
436static const struct ieee80211_iface_limit
437 wlan_hdd_adhoc_iface_limit[] = {
438 {
439 .max = 1,
440 .types = BIT(NL80211_IFTYPE_STATION),
441 },
442 {
443 .max = 1,
444 .types = BIT(NL80211_IFTYPE_ADHOC),
445 },
446};
447
448/* AP ( + AP ) combination */
449static const struct ieee80211_iface_limit
450 wlan_hdd_ap_iface_limit[] = {
451 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530452 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800453 .types = BIT(NL80211_IFTYPE_AP),
454 },
455};
456
457/* P2P limit */
458static const struct ieee80211_iface_limit
459 wlan_hdd_p2p_iface_limit[] = {
460 {
461 .max = 1,
462 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
463 },
464 {
465 .max = 1,
466 .types = BIT(NL80211_IFTYPE_P2P_GO),
467 },
468};
469
470static const struct ieee80211_iface_limit
471 wlan_hdd_sta_ap_iface_limit[] = {
472 {
473 /* We need 1 extra STA interface for OBSS scan when SAP starts
474 * with HT40 in STA+SAP concurrency mode
475 */
476 .max = (1 + SAP_MAX_OBSS_STA_CNT),
477 .types = BIT(NL80211_IFTYPE_STATION),
478 },
479 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530480 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800481 .types = BIT(NL80211_IFTYPE_AP),
482 },
483};
484
485/* STA + P2P combination */
486static const struct ieee80211_iface_limit
487 wlan_hdd_sta_p2p_iface_limit[] = {
488 {
489 /* One reserved for dedicated P2PDEV usage */
490 .max = 2,
491 .types = BIT(NL80211_IFTYPE_STATION)
492 },
493 {
494 /* Support for two identical (GO + GO or CLI + CLI)
495 * or dissimilar (GO + CLI) P2P interfaces
496 */
497 .max = 2,
498 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
499 },
500};
501
502/* STA + AP + P2PGO combination */
503static const struct ieee80211_iface_limit
504wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
505 /* Support for AP+P2PGO interfaces */
506 {
507 .max = 2,
508 .types = BIT(NL80211_IFTYPE_STATION)
509 },
510 {
511 .max = 1,
512 .types = BIT(NL80211_IFTYPE_P2P_GO)
513 },
514 {
515 .max = 1,
516 .types = BIT(NL80211_IFTYPE_AP)
517 }
518};
519
520/* SAP + P2P combination */
521static const struct ieee80211_iface_limit
522wlan_hdd_sap_p2p_iface_limit[] = {
523 {
524 /* 1 dedicated for p2p0 which is a STA type */
525 .max = 1,
526 .types = BIT(NL80211_IFTYPE_STATION)
527 },
528 {
529 /* The p2p interface in SAP+P2P can be GO/CLI.
530 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
531 */
532 .max = 1,
533 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
534 },
535 {
536 /* SAP+GO to support only one SAP interface */
537 .max = 1,
538 .types = BIT(NL80211_IFTYPE_AP)
539 }
540};
541
542/* P2P + P2P combination */
543static const struct ieee80211_iface_limit
544wlan_hdd_p2p_p2p_iface_limit[] = {
545 {
546 /* 1 dedicated for p2p0 which is a STA type */
547 .max = 1,
548 .types = BIT(NL80211_IFTYPE_STATION)
549 },
550 {
551 /* The p2p interface in P2P+P2P can be GO/CLI.
552 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
553 */
554 .max = 2,
555 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
556 },
557};
558
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700559static const struct ieee80211_iface_limit
560 wlan_hdd_mon_iface_limit[] = {
561 {
562 .max = 3, /* Monitor interface */
563 .types = BIT(NL80211_IFTYPE_MONITOR),
564 },
565};
566
567static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800568 wlan_hdd_iface_combination[] = {
569 /* STA */
570 {
571 .limits = wlan_hdd_sta_iface_limit,
572 .num_different_channels = 2,
573 .max_interfaces = 3,
574 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
575 },
576 /* ADHOC */
577 {
578 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700579 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 .max_interfaces = 2,
581 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
582 },
583 /* AP */
584 {
585 .limits = wlan_hdd_ap_iface_limit,
586 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530587 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
hqu3c4ed3d2017-09-19 11:42:35 +0800589#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
590 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
591 .beacon_int_min_gcd = 1,
592#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593 },
594 /* P2P */
595 {
596 .limits = wlan_hdd_p2p_iface_limit,
597 .num_different_channels = 2,
598 .max_interfaces = 2,
599 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
600 },
601 /* STA + AP */
602 {
603 .limits = wlan_hdd_sta_ap_iface_limit,
604 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530605 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800606 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
607 .beacon_int_infra_match = true,
hqu3c4ed3d2017-09-19 11:42:35 +0800608#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
609 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
610 .beacon_int_min_gcd = 1,
611#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800612 },
613 /* STA + P2P */
614 {
615 .limits = wlan_hdd_sta_p2p_iface_limit,
616 .num_different_channels = 2,
617 /* one interface reserved for P2PDEV dedicated usage */
618 .max_interfaces = 4,
619 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
620 .beacon_int_infra_match = true,
621 },
622 /* STA + P2P GO + SAP */
623 {
624 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
625 /* we can allow 3 channels for three different persona
626 * but due to firmware limitation, allow max 2 concrnt channels.
627 */
628 .num_different_channels = 2,
629 /* one interface reserved for P2PDEV dedicated usage */
630 .max_interfaces = 4,
631 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
632 .beacon_int_infra_match = true,
633 },
634 /* SAP + P2P */
635 {
636 .limits = wlan_hdd_sap_p2p_iface_limit,
637 .num_different_channels = 2,
638 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
639 .max_interfaces = 3,
640 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
641 .beacon_int_infra_match = true,
642 },
643 /* P2P + P2P */
644 {
645 .limits = wlan_hdd_p2p_p2p_iface_limit,
646 .num_different_channels = 2,
647 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
648 .max_interfaces = 3,
649 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
650 .beacon_int_infra_match = true,
651 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530652 /* Monitor */
653 {
654 .limits = wlan_hdd_mon_iface_limit,
655 .max_interfaces = 3,
656 .num_different_channels = 2,
657 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
658 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800659};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800660
661static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800662
663#ifdef WLAN_NL80211_TESTMODE
664enum wlan_hdd_tm_attr {
665 WLAN_HDD_TM_ATTR_INVALID = 0,
666 WLAN_HDD_TM_ATTR_CMD = 1,
667 WLAN_HDD_TM_ATTR_DATA = 2,
668 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
669 WLAN_HDD_TM_ATTR_TYPE = 4,
670 /* keep last */
671 WLAN_HDD_TM_ATTR_AFTER_LAST,
672 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
673};
674
675enum wlan_hdd_tm_cmd {
676 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
677 WLAN_HDD_TM_CMD_WLAN_HB = 1,
678};
679
680#define WLAN_HDD_TM_DATA_MAX_LEN 5000
681
682static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
683 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
684 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
685 .len = WLAN_HDD_TM_DATA_MAX_LEN},
686};
687#endif /* WLAN_NL80211_TESTMODE */
688
Lin Baia016e9a2017-08-29 19:10:42 +0800689enum wlan_hdd_vendor_ie_access_policy {
690 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
691 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
692};
693
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800694#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
695static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
696 .flags = WIPHY_WOWLAN_MAGIC_PKT,
697 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
698 .pattern_min_len = 1,
699 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
700};
701#endif
702
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800703/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530704 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
705 * @flags: Pointer to the flags to Add channel switch flag.
706 *
707 * This Function adds Channel Switch support flag, if channel switch is
708 * supported by kernel.
709 * Return: void.
710 */
711#ifdef CHANNEL_SWITCH_SUPPORTED
712static inline void hdd_add_channel_switch_support(uint32_t *flags)
713{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800714 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530715}
716#else
717static inline void hdd_add_channel_switch_support(uint32_t *flags)
718{
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530719}
720#endif
721
Manikandan Mohan22b83722015-12-15 15:03:23 -0800722#ifdef FEATURE_WLAN_TDLS
723
724/* TDLS capabilities params */
725#define PARAM_MAX_TDLS_SESSION \
726 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
727#define PARAM_TDLS_FEATURE_SUPPORT \
728 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
729
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530730/**
Jeff Johnson118a4a02018-05-06 00:14:15 -0700731 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800732 * @wiphy: WIPHY structure pointer
733 * @wdev: Wireless device structure pointer
734 * @data: Pointer to the data received
735 * @data_len: Length of the data received
736 *
737 * This function provides TDLS capabilities
738 *
739 * Return: 0 on success and errno on failure
740 */
741static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
742 struct wireless_dev *wdev,
743 const void *data,
744 int data_len)
745{
746 int status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -0700747 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800748 struct sk_buff *skb;
749 uint32_t set = 0;
Frank Liu5c63dc82017-09-07 14:49:05 +0800750 uint32_t max_num_tdls_sta = 0;
Wu Gaobdb7f272018-07-05 19:33:26 +0800751 bool tdls_support;
752 bool tdls_external_control;
753 bool tdls_sleep_sta_enable;
754 bool tdls_buffer_sta;
755 bool tdls_off_channel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800756
Dustin Brownfdf17c12018-03-14 12:55:34 -0700757 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -0800758
Anurag Chouhan6d760662016-02-20 16:05:43 +0530759 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800760 hdd_err("Command not allowed in FTM mode");
761 return -EPERM;
762 }
763
764 status = wlan_hdd_validate_context(hdd_ctx);
765 if (status)
766 return status;
767
768 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
769 NLMSG_HDRLEN);
770 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700771 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772 goto fail;
773 }
774
Dustin Brown76cd2932018-09-11 16:03:05 -0700775 if ((cfg_tdls_get_support_enable(hdd_ctx->psoc, &tdls_support) ==
Bala Venkateshdcbad342019-03-18 13:57:24 +0530776 QDF_STATUS_SUCCESS) && !tdls_support) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800777 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800778 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
779 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700780 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800781 goto fail;
782 }
783 } else {
Dustin Brown76cd2932018-09-11 16:03:05 -0700784 cfg_tdls_get_external_control(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800785 &tdls_external_control);
Dustin Brown76cd2932018-09-11 16:03:05 -0700786 cfg_tdls_get_sleep_sta_enable(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800787 &tdls_sleep_sta_enable);
Dustin Brown76cd2932018-09-11 16:03:05 -0700788 cfg_tdls_get_buffer_sta_enable(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800789 &tdls_buffer_sta);
Dustin Brown76cd2932018-09-11 16:03:05 -0700790 cfg_tdls_get_off_channel_enable(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800791 &tdls_off_channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800792 set = set | WIFI_TDLS_SUPPORT;
Wu Gaobdb7f272018-07-05 19:33:26 +0800793 set = set | (tdls_external_control ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800794 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
Wu Gaobdb7f272018-07-05 19:33:26 +0800795 set = set | (tdls_off_channel ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800796 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Wu Gaobdb7f272018-07-05 19:33:26 +0800797 if (tdls_sleep_sta_enable || tdls_buffer_sta ||
798 tdls_off_channel)
Frank Liu5c63dc82017-09-07 14:49:05 +0800799 max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA_P_UAPSD_OFFCHAN;
800 else
801 max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA;
802
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800803 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
Frank Liu5c63dc82017-09-07 14:49:05 +0800805 max_num_tdls_sta) ||
806 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700807 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800808 goto fail;
809 }
810 }
811 return cfg80211_vendor_cmd_reply(skb);
812fail:
813 if (skb)
814 kfree_skb(skb);
815 return -EINVAL;
816}
817
818/**
Jeff Johnson118a4a02018-05-06 00:14:15 -0700819 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800820 * @wiphy: WIPHY structure pointer
821 * @wdev: Wireless device structure pointer
822 * @data: Pointer to the data received
823 * @data_len: Length of the data received
824 *
825 * This function provides TDLS capabilities
826 *
827 * Return: 0 on success and errno on failure
828 */
829static int
830wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
831 struct wireless_dev *wdev,
832 const void *data,
833 int data_len)
834{
Dustin Brown363b4792019-02-05 16:11:55 -0800835 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -0800836 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +0530837
Dustin Brown363b4792019-02-05 16:11:55 -0800838 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -0800839 if (errno)
840 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800841
Dustin Brownf0f00612019-01-31 16:02:24 -0800842 errno = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
843 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800844
Dustin Brown363b4792019-02-05 16:11:55 -0800845 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -0800846
847 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800848}
jiad7b8a5e02018-11-26 16:37:57 +0800849
850static uint8_t hdd_get_bw_offset(uint32_t ch_width)
851{
852 uint8_t bw_offset = 0;
853
854 if (ch_width == CH_WIDTH_40MHZ)
855 bw_offset = 1 << BW_40_OFFSET_BIT;
856 else if (ch_width == CH_WIDTH_20MHZ)
857 bw_offset = 1 << BW_20_OFFSET_BIT;
858
859 return bw_offset;
860}
861
862#else /* !FEATURE_WLAN_TDLS */
863
864static inline uint8_t hdd_get_bw_offset(uint32_t ch_width)
865{
866 return 0;
867}
868
869#endif /* FEATURE_WLAN_TDLS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800870
871#ifdef QCA_HT_2040_COEX
872static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
873#endif
874
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700875int wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type *destFreqList,
876 struct ch_avoid_ind_type *srcFreqList)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530877{
878 int i;
Jeff Johnson62f28992019-03-05 14:48:42 -0800879 uint32_t room;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700880 struct ch_avoid_freq_type *avoid_range =
881 &destFreqList->avoid_freq_range[destFreqList->ch_avoid_range_cnt];
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530882
Jeff Johnson62f28992019-03-05 14:48:42 -0800883 room = CH_AVOID_MAX_RANGE - destFreqList->ch_avoid_range_cnt;
884 if (srcFreqList->ch_avoid_range_cnt > room) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530885 hdd_err("avoid freq overflow");
886 return -EINVAL;
887 }
Jeff Johnson62f28992019-03-05 14:48:42 -0800888 destFreqList->ch_avoid_range_cnt += srcFreqList->ch_avoid_range_cnt;
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530889
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700890 for (i = 0; i < srcFreqList->ch_avoid_range_cnt; i++) {
891 avoid_range->start_freq =
892 srcFreqList->avoid_freq_range[i].start_freq;
893 avoid_range->end_freq =
894 srcFreqList->avoid_freq_range[i].end_freq;
895 avoid_range++;
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530896 }
897 return 0;
898}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800899/*
900 * FUNCTION: wlan_hdd_send_avoid_freq_event
901 * This is called when wlan driver needs to send vendor specific
902 * avoid frequency range event to userspace
903 */
Jeff Johnsonb8944722017-09-03 09:03:19 -0700904int wlan_hdd_send_avoid_freq_event(struct hdd_context *hdd_ctx,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700905 struct ch_avoid_ind_type *avoid_freq_list)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800906{
907 struct sk_buff *vendor_event;
908
Dustin Brown491d54b2018-03-14 12:39:11 -0700909 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800910
Jeff Johnsonb8944722017-09-03 09:03:19 -0700911 if (!hdd_ctx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700912 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800913 return -EINVAL;
914 }
915
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700916 if (!avoid_freq_list) {
917 hdd_err("avoid_freq_list is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800918 return -EINVAL;
919 }
920
Jeff Johnsonb8944722017-09-03 09:03:19 -0700921 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700922 NULL, sizeof(struct ch_avoid_ind_type),
923 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
924 GFP_KERNEL);
925
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800926 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700927 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800928 return -EINVAL;
929 }
930
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700931 memcpy(skb_put(vendor_event, sizeof(struct ch_avoid_ind_type)),
932 (void *)avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800933
934 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
935
Dustin Browne74003f2018-03-14 12:51:58 -0700936 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800937 return 0;
938}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530940/*
941 * define short names for the global vendor params
942 * used by QCA_NL80211_VENDOR_SUBCMD_HANG
943 */
944#define HANG_REASON_INDEX QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX
945
946/**
947 * hdd_convert_hang_reason() - Convert cds recovery reason to vendor specific
948 * hang reason
949 * @reason: cds recovery reason
950 *
951 * Return: Vendor specific reason code
952 */
953static enum qca_wlan_vendor_hang_reason
954hdd_convert_hang_reason(enum qdf_hang_reason reason)
955{
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -0700956 u32 ret_val;
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530957
958 switch (reason) {
959 case QDF_RX_HASH_NO_ENTRY_FOUND:
960 ret_val = QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND;
961 break;
962 case QDF_PEER_DELETION_TIMEDOUT:
963 ret_val = QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT;
964 break;
965 case QDF_PEER_UNMAP_TIMEDOUT:
966 ret_val = QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT;
967 break;
968 case QDF_SCAN_REQ_EXPIRED:
969 ret_val = QCA_WLAN_HANG_SCAN_REQ_EXPIRED;
970 break;
971 case QDF_SCAN_ATTEMPT_FAILURES:
972 ret_val = QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES;
973 break;
974 case QDF_GET_MSG_BUFF_FAILURE:
975 ret_val = QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE;
976 break;
977 case QDF_ACTIVE_LIST_TIMEOUT:
978 ret_val = QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT;
979 break;
980 case QDF_SUSPEND_TIMEOUT:
981 ret_val = QCA_WLAN_HANG_SUSPEND_TIMEOUT;
982 break;
983 case QDF_RESUME_TIMEOUT:
984 ret_val = QCA_WLAN_HANG_RESUME_TIMEOUT;
985 break;
Jingxiang Ge2a67be52019-04-10 14:47:51 +0800986 case QDF_WMI_EXCEED_MAX_PENDING_CMDS:
987 ret_val = QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS;
988 break;
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530989 case QDF_REASON_UNSPECIFIED:
990 default:
991 ret_val = QCA_WLAN_HANG_REASON_UNSPECIFIED;
992 }
993 return ret_val;
994}
995
996/**
997 * wlan_hdd_send_hang_reason_event() - Send hang reason to the userspace
998 * @hdd_ctx: Pointer to hdd context
999 * @reason: cds recovery reason
1000 *
1001 * Return: 0 on success or failure reason
1002 */
1003int wlan_hdd_send_hang_reason_event(struct hdd_context *hdd_ctx,
1004 enum qdf_hang_reason reason)
1005{
1006 struct sk_buff *vendor_event;
1007 enum qca_wlan_vendor_hang_reason hang_reason;
1008
Dustin Brown491d54b2018-03-14 12:39:11 -07001009 hdd_enter();
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301010
1011 if (!hdd_ctx) {
1012 hdd_err("HDD context is null");
1013 return -EINVAL;
1014 }
1015
1016 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1017 NULL,
1018 sizeof(uint32_t),
1019 HANG_REASON_INDEX,
1020 GFP_KERNEL);
1021 if (!vendor_event) {
1022 hdd_err("cfg80211_vendor_event_alloc failed");
1023 return -ENOMEM;
1024 }
1025
1026 hang_reason = hdd_convert_hang_reason(reason);
1027
1028 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON,
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -07001029 (uint32_t)hang_reason)) {
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301030 hdd_err("QCA_WLAN_VENDOR_ATTR_HANG_REASON put fail");
1031 kfree_skb(vendor_event);
1032 return -EINVAL;
1033 }
1034
1035 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1036
Dustin Browne74003f2018-03-14 12:51:58 -07001037 hdd_exit();
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301038 return 0;
1039}
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -07001040
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301041#undef HANG_REASON_INDEX
1042
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301043/**
1044 * wlan_hdd_get_adjacent_chan(): Gets next/previous channel
1045 * with respect to the channel passed.
1046 * @chan: Channel
1047 * @upper: If "true" then next channel is returned or else
1048 * previous channel is returned.
1049 *
1050 * This function returns the next/previous adjacent-channel to
1051 * the channel passed. If "upper = true" then next channel is
1052 * returned else previous is returned.
1053 */
1054int wlan_hdd_get_adjacent_chan(uint8_t chan, bool upper)
1055{
Ashish Kumar Dhanotiyaaa9fdbb2018-12-14 15:29:14 +05301056 enum channel_enum ch_idx = wlan_reg_get_chan_enum(chan);
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301057
1058 if (ch_idx == INVALID_CHANNEL)
1059 return -EINVAL;
1060
1061 if (upper && (ch_idx < (NUM_CHANNELS - 1)))
1062 ch_idx++;
Amar Singhal2e4cccc2019-08-06 12:47:18 -07001063 else if (!upper && (ch_idx > CHAN_ENUM_2412))
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301064 ch_idx--;
1065 else
1066 return -EINVAL;
1067
1068 return WLAN_REG_CH_NUM(ch_idx);
1069}
1070
1071/**
1072 * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
1073 * avoided when Do_Not_Break_Stream is active.
Jeff Johnsonb8944722017-09-03 09:03:19 -07001074 * @hdd_ctx: HDD Context
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301075 * @op_chan: AP/P2P-GO operating channel
1076 *
1077 * This function sends list of frequencies to be avoided when
1078 * Do_Not_Break_Stream is active.
1079 * To clear the avoid_frequency_list in the application,
1080 * op_chan = 0 can be passed.
1081 *
1082 * Return: 0 on success and errno on failure
1083 */
Jeff Johnsonb8944722017-09-03 09:03:19 -07001084int wlan_hdd_send_avoid_freq_for_dnbs(struct hdd_context *hdd_ctx, uint8_t op_chan)
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301085{
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001086 struct ch_avoid_ind_type p2p_avoid_freq_list;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301087 uint8_t min_chan, max_chan;
1088 int ret;
1089 int chan;
1090
Dustin Brown491d54b2018-03-14 12:39:11 -07001091 hdd_enter();
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301092
Jeff Johnsonb8944722017-09-03 09:03:19 -07001093 if (!hdd_ctx) {
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301094 hdd_err("invalid param");
1095 return -EINVAL;
1096 }
1097
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001098 qdf_mem_zero(&p2p_avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301099 /*
1100 * If channel passed is zero, clear the avoid_freq list in application.
1101 */
1102 if (!op_chan) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301103#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001104 mutex_lock(&hdd_ctx->avoid_freq_lock);
1105 qdf_mem_zero(&hdd_ctx->dnbs_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001106 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001107 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301108 memcpy(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001109 &hdd_ctx->coex_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001110 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001111 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301112#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001113 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx,
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301114 &p2p_avoid_freq_list);
1115 if (ret)
1116 hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
1117 ret);
1118
1119 return ret;
1120 }
1121
1122 if (WLAN_REG_IS_24GHZ_CH(op_chan)) {
Ashish Kumar Dhanotiyaaa9fdbb2018-12-14 15:29:14 +05301123 min_chan = WLAN_REG_MIN_24GHZ_CH_NUM;
1124 max_chan = WLAN_REG_MAX_24GHZ_CH_NUM;
1125 } else if (WLAN_REG_IS_5GHZ_CH(op_chan)) {
1126 min_chan = WLAN_REG_MIN_5GHZ_CH_NUM;
1127 max_chan = WLAN_REG_MAX_5GHZ_CH_NUM;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301128 } else {
1129 hdd_err("invalid channel:%d", op_chan);
1130 return -EINVAL;
1131 }
1132
1133 if ((op_chan > min_chan) && (op_chan < max_chan)) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001134 p2p_avoid_freq_list.ch_avoid_range_cnt = 2;
1135 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301136 wlan_chan_to_freq(min_chan);
1137
1138 /* Get channel before the op_chan */
1139 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1140 if (chan < 0)
1141 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001142 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301143 wlan_chan_to_freq(chan);
1144
1145 /* Get channel next to the op_chan */
1146 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1147 if (chan < 0)
1148 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001149 p2p_avoid_freq_list.avoid_freq_range[1].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301150 wlan_chan_to_freq(chan);
1151
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001152 p2p_avoid_freq_list.avoid_freq_range[1].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301153 wlan_chan_to_freq(max_chan);
1154 } else if (op_chan == min_chan) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001155 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301156
1157 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1158 if (chan < 0)
1159 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001160 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301161 wlan_chan_to_freq(chan);
1162
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001163 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301164 wlan_chan_to_freq(max_chan);
1165 } else {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001166 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
1167 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301168 wlan_chan_to_freq(min_chan);
1169
1170 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1171 if (chan < 0)
1172 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001173 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301174 wlan_chan_to_freq(chan);
1175 }
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301176#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001177 mutex_lock(&hdd_ctx->avoid_freq_lock);
1178 hdd_ctx->dnbs_avoid_freq_list = p2p_avoid_freq_list;
1179 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301180 ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001181 &hdd_ctx->coex_avoid_freq_list);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301182 if (ret) {
Jeff Johnsonb8944722017-09-03 09:03:19 -07001183 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301184 hdd_err("avoid freq merge failed");
1185 return ret;
1186 }
1187 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07001188 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301189#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001190 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx, &p2p_avoid_freq_list);
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301191 if (ret)
1192 hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
1193
1194 return ret;
1195}
1196
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001197/* vendor specific events */
1198static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001199 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
1200 .vendor_id =
1201 QCA_NL80211_VENDOR_ID,
1202 .subcmd =
1203 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
1204 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001205
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
1207 .vendor_id =
1208 QCA_NL80211_VENDOR_ID,
1209 .subcmd =
1210 QCA_NL80211_VENDOR_SUBCMD_NAN
1211 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001212
1213#ifdef WLAN_FEATURE_STATS_EXT
1214 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
1215 .vendor_id =
1216 QCA_NL80211_VENDOR_ID,
1217 .subcmd =
1218 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
1219 },
1220#endif /* WLAN_FEATURE_STATS_EXT */
1221#ifdef FEATURE_WLAN_EXTSCAN
1222 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
1223 .vendor_id =
1224 QCA_NL80211_VENDOR_ID,
1225 .subcmd =
1226 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
1227 },
1228 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
1229 .vendor_id =
1230 QCA_NL80211_VENDOR_ID,
1231 .subcmd =
1232 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
1233 },
1234 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
1235 .
1236 vendor_id
1237 =
1238 QCA_NL80211_VENDOR_ID,
1239 .subcmd =
1240 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
1241 },
1242 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
1243 .
1244 vendor_id
1245 =
1246 QCA_NL80211_VENDOR_ID,
1247 .
1248 subcmd =
1249 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
1250 },
1251 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
1252 .
1253 vendor_id
1254 =
1255 QCA_NL80211_VENDOR_ID,
1256 .
1257 subcmd
1258 =
1259 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1260 },
1261 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1262 .
1263 vendor_id
1264 =
1265 QCA_NL80211_VENDOR_ID,
1266 .subcmd =
1267 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1268 },
1269 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1270 .vendor_id =
1271 QCA_NL80211_VENDOR_ID,
1272 .subcmd =
1273 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1274 },
1275 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1276 .
1277 vendor_id
1278 =
1279 QCA_NL80211_VENDOR_ID,
1280 .subcmd =
1281 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1282 },
1283 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1284 .
1285 vendor_id
1286 =
1287 QCA_NL80211_VENDOR_ID,
1288 .subcmd =
1289 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1290 },
1291 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1292 .
1293 vendor_id
1294 =
1295 QCA_NL80211_VENDOR_ID,
1296 .
1297 subcmd
1298 =
1299 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1300 },
1301 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1302 .
1303 vendor_id
1304 =
1305 QCA_NL80211_VENDOR_ID,
1306 .
1307 subcmd =
1308 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1309 },
1310 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1311 .
1312 vendor_id
1313 =
1314 QCA_NL80211_VENDOR_ID,
1315 .
1316 subcmd
1317 =
1318 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
1319 },
1320 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
1321 .
1322 vendor_id
1323 =
1324 QCA_NL80211_VENDOR_ID,
1325 .
1326 subcmd
1327 =
1328 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
1329 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001330#endif /* FEATURE_WLAN_EXTSCAN */
1331
1332#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1333 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
1334 .vendor_id =
1335 QCA_NL80211_VENDOR_ID,
1336 .subcmd =
1337 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
1338 },
1339 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
1340 .vendor_id =
1341 QCA_NL80211_VENDOR_ID,
1342 .subcmd =
1343 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
1344 },
1345 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
1346 .vendor_id =
1347 QCA_NL80211_VENDOR_ID,
1348 .subcmd =
1349 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
1350 },
1351 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
1352 .vendor_id =
1353 QCA_NL80211_VENDOR_ID,
1354 .subcmd =
1355 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
1356 },
1357 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
1358 .vendor_id =
1359 QCA_NL80211_VENDOR_ID,
1360 .subcmd =
1361 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
1362 },
1363 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
1364 .vendor_id =
1365 QCA_NL80211_VENDOR_ID,
1366 .subcmd =
1367 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
1368 },
Zhang Qianca38fb12016-12-23 11:10:48 +08001369 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
1370 .vendor_id =
1371 QCA_NL80211_VENDOR_ID,
1372 .subcmd =
1373 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
1374 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001375#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1376 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1377 .vendor_id =
1378 QCA_NL80211_VENDOR_ID,
1379 .subcmd =
1380 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1381 },
1382 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1383 .vendor_id = QCA_NL80211_VENDOR_ID,
1384 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1385 },
1386#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1387 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1388 .vendor_id =
1389 QCA_NL80211_VENDOR_ID,
1390 .subcmd =
1391 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1392 },
1393#endif
1394 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1395 .vendor_id =
1396 QCA_NL80211_VENDOR_ID,
1397 .subcmd =
1398 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1399 },
1400 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1401 .vendor_id =
1402 QCA_NL80211_VENDOR_ID,
1403 .subcmd =
1404 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1405 },
1406 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1407 .vendor_id =
1408 QCA_NL80211_VENDOR_ID,
1409 .subcmd =
1410 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1411 },
1412 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1413 .vendor_id =
1414 QCA_NL80211_VENDOR_ID,
1415 .subcmd =
1416 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1417 },
1418 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1419 .vendor_id =
1420 QCA_NL80211_VENDOR_ID,
1421 .subcmd =
1422 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1423 },
1424#ifdef FEATURE_WLAN_EXTSCAN
1425 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1426 .vendor_id = QCA_NL80211_VENDOR_ID,
1427 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1428 },
1429 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1430 .vendor_id = QCA_NL80211_VENDOR_ID,
1431 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1432 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001433 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1434 .vendor_id = QCA_NL80211_VENDOR_ID,
1435 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1436 },
1437#endif /* FEATURE_WLAN_EXTSCAN */
Qiwei Caie689a262018-07-26 15:50:22 +08001438
1439 FEATURE_RSSI_MONITOR_VENDOR_EVENTS
1440
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001441#ifdef WLAN_FEATURE_TSF
1442 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1443 .vendor_id = QCA_NL80211_VENDOR_ID,
1444 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1445 },
1446#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001447 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1448 .vendor_id = QCA_NL80211_VENDOR_ID,
1449 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1450 },
1451 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1452 .vendor_id = QCA_NL80211_VENDOR_ID,
1453 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1454 },
1455 /* OCB events */
1456 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1457 .vendor_id = QCA_NL80211_VENDOR_ID,
1458 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1459 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001460#ifdef FEATURE_LFR_SUBNET_DETECTION
1461 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1462 .vendor_id = QCA_NL80211_VENDOR_ID,
1463 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1464 },
1465#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001466
Paul Zhang37185672019-05-14 11:20:14 +08001467 FEATURE_INTEROP_ISSUES_AP_VENDOR_COMMANDS_INDEX
1468
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001469 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1470 .vendor_id = QCA_NL80211_VENDOR_ID,
1471 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1472 },
Peng Xu8fdaa492016-06-22 10:20:47 -07001473
1474 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1475 .vendor_id = QCA_NL80211_VENDOR_ID,
1476 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1477 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301478 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1479 .vendor_id = QCA_NL80211_VENDOR_ID,
1480 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1481 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301482 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1483 .vendor_id = QCA_NL80211_VENDOR_ID,
1484 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1485 },
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05301486 [QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX] = {
1487 .vendor_id = QCA_NL80211_VENDOR_ID,
1488 .subcmd = QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE
Anurag Chouhan3920c0f2017-09-11 17:10:56 +05301489 },
1490 [QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX] = {
1491 .vendor_id = QCA_NL80211_VENDOR_ID,
1492 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
1493 },
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301494 [QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX] = {
1495 .vendor_id = QCA_NL80211_VENDOR_ID,
1496 .subcmd = QCA_NL80211_VENDOR_SUBCMD_HANG,
1497 },
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +05301498 [QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX] = {
1499 .vendor_id = QCA_NL80211_VENDOR_ID,
1500 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO,
1501 },
Alok Kumar2fad6442018-11-08 19:19:28 +05301502 [QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT_INDEX] = {
1503 .vendor_id = QCA_NL80211_VENDOR_ID,
1504 .subcmd = QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT,
1505 },
Nachiket Kukadea6a70a92018-10-09 20:07:21 +05301506 [QCA_NL80211_VENDOR_SUBCMD_NAN_EXT_INDEX] = {
1507 .vendor_id = QCA_NL80211_VENDOR_ID,
1508 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN_EXT
1509 },
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +05301510 [QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX] = {
1511 .vendor_id = QCA_NL80211_VENDOR_ID,
1512 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
1513 },
Abhinav Kumar4d1f9f42019-05-07 13:14:49 +05301514
1515 BCN_RECV_FEATURE_VENDOR_EVENTS
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05301516 [QCA_NL80211_VENDOR_SUBCMD_ROAM_INDEX] = {
1517 .vendor_id = QCA_NL80211_VENDOR_ID,
1518 .subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
1519 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001520};
1521
1522/**
1523 * __is_driver_dfs_capable() - get driver DFS capability
1524 * @wiphy: pointer to wireless wiphy structure.
1525 * @wdev: pointer to wireless_dev structure.
1526 * @data: Pointer to the data to be passed via vendor interface
1527 * @data_len:Length of the data to be passed
1528 *
1529 * This function is called by userspace to indicate whether or not
1530 * the driver supports DFS offload.
1531 *
1532 * Return: 0 on success, negative errno on failure
1533 */
1534static int __is_driver_dfs_capable(struct wiphy *wiphy,
1535 struct wireless_dev *wdev,
1536 const void *data,
1537 int data_len)
1538{
1539 u32 dfs_capability = 0;
1540 struct sk_buff *temp_skbuff;
1541 int ret_val;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001542 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001543
Dustin Brownfdf17c12018-03-14 12:55:34 -07001544 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545
1546 ret_val = wlan_hdd_validate_context(hdd_ctx);
1547 if (ret_val)
1548 return ret_val;
1549
Anurag Chouhan6d760662016-02-20 16:05:43 +05301550 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001551 hdd_err("Command not allowed in FTM mode");
1552 return -EPERM;
1553 }
1554
Peng Xu8e8b0392018-04-30 11:32:34 -07001555#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
1556 defined(CFG80211_DFS_OFFLOAD_BACKPORT)
1557 dfs_capability =
1558 wiphy_ext_feature_isset(wiphy,
1559 NL80211_EXT_FEATURE_DFS_OFFLOAD);
1560#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001561 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Peng Xu8e8b0392018-04-30 11:32:34 -07001562#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563
1564 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1565 NLMSG_HDRLEN);
1566
Jeff Johnsond36fa332019-03-18 13:42:25 -07001567 if (temp_skbuff) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001568 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1569 dfs_capability);
1570 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001571 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001572 kfree_skb(temp_skbuff);
1573
1574 return ret_val;
1575 }
1576
1577 return cfg80211_vendor_cmd_reply(temp_skbuff);
1578 }
1579
Jeff Johnson020db452016-06-29 14:37:26 -07001580 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001581 return -ENOMEM;
1582}
1583
1584/**
1585 * is_driver_dfs_capable() - get driver DFS capability
1586 * @wiphy: pointer to wireless wiphy structure.
1587 * @wdev: pointer to wireless_dev structure.
1588 * @data: Pointer to the data to be passed via vendor interface
1589 * @data_len:Length of the data to be passed
1590 *
1591 * This function is called by userspace to indicate whether or not
1592 * the driver supports DFS offload. This is an SSR-protected
1593 * wrapper function.
1594 *
1595 * Return: 0 on success, negative errno on failure
1596 */
1597static int is_driver_dfs_capable(struct wiphy *wiphy,
1598 struct wireless_dev *wdev,
1599 const void *data,
1600 int data_len)
1601{
Dustin Brown363b4792019-02-05 16:11:55 -08001602 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08001603 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05301604
Dustin Brown363b4792019-02-05 16:11:55 -08001605 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001606 if (errno)
1607 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001608
Dustin Brownf0f00612019-01-31 16:02:24 -08001609 errno = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001610
Dustin Brown363b4792019-02-05 16:11:55 -08001611 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001612
1613 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001614}
1615
1616/**
1617 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1618 *
1619 * @adapter: SAP adapter pointer
1620 *
1621 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1622 * radio. So in case of DFS MCC scenario override current SAP given config
1623 * to follow concurrent SAP DFS config
1624 *
1625 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1626 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001627int wlan_hdd_sap_cfg_dfs_override(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001628{
Jeff Johnsone5006672017-08-29 14:39:02 -07001629 struct hdd_adapter *con_sap_adapter;
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001630 struct sap_config *sap_config, *con_sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001631 int con_ch;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001632 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001633 uint32_t con_ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001634
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001635 if (!hdd_ctx) {
1636 hdd_err("hdd context is NULL");
1637 return 0;
1638 }
1639
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001640 /*
1641 * Check if AP+AP case, once primary AP chooses a DFS
1642 * channel secondary AP should always follow primary APs channel
1643 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001644 if (!policy_mgr_concurrent_beaconing_sessions_running(
Dustin Brown76cd2932018-09-11 16:03:05 -07001645 hdd_ctx->psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001646 return 0;
1647
1648 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1649 if (!con_sap_adapter)
1650 return 0;
1651
Jeff Johnsonb9424862017-10-30 08:49:35 -07001652 sap_config = &adapter->session.ap.sap_config;
1653 con_sap_config = &con_sap_adapter->session.ap.sap_config;
1654 con_ch = con_sap_adapter->session.ap.operating_channel;
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001655 con_ch_freq = wlan_reg_chan_to_freq(hdd_ctx->pdev, con_ch);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001656
Dustin Brown07901ec2018-09-07 11:02:41 -07001657 if (!wlan_reg_is_dfs_ch(hdd_ctx->pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001658 return 0;
1659
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001660 hdd_debug("Only SCC AP-AP DFS Permitted (ch_freq=%d, con_ch_freq=%d)",
1661 sap_config->chan_freq, con_ch_freq);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001662 hdd_debug("Overriding guest AP's channel");
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001663 sap_config->chan_freq = con_ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001664
1665 if (con_sap_config->acs_cfg.acs_mode == true) {
1666 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1667 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001668 hdd_err("Primary AP channel config error");
1669 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001670 con_ch, con_sap_config->acs_cfg.pri_ch,
1671 con_sap_config->acs_cfg.ht_sec_ch);
1672 return -EINVAL;
1673 }
1674 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1675 * MCC restriction. So free ch list allocated in do_acs
1676 * func for Sec AP and realloc for Pri AP ch list size
1677 */
1678 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301679 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001680
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301681 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001682 &con_sap_config->acs_cfg,
1683 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301684 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001685 sizeof(uint8_t) *
1686 con_sap_config->acs_cfg.ch_list_count);
gaurank kathpalia6701aef2019-06-27 11:53:08 +05301687 if (!sap_config->acs_cfg.ch_list) {
1688 sap_config->acs_cfg.ch_list_count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001689 return -ENOMEM;
gaurank kathpalia6701aef2019-06-27 11:53:08 +05301690 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301691 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001692 con_sap_config->acs_cfg.ch_list,
1693 con_sap_config->acs_cfg.ch_list_count);
gaurank kathpalia6701aef2019-06-27 11:53:08 +05301694 sap_config->acs_cfg.ch_list_count =
1695 con_sap_config->acs_cfg.ch_list_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001696
1697 } else {
1698 sap_config->acs_cfg.pri_ch = con_ch;
1699 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001700 sap_config->acs_cfg.ht_sec_ch = wlan_reg_freq_to_chan(
1701 hdd_ctx->pdev,
1702 con_sap_config->sec_ch_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001703 }
1704
1705 return con_ch;
1706}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001707
1708/**
wadesong1795e142018-01-05 11:13:07 +08001709 * wlan_hdd_set_acs_ch_range : Populate ACS hw mode and channel range values
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001710 * @sap_cfg: pointer to SAP config struct
wadesong1795e142018-01-05 11:13:07 +08001711 * @hw_mode: hw mode retrieved from vendor command buffer
1712 * @ht_enabled: whether HT phy mode is enabled
1713 * @vht_enabled: whether VHT phy mode is enabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001714 *
wadesong1795e142018-01-05 11:13:07 +08001715 * This function populates the ACS hw mode based on the configuration retrieved
1716 * from the vendor command buffer; and sets ACS start and end channel for the
1717 * given band.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001718 *
wadesong1795e142018-01-05 11:13:07 +08001719 * Return: 0 if success; -EINVAL if ACS channel list is NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001720 */
wadesong1795e142018-01-05 11:13:07 +08001721static int wlan_hdd_set_acs_ch_range(
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001722 struct sap_config *sap_cfg, enum qca_wlan_vendor_acs_hw_mode hw_mode,
wadesong1795e142018-01-05 11:13:07 +08001723 bool ht_enabled, bool vht_enabled)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001724{
1725 int i;
Srinivas Girigowda576b2352017-08-25 14:44:26 -07001726
wadesong1795e142018-01-05 11:13:07 +08001727 if (hw_mode == QCA_ACS_MODE_IEEE80211B) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhal2e4cccc2019-08-06 12:47:18 -07001729 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_2412);
1730 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_2484);
wadesong1795e142018-01-05 11:13:07 +08001731 } else if (hw_mode == QCA_ACS_MODE_IEEE80211G) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001732 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhal2e4cccc2019-08-06 12:47:18 -07001733 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_2412);
1734 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_2472);
wadesong1795e142018-01-05 11:13:07 +08001735 } else if (hw_mode == QCA_ACS_MODE_IEEE80211A) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhal2e4cccc2019-08-06 12:47:18 -07001737 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_5180);
1738 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_5865);
wadesong1795e142018-01-05 11:13:07 +08001739 } else if (hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001740 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhal2e4cccc2019-08-06 12:47:18 -07001741 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_2412);
1742 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_5865);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001743 }
1744
1745 if (ht_enabled)
1746 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1747
1748 if (vht_enabled)
1749 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1750
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001751 /* Parse ACS Chan list from hostapd */
1752 if (!sap_cfg->acs_cfg.ch_list)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301753 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001754
1755 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1756 sap_cfg->acs_cfg.end_ch =
1757 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1758 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301759 /* avoid channel as start channel */
1760 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1761 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001762 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1763 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1764 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1765 }
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301766
1767 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001768}
1769
1770
1771static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1772
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301773
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001774static void hdd_update_acs_channel_list(struct sap_config *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001775 enum band_info band)
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301776{
1777 int i, temp_count = 0;
1778 int acs_list_count = sap_config->acs_cfg.ch_list_count;
1779
1780 for (i = 0; i < acs_list_count; i++) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001781 if (BAND_2G == band) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301782 if (WLAN_REG_IS_24GHZ_CH(
1783 sap_config->acs_cfg.ch_list[i])) {
1784 sap_config->acs_cfg.ch_list[temp_count] =
1785 sap_config->acs_cfg.ch_list[i];
1786 temp_count++;
1787 }
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001788 } else if (BAND_5G == band) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301789 if (WLAN_REG_IS_5GHZ_CH(
1790 sap_config->acs_cfg.ch_list[i])) {
1791 sap_config->acs_cfg.ch_list[temp_count] =
1792 sap_config->acs_cfg.ch_list[i];
1793 temp_count++;
1794 }
1795 }
1796 }
1797 sap_config->acs_cfg.ch_list_count = temp_count;
1798}
1799
1800
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001801/**
1802 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1803 * @adapter: pointer to SAP adapter struct
1804 *
1805 * This function starts the ACS procedure if there are no
1806 * constraints like MBSSID DFS restrictions.
1807 *
1808 * Return: Status of ACS Start procedure
1809 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001810int wlan_hdd_cfg80211_start_acs(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001811{
1812
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001813 struct hdd_context *hdd_ctx;
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001814 struct sap_config *sap_config;
Jeff Johnson7dcac7e2019-03-23 15:10:06 -07001815 sap_event_cb acs_event_callback;
Krunal Soni5e3f9622018-09-26 16:35:50 -07001816 uint8_t mcc_to_scc_switch = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001817 int status;
1818
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001819 if (!adapter) {
Jeff Johnsondd2f1fc2018-05-06 11:22:52 -07001820 hdd_err("adapter is NULL");
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001821 return -EINVAL;
1822 }
1823 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Ashish Kumar Dhanotiyadc3900f2019-01-11 20:42:04 +05301824 status = wlan_hdd_validate_context(hdd_ctx);
1825 if (0 != status)
1826 return status;
1827
Jeff Johnsonb9424862017-10-30 08:49:35 -07001828 sap_config = &adapter->session.ap.sap_config;
Ashish Kumar Dhanotiyab0629622018-09-21 18:58:59 +05301829 if (!sap_config) {
1830 hdd_err("SAP config is NULL");
1831 return -EINVAL;
1832 }
Agrawal Ashish65634612016-08-18 13:24:32 +05301833 if (hdd_ctx->acs_policy.acs_channel)
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001834 sap_config->chan_freq = wlan_reg_chan_to_freq(hdd_ctx->pdev,
1835 hdd_ctx->acs_policy.acs_channel);
Agrawal Ashish65634612016-08-18 13:24:32 +05301836 else
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001837 sap_config->chan_freq = AUTO_CHANNEL_SELECT;
Krunal Soni5e3f9622018-09-26 16:35:50 -07001838 ucfg_policy_mgr_get_mcc_scc_switch(hdd_ctx->psoc,
1839 &mcc_to_scc_switch);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301840 /*
1841 * No DFS SCC is allowed in Auto use case. Hence not
1842 * calling DFS override
1843 */
1844 if (QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION !=
Jianmin Zhu7f212f72019-06-18 15:41:10 +08001845 mcc_to_scc_switch &&
1846 !(policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) &&
1847 IS_24G_CH(sap_config->acs_cfg.end_ch))) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301848 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1849 if (status < 0)
1850 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001851
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301852 if (status > 0) {
1853 /*notify hostapd about channel override */
1854 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1855 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1856 return 0;
1857 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001858 }
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301859 /* When first 2 connections are on the same frequency band,
1860 * then PCL would include only channels from the other
1861 * frequency band on which no connections are active
1862 */
Dustin Brown76cd2932018-09-11 16:03:05 -07001863 if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301864 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
1865 struct policy_mgr_conc_connection_info *conc_connection_info;
1866 uint32_t i;
Jeff Johnson68755312017-02-10 11:46:55 -08001867
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301868 conc_connection_info = policy_mgr_get_conn_info(&i);
1869 if (conc_connection_info[0].mac ==
1870 conc_connection_info[1].mac) {
1871 if (WLAN_REG_IS_5GHZ_CH(sap_config->acs_cfg.
1872 pcl_channels[0])) {
1873 sap_config->acs_cfg.band =
1874 QCA_ACS_MODE_IEEE80211A;
1875 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001876 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301877 } else {
1878 sap_config->acs_cfg.band =
1879 QCA_ACS_MODE_IEEE80211G;
1880 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001881 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301882 }
1883 }
1884 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1886 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001887 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888 return -EINVAL;
1889 }
1890
1891 acs_event_callback = hdd_hostapd_sap_event_cb;
1892
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301893 qdf_mem_copy(sap_config->self_macaddr.bytes,
Jeff Johnson1e851a12017-10-28 14:36:12 -07001894 adapter->mac_addr.bytes, sizeof(struct qdf_mac_addr));
Dustin Brown5e89ef82018-03-14 11:50:23 -07001895 hdd_info("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001896 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001898 acs_event_callback, sap_config, adapter->dev);
1899
1900
1901 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001902 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903 return -EINVAL;
1904 }
bings394afdd2017-01-09 11:22:38 +08001905 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1906 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001907 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1908
1909 return 0;
1910}
1911
1912/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301913 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1914 * @hdd_ctx: hdd context
1915 * @acs_chan_params: external acs channel params
1916 * @sap_config: SAP config
1917 *
1918 * This API provides unsorted pcl list.
1919 * this list is a subset of the valid channel list given by hostapd.
1920 * if channel is not present in pcl, weightage will be given as zero
1921 *
1922 * Return: Zero on success, non-zero on failure
1923 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001924static void hdd_update_vendor_pcl_list(struct hdd_context *hdd_ctx,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301925 struct hdd_vendor_acs_chan_params *acs_chan_params,
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001926 struct sap_config *sap_config)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301927{
1928 int i, j;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301929 /*
1930 * PCL shall contain only the preferred channels from the
1931 * application. If those channels are not present in the
1932 * driver PCL, then set the weight to zero
1933 */
1934 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1935 acs_chan_params->vendor_pcl_list[i] =
1936 sap_config->acs_cfg.ch_list[i];
1937 acs_chan_params->vendor_weight_list[i] = 0;
1938 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1939 if (sap_config->acs_cfg.ch_list[i] ==
1940 sap_config->acs_cfg.pcl_channels[j]) {
1941 acs_chan_params->vendor_weight_list[i] =
1942 sap_config->
1943 acs_cfg.pcl_channels_weight_list[j];
1944 break;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301945 }
1946 }
1947 }
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301948 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301949}
1950
1951/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301952 * hdd_update_reg_chan_info : This API contructs channel info
1953 * for all the given channel
1954 * @adapter: pointer to SAP adapter struct
1955 * @channel_count: channel count
1956 * @channel_list: channel list
1957 *
1958 * Return: Status of of channel information updation
1959 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001960static int hdd_update_reg_chan_info(struct hdd_adapter *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301961 uint32_t channel_count,
1962 uint8_t *channel_list)
1963{
1964 int i;
1965 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001966 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301967 uint8_t bw_offset = 0, chan = 0;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001968 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001969 struct sap_config *sap_config = &adapter->session.ap.sap_config;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07001970 mac_handle_t mac_handle;
Vignesh Viswanathana1f3a1a2018-10-04 13:10:46 +05301971 uint8_t sub_20_chan_width = 0;
1972 QDF_STATUS status;
Kapil Gupta086c6202016-12-11 18:17:06 +05301973
Jeff Johnson34fc63a2018-06-14 10:10:02 -07001974 mac_handle = hdd_ctx->mac_handle;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301975 sap_config->channel_info_count = channel_count;
Vignesh Viswanathana1f3a1a2018-10-04 13:10:46 +05301976
1977 status = ucfg_mlme_get_sub_20_chan_width(hdd_ctx->psoc,
1978 &sub_20_chan_width);
1979 if (QDF_IS_STATUS_ERROR(status))
1980 hdd_err("Failed to get sub_20_chan_width config");
1981
Kapil Gupta086c6202016-12-11 18:17:06 +05301982 for (i = 0; i < channel_count; i++) {
1983 icv = &sap_config->channel_info[i];
1984 chan = channel_list[i];
1985
1986 if (chan == 0)
1987 continue;
1988
Dustin Brown07901ec2018-09-07 11:02:41 -07001989 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301990 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001991 icv->max_reg_power = wlan_reg_get_channel_reg_power(
Dustin Brown07901ec2018-09-07 11:02:41 -07001992 hdd_ctx->pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301993
1994 /* filling demo values */
1995 icv->max_radio_power = HDD_MAX_TX_POWER;
1996 icv->min_radio_power = HDD_MIN_TX_POWER;
1997 /* not supported in current driver */
1998 icv->max_antenna_gain = 0;
1999
jiad7b8a5e02018-11-26 16:37:57 +08002000 bw_offset = hdd_get_bw_offset(sap_config->acs_cfg.ch_width);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07002001 icv->reg_class_id =
2002 wlan_hdd_find_opclass(mac_handle, chan, bw_offset);
Kapil Gupta086c6202016-12-11 18:17:06 +05302003
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002004 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05302005 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Dustin Brown07901ec2018-09-07 11:02:41 -07002006 wlan_reg_set_channel_params(hdd_ctx->pdev, chan,
2007 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05302008 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
2009 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
2010 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002011
Kapil Gupta086c6202016-12-11 18:17:06 +05302012 icv->flags = 0;
Dustin Brown07901ec2018-09-07 11:02:41 -07002013 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05302014 sap_config->acs_cfg.ch_width,
2015 sap_config->acs_cfg.is_ht_enabled,
2016 sap_config->acs_cfg.is_vht_enabled,
Vignesh Viswanathana1f3a1a2018-10-04 13:10:46 +05302017 sub_20_chan_width);
Kapil Guptac1224bf2017-06-22 21:22:40 +05302018 if (icv->flags & IEEE80211_CHAN_PASSIVE)
2019 icv->flagext |= IEEE80211_CHAN_DFS;
Kapil Gupta086c6202016-12-11 18:17:06 +05302020
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +05302021 hdd_debug("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
Kapil Gupta086c6202016-12-11 18:17:06 +05302022 icv->freq, icv->flags,
2023 icv->flagext, icv->ieee_chan_number,
2024 icv->max_reg_power, icv->max_radio_power,
2025 icv->min_radio_power, icv->reg_class_id,
2026 icv->max_antenna_gain, icv->vht_center_freq_seg0,
2027 icv->vht_center_freq_seg1);
2028 }
2029 return 0;
2030}
2031
2032/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
2033#define CHAN_INFO_ATTR_FLAGS \
2034 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
2035#define CHAN_INFO_ATTR_FLAG_EXT \
2036 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
2037#define CHAN_INFO_ATTR_FREQ \
2038 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
2039#define CHAN_INFO_ATTR_MAX_REG_POWER \
2040 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
2041#define CHAN_INFO_ATTR_MAX_POWER \
2042 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
2043#define CHAN_INFO_ATTR_MIN_POWER \
2044 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
2045#define CHAN_INFO_ATTR_REG_CLASS_ID \
2046 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
2047#define CHAN_INFO_ATTR_ANTENNA_GAIN \
2048 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
2049#define CHAN_INFO_ATTR_VHT_SEG_0 \
2050 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
2051#define CHAN_INFO_ATTR_VHT_SEG_1 \
2052 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
2053
2054/**
2055 * hdd_cfg80211_update_channel_info() - add channel info attributes
2056 * @skb: pointer to sk buff
2057 * @hdd_ctx: pointer to hdd station context
2058 * @idx: attribute index
2059 *
2060 * Return: Success(0) or reason code for failure
2061 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05302062static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05302063hdd_cfg80211_update_channel_info(struct sk_buff *skb,
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002064 struct sap_config *sap_config, int idx)
Kapil Gupta086c6202016-12-11 18:17:06 +05302065{
2066 struct nlattr *nla_attr, *channel;
2067 struct hdd_channel_info *icv;
2068 int i;
2069
2070 nla_attr = nla_nest_start(skb, idx);
2071 if (!nla_attr)
2072 goto fail;
2073
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302074 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05302075 channel = nla_nest_start(skb, i);
2076 if (!channel)
2077 goto fail;
2078
2079 icv = &sap_config->channel_info[i];
2080 if (!icv) {
2081 hdd_err("channel info not found");
2082 goto fail;
2083 }
2084 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
2085 icv->freq) ||
2086 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
2087 icv->flags) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302088 nla_put_u32(skb, CHAN_INFO_ATTR_FLAG_EXT,
Kapil Gupta086c6202016-12-11 18:17:06 +05302089 icv->flagext) ||
2090 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
2091 icv->max_reg_power) ||
2092 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
2093 icv->max_radio_power) ||
2094 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
2095 icv->min_radio_power) ||
2096 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
2097 icv->reg_class_id) ||
2098 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
2099 icv->max_antenna_gain) ||
2100 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
2101 icv->vht_center_freq_seg0) ||
2102 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
2103 icv->vht_center_freq_seg1)) {
2104 hdd_err("put fail");
2105 goto fail;
2106 }
2107 nla_nest_end(skb, channel);
2108 }
2109 nla_nest_end(skb, nla_attr);
2110 return 0;
2111fail:
2112 hdd_err("nl channel update failed");
2113 return -EINVAL;
2114}
2115#undef CHAN_INFO_ATTR_FLAGS
2116#undef CHAN_INFO_ATTR_FLAG_EXT
2117#undef CHAN_INFO_ATTR_FREQ
2118#undef CHAN_INFO_ATTR_MAX_REG_POWER
2119#undef CHAN_INFO_ATTR_MAX_POWER
2120#undef CHAN_INFO_ATTR_MIN_POWER
2121#undef CHAN_INFO_ATTR_REG_CLASS_ID
2122#undef CHAN_INFO_ATTR_ANTENNA_GAIN
2123#undef CHAN_INFO_ATTR_VHT_SEG_0
2124#undef CHAN_INFO_ATTR_VHT_SEG_1
2125
2126/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05302127 * hdd_cfg80211_update_pcl() - add pcl info attributes
2128 * @skb: pointer to sk buff
2129 * @hdd_ctx: pointer to hdd station context
2130 * @idx: attribute index
2131 * @vendor_pcl_list: PCL list
2132 * @vendor_weight_list: PCL weights
2133 *
2134 * Return: Success(0) or reason code for failure
2135 */
2136static int32_t
2137hdd_cfg80211_update_pcl(struct sk_buff *skb,
2138 uint8_t ch_list_count, int idx,
2139 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
2140{
2141 struct nlattr *nla_attr, *channel;
2142 int i;
2143
2144 nla_attr = nla_nest_start(skb, idx);
2145
2146 if (!nla_attr)
2147 goto fail;
2148
2149 for (i = 0; i < ch_list_count; i++) {
2150 channel = nla_nest_start(skb, i);
2151 if (!channel)
2152 goto fail;
Kapil Gupta63e75282017-05-18 20:55:10 +05302153 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302154 vendor_pcl_list[i]) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302155 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302156 vendor_weight_list[i])) {
2157 hdd_err("put fail");
2158 goto fail;
2159 }
2160 nla_nest_end(skb, channel);
2161 }
2162 nla_nest_end(skb, nla_attr);
2163
2164 return 0;
2165fail:
2166 hdd_err("updating pcl list failed");
2167 return -EINVAL;
2168}
2169
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002170static void hdd_get_scan_band(struct hdd_context *hdd_ctx,
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002171 struct sap_config *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002172 enum band_info *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302173{
2174 /* Get scan band */
Kapil Guptac1224bf2017-06-22 21:22:40 +05302175 if ((sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211B) ||
2176 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211G)) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002177 *band = BAND_2G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302178 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002179 *band = BAND_5G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302180 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002181 *band = BAND_ALL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302182 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302183}
2184
Kapil Gupta63e75282017-05-18 20:55:10 +05302185
2186/**
2187 * hdd_get_freq_list: API to get Frequency list based on channel list
2188 * @channel_list: channel list
2189 * @freq_list: frequency list
2190 * @channel_count: channel count
2191 *
2192 * Return: None
2193 */
2194static void hdd_get_freq_list(uint8_t *channel_list, uint32_t *freq_list,
2195 uint32_t channel_count)
2196{
2197 int count;
2198
2199 for (count = 0; count < channel_count ; count++)
2200 freq_list[count] = cds_chan_to_freq(channel_list[count]);
2201}
2202
Qiwei Caie689a262018-07-26 15:50:22 +08002203/**
2204 * wlan_hdd_sap_get_valid_channellist() - Get SAPs valid channel list
2205 * @ap_adapter: adapter
2206 * @channel_count: valid channel count
2207 * @channel_list: valid channel list
2208 * @band: frequency band
2209 *
2210 * This API returns valid channel list for SAP after removing nol and
2211 * channel which lies outside of configuration.
2212 *
2213 * Return: Zero on success, non-zero on failure
2214 */
2215static int wlan_hdd_sap_get_valid_channellist(struct hdd_adapter *adapter,
2216 uint32_t *channel_count,
2217 uint8_t *channel_list,
2218 enum band_info band)
2219{
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002220 struct sap_config *sap_config;
Qiwei Caie689a262018-07-26 15:50:22 +08002221 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2222 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
2223 uint32_t chan_count;
2224 uint8_t i;
2225 QDF_STATUS status;
Dustin Brown07901ec2018-09-07 11:02:41 -07002226 struct wlan_objmgr_pdev *pdev = hdd_ctx->pdev;
Qiwei Caie689a262018-07-26 15:50:22 +08002227 uint8_t tmp_chan;
2228
2229 sap_config = &adapter->session.ap.sap_config;
2230
2231 status =
Dustin Brown76cd2932018-09-11 16:03:05 -07002232 policy_mgr_get_valid_chans(hdd_ctx->psoc,
Qiwei Caie689a262018-07-26 15:50:22 +08002233 tmp_chan_list,
2234 &chan_count);
2235 if (QDF_IS_STATUS_ERROR(status)) {
2236 hdd_err("Failed to get channel list");
2237 return -EINVAL;
2238 }
2239
2240 for (i = 0; i < chan_count; i++) {
2241 tmp_chan = tmp_chan_list[i];
2242 if (*channel_count < QDF_MAX_NUM_CHAN) {
2243 if ((band == BAND_2G) &&
2244 (WLAN_REG_IS_24GHZ_CH(tmp_chan)) &&
2245 (!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
2246 channel_list[*channel_count] = tmp_chan;
2247 *channel_count += 1;
2248 } else if ((band == BAND_5G) &&
2249 (WLAN_REG_IS_5GHZ_CH(tmp_chan)) &&
2250 (!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
2251 channel_list[*channel_count] = tmp_chan;
2252 *channel_count += 1;
2253 }
2254 } else {
2255 break;
2256 }
2257 }
2258
2259 if (*channel_count == 0) {
2260 hdd_err("no valid channel found");
2261 return -EINVAL;
2262 }
2263
2264 return 0;
2265}
2266
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302267int hdd_cfg80211_update_acs_config(struct hdd_adapter *adapter,
2268 uint8_t reason)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302269{
2270 struct sk_buff *skb;
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002271 struct sap_config *sap_config;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302272 uint32_t channel_count = 0, status = -EINVAL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302273 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
Kapil Gupta63e75282017-05-18 20:55:10 +05302274 uint32_t freq_list[QDF_MAX_NUM_CHAN] = {0};
Kapil Gupta8878ad92017-02-13 11:56:04 +05302275 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
2276 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
2277 struct hdd_vendor_acs_chan_params acs_chan_params;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002278 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002279 enum band_info band = BAND_2G;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302280 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302281 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
2282 uint32_t i;
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002283 QDF_STATUS qdf_status;
2284 bool is_external_acs_policy = cfg_default(CFG_EXTERNAL_ACS_POLICY);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302285
Kapil Gupta8878ad92017-02-13 11:56:04 +05302286 if (!hdd_ctx) {
2287 hdd_err("HDD context is NULL");
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302288 return -EINVAL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302289 }
2290
Dustin Brown491d54b2018-03-14 12:39:11 -07002291 hdd_enter();
Jeff Johnsonb9424862017-10-30 08:49:35 -07002292 sap_config = &adapter->session.ap.sap_config;
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302293 /* When first 2 connections are on the same frequency band,
2294 * then PCL would include only channels from the other
2295 * frequency band on which no connections are active
2296 */
Dustin Brown76cd2932018-09-11 16:03:05 -07002297 if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302298 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
2299 struct policy_mgr_conc_connection_info *conc_connection_info;
2300
2301 conc_connection_info = policy_mgr_get_conn_info(&i);
2302 if (conc_connection_info[0].mac ==
2303 conc_connection_info[1].mac) {
2304
2305 if (WLAN_REG_IS_5GHZ_CH(sap_config->acs_cfg.
2306 pcl_channels[0])) {
2307 sap_config->acs_cfg.band =
2308 QCA_ACS_MODE_IEEE80211A;
2309 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002310 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302311 } else {
2312 sap_config->acs_cfg.band =
2313 QCA_ACS_MODE_IEEE80211G;
2314 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002315 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302316 }
2317 }
2318 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302319
Jeff Johnsonb9424862017-10-30 08:49:35 -07002320 hdd_get_scan_band(hdd_ctx, &adapter->session.ap.sap_config, &band);
Nachiket Kukade3208c162017-08-29 17:40:59 +05302321
2322 if (sap_config->acs_cfg.ch_list) {
2323 /* Copy INI or hostapd provided ACS channel range*/
2324 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
2325 sap_config->acs_cfg.ch_list_count);
2326 channel_count = sap_config->acs_cfg.ch_list_count;
2327 } else {
2328 /* No channel list provided, copy all valid channels */
2329 wlan_hdd_sap_get_valid_channellist(adapter,
2330 &channel_count,
2331 channel_list,
2332 band);
2333 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302334
Lin Baifac77972018-07-05 19:51:49 +08002335 sap_config->channel_info = qdf_mem_malloc(
2336 sizeof(struct hdd_channel_info) *
2337 channel_count);
Min Liu74a1a502018-10-10 19:59:07 +08002338 if (!sap_config->channel_info)
Lin Baifac77972018-07-05 19:51:49 +08002339 return -ENOMEM;
Lin Baifac77972018-07-05 19:51:49 +08002340
Kapil Gupta8878ad92017-02-13 11:56:04 +05302341 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta63e75282017-05-18 20:55:10 +05302342 hdd_get_freq_list(channel_list, freq_list, channel_count);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302343 /* Get phymode */
Jeff Johnsonb9424862017-10-30 08:49:35 -07002344 phy_mode = adapter->session.ap.sap_config.acs_cfg.hw_mode;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302345
2346 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
2347 &(adapter->wdev),
2348 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2349 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
2350 GFP_KERNEL);
2351
2352 if (!skb) {
2353 hdd_err("cfg80211_vendor_event_alloc failed");
Lin Baifac77972018-07-05 19:51:49 +08002354 qdf_mem_free(sap_config->channel_info);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302355 return -ENOMEM;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302356 }
2357 /*
2358 * Application expects pcl to be a subset of channel list
2359 * Remove all channels which are not in channel list from pcl
2360 * and add weight as zero
2361 */
2362 acs_chan_params.channel_count = channel_count;
2363 acs_chan_params.channel_list = channel_list;
2364 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
2365 acs_chan_params.vendor_weight_list = vendor_weight_list;
2366
2367 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
2368 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302369
2370 if (acs_chan_params.channel_count) {
2371 hdd_debug("ACS channel list: len: %d",
2372 acs_chan_params.channel_count);
2373 for (i = 0; i < acs_chan_params.channel_count; i++)
2374 hdd_debug("%d ", acs_chan_params.channel_list[i]);
2375 }
2376
2377 if (acs_chan_params.pcl_count) {
2378 hdd_debug("ACS PCL list: len: %d",
2379 acs_chan_params.pcl_count);
2380 for (i = 0; i < acs_chan_params.pcl_count; i++)
2381 hdd_debug("channel:%d, weight:%d ",
2382 acs_chan_params.
2383 vendor_pcl_list[i],
2384 acs_chan_params.
2385 vendor_weight_list[i]);
2386 }
2387
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002388 qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
2389 &is_external_acs_policy);
2390 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2391 hdd_err("get_external_acs_policy failed, set default");
2392
2393 if (is_external_acs_policy) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302394 acs_policy =
2395 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
2396 } else {
2397 acs_policy =
2398 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
2399 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302400 /* Update values in NL buffer */
2401 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
2402 reason) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302403 nla_put_flag(skb,
2404 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED) ||
2405 nla_put_flag(skb,
2406 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT)
2407 ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302408 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
2409 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302410 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
2411 band) ||
2412 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
2413 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05302414 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta63e75282017-05-18 20:55:10 +05302415 channel_count * sizeof(uint32_t), freq_list)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302416 hdd_err("nla put fail");
2417 goto fail;
2418 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302419 status =
2420 hdd_cfg80211_update_pcl(skb,
2421 acs_chan_params.
2422 pcl_count,
2423 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
2424 vendor_pcl_list,
2425 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302426
2427 if (status != 0)
2428 goto fail;
2429
2430 status = hdd_cfg80211_update_channel_info(skb, sap_config,
2431 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
2432
2433 if (status != 0)
2434 goto fail;
2435
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302436 status = nla_put_u32(skb,
2437 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
2438 acs_policy);
2439
2440 if (status != 0)
2441 goto fail;
2442
Kapil Gupta8878ad92017-02-13 11:56:04 +05302443 cfg80211_vendor_event(skb, GFP_KERNEL);
Lin Baifac77972018-07-05 19:51:49 +08002444 qdf_mem_free(sap_config->channel_info);
2445
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302446 return 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302447fail:
Lin Baifac77972018-07-05 19:51:49 +08002448 qdf_mem_free(sap_config->channel_info);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302449 if (skb)
2450 kfree_skb(skb);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302451 return status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302452}
2453
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302454/**
2455 * hdd_create_acs_timer(): Initialize vendor ACS timer
2456 * @adapter: pointer to SAP adapter struct
2457 *
2458 * This function initializes the vendor ACS timer.
2459 *
2460 * Return: Status of create vendor ACS timer
2461 */
Jeff Johnsone5006672017-08-29 14:39:02 -07002462static int hdd_create_acs_timer(struct hdd_adapter *adapter)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302463{
2464 struct hdd_external_acs_timer_context *timer_context;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302465 QDF_STATUS status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302466
Jeff Johnsonb9424862017-10-30 08:49:35 -07002467 if (adapter->session.ap.vendor_acs_timer_initialized)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302468 return 0;
2469
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302470 hdd_debug("Starting vendor app based ACS");
Kapil Gupta8878ad92017-02-13 11:56:04 +05302471 timer_context = qdf_mem_malloc(sizeof(*timer_context));
Min Liu74a1a502018-10-10 19:59:07 +08002472 if (!timer_context)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302473 return -ENOMEM;
Min Liu74a1a502018-10-10 19:59:07 +08002474
Kapil Gupta8878ad92017-02-13 11:56:04 +05302475 timer_context->adapter = adapter;
2476
2477 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
Jeff Johnsonb9424862017-10-30 08:49:35 -07002478 status = qdf_mc_timer_init(&adapter->session.ap.vendor_acs_timer,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302479 QDF_TIMER_TYPE_SW,
2480 hdd_acs_response_timeout_handler, timer_context);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302481 if (status != QDF_STATUS_SUCCESS) {
2482 hdd_err("Failed to initialize acs response timeout timer");
2483 return -EFAULT;
2484 }
Jeff Johnsonb9424862017-10-30 08:49:35 -07002485 adapter->session.ap.vendor_acs_timer_initialized = true;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302486 return 0;
2487}
2488
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302489static const struct nla_policy
2490wlan_hdd_cfg80211_do_acs_policy[QCA_WLAN_VENDOR_ATTR_ACS_MAX+1] = {
2491 [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
2492 [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
2493 [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
2494 [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
2495 [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
2496 [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_UNSPEC },
2497 [QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_UNSPEC },
2498};
2499
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302500int hdd_start_vendor_acs(struct hdd_adapter *adapter)
2501{
2502 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2503 int status;
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002504 QDF_STATUS qdf_status;
2505 bool is_acs_support_for_dfs_ltecoex = cfg_default(CFG_USER_ACS_DFS_LTE);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302506
2507 status = hdd_create_acs_timer(adapter);
2508 if (status != 0) {
2509 hdd_err("failed to create acs timer");
2510 return status;
2511 }
2512 status = hdd_update_acs_timer_reason(adapter,
2513 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2514 if (status != 0) {
2515 hdd_err("failed to update acs timer reason");
2516 return status;
2517 }
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002518 qdf_status = ucfg_mlme_get_acs_support_for_dfs_ltecoex(
2519 hdd_ctx->psoc,
2520 &is_acs_support_for_dfs_ltecoex);
2521 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2522 hdd_err("get_acs_support_for_dfs_ltecoex failed, set def");
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302523
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002524 if (is_acs_support_for_dfs_ltecoex)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302525 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2526 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2527 true));
2528 else
2529 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2530 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2531 false));
2532
2533 return status;
2534}
2535
Kapil Gupta8878ad92017-02-13 11:56:04 +05302536/**
Ashish Kumar Dhanotiya2168aad2019-06-12 20:51:36 +05302537 * hdd_avoid_acs_channels() - Avoid acs channels
2538 * @hdd_ctx: Pointer to the hdd context
2539 * @sap_config: Sap config structure pointer
2540 *
2541 * This function avoids channels from the acs corresponding to
2542 * the frequencies configured in the ini sap_avoid_acs_freq_list
2543 *
2544 * Return: None
2545 */
2546
2547#ifdef SAP_AVOID_ACS_FREQ_LIST
2548static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
2549 struct sap_config *sap_config)
2550{
2551 int i, j, ch_cnt = 0;
2552 uint16_t avoid_acs_freq_list[CFG_VALID_CHANNEL_LIST_LEN];
2553 uint8_t avoid_acs_freq_list_num;
2554
2555 hdd_enter();
2556
2557 ucfg_mlme_get_acs_avoid_freq_list(hdd_ctx->psoc,
2558 avoid_acs_freq_list,
2559 &avoid_acs_freq_list_num);
2560
2561 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
2562 for (j = 0; j < avoid_acs_freq_list_num; j++) {
2563 if (sap_config->acs_cfg.ch_list[i] ==
2564 wlan_reg_freq_to_chan(
2565 hdd_ctx->pdev,
2566 avoid_acs_freq_list[j])) {
2567 hdd_debug("skip channel %d",
2568 sap_config->acs_cfg.ch_list[i]);
2569 break;
2570 }
2571 }
2572 if (j == avoid_acs_freq_list_num)
2573 sap_config->acs_cfg.ch_list[ch_cnt++] =
2574 sap_config->acs_cfg.ch_list[i];
2575 }
2576 sap_config->acs_cfg.ch_list_count = ch_cnt;
2577}
2578#else
2579static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
2580 struct sap_config *sap_config)
2581{
2582}
2583#endif
2584
2585/**
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302586 * __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002587 * @wiphy: Linux wiphy struct pointer
2588 * @wdev: Linux wireless device struct pointer
2589 * @data: ACS information from hostapd
2590 * @data_len: ACS information length
2591 *
2592 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2593 * and starts ACS procedure.
2594 *
2595 * Return: ACS procedure start status
2596 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002597static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2598 struct wireless_dev *wdev,
2599 const void *data, int data_len)
2600{
2601 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07002602 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002603 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002604 struct sap_config *sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002605 struct sk_buff *temp_skbuff;
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002606 int ret, i, ch_cnt = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002607 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
2608 bool ht_enabled, ht40_enabled, vht_enabled;
wadesong1795e142018-01-05 11:13:07 +08002609 uint8_t ch_width;
2610 enum qca_wlan_vendor_acs_hw_mode hw_mode;
Rachit Kankanedef2b172019-03-07 11:34:44 +05302611 enum policy_mgr_con_mode pm_mode;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302612 QDF_STATUS qdf_status;
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002613 bool skip_etsi13_srd_chan = false;
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002614 bool is_vendor_acs_support =
2615 cfg_default(CFG_USER_AUTO_CHANNEL_SELECTION);
2616 bool is_external_acs_policy =
2617 cfg_default(CFG_EXTERNAL_ACS_POLICY);
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302618 bool sap_force_11n_for_11ac = 0;
2619 bool go_force_11n_for_11ac = 0;
lifeng0b46ae52018-12-13 09:42:27 +08002620 bool etsi13_srd_chan;
Sandeep Puligilla34618782019-01-04 17:42:42 -08002621 bool go_11ac_override = 0;
2622 bool sap_11ac_override = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002623
2624 /* ***Note*** Donot set SME config related to ACS operation here because
2625 * ACS operation is not synchronouse and ACS for Second AP may come when
2626 * ACS operation for first AP is going on. So only do_acs is split to
Jeff Johnsonfa7d9602018-05-06 11:25:31 -07002627 * separate start_acs routine. Also SME-PMAC struct that is used to
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
2629 * config shall be set only from start_acs.
2630 */
2631
Dustin Brownfdf17c12018-03-14 12:55:34 -07002632 hdd_enter_dev(ndev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08002633
Anurag Chouhan6d760662016-02-20 16:05:43 +05302634 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002635 hdd_err("Command not allowed in FTM mode");
2636 return -EPERM;
2637 }
2638
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302639 ret = wlan_hdd_validate_context(hdd_ctx);
2640 if (ret)
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302641 return ret;
2642
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302643 ucfg_mlme_get_sap_force_11n_for_11ac(hdd_ctx->psoc,
2644 &sap_force_11n_for_11ac);
2645 ucfg_mlme_get_go_force_11n_for_11ac(hdd_ctx->psoc,
2646 &go_force_11n_for_11ac);
2647
Amar Singhalf9898792018-08-20 12:13:34 -07002648 hdd_debug("current country is %s", hdd_ctx->reg.alpha2);
2649
Hanumanth Reddy Pothula89b0dce2018-05-18 12:49:43 +05302650 if (!((adapter->device_mode == QDF_SAP_MODE) ||
2651 (adapter->device_mode == QDF_P2P_GO_MODE))) {
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302652 hdd_err("Invalid device mode %d", adapter->device_mode);
2653 return -EINVAL;
2654 }
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302655
Naveen Rawat64e477e2016-05-20 10:34:56 -07002656 if (cds_is_sub_20_mhz_enabled()) {
2657 hdd_err("ACS not supported in sub 20 MHz ch wd.");
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302658 return -EINVAL;
Naveen Rawat64e477e2016-05-20 10:34:56 -07002659 }
2660
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302661 if (qdf_atomic_read(&adapter->session.ap.acs_in_progress) > 0) {
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302662 hdd_err("ACS rejected as previous req already in progress");
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302663 return -EINVAL;
2664 } else {
2665 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 1);
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302666 }
2667
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302668 ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
Dustin Brown4ea21db2018-01-05 14:13:17 -08002669 data_len,
2670 wlan_hdd_cfg80211_do_acs_policy);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302671 if (ret) {
Jeff Johnson020db452016-06-29 14:37:26 -07002672 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673 goto out;
2674 }
2675
2676 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002677 hdd_err("Attr hw_mode failed");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302678 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002679 goto out;
2680 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302681 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682
2683 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
2684 ht_enabled =
2685 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2686 else
2687 ht_enabled = 0;
2688
2689 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2690 ht40_enabled =
2691 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2692 else
2693 ht40_enabled = 0;
2694
Kapil Guptac1224bf2017-06-22 21:22:40 +05302695 hdd_debug("ht40_enabled %d", ht40_enabled);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2697 vht_enabled =
2698 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2699 else
2700 vht_enabled = 0;
2701
Bala Venkateshb9cf3362017-11-09 15:48:46 +05302702 if (((adapter->device_mode == QDF_SAP_MODE) &&
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302703 sap_force_11n_for_11ac) ||
2704 ((adapter->device_mode == QDF_P2P_GO_MODE) &&
2705 go_force_11n_for_11ac)) {
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302706 vht_enabled = 0;
Dustin Brownbacc48f2018-03-14 14:48:44 -07002707 hdd_info("VHT is Disabled in ACS");
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302708 }
2709
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002710 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2711 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2712 } else {
2713 if (ht_enabled && ht40_enabled)
2714 ch_width = 40;
2715 else
2716 ch_width = 20;
2717 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302718
Bala Venkateshb9cf3362017-11-09 15:48:46 +05302719 /* this may be possible, when sap_force_11n_for_11ac or
2720 * go_force_11n_for_11ac is set
2721 */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302722 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2723 if (ht_enabled && ht40_enabled)
2724 ch_width = 40;
2725 else
2726 ch_width = 20;
2727 }
2728
Hanumanth Reddy Pothula560d5712018-03-15 18:11:27 +05302729 sap_config = &adapter->session.ap.sap_config;
2730
2731 /* Check and free if memory is already allocated for acs channel list */
2732 wlan_hdd_undo_acs(adapter);
2733
2734 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
2735
Kapil Guptac1224bf2017-06-22 21:22:40 +05302736 hdd_debug("channel width =%d", ch_width);
Himanshu Agarwal75e74412018-02-01 20:51:47 +05302737 if (ch_width == 160)
2738 sap_config->acs_cfg.ch_width = CH_WIDTH_160MHZ;
2739 else if (ch_width == 80)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2741 else if (ch_width == 40)
2742 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2743 else
2744 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2745
2746 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2747 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2748 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2749 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2750 * since it contains the frequency values of the channels in
2751 * the channel list.
2752 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2753 * is present
2754 */
Himanshu Agarwal1b3be702018-02-20 12:16:57 +05302755
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002756 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2757 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
Srinivas Girigowda576b2352017-08-25 14:44:26 -07002758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002759 sap_config->acs_cfg.ch_list_count = nla_len(
2760 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2761 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302762 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002763 sap_config->acs_cfg.ch_list_count);
gaurank kathpalia7ca94ae2019-08-14 11:33:52 +05302764 sap_config->acs_cfg.master_ch_list = qdf_mem_malloc(
2765 sap_config->acs_cfg.ch_list_count);
2766 if (!sap_config->acs_cfg.ch_list ||
2767 !sap_config->acs_cfg.master_ch_list) {
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302768 ret = -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002769 goto out;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302770 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002771
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302772 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
gaurank kathpalia7ca94ae2019-08-14 11:33:52 +05302773 sap_config->acs_cfg.ch_list_count);
2774 qdf_mem_copy(sap_config->acs_cfg.master_ch_list, tmp,
2775 sap_config->acs_cfg.ch_list_count);
2776 sap_config->acs_cfg.master_ch_list_count =
2777 sap_config->acs_cfg.ch_list_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002778 }
2779 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2780 uint32_t *freq =
2781 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2782 sap_config->acs_cfg.ch_list_count = nla_len(
2783 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2784 sizeof(uint32_t);
2785 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302786 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 sap_config->acs_cfg.ch_list_count);
gaurank kathpalia7ca94ae2019-08-14 11:33:52 +05302788 sap_config->acs_cfg.master_ch_list = qdf_mem_malloc(
2789 sap_config->acs_cfg.ch_list_count);
2790 if (!sap_config->acs_cfg.ch_list ||
2791 !sap_config->acs_cfg.master_ch_list) {
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302792 ret = -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793 goto out;
2794 }
2795
2796 /* convert frequency to channel */
2797 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2798 sap_config->acs_cfg.ch_list[i] =
2799 ieee80211_frequency_to_channel(freq[i]);
gaurank kathpalia7ca94ae2019-08-14 11:33:52 +05302800 qdf_mem_copy(sap_config->acs_cfg.master_ch_list,
2801 sap_config->acs_cfg.ch_list,
2802 sap_config->acs_cfg.ch_list_count);
2803 sap_config->acs_cfg.master_ch_list_count =
2804 sap_config->acs_cfg.ch_list_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002805 }
2806 }
2807
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302808 if (!sap_config->acs_cfg.ch_list_count) {
Amar Singhal5f783132018-03-29 13:58:50 -07002809 hdd_err("acs config chan count 0");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302810 ret = -EINVAL;
2811 goto out;
2812 }
2813
lifeng0b46ae52018-12-13 09:42:27 +08002814 ucfg_mlme_get_etsi13_srd_chan_in_master_mode(hdd_ctx->psoc,
2815 &etsi13_srd_chan);
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002816 skip_etsi13_srd_chan =
lifeng0b46ae52018-12-13 09:42:27 +08002817 !etsi13_srd_chan &&
Dustin Brown07901ec2018-09-07 11:02:41 -07002818 wlan_reg_is_etsi13_regdmn(hdd_ctx->pdev);
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002819
2820 if (skip_etsi13_srd_chan) {
2821 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
Dustin Brown07901ec2018-09-07 11:02:41 -07002822 if (wlan_reg_is_etsi13_srd_chan(hdd_ctx->pdev,
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002823 sap_config->acs_cfg.
2824 ch_list[i]))
2825 sap_config->acs_cfg.ch_list[i] = 0;
2826 else
2827 sap_config->acs_cfg.ch_list[ch_cnt++] =
2828 sap_config->acs_cfg.ch_list[i];
2829 }
2830 sap_config->acs_cfg.ch_list_count = ch_cnt;
2831 }
Ashish Kumar Dhanotiya2168aad2019-06-12 20:51:36 +05302832
2833 hdd_avoid_acs_channels(hdd_ctx, sap_config);
2834
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002835 hdd_debug("get pcl for DO_ACS vendor command");
2836
Rachit Kankanedef2b172019-03-07 11:34:44 +05302837 pm_mode =
2838 policy_mgr_convert_device_mode_to_qdf_type(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002839 /* consult policy manager to get PCL */
Rachit Kankanedef2b172019-03-07 11:34:44 +05302840 qdf_status = policy_mgr_get_pcl(hdd_ctx->psoc, pm_mode,
2841 sap_config->acs_cfg.pcl_channels,
2842 &sap_config->acs_cfg.pcl_ch_count,
2843 sap_config->acs_cfg.
2844 pcl_channels_weight_list,
2845 QDF_MAX_NUM_CHAN);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302846 if (qdf_status != QDF_STATUS_SUCCESS)
Jeff Johnson020db452016-06-29 14:37:26 -07002847 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002848
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302849 if (sap_config->acs_cfg.pcl_ch_count) {
2850 hdd_debug("ACS config PCL: len: %d",
2851 sap_config->acs_cfg.pcl_ch_count);
2852 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2853 hdd_debug("channel:%d, weight:%d ",
2854 sap_config->acs_cfg.
2855 pcl_channels[i],
2856 sap_config->acs_cfg.
2857 pcl_channels_weight_list[i]);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302858 }
Kapil Guptac1224bf2017-06-22 21:22:40 +05302859 sap_config->acs_cfg.band = hw_mode;
Rachit Kankanedef2b172019-03-07 11:34:44 +05302860
2861 qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
2862 &is_external_acs_policy);
2863 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2864 hdd_err("get_external_acs_policy failed");
2865
gaurank kathpaliaaf483f52019-07-19 09:04:07 +05302866 sap_config->acs_cfg.acs_mode = true;
2867
Rachit Kankanedef2b172019-03-07 11:34:44 +05302868 if (is_external_acs_policy &&
2869 policy_mgr_is_force_scc(hdd_ctx->psoc) &&
2870 policy_mgr_get_connection_count(hdd_ctx->psoc)) {
2871 policy_mgr_trim_acs_channel_list(
2872 sap_config->acs_cfg.pcl_channels,
2873 sap_config->acs_cfg.pcl_ch_count,
2874 sap_config->acs_cfg.ch_list,
2875 &sap_config->acs_cfg.ch_list_count);
2876
2877 /* if it is only one channel, send ACS event to upper layer */
2878 if (sap_config->acs_cfg.ch_list_count == 1) {
2879 sap_config->acs_cfg.pri_ch =
2880 sap_config->acs_cfg.ch_list[0];
2881 wlan_sap_set_sap_ctx_acs_cfg(
2882 WLAN_HDD_GET_SAP_CTX_PTR(adapter), sap_config);
2883 sap_config_acs_result(hdd_ctx->mac_handle,
2884 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2885 sap_config->acs_cfg.ht_sec_ch);
2886 sap_config->ch_params.ch_width =
2887 sap_config->acs_cfg.ch_width;
2888 sap_config->ch_params.sec_ch_offset =
2889 sap_config->acs_cfg.ht_sec_ch;
2890 sap_config->ch_params.center_freq_seg0 =
2891 sap_config->acs_cfg.vht_seg0_center_ch;
2892 sap_config->ch_params.center_freq_seg1 =
2893 sap_config->acs_cfg.vht_seg1_center_ch;
2894 /*notify hostapd about channel override */
2895 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
2896 ret = 0;
2897 goto out;
2898 }
2899 }
2900
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302901 ret = wlan_hdd_set_acs_ch_range(sap_config, hw_mode,
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302902 ht_enabled, vht_enabled);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302903 if (ret) {
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302904 hdd_err("set acs channel range failed");
2905 goto out;
2906 }
2907
Sandeep Puligilla34618782019-01-04 17:42:42 -08002908 ucfg_mlme_is_go_11ac_override(hdd_ctx->psoc, &go_11ac_override);
2909 ucfg_mlme_is_sap_11ac_override(hdd_ctx->psoc, &sap_11ac_override);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302910 /* ACS override for android */
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05302911 if (ht_enabled &&
Amar Singhal2e4cccc2019-08-06 12:47:18 -07002912 sap_config->acs_cfg.end_ch >= WLAN_REG_CH_NUM(CHAN_ENUM_5180) &&
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05302913 ((adapter->device_mode == QDF_SAP_MODE &&
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302914 !sap_force_11n_for_11ac &&
Sandeep Puligilla34618782019-01-04 17:42:42 -08002915 sap_11ac_override) ||
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05302916 (adapter->device_mode == QDF_P2P_GO_MODE &&
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302917 !go_force_11n_for_11ac &&
Sandeep Puligilla34618782019-01-04 17:42:42 -08002918 go_11ac_override))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919 vht_enabled = 1;
2920 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05302921 qdf_status =
2922 ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
2923 &ch_width);
2924 sap_config->acs_cfg.ch_width = ch_width;
Himanshu Agarwal29a9a3e2018-02-21 17:44:37 +05302925 }
2926
2927 /* No VHT80 in 2.4G so perform ACS accordingly */
2928 if (sap_config->acs_cfg.end_ch <= 14 &&
2929 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
2930 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
2931 hdd_debug("resetting to 40Mhz in 2.4Ghz");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002932 }
2933
Kapil Guptac1224bf2017-06-22 21:22:40 +05302934 hdd_debug("ACS Config for %s: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d band %d",
2935 adapter->dev->name, sap_config->acs_cfg.hw_mode,
Himanshu Agarwal1ed8bff2018-02-07 12:50:41 +05302936 sap_config->acs_cfg.ch_width, ht_enabled, vht_enabled,
Kapil Guptac1224bf2017-06-22 21:22:40 +05302937 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch,
2938 sap_config->acs_cfg.band);
wadesongcb0ded22018-02-02 17:57:20 +08002939 host_log_acs_req_event(adapter->dev->name,
2940 csr_phy_mode_str(sap_config->acs_cfg.hw_mode),
2941 ch_width, ht_enabled, vht_enabled,
2942 sap_config->acs_cfg.start_ch,
2943 sap_config->acs_cfg.end_ch);
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002944
Kapil Gupta8878ad92017-02-13 11:56:04 +05302945 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2946 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2947
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002948 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002949 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 sap_config->acs_cfg.ch_list_count);
2951 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002952 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002953 }
Himanshu Agarwal33163982018-05-17 18:11:10 +05302954
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002955 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002956 /* ***Note*** Completion variable usage is not allowed
2957 * here since ACS scan operation may take max 2.2 sec
2958 * for 5G band:
2959 * 9 Active channel X 40 ms active scan time +
2960 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002961 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2962 * for this long. So we split up the scanning part.
2963 */
2964 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002965 hdd_debug("ACS Pending for %s", adapter->dev->name);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302966 ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967 } else {
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002968 qdf_status =
2969 ucfg_mlme_get_vendor_acs_support(
2970 hdd_ctx->psoc,
2971 &is_vendor_acs_support);
2972 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2973 hdd_err("get_vendor_acs_support failed, set default");
2974
Kapil Gupta8878ad92017-02-13 11:56:04 +05302975 /* Check if vendor specific acs is enabled */
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002976 if (is_vendor_acs_support)
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302977 ret = hdd_start_vendor_acs(adapter);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302978 else
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302979 ret = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002980 }
2981
2982out:
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302983 if (ret == 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002984 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2985 NLMSG_HDRLEN);
Jeff Johnsond36fa332019-03-18 13:42:25 -07002986 if (temp_skbuff)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002987 return cfg80211_vendor_cmd_reply(temp_skbuff);
2988 }
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302989 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002990 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2991
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302992 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002993}
2994
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002995/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002996 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2997 * @wiphy: Linux wiphy struct pointer
2998 * @wdev: Linux wireless device struct pointer
2999 * @data: ACS information from hostapd
3000 * @data_len: ACS information len
3001 *
3002 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
3003 * and starts ACS procedure.
3004 *
3005 * Return: ACS procedure start status
3006 */
3007
3008static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
3009 struct wireless_dev *wdev,
3010 const void *data, int data_len)
3011{
Dustin Browna09acf42018-11-08 12:32:26 +05303012 int errno;
3013 struct osif_vdev_sync *vdev_sync;
3014
3015 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
3016 if (errno)
3017 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003018
Dustin Browna09acf42018-11-08 12:32:26 +05303019 errno = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003020
Dustin Browna09acf42018-11-08 12:32:26 +05303021 osif_vdev_sync_op_stop(vdev_sync);
3022
3023 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003024}
3025
3026/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003027 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
3028 * @adapter: Pointer to adapter struct
3029 *
3030 * This function handle cleanup of what was done in DO_ACS, including free
3031 * memory.
3032 *
3033 * Return: void
3034 */
Jeff Johnsone5006672017-08-29 14:39:02 -07003035void wlan_hdd_undo_acs(struct hdd_adapter *adapter)
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003036{
gaurank kathpalia081c66c2019-09-19 14:44:35 +05303037 sap_undo_acs(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
3038 &adapter->session.ap.sap_config);
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003039}
3040
3041/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
3043 * @work: Linux workqueue struct pointer for ACS work
3044 *
3045 * This function starts the ACS procedure which was marked pending when an ACS
3046 * procedure was in progress for a concurrent SAP interface.
3047 *
3048 * Return: None
3049 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003050static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
3051{
Jeff Johnsone5006672017-08-29 14:39:02 -07003052 struct hdd_adapter *adapter = container_of(work, struct hdd_adapter,
Jeff Johnson3aa54d42018-06-26 11:36:50 -07003053 acs_pending_work.work);
Dustin Brown4376fed2019-03-06 11:00:38 -08003054 struct osif_vdev_sync *vdev_sync;
Jeff Johnson3aa54d42018-06-26 11:36:50 -07003055
Dustin Brown4376fed2019-03-06 11:00:38 -08003056 if (osif_vdev_sync_op_start(adapter->dev, &vdev_sync))
3057 return;
3058
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 wlan_hdd_cfg80211_start_acs(adapter);
Will Huang7049bae2018-08-13 17:25:02 +08003060 clear_bit(ACS_PENDING, &adapter->event_flags);
Dustin Brown4376fed2019-03-06 11:00:38 -08003061
3062 osif_vdev_sync_op_stop(vdev_sync);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003063}
3064
3065/**
3066 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
3067 * @adapter: Pointer to SAP adapter struct
3068 * @pri_channel: SAP ACS procedure selected Primary channel
3069 * @sec_channel: SAP ACS procedure selected secondary channel
3070 *
3071 * This is a callback function from SAP module on ACS procedure is completed.
3072 * This function send the ACS selected channel information to hostapd
3073 *
3074 * Return: None
3075 */
3076
Jeff Johnsone5006672017-08-29 14:39:02 -07003077void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003078{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003079 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07003080 struct sap_config *sap_cfg =
3081 &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003082 struct sk_buff *vendor_event;
3083 int ret_val;
Jeff Johnsone5006672017-08-29 14:39:02 -07003084 struct hdd_adapter *con_sap_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003085 uint16_t ch_width;
3086
3087 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08003088 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003089 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
3090 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
3091 GFP_KERNEL);
3092
3093 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003094 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003095 return;
3096 }
3097
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003098 ret_val = nla_put_u8(vendor_event,
3099 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
3100 sap_cfg->acs_cfg.pri_ch);
3101 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003102 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003103 kfree_skb(vendor_event);
3104 return;
3105 }
3106
3107 ret_val = nla_put_u8(vendor_event,
3108 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
3109 sap_cfg->acs_cfg.ht_sec_ch);
3110 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003111 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003112 kfree_skb(vendor_event);
3113 return;
3114 }
3115
3116 ret_val = nla_put_u8(vendor_event,
3117 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
3118 sap_cfg->acs_cfg.vht_seg0_center_ch);
3119 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003120 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003121 kfree_skb(vendor_event);
3122 return;
3123 }
3124
3125 ret_val = nla_put_u8(vendor_event,
3126 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
3127 sap_cfg->acs_cfg.vht_seg1_center_ch);
3128 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003129 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003130 kfree_skb(vendor_event);
3131 return;
3132 }
3133
Himanshu Agarwal75e74412018-02-01 20:51:47 +05303134 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_160MHZ)
3135 ch_width = 160;
3136 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003137 ch_width = 80;
3138 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
3139 ch_width = 40;
3140 else
3141 ch_width = 20;
3142
3143 ret_val = nla_put_u16(vendor_event,
3144 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
3145 ch_width);
3146 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003147 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148 kfree_skb(vendor_event);
3149 return;
3150 }
3151 if (sap_cfg->acs_cfg.pri_ch > 14)
3152 ret_val = nla_put_u8(vendor_event,
3153 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
3154 QCA_ACS_MODE_IEEE80211A);
3155 else
3156 ret_val = nla_put_u8(vendor_event,
3157 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
3158 QCA_ACS_MODE_IEEE80211G);
3159
3160 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003161 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003162 kfree_skb(vendor_event);
3163 return;
3164 }
3165
Mahesh Kumar Kalikot Veetilec1da142017-09-20 10:01:13 -07003166 hdd_debug("ACS result for %s: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
3167 adapter->dev->name, sap_cfg->acs_cfg.pri_ch,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
3169 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
3170
3171 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
3172 /* ***Note*** As already mentioned Completion variable usage is not
3173 * allowed here since ACS scan operation may take max 2.2 sec.
3174 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
3175 * operation.
3176 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
3177 * when Primary AP ACS is complete and secondary AP ACS is started here
3178 * immediately, Primary AP start_bss may come inbetween ACS operation
Jeff Johnson60ed45a2018-05-06 15:28:49 -07003179 * and overwrite Sec AP ACS parameters. Thus Sec AP ACS is executed with
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180 * delay. This path and below constraint will be removed on sessionizing
3181 * SAP acs parameters and decoupling SAP from PMAC (WIP).
3182 * As per design constraint user space control application must take
3183 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
3184 * this code path. Sec AP hostapd should be started after Primary AP
3185 * start beaconing which can be confirmed by getchannel iwpriv command
3186 */
3187
3188 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
3189 if (con_sap_adapter &&
3190 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003191 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
3192 wlan_hdd_cfg80211_start_pending_acs);
hqu71a1a3b2018-01-23 15:38:13 +08003193 /* Lets give 1500ms for OBSS + START_BSS to complete */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
hqu71a1a3b2018-01-23 15:38:13 +08003195 msecs_to_jiffies(1500));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003196 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197}
3198
Sourav Mohapatrac457ae62018-12-06 15:19:41 +05303199/**
3200 * hdd_is_wlm_latency_manager_supported - Checks if WLM Latency manager is
3201 * supported
3202 * @hdd_ctx: The HDD context
3203 *
3204 * Return: True if supported, false otherwise
3205 */
3206static inline
3207bool hdd_is_wlm_latency_manager_supported(struct hdd_context *hdd_ctx)
3208{
3209 bool latency_enable;
3210
3211 if (QDF_IS_STATUS_ERROR(ucfg_mlme_get_latency_enable
3212 (hdd_ctx->psoc, &latency_enable)))
3213 return false;
3214
3215 if (latency_enable &&
3216 sme_is_feature_supported_by_fw(VDEV_LATENCY_CONFIG))
3217 return true;
3218 else
3219 return false;
3220}
3221
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003222static int
3223__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
3224 struct wireless_dev *wdev,
3225 const void *data,
3226 int data_len)
3227{
Jeff Johnsonb8944722017-09-03 09:03:19 -07003228 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003229 struct sk_buff *skb = NULL;
3230 uint32_t fset = 0;
3231 int ret;
Wu Gaobdb7f272018-07-05 19:33:26 +08003232#ifdef FEATURE_WLAN_TDLS
3233 bool bvalue;
3234#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07003236 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303237
Anurag Chouhan6d760662016-02-20 16:05:43 +05303238 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003239 hdd_err("Command not allowed in FTM mode");
3240 return -EPERM;
3241 }
3242
Jeff Johnsonb8944722017-09-03 09:03:19 -07003243 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303244 if (ret)
3245 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003246
3247 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003248 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003249 fset |= WIFI_FEATURE_INFRA;
3250 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07003251 if (true == hdd_is_5g_supported(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003252 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003253 fset |= WIFI_FEATURE_INFRA_5G;
3254 }
3255#ifdef WLAN_FEATURE_P2P
3256 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
3257 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003258 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003259 fset |= WIFI_FEATURE_P2P;
3260 }
3261#endif
3262 fset |= WIFI_FEATURE_SOFT_AP;
3263
3264 /* HOTSPOT is a supplicant feature, enable it by default */
3265 fset |= WIFI_FEATURE_HOTSPOT;
3266
Dustin Brown76cd2932018-09-11 16:03:05 -07003267 if (ucfg_extscan_get_enable(hdd_ctx->psoc) &&
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303268 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003269 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003270 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
3271 }
Nachiket Kukade989bb352018-07-31 18:01:17 +05303272 if (wlan_hdd_nan_is_supported(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003273 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274 fset |= WIFI_FEATURE_NAN;
3275 }
Sourav Mohapatra9e014cf2018-12-11 09:39:33 +05303276 if (sme_is_feature_supported_by_fw(RTT) &&
3277 hdd_ctx->config->enable_rtt_support) {
3278 hdd_debug("RTT is supported by firmware and framework");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279 fset |= WIFI_FEATURE_D2D_RTT;
3280 fset |= WIFI_FEATURE_D2AP_RTT;
3281 }
3282#ifdef FEATURE_WLAN_SCAN_PNO
Pragaspathi Thilagaraj24789d32018-12-10 22:28:03 +05303283 if (ucfg_scan_get_pno_scan_support(hdd_ctx->psoc) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003285 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003286 fset |= WIFI_FEATURE_PNO;
3287 }
3288#endif
3289 fset |= WIFI_FEATURE_ADDITIONAL_STA;
3290#ifdef FEATURE_WLAN_TDLS
Dustin Brown76cd2932018-09-11 16:03:05 -07003291 cfg_tdls_get_support_enable(hdd_ctx->psoc, &bvalue);
Wu Gaobdb7f272018-07-05 19:33:26 +08003292 if ((bvalue) && sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003293 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003294 fset |= WIFI_FEATURE_TDLS;
3295 }
Wu Gaobdb7f272018-07-05 19:33:26 +08003296
Dustin Brown76cd2932018-09-11 16:03:05 -07003297 cfg_tdls_get_off_channel_enable(hdd_ctx->psoc, &bvalue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003298 if (sme_is_feature_supported_by_fw(TDLS) &&
Wu Gaobdb7f272018-07-05 19:33:26 +08003299 bvalue && sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003300 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003301 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
3302 }
3303#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003304 fset |= WIFI_FEATURE_AP_STA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003305 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07003306 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Srinivas Girigowda5a1da622017-07-12 17:07:44 -07003307 fset |= WIFI_FEATURE_SET_TX_POWER_LIMIT;
Sourav Mohapatra804359e2017-12-07 13:52:05 +05303308 fset |= WIFI_FEATURE_CONFIG_NDO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003309
3310 if (hdd_link_layer_stats_supported())
3311 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
3312
Jeff Johnsonb8944722017-09-03 09:03:19 -07003313 if (hdd_roaming_supported(hdd_ctx))
Srinivas Girigowda8df27ea2017-01-06 12:42:16 -08003314 fset |= WIFI_FEATURE_CONTROL_ROAMING;
3315
3316 if (hdd_scan_random_mac_addr_supported())
3317 fset |= WIFI_FEATURE_SCAN_RAND;
3318
Sourav Mohapatrac457ae62018-12-06 15:19:41 +05303319 if (hdd_is_wlm_latency_manager_supported(hdd_ctx))
3320 fset |= WIFI_FEATURE_SET_LATENCY_MODE;
3321
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003322 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
3323 NLMSG_HDRLEN);
3324 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003325 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003326 return -EINVAL;
3327 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003328 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003329 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003330 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003331 goto nla_put_failure;
3332 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303333 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303334 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003335nla_put_failure:
3336 kfree_skb(skb);
3337 return -EINVAL;
3338}
3339
3340/**
3341 * wlan_hdd_cfg80211_get_supported_features() - get supported features
3342 * @wiphy: pointer to wireless wiphy structure.
3343 * @wdev: pointer to wireless_dev structure.
3344 * @data: Pointer to the data to be passed via vendor interface
3345 * @data_len:Length of the data to be passed
3346 *
3347 * Return: Return the Success or Failure code.
3348 */
3349static int
3350wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
3351 struct wireless_dev *wdev,
3352 const void *data, int data_len)
3353{
Dustin Brown363b4792019-02-05 16:11:55 -08003354 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08003355 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303356
Dustin Brown363b4792019-02-05 16:11:55 -08003357 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08003358 if (errno)
3359 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003360
Dustin Brownf0f00612019-01-31 16:02:24 -08003361 errno = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
3362 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003363
Dustin Brown363b4792019-02-05 16:11:55 -08003364 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303365
Dustin Brownf0f00612019-01-31 16:02:24 -08003366 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003367}
3368
3369/**
3370 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3371 * @wiphy: pointer to wireless wiphy structure.
3372 * @wdev: pointer to wireless_dev structure.
3373 * @data: Pointer to the data to be passed via vendor interface
3374 * @data_len:Length of the data to be passed
3375 *
3376 * Set the MAC address that is to be used for scanning.
3377 *
3378 * Return: Return the Success or Failure code.
3379 */
3380static int
3381__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3382 struct wireless_dev *wdev,
3383 const void *data,
3384 int data_len)
3385{
Jeff Johnson9d45f332019-01-29 08:42:00 -08003386 struct scan_mac_oui scan_mac_oui = { {0} };
Jeff Johnsonb8944722017-09-03 09:03:19 -07003387 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003388 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303389 QDF_STATUS status;
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +05303390 int ret, len;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303391 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07003392 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003393 mac_handle_t mac_handle;
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +05303394 bool mac_spoofing_enabled;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003395
Dustin Brownfdf17c12018-03-14 12:55:34 -07003396 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003397
Anurag Chouhan6d760662016-02-20 16:05:43 +05303398 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003399 hdd_err("Command not allowed in FTM mode");
3400 return -EPERM;
3401 }
3402
Jeff Johnsonb8944722017-09-03 09:03:19 -07003403 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303404 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003405 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003406
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +05303407 mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
3408 if (!mac_spoofing_enabled) {
Dustin Browna7bb6ae2018-08-16 16:51:50 -07003409 hdd_debug("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003410 return -ENOTSUPP;
3411 }
3412
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003413 /*
3414 * audit note: it is ok to pass a NULL policy here since only
3415 * one attribute is parsed and it is explicitly validated
3416 */
Dustin Brown4ea21db2018-01-05 14:13:17 -08003417 if (wlan_cfg80211_nla_parse(tb,
3418 QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
3419 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003420 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003421 return -EINVAL;
3422 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003423
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003424 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003425 hdd_err("attr mac oui failed");
Jeff Johnson9d45f332019-01-29 08:42:00 -08003426 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003427 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003428
3429 len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]);
Jeff Johnson9d45f332019-01-29 08:42:00 -08003430 if (len != sizeof(scan_mac_oui.oui)) {
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003431 hdd_err("attr mac oui invalid size %d expected %zu",
Jeff Johnson9d45f332019-01-29 08:42:00 -08003432 len, sizeof(scan_mac_oui.oui));
3433 return -EINVAL;
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003434 }
3435
Jeff Johnson9d45f332019-01-29 08:42:00 -08003436 nla_memcpy(scan_mac_oui.oui,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003437 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
Jeff Johnson9d45f332019-01-29 08:42:00 -08003438 sizeof(scan_mac_oui.oui));
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303439
Jeff Johnson9d45f332019-01-29 08:42:00 -08003440 /* populate rest of scan_mac_oui for mac addr randomization */
Jeff Johnsoncf07c312019-02-04 13:53:29 -08003441 scan_mac_oui.vdev_id = adapter->vdev_id;
Jeff Johnson9d45f332019-01-29 08:42:00 -08003442 scan_mac_oui.enb_probe_req_sno_randomization = true;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303443
Jeff Johnson9d45f332019-01-29 08:42:00 -08003444 hdd_debug("Oui (%02x:%02x:%02x), vdev_id = %d",
3445 scan_mac_oui.oui[0], scan_mac_oui.oui[1],
3446 scan_mac_oui.oui[2], scan_mac_oui.vdev_id);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303447
Jeff Johnson9d45f332019-01-29 08:42:00 -08003448 hdd_update_ie_whitelist_attr(&scan_mac_oui.ie_whitelist, hdd_ctx);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303449
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003450 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson9d45f332019-01-29 08:42:00 -08003451 status = sme_set_scanning_mac_oui(mac_handle, &scan_mac_oui);
3452 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson020db452016-06-29 14:37:26 -07003453 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Jeff Johnson9d45f332019-01-29 08:42:00 -08003454
3455 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003456}
3457
3458/**
3459 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3460 * @wiphy: pointer to wireless wiphy structure.
3461 * @wdev: pointer to wireless_dev structure.
3462 * @data: Pointer to the data to be passed via vendor interface
3463 * @data_len:Length of the data to be passed
3464 *
3465 * Set the MAC address that is to be used for scanning. This is an
3466 * SSR-protecting wrapper function.
3467 *
3468 * Return: Return the Success or Failure code.
3469 */
3470static int
3471wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3472 struct wireless_dev *wdev,
3473 const void *data,
3474 int data_len)
3475{
Dustin Browna09acf42018-11-08 12:32:26 +05303476 int errno;
3477 struct osif_vdev_sync *vdev_sync;
3478
3479 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
3480 if (errno)
3481 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003482
Dustin Browna09acf42018-11-08 12:32:26 +05303483 errno = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
3484 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003485
Dustin Browna09acf42018-11-08 12:32:26 +05303486 osif_vdev_sync_op_stop(vdev_sync);
3487
3488 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003489}
3490
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303491/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
3493 * @feature_flags: pointer to the byte array of features.
3494 * @feature: Feature to be turned ON in the byte array.
3495 *
3496 * Return: None
3497 *
3498 * This is called to turn ON or SET the feature flag for the requested feature.
3499 **/
3500#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07003501static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
3502 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003503{
3504 uint32_t index;
3505 uint8_t bit_mask;
3506
3507 index = feature / NUM_BITS_IN_BYTE;
3508 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
3509 feature_flags[index] |= bit_mask;
3510}
3511
3512/**
3513 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
3514 * @wiphy: pointer to wireless wiphy structure.
3515 * @wdev: pointer to wireless_dev structure.
3516 * @data: Pointer to the data to be passed via vendor interface
3517 * @data_len:Length of the data to be passed
3518 *
3519 * This is called when wlan driver needs to send supported feature set to
3520 * supplicant upon a request/query from the supplicant.
3521 *
3522 * Return: Return the Success or Failure code.
3523 **/
3524#define MAX_CONCURRENT_CHAN_ON_24G 2
3525#define MAX_CONCURRENT_CHAN_ON_5G 2
3526static int
3527__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3528 struct wireless_dev *wdev,
3529 const void *data, int data_len)
3530{
3531 struct sk_buff *skb = NULL;
3532 uint32_t dbs_capability = 0;
3533 bool one_by_one_dbs, two_by_two_dbs;
Ashish Kumar Dhanotiya12de5332019-03-27 14:45:27 +05303534 bool value, twt_req, twt_res;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303535 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303536 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003537 int ret_val;
3538
3539 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003540 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003541
Dustin Brownfdf17c12018-03-14 12:55:34 -07003542 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08003543
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003544 ret_val = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003545 if (ret_val)
3546 return ret_val;
3547
Anurag Chouhan6d760662016-02-20 16:05:43 +05303548 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003549 hdd_err("Command not allowed in FTM mode");
3550 return -EPERM;
3551 }
3552
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003553 if (roaming_offload_enabled(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003554 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003555 wlan_hdd_cfg80211_set_feature(feature_flags,
3556 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
3557 }
3558
3559 wlan_hdd_cfg80211_set_feature(feature_flags,
3560 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Dustin Brown76cd2932018-09-11 16:03:05 -07003561 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx->psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003562 wlan_hdd_cfg80211_set_feature(feature_flags,
3563 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07003564
3565 if (wma_is_p2p_lo_capable())
3566 wlan_hdd_cfg80211_set_feature(feature_flags,
3567 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
3568
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303569 value = 0;
Dustin Brown05d81302018-09-11 16:49:22 -07003570 status = ucfg_mlme_get_oce_sta_enabled_info(hdd_ctx->psoc, &value);
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303571 if (QDF_IS_STATUS_ERROR(status))
3572 hdd_err("could not get OCE STA enable info");
3573 if (value)
yeshwanth sriram guntuka1413dfb2017-06-23 14:09:48 +05303574 wlan_hdd_cfg80211_set_feature(feature_flags,
3575 QCA_WLAN_VENDOR_FEATURE_OCE_STA);
3576
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303577 value = 0;
Dustin Brown05d81302018-09-11 16:49:22 -07003578 status = ucfg_mlme_get_oce_sap_enabled_info(hdd_ctx->psoc, &value);
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303579 if (QDF_IS_STATUS_ERROR(status))
3580 hdd_err("could not get OCE SAP enable info");
3581 if (value)
yeshwanth sriram guntuka1413dfb2017-06-23 14:09:48 +05303582 wlan_hdd_cfg80211_set_feature(feature_flags,
3583 QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON);
3584
Ashish Kumar Dhanotiya12de5332019-03-27 14:45:27 +05303585 ucfg_mlme_get_twt_requestor(hdd_ctx->psoc, &twt_req);
3586 ucfg_mlme_get_twt_responder(hdd_ctx->psoc, &twt_res);
3587
3588 if (twt_req || twt_res)
3589 wlan_hdd_cfg80211_set_feature(feature_flags,
3590 QCA_WLAN_VENDOR_FEATURE_TWT);
3591
Kiran Kumar Lokere0508af92018-04-23 18:38:32 -07003592 /* Check the kernel version for upstream commit aced43ce780dc5 that
3593 * has support for processing user cell_base hints when wiphy is
3594 * self managed or check the backport flag for the same.
3595 */
3596#if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
3597 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
3598 wlan_hdd_cfg80211_set_feature(feature_flags,
3599 QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY);
3600#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003601 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
3602 NLMSG_HDRLEN);
3603
3604 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003605 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003606 return -ENOMEM;
3607 }
3608
3609 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
3610 sizeof(feature_flags), feature_flags))
3611 goto nla_put_failure;
3612
Dustin Brown76cd2932018-09-11 16:03:05 -07003613 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx->psoc,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003614 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303615 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003616 if (one_by_one_dbs)
3617 dbs_capability = DRV_DBS_CAPABILITY_1X1;
3618
3619 if (two_by_two_dbs)
3620 dbs_capability = DRV_DBS_CAPABILITY_2X2;
3621
3622 if (!one_by_one_dbs && !two_by_two_dbs)
3623 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
3624 } else {
3625 hdd_err("wma_get_dbs_hw_mode failed");
3626 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
3627 }
3628
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003629 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003630
3631 if (nla_put_u32(skb,
Ganesh Kondabattinid921ed92017-06-20 16:40:48 +05303632 QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA,
3633 dbs_capability))
3634 goto nla_put_failure;
3635
3636
3637 if (nla_put_u32(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003638 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
3639 MAX_CONCURRENT_CHAN_ON_24G))
3640 goto nla_put_failure;
3641
3642 if (nla_put_u32(skb,
3643 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
3644 MAX_CONCURRENT_CHAN_ON_5G))
3645 goto nla_put_failure;
3646
3647 return cfg80211_vendor_cmd_reply(skb);
3648
3649nla_put_failure:
3650 kfree_skb(skb);
3651 return -EINVAL;
3652}
3653
3654/**
3655 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
3656 * @wiphy: pointer to wireless wiphy structure.
3657 * @wdev: pointer to wireless_dev structure.
3658 * @data: Pointer to the data to be passed via vendor interface
3659 * @data_len:Length of the data to be passed
3660 *
3661 * This is called when wlan driver needs to send supported feature set to
3662 * supplicant upon a request/query from the supplicant.
3663 *
3664 * Return: Return the Success or Failure code.
3665 */
3666static int
3667wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3668 struct wireless_dev *wdev,
3669 const void *data, int data_len)
3670{
Dustin Brown363b4792019-02-05 16:11:55 -08003671 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08003672 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303673
Dustin Brown363b4792019-02-05 16:11:55 -08003674 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08003675 if (errno)
3676 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003677
Dustin Brownf0f00612019-01-31 16:02:24 -08003678 errno = __wlan_hdd_cfg80211_get_features(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003679
Dustin Brown363b4792019-02-05 16:11:55 -08003680 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303681
Dustin Brownf0f00612019-01-31 16:02:24 -08003682 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003683}
3684
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303685#define PARAM_NUM_NW \
3686 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
3687#define PARAM_SET_BSSID \
3688 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05303689#define PARAM_SET_BSSID_HINT \
3690 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003691#define PARAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303692#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303693#define MAX_ROAMING_PARAM \
3694 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003695#define PARAM_NUM_BSSID \
3696 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID
3697#define PARAM_BSSID_PREFS \
3698 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS
3699#define PARAM_ROAM_BSSID \
3700 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID
3701#define PARAM_RSSI_MODIFIER \
3702 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER
3703#define PARAMS_NUM_BSSID \
3704 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID
3705#define PARAM_BSSID_PARAMS \
3706 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS
3707#define PARAM_A_BAND_BOOST_THLD \
3708 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD
3709#define PARAM_A_BAND_PELT_THLD \
3710 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD
3711#define PARAM_A_BAND_BOOST_FACTOR \
3712 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR
3713#define PARAM_A_BAND_PELT_FACTOR \
3714 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR
3715#define PARAM_A_BAND_MAX_BOOST \
3716 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST
3717#define PARAM_ROAM_HISTERESYS \
3718 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS
3719#define PARAM_RSSI_TRIGGER \
3720 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER
3721#define PARAM_ROAM_ENABLE \
3722 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE
Srinivas Dasari25d77b22019-08-07 16:21:48 +05303723#define PARAM_ROAM_CONTROL_CONFIG \
3724 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL
3725#define PARAM_FREQ_LIST_SCHEME \
3726 QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME
3727#define PARAM_FREQ_LIST_SCHEME_MAX \
3728 QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_MAX
3729#define PARAM_SCAN_FREQ_LIST \
3730 QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST
3731#define PARAM_SCAN_FREQ_LIST_TYPE \
3732 QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_TYPE
Srinivas Dasari5fb81902019-08-22 01:39:42 +05303733#define PARAM_CAND_SEL_CRITERIA_MAX \
3734 QCA_ATTR_ROAM_CAND_SEL_CRITERIA_RATE_MAX
3735#define PARAM_CAND_SEL_SCORE_RSSI \
3736 QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_RSSI
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003737
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303738
3739static const struct nla_policy
3740wlan_hdd_set_roam_param_policy[MAX_ROAMING_PARAM + 1] = {
3741 [QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD] = {.type = NLA_U32},
3742 [QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID] = {.type = NLA_U32},
3743 [PARAM_NUM_NW] = {.type = NLA_U32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003744 [PARAM_A_BAND_BOOST_FACTOR] = {.type = NLA_U32},
3745 [PARAM_A_BAND_PELT_FACTOR] = {.type = NLA_U32},
3746 [PARAM_A_BAND_MAX_BOOST] = {.type = NLA_U32},
3747 [PARAM_ROAM_HISTERESYS] = {.type = NLA_S32},
3748 [PARAM_A_BAND_BOOST_THLD] = {.type = NLA_S32},
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07003749 [PARAM_A_BAND_PELT_THLD] = {.type = NLA_S32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003750 [PARAM_RSSI_TRIGGER] = {.type = NLA_U32},
3751 [PARAM_ROAM_ENABLE] = { .type = NLA_S32},
3752 [PARAM_NUM_BSSID] = {.type = NLA_U32},
3753 [PARAM_RSSI_MODIFIER] = {.type = NLA_U32},
3754 [PARAMS_NUM_BSSID] = {.type = NLA_U32},
3755 [PARAM_ROAM_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
3756 [PARAM_SET_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05303757 [PARAM_SET_BSSID_HINT] = {.type = NLA_FLAG},
Srinivas Dasari25d77b22019-08-07 16:21:48 +05303758 [PARAM_ROAM_CONTROL_CONFIG] = {.type = NLA_NESTED},
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303759};
3760
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003761/**
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003762 * hdd_set_white_list() - parse white list
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003763 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003764 * @roam_params: roam params
3765 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003766 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003767 *
3768 * Return: 0 on success; error number on failure
3769 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003770static int hdd_set_white_list(struct hdd_context *hdd_ctx,
3771 struct roam_ext_params *roam_params,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003772 struct nlattr **tb, uint8_t vdev_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003773{
3774 int rem, i;
3775 uint32_t buf_len = 0, count;
3776 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3777 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003778 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003779
3780 i = 0;
3781 if (tb[PARAM_NUM_NW]) {
3782 count = nla_get_u32(tb[PARAM_NUM_NW]);
3783 } else {
3784 hdd_err("Number of networks is not provided");
3785 goto fail;
3786 }
3787
3788 if (count && tb[PARAM_SSID_LIST]) {
3789 nla_for_each_nested(curr_attr,
Min Liudd308892019-05-16 18:48:41 +08003790 tb[PARAM_SSID_LIST], rem) {
3791 if (i == MAX_SSID_ALLOWED_LIST) {
3792 hdd_err("Excess MAX_SSID_ALLOWED_LIST");
3793 goto fail;
3794 }
Dustin Brown4ea21db2018-01-05 14:13:17 -08003795 if (wlan_cfg80211_nla_parse(tb2,
Srinivas Dasari0cc64372019-08-13 12:04:20 +05303796 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3797 nla_data(curr_attr),
3798 nla_len(curr_attr),
3799 wlan_hdd_set_roam_param_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08003800 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003801 goto fail;
3802 }
3803 /* Parse and Fetch allowed SSID list*/
3804 if (!tb2[PARAM_LIST_SSID]) {
3805 hdd_err("attr allowed ssid failed");
3806 goto fail;
3807 }
3808 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
3809 /*
3810 * Upper Layers include a null termination
3811 * character. Check for the actual permissible
3812 * length of SSID and also ensure not to copy
3813 * the NULL termination character to the driver
3814 * buffer.
3815 */
Min Liudd308892019-05-16 18:48:41 +08003816 if (buf_len > 1 &&
Srinivas Girigowdab8fdc642019-03-19 15:33:03 -07003817 ((buf_len - 1) <= WLAN_SSID_MAX_LEN)) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003818 nla_memcpy(roam_params->ssid_allowed_list[i].ssId,
3819 tb2[PARAM_LIST_SSID], buf_len - 1);
3820 roam_params->ssid_allowed_list[i].length = buf_len - 1;
3821 hdd_debug("SSID[%d]: %.*s,length = %d",
3822 i,
3823 roam_params->ssid_allowed_list[i].length,
3824 roam_params->ssid_allowed_list[i].ssId,
3825 roam_params->ssid_allowed_list[i].length);
3826 i++;
3827 } else {
3828 hdd_err("Invalid buffer length");
3829 }
3830 }
3831 }
3832
3833 if (i != count) {
3834 hdd_err("Invalid number of SSIDs i = %d, count = %d", i, count);
3835 goto fail;
3836 }
3837
3838 roam_params->num_ssid_allowed_list = i;
3839 hdd_debug("Num of Allowed SSID %d", roam_params->num_ssid_allowed_list);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003840 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003841 sme_update_roam_params(mac_handle, vdev_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003842 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3843 return 0;
3844
3845fail:
3846 return -EINVAL;
3847}
3848
3849/**
3850 * hdd_set_bssid_prefs() - parse set bssid prefs
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003851 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003852 * @roam_params: roam params
3853 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003854 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003855 *
3856 * Return: 0 on success; error number on failure
3857 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003858static int hdd_set_bssid_prefs(struct hdd_context *hdd_ctx,
3859 struct roam_ext_params *roam_params,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003860 struct nlattr **tb, uint8_t vdev_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003861{
3862 int rem, i;
3863 uint32_t count;
3864 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3865 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003866 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003867
3868 /* Parse and fetch number of preferred BSSID */
3869 if (!tb[PARAM_NUM_BSSID]) {
3870 hdd_err("attr num of preferred bssid failed");
3871 goto fail;
3872 }
3873 count = nla_get_u32(tb[PARAM_NUM_BSSID]);
3874 if (count > MAX_BSSID_FAVORED) {
3875 hdd_err("Preferred BSSID count %u exceeds max %u",
3876 count, MAX_BSSID_FAVORED);
3877 goto fail;
3878 }
3879 hdd_debug("Num of Preferred BSSID (%d)", count);
3880 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS]) {
3881 hdd_err("attr Preferred BSSID failed");
3882 goto fail;
3883 }
3884
3885 i = 0;
3886 nla_for_each_nested(curr_attr,
3887 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3888 rem) {
3889 if (i == count) {
3890 hdd_warn("Ignoring excess Preferred BSSID");
3891 break;
3892 }
3893
Dustin Brown4ea21db2018-01-05 14:13:17 -08003894 if (wlan_cfg80211_nla_parse(tb2,
3895 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3896 nla_data(curr_attr),
3897 nla_len(curr_attr),
3898 wlan_hdd_set_roam_param_policy)) {
3899 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003900 goto fail;
3901 }
3902 /* Parse and fetch MAC address */
3903 if (!tb2[PARAM_ROAM_BSSID]) {
3904 hdd_err("attr mac address failed");
3905 goto fail;
3906 }
3907 nla_memcpy(roam_params->bssid_favored[i].bytes,
3908 tb2[PARAM_ROAM_BSSID],
3909 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07003910 hdd_debug(QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07003911 QDF_MAC_ADDR_ARRAY(roam_params->bssid_favored[i].bytes));
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003912 /* Parse and fetch preference factor*/
3913 if (!tb2[PARAM_RSSI_MODIFIER]) {
3914 hdd_err("BSSID Preference score failed");
3915 goto fail;
3916 }
3917 roam_params->bssid_favored_factor[i] = nla_get_u32(
3918 tb2[PARAM_RSSI_MODIFIER]);
3919 hdd_debug("BSSID Preference score (%d)",
3920 roam_params->bssid_favored_factor[i]);
3921 i++;
3922 }
3923 if (i < count)
3924 hdd_warn("Num Preferred BSSID %u less than expected %u",
3925 i, count);
3926
3927 roam_params->num_bssid_favored = i;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003928 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003929 sme_update_roam_params(mac_handle, vdev_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003930 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3931
3932 return 0;
3933
3934fail:
3935 return -EINVAL;
3936}
3937
3938/**
3939 * hdd_set_blacklist_bssid() - parse set blacklist bssid
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003940 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003941 * @roam_params: roam params
3942 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003943 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003944 *
3945 * Return: 0 on success; error number on failure
3946 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003947static int hdd_set_blacklist_bssid(struct hdd_context *hdd_ctx,
3948 struct roam_ext_params *roam_params,
3949 struct nlattr **tb,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003950 uint8_t vdev_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003951{
3952 int rem, i;
3953 uint32_t count;
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05303954 uint8_t j = 0;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003955 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3956 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003957 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003958
3959 /* Parse and fetch number of blacklist BSSID */
3960 if (!tb[PARAMS_NUM_BSSID]) {
3961 hdd_err("attr num of blacklist bssid failed");
3962 goto fail;
3963 }
3964 count = nla_get_u32(tb[PARAMS_NUM_BSSID]);
3965 if (count > MAX_BSSID_AVOID_LIST) {
3966 hdd_err("Blacklist BSSID count %u exceeds max %u",
3967 count, MAX_BSSID_AVOID_LIST);
3968 goto fail;
3969 }
3970 hdd_debug("Num of blacklist BSSID (%d)", count);
3971
3972 i = 0;
3973 if (count && tb[PARAM_BSSID_PARAMS]) {
3974 nla_for_each_nested(curr_attr,
3975 tb[PARAM_BSSID_PARAMS],
3976 rem) {
3977 if (i == count) {
3978 hdd_warn("Ignoring excess Blacklist BSSID");
3979 break;
3980 }
3981
Dustin Brown4ea21db2018-01-05 14:13:17 -08003982 if (wlan_cfg80211_nla_parse(tb2,
Dustin Brown3fb15042017-08-15 15:54:49 -07003983 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3984 nla_data(curr_attr),
3985 nla_len(curr_attr),
3986 wlan_hdd_set_roam_param_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08003987 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003988 goto fail;
3989 }
3990 /* Parse and fetch MAC address */
3991 if (!tb2[PARAM_SET_BSSID]) {
3992 hdd_err("attr blacklist addr failed");
3993 goto fail;
3994 }
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05303995 if (tb2[PARAM_SET_BSSID_HINT]) {
3996 struct reject_ap_info ap_info;
3997
3998 nla_memcpy(ap_info.bssid.bytes,
3999 tb2[PARAM_SET_BSSID],
4000 QDF_MAC_ADDR_SIZE);
4001 ap_info.reject_ap_type = USERSPACE_AVOID_TYPE;
4002 /* This BSSID is avoided and not blacklisted */
4003 ucfg_blm_add_bssid_to_reject_list(hdd_ctx->pdev,
4004 &ap_info);
4005 i++;
4006 continue;
4007 }
4008 nla_memcpy(roam_params->bssid_avoid_list[j].bytes,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004009 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07004010 hdd_debug(QDF_MAC_ADDR_STR,
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304011 QDF_MAC_ADDR_ARRAY(roam_params->
4012 bssid_avoid_list[j].bytes));
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004013 i++;
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304014 j++;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004015 }
4016 }
4017
4018 if (i < count)
4019 hdd_warn("Num Blacklist BSSID %u less than expected %u",
4020 i, count);
4021
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304022 roam_params->num_bssid_avoid_list = j;
4023 /* Send the blacklist to the blacklist mgr component */
4024 ucfg_blm_add_userspace_black_list(hdd_ctx->pdev,
4025 roam_params->bssid_avoid_list,
4026 roam_params->num_bssid_avoid_list);
4027
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004028 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004029 sme_update_roam_params(mac_handle, vdev_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004030 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
4031
4032 return 0;
4033fail:
4034 return -EINVAL;
4035}
4036
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304037static const struct nla_policy
4038roam_scan_freq_list_scheme_policy[PARAM_FREQ_LIST_SCHEME_MAX + 1] = {
4039 [PARAM_SCAN_FREQ_LIST_TYPE] = {.type = NLA_U32},
4040 [PARAM_SCAN_FREQ_LIST] = {.type = NLA_NESTED},
4041};
4042
4043/**
4044 * hdd_send_roam_scan_channel_freq_list_to_sme() - Send control roam scan freqs
4045 * @hdd_ctx: HDD context
4046 * @vdev_id: vdev id
4047 * @tb: Nested attribute carrying frequency list scheme
4048 *
4049 * Extracts the frequency list and frequency list type from the frequency
4050 * list scheme and send the frequencies to SME.
4051 *
4052 * Return: QDF_STATUS
4053 */
4054static QDF_STATUS
4055hdd_send_roam_scan_channel_freq_list_to_sme(struct hdd_context *hdd_ctx,
4056 uint8_t vdev_id, struct nlattr *tb)
4057{
4058 QDF_STATUS status;
4059 struct nlattr *tb2[PARAM_FREQ_LIST_SCHEME_MAX + 1], *curr_attr;
4060 uint8_t num_chan = 0;
4061 uint32_t freq_list[SIR_MAX_SUPPORTED_CHANNEL_LIST] = {0};
4062 uint32_t list_type;
4063 mac_handle_t mac_handle = hdd_ctx->mac_handle;
4064 int rem;
4065
4066 if (wlan_cfg80211_nla_parse_nested(tb2, PARAM_FREQ_LIST_SCHEME_MAX,
4067 tb,
4068 roam_scan_freq_list_scheme_policy)) {
4069 hdd_err("nla_parse failed");
4070 return QDF_STATUS_E_INVAL;
4071 }
4072
4073 if (!tb2[PARAM_SCAN_FREQ_LIST] || !tb2[PARAM_SCAN_FREQ_LIST_TYPE]) {
4074 hdd_err("ROAM_CONTROL_SCAN_FREQ_LIST or type are not present");
4075 return QDF_STATUS_E_INVAL;
4076 }
4077
4078 list_type = nla_get_u32(tb2[PARAM_SCAN_FREQ_LIST_TYPE]);
4079 if (list_type != QCA_PREFERRED_SCAN_FREQ_LIST &&
4080 list_type != QCA_SPECIFIC_SCAN_FREQ_LIST) {
4081 hdd_err("Invalid freq list type received: %u", list_type);
4082 return QDF_STATUS_E_INVAL;
4083 }
4084
4085 nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem)
4086 num_chan++;
4087 if (num_chan > SIR_MAX_SUPPORTED_CHANNEL_LIST) {
4088 hdd_err("number of channels (%d) supported exceeded max (%d)",
4089 num_chan, SIR_MAX_SUPPORTED_CHANNEL_LIST);
4090 return QDF_STATUS_E_INVAL;
4091 }
4092 num_chan = 0;
4093
Srinivas Dasariac5312a2019-08-23 07:21:46 +05304094 nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem) {
4095 if (nla_len(curr_attr) != sizeof(uint32_t)) {
4096 hdd_err("len is not correct for frequency %d",
4097 num_chan);
4098 return QDF_STATUS_E_INVAL;
4099 }
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304100 freq_list[num_chan++] = nla_get_u32(curr_attr);
Srinivas Dasariac5312a2019-08-23 07:21:46 +05304101 }
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304102
4103 status = sme_update_roam_scan_freq_list(mac_handle, vdev_id, freq_list,
4104 num_chan, list_type);
4105 if (QDF_IS_STATUS_ERROR(status))
4106 hdd_err("Failed to update channel list information");
4107
4108 return status;
4109}
4110
4111static const struct nla_policy
4112roam_control_policy[QCA_ATTR_ROAM_CONTROL_MAX + 1] = {
Srinivas Dasari391692d2019-08-21 08:40:53 +05304113 [QCA_ATTR_ROAM_CONTROL_ENABLE] = {.type = NLA_U8},
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304114 [QCA_ATTR_ROAM_CONTROL_STATUS] = {.type = NLA_U8},
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304115 [PARAM_FREQ_LIST_SCHEME] = {.type = NLA_NESTED},
Srinivas Dasari0628e842019-08-22 01:17:38 +05304116 [QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD] = {.type = NLA_U32},
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05304117 [QCA_ATTR_ROAM_CONTROL_CLEAR_ALL] = {.type = NLA_FLAG},
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304118 [QCA_ATTR_ROAM_CONTROL_TRIGGERS] = {.type = NLA_U32},
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304119 [QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA] = {.type = NLA_NESTED},
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304120 [QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD] = {.type = NLA_U32},
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304121};
4122
4123/**
Srinivas Dasari0628e842019-08-22 01:17:38 +05304124 * hdd_send_roam_full_scan_period_to_sme() - Send full roam scan period to SME
4125 * @hdd_ctx: HDD context
4126 * @vdev_id: vdev id
4127 * @full_roam_scan_period: Idle period in seconds between two successive
4128 * full channel roam scans
4129 *
4130 * Validate the full roam scan period and send it to firmware
4131 *
4132 * Return: QDF_STATUS
4133 */
4134static QDF_STATUS
4135hdd_send_roam_full_scan_period_to_sme(struct hdd_context *hdd_ctx,
4136 uint8_t vdev_id,
4137 uint32_t full_roam_scan_period)
4138{
4139 QDF_STATUS status;
4140
4141 if (!ucfg_mlme_validate_full_roam_scan_period(full_roam_scan_period))
4142 return QDF_STATUS_E_INVAL;
4143
4144 hdd_debug("Received Command to Set full roam scan period = %u",
4145 full_roam_scan_period);
4146
4147 status = sme_update_full_roam_scan_period(hdd_ctx->mac_handle, vdev_id,
4148 full_roam_scan_period);
4149 if (QDF_IS_STATUS_ERROR(status))
4150 hdd_err("Failed to set full scan period");
4151
4152 return status;
4153}
4154
4155/**
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304156 * hdd_send_roam_triggers_to_sme() - Send roam trigger bitmap to SME
4157 * @hdd_ctx: HDD context
4158 * @vdev_id: vdev id
4159 * @roam_trigger_bitmap: Vendor configured roam trigger bitmap to be configured
4160 * to firmware
4161 *
4162 * Send the roam trigger bitmap received to SME
4163 *
4164 * Return: QDF_STATUS
4165 */
4166static QDF_STATUS
4167hdd_send_roam_triggers_to_sme(struct hdd_context *hdd_ctx,
4168 uint8_t vdev_id,
4169 uint32_t roam_trigger_bitmap)
4170{
4171 QDF_STATUS status;
4172 struct roam_triggers triggers;
4173
4174 triggers.vdev_id = vdev_id;
4175 triggers.trigger_bitmap = roam_trigger_bitmap;
4176
4177 status = sme_set_roam_triggers(hdd_ctx->mac_handle, &triggers);
4178 if (QDF_IS_STATUS_ERROR(status))
4179 hdd_err("Failed to set roam control trigger bitmap");
4180
4181 return status;
4182}
4183
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304184/*
4185 * Disable default scoring algorithm. This is intended to set all bits of the
4186 * disable_bitmap in struct scoring_param.
4187 */
4188#define DISABLE_SCORING 0
4189
4190/*
4191 * Enable scoring algorithm. This is intended to clear all bits of the
4192 * disable_bitmap in struct scoring_param.
4193 */
4194#define ENABLE_SCORING 1
4195
4196/*
4197 * Controlled roam candidate selection is enabled from userspace.
4198 * Driver/firmware should honor the selection criteria
4199 */
4200#define CONTROL_ROAM_CAND_SEL_ENABLE 1
4201
4202/*
4203 * Controlled roam candidate selection is disabled from userspace.
4204 * Driver/firmware can use its internal candidate selection criteria
4205 */
4206#define CONTROL_ROAM_CAND_SEL_DISABLE 0
4207
4208static const struct nla_policy
4209roam_scan_cand_sel_policy[PARAM_CAND_SEL_CRITERIA_MAX + 1] = {
4210 [PARAM_CAND_SEL_SCORE_RSSI] = {.type = NLA_U8},
4211};
4212
4213/**
4214 * hdd_send_roam_cand_sel_criteria_to_sme() - Send candidate sel criteria to SME
4215 * @hdd_ctx: HDD context
4216 * @vdev_id: vdev id
4217 * @attr: Nested attribute carrying candidate selection criteria
4218 *
4219 * Extract different candidate sel criteria mentioned and convert it to
4220 * driver/firmware understable format.
4221 *
4222 * Return: QDF_STATUS
4223 */
4224static QDF_STATUS
4225hdd_send_roam_cand_sel_criteria_to_sme(struct hdd_context *hdd_ctx,
4226 uint8_t vdev_id,
4227 struct nlattr *attr)
4228{
4229 QDF_STATUS status;
4230 struct nlattr *tb2[PARAM_CAND_SEL_CRITERIA_MAX + 1];
4231 struct nlattr *curr_attr;
4232 uint8_t sel_criteria = 0, rssi_score = 0, scoring;
4233 int rem;
4234
4235 hdd_debug("Received Command to Set candidate selection criteria ");
4236 nla_for_each_nested(curr_attr, attr, rem) {
4237 sel_criteria++;
4238 break;
4239 }
4240
4241 if (sel_criteria &&
4242 wlan_cfg80211_nla_parse_nested(tb2, PARAM_CAND_SEL_CRITERIA_MAX,
4243 attr, roam_scan_cand_sel_policy)) {
4244 hdd_err("nla_parse failed");
4245 return QDF_STATUS_E_INVAL;
4246 }
4247
4248 /*
4249 * Firmware supports the below configurations currently,
4250 * 1. Default selection criteria where all scoring params
4251 * are enabled and different weightages/scores are given to
4252 * different parameters.
4253 * When userspace doesn't specify any candidate selection criteria,
4254 * this will be enabled.
4255 * 2. Legacy candidate selection criteria where scoring
4256 * algorithm is disabled and only RSSI is considered for
4257 * roam candidate selection.
4258 * When userspace specify 100% weightage for RSSI, this will
4259 * be enabled.
4260 * Rest of the combinations are not supported for now.
4261 */
4262 if (sel_criteria == CONTROL_ROAM_CAND_SEL_ENABLE) {
4263 /* Legacy selection criteria: 100% weightage to RSSI */
4264 if (tb2[PARAM_CAND_SEL_SCORE_RSSI])
4265 rssi_score = nla_get_u8(tb2[PARAM_CAND_SEL_SCORE_RSSI]);
4266
4267 if (rssi_score != 100) {
4268 hdd_debug("Ignore the candidate selection criteria");
4269 return QDF_STATUS_E_INVAL;
4270 }
4271 scoring = DISABLE_SCORING;
4272 } else {
4273 /* Default selection criteria */
4274 scoring = ENABLE_SCORING;
4275 }
4276
4277 status = sme_modify_roam_cand_sel_criteria(hdd_ctx->mac_handle, vdev_id,
4278 !!scoring);
4279 if (QDF_IS_STATUS_ERROR(status))
4280 hdd_err("Failed to disable scoring");
4281
4282 return status;
4283}
4284
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304285/**
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304286 * hdd_send_roam_scan_period_to_sme() - Send roam scan period to SME
4287 * @hdd_ctx: HDD context
4288 * @vdev_id: vdev id
4289 * @roam_scan_period: Roam scan period in seconds
4290 *
4291 * Validate the roam scan period and send it to firmware if valid.
4292 *
4293 * Return: QDF_STATUS
4294 */
4295static QDF_STATUS
4296hdd_send_roam_scan_period_to_sme(struct hdd_context *hdd_ctx,
4297 uint8_t vdev_id,
4298 uint32_t roam_scan_period)
4299{
4300 QDF_STATUS status;
4301
4302 if (!ucfg_mlme_validate_scan_period(roam_scan_period * 1000))
4303 return QDF_STATUS_E_INVAL;
4304
4305 hdd_debug("Received Command to Set roam scan period (Empty Scan refresh period) = %d",
4306 roam_scan_period);
4307
4308 status = sme_update_empty_scan_refresh_period(hdd_ctx->mac_handle,
4309 vdev_id,
4310 roam_scan_period * 1000);
4311 if (QDF_IS_STATUS_ERROR(status))
4312 hdd_err("Failed to set scan period");
4313
4314 return status;
4315}
4316
4317/**
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304318 * hdd_set_roam_with_control_config() - Set roam control configuration
4319 * @hdd_ctx: HDD context
4320 * @tb: List of attributes carrying roam subcmd data
4321 * @vdev_id: vdev id
4322 *
4323 * Extracts the attribute PARAM_ROAM_CONTROL_CONFIG from the attributes list tb
4324 * and sends the corresponding roam control configuration to driver/firmware.
4325 *
4326 * Return: 0 on success; error number on failure
4327 */
4328static int
4329hdd_set_roam_with_control_config(struct hdd_context *hdd_ctx,
4330 struct nlattr **tb,
4331 uint8_t vdev_id)
4332{
4333 QDF_STATUS status = QDF_STATUS_SUCCESS;
4334 struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1], *attr;
Srinivas Dasari0628e842019-08-22 01:17:38 +05304335 uint32_t value;
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304336
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304337 hdd_enter();
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304338 /* The command must carry PARAM_ROAM_CONTROL_CONFIG */
4339 if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
4340 hdd_err("Attribute CONTROL_CONFIG is not present");
4341 return -EINVAL;
4342 }
4343
4344 if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
4345 tb[PARAM_ROAM_CONTROL_CONFIG],
4346 roam_control_policy)) {
4347 hdd_err("nla_parse failed");
4348 return -EINVAL;
4349 }
4350
4351 attr = tb2[PARAM_FREQ_LIST_SCHEME];
4352 if (attr) {
4353 status = hdd_send_roam_scan_channel_freq_list_to_sme(hdd_ctx,
4354 vdev_id,
4355 attr);
4356 if (QDF_IS_STATUS_ERROR(status))
4357 hdd_err("failed to config roam control");
4358 }
4359
Srinivas Dasari0628e842019-08-22 01:17:38 +05304360 attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD];
4361 if (attr) {
4362 hdd_debug("Parse and send full scan period to firmware");
4363 value = nla_get_u32(attr);
4364 status = hdd_send_roam_full_scan_period_to_sme(hdd_ctx,
4365 vdev_id,
4366 value);
4367 if (status)
4368 hdd_err("failed to config full scan period");
4369 }
4370
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304371 if (tb2[QCA_ATTR_ROAM_CONTROL_TRIGGERS]) {
4372 hdd_debug("Parse and send roam triggers to firmware");
4373 value = nla_get_u32(tb2[QCA_ATTR_ROAM_CONTROL_TRIGGERS]);
4374 hdd_debug("Received roam trigger bitmap: 0x%x", value);
4375 status = hdd_send_roam_triggers_to_sme(hdd_ctx,
4376 vdev_id,
4377 value);
4378 if (status)
4379 hdd_err("failed to config roam triggers");
4380 }
4381
Srinivas Dasari391692d2019-08-21 08:40:53 +05304382 attr = tb2[QCA_ATTR_ROAM_CONTROL_ENABLE];
4383 if (attr) {
4384 hdd_debug("Parse and send roam control enable/disable");
4385 status = sme_set_roam_config_enable(hdd_ctx->mac_handle,
4386 vdev_id,
4387 nla_get_u8(attr));
4388 if (QDF_IS_STATUS_ERROR(status))
4389 hdd_err("failed to enable/disable roam control config");
4390 }
4391
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304392 /* Scoring and roam candidate selection criteria */
4393 attr = tb2[QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA];
4394 if (attr) {
4395 hdd_debug("Send candidate selection criteria to firmware");
4396 status = hdd_send_roam_cand_sel_criteria_to_sme(hdd_ctx,
4397 vdev_id, attr);
4398 if (QDF_IS_STATUS_ERROR(status))
4399 hdd_err("failed to set candidate selection criteria");
4400 }
4401
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304402 attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD];
4403 if (attr) {
4404 hdd_debug("Parse and send scan period to firmware");
4405 status = hdd_send_roam_scan_period_to_sme(hdd_ctx, vdev_id,
4406 nla_get_u32(attr));
4407 if (QDF_IS_STATUS_ERROR(status))
4408 hdd_err("failed to send scan period to firmware");
4409 }
4410
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304411 return qdf_status_to_os_return(status);
4412}
4413
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05304414#define ENABLE_ROAM_TRIGGERS_ALL (QCA_ROAM_TRIGGER_REASON_PER | \
4415 QCA_ROAM_TRIGGER_REASON_BEACON_MISS | \
4416 QCA_ROAM_TRIGGER_REASON_POOR_RSSI | \
4417 QCA_ROAM_TRIGGER_REASON_BETTER_RSSI | \
4418 QCA_ROAM_TRIGGER_REASON_PERIODIC | \
4419 QCA_ROAM_TRIGGER_REASON_DENSE | \
4420 QCA_ROAM_TRIGGER_REASON_BTM | \
4421 QCA_ROAM_TRIGGER_REASON_BSS_LOAD)
4422
4423static int
4424hdd_clear_roam_control_config(struct hdd_context *hdd_ctx,
4425 struct nlattr **tb,
4426 uint8_t vdev_id)
4427{
4428 QDF_STATUS status;
4429 struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1];
4430 mac_handle_t mac_handle = hdd_ctx->mac_handle;
Srinivas Dasari05bc2c22019-08-23 17:54:53 +05304431 uint32_t value;
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05304432
4433 /* The command must carry PARAM_ROAM_CONTROL_CONFIG */
4434 if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
4435 hdd_err("Attribute CONTROL_CONFIG is not present");
4436 return -EINVAL;
4437 }
4438
4439 if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
4440 tb[PARAM_ROAM_CONTROL_CONFIG],
4441 roam_control_policy)) {
4442 hdd_err("nla_parse failed");
4443 return -EINVAL;
4444 }
4445
4446 hdd_debug("Clear the control config done through SET");
4447 if (tb2[QCA_ATTR_ROAM_CONTROL_CLEAR_ALL]) {
4448 hdd_debug("Disable roam control config done through SET");
4449 status = sme_set_roam_config_enable(hdd_ctx->mac_handle,
4450 vdev_id, 0);
4451 if (QDF_IS_STATUS_ERROR(status)) {
4452 hdd_err("failed to enable/disable roam control config");
4453 return qdf_status_to_os_return(status);
4454 }
4455
Srinivas Dasari05bc2c22019-08-23 17:54:53 +05304456 value = ENABLE_ROAM_TRIGGERS_ALL;
4457 hdd_debug("Reset roam trigger bitmap to 0x%x", value);
4458 status = hdd_send_roam_triggers_to_sme(hdd_ctx, vdev_id, value);
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05304459 if (QDF_IS_STATUS_ERROR(status)) {
4460 hdd_err("failed to restore roam trigger bitmap");
4461 return qdf_status_to_os_return(status);
4462 }
4463
4464 status = sme_roam_control_restore_default_config(mac_handle,
4465 vdev_id);
4466 if (QDF_IS_STATUS_ERROR(status)) {
4467 hdd_err("failed to config roam control");
4468 return qdf_status_to_os_return(status);
4469 }
4470 }
4471
4472 return 0;
4473}
4474
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304475/**
4476 * hdd_roam_control_config_buf_size() - Calculate the skb size to be allocated
4477 * @hdd_ctx: HDD context
4478 * @tb: List of attributes to be populated
4479 *
4480 * Calculate the buffer size to be allocated based on the attributes
4481 * mentioned in tb.
4482 *
4483 * Return: buffer size to be allocated
4484 */
4485static uint16_t
4486hdd_roam_control_config_buf_size(struct hdd_context *hdd_ctx,
4487 struct nlattr **tb)
4488{
4489 uint16_t skb_len = 0;
4490
4491 if (tb[QCA_ATTR_ROAM_CONTROL_STATUS])
4492 skb_len += NLA_HDRLEN + sizeof(uint8_t);
4493
Srinivas Dasaria33fdd82019-08-21 16:15:22 +05304494 if (tb[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD])
4495 skb_len += NLA_HDRLEN + sizeof(uint32_t);
4496
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304497 return skb_len;
4498}
4499
4500/**
4501 * hdd_roam_control_config_fill_data() - Fill the data requested by userspace
4502 * @hdd_ctx: HDD context
4503 * @vdev_id: vdev id
4504 * @skb: SK buffer
4505 * @tb: List of attributes
4506 *
4507 * Get the data corresponding to the attribute list specified in tb and
4508 * update the same to skb by populating the same attributes.
4509 *
4510 * Return: 0 on success; error number on failure
4511 */
4512static int
4513hdd_roam_control_config_fill_data(struct hdd_context *hdd_ctx, uint8_t vdev_id,
4514 struct sk_buff *skb, struct nlattr **tb)
4515{
4516 QDF_STATUS status = QDF_STATUS_SUCCESS;
4517 uint8_t roam_control;
4518 struct nlattr *config;
Srinivas Dasaria33fdd82019-08-21 16:15:22 +05304519 uint32_t full_roam_scan_period;
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304520
4521 config = nla_nest_start(skb, PARAM_ROAM_CONTROL_CONFIG);
4522 if (!config)
4523 return -EINVAL;
4524
4525 if (tb[QCA_ATTR_ROAM_CONTROL_STATUS]) {
4526 status = sme_get_roam_config_status(hdd_ctx->mac_handle,
4527 vdev_id,
4528 &roam_control);
4529 if (QDF_IS_STATUS_ERROR(status))
4530 goto out;
4531 hdd_debug("Roam control: %s",
4532 roam_control ? "Enabled" : "Disabled");
4533 if (nla_put_u8(skb, QCA_ATTR_ROAM_CONTROL_STATUS,
4534 roam_control)) {
4535 hdd_info("failed to put vendor_roam_control");
4536 return -ENOMEM;
4537 }
4538 }
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304539
Srinivas Dasaria33fdd82019-08-21 16:15:22 +05304540 if (tb[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD]) {
4541 status = sme_get_full_roam_scan_period(hdd_ctx->mac_handle,
4542 vdev_id,
4543 &full_roam_scan_period);
4544 if (QDF_IS_STATUS_ERROR(status))
4545 goto out;
4546 hdd_debug("full_roam_scan_period: %u", full_roam_scan_period);
4547
4548 if (nla_put_u32(skb, QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD,
4549 full_roam_scan_period)) {
4550 hdd_info("failed to put full_roam_scan_period");
4551 return -EINVAL;
4552 }
4553 }
4554
4555 nla_nest_end(skb, config);
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304556out:
4557 return qdf_status_to_os_return(status);
4558}
4559
4560/**
4561 * hdd_send_roam_control_config() - Send the roam config as vendor cmd reply
4562 * @mac_handle: Opaque handle to the MAC context
4563 * @vdev_id: vdev id
4564 * @tb: List of attributes
4565 *
4566 * Parse the attributes list tb and get the data corresponding to the
4567 * attributes specified in tb. Send them as a vendor response.
4568 *
4569 * Return: 0 on success; error number on failure
4570 */
4571static int
4572hdd_send_roam_control_config(struct hdd_context *hdd_ctx,
4573 uint8_t vdev_id,
4574 struct nlattr **tb)
4575{
4576 struct sk_buff *skb;
4577 uint16_t skb_len;
4578 int status;
4579
4580 hdd_enter();
4581 skb_len = hdd_roam_control_config_buf_size(hdd_ctx, tb);
4582 if (!skb_len) {
4583 hdd_err("No data requested");
4584 return -EINVAL;
4585 }
4586
4587 skb_len += NLMSG_HDRLEN;
4588 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, skb_len);
4589 if (!skb) {
4590 hdd_info("cfg80211_vendor_cmd_alloc_reply_skb failed");
4591 return -ENOMEM;
4592 }
4593
4594 status = hdd_roam_control_config_fill_data(hdd_ctx, vdev_id, skb, tb);
4595 if (status)
4596 goto fail;
4597
4598 hdd_exit();
4599 return cfg80211_vendor_cmd_reply(skb);
4600
4601fail:
4602 hdd_err("nla put fail");
4603 kfree_skb(skb);
4604 return status;
4605}
4606
4607/**
4608 * hdd_get_roam_control_config() - Send requested roam config to userspace
4609 * @hdd_ctx: HDD context
4610 * @tb: list of attributes
4611 * @vdev_id: vdev id
4612 *
4613 * Return: 0 on success; error number on failure
4614 */
4615static int hdd_get_roam_control_config(struct hdd_context *hdd_ctx,
4616 struct nlattr **tb,
4617 uint8_t vdev_id)
4618{
4619 QDF_STATUS status;
4620 struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1];
4621
4622 hdd_enter();
4623 /* The command must carry PARAM_ROAM_CONTROL_CONFIG */
4624 if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
4625 hdd_err("Attribute CONTROL_CONFIG is not present");
4626 return -EINVAL;
4627 }
4628
4629 if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
4630 tb[PARAM_ROAM_CONTROL_CONFIG],
4631 roam_control_policy)) {
4632 hdd_err("nla_parse failed");
4633 return -EINVAL;
4634 }
4635
4636 status = hdd_send_roam_control_config(hdd_ctx, vdev_id, tb2);
4637 if (status) {
4638 hdd_err("failed to enable/disable roam control");
4639 return status;
4640 }
4641
4642 return qdf_status_to_os_return(status);
4643}
4644
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304645#undef PARAM_ROAM_CONTROL_CONFIG
4646#undef PARAM_FREQ_LIST_SCHEME_MAX
4647#undef PARAM_FREQ_LIST_SCHEME
4648#undef PARAM_SCAN_FREQ_LIST
4649#undef PARAM_SCAN_FREQ_LIST_TYPE
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304650#undef PARAM_CAND_SEL_CRITERIA_MAX
4651#undef PARAM_CAND_SEL_SCORE_RSSI
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304652
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004653/**
4654 * hdd_set_ext_roam_params() - parse ext roam params
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004655 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004656 * @roam_params: roam params
4657 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004658 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004659 *
4660 * Return: 0 on success; error number on failure
4661 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004662static int hdd_set_ext_roam_params(struct hdd_context *hdd_ctx,
4663 const void *data, int data_len,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004664 uint8_t vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004665 struct roam_ext_params *roam_params)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004666{
4667 uint32_t cmd_type, req_id;
4668 struct nlattr *tb[MAX_ROAMING_PARAM + 1];
4669 int ret;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004670 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004671
Dustin Brown4ea21db2018-01-05 14:13:17 -08004672 if (wlan_cfg80211_nla_parse(tb, MAX_ROAMING_PARAM, data, data_len,
4673 wlan_hdd_set_roam_param_policy)) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004674 hdd_err("Invalid ATTR");
4675 return -EINVAL;
4676 }
4677 /* Parse and fetch Command Type */
4678 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
4679 hdd_err("roam cmd type failed");
4680 goto fail;
4681 }
4682
4683 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
4684 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
4685 hdd_err("attr request id failed");
4686 goto fail;
4687 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004688 mac_handle = hdd_ctx->mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004689 req_id = nla_get_u32(
4690 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
4691 hdd_debug("Req Id: %u Cmd Type: %u", req_id, cmd_type);
4692 switch (cmd_type) {
Srinivas Dasari0cc64372019-08-13 12:04:20 +05304693 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST:
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004694 ret = hdd_set_white_list(hdd_ctx, roam_params, tb, vdev_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004695 if (ret)
4696 goto fail;
4697 break;
4698
Srinivas Dasari0cc64372019-08-13 12:04:20 +05304699 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004700 /* Parse and fetch 5G Boost Threshold */
4701 if (!tb[PARAM_A_BAND_BOOST_THLD]) {
4702 hdd_err("5G boost threshold failed");
4703 goto fail;
4704 }
4705 roam_params->raise_rssi_thresh_5g = nla_get_s32(
4706 tb[PARAM_A_BAND_BOOST_THLD]);
4707 hdd_debug("5G Boost Threshold (%d)",
4708 roam_params->raise_rssi_thresh_5g);
4709 /* Parse and fetch 5G Penalty Threshold */
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07004710 if (!tb[PARAM_A_BAND_PELT_THLD]) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004711 hdd_err("5G penalty threshold failed");
4712 goto fail;
4713 }
4714 roam_params->drop_rssi_thresh_5g = nla_get_s32(
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07004715 tb[PARAM_A_BAND_PELT_THLD]);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004716 hdd_debug("5G Penalty Threshold (%d)",
4717 roam_params->drop_rssi_thresh_5g);
4718 /* Parse and fetch 5G Boost Factor */
4719 if (!tb[PARAM_A_BAND_BOOST_FACTOR]) {
4720 hdd_err("5G boost Factor failed");
4721 goto fail;
4722 }
4723 roam_params->raise_factor_5g = nla_get_u32(
4724 tb[PARAM_A_BAND_BOOST_FACTOR]);
4725 hdd_debug("5G Boost Factor (%d)",
4726 roam_params->raise_factor_5g);
4727 /* Parse and fetch 5G Penalty factor */
4728 if (!tb[PARAM_A_BAND_PELT_FACTOR]) {
4729 hdd_err("5G Penalty Factor failed");
4730 goto fail;
4731 }
4732 roam_params->drop_factor_5g = nla_get_u32(
4733 tb[PARAM_A_BAND_PELT_FACTOR]);
4734 hdd_debug("5G Penalty factor (%d)",
4735 roam_params->drop_factor_5g);
4736 /* Parse and fetch 5G Max Boost */
4737 if (!tb[PARAM_A_BAND_MAX_BOOST]) {
4738 hdd_err("5G Max Boost failed");
4739 goto fail;
4740 }
4741 roam_params->max_raise_rssi_5g = nla_get_u32(
4742 tb[PARAM_A_BAND_MAX_BOOST]);
4743 hdd_debug("5G Max Boost (%d)",
4744 roam_params->max_raise_rssi_5g);
4745 /* Parse and fetch Rssi Diff */
4746 if (!tb[PARAM_ROAM_HISTERESYS]) {
4747 hdd_err("Rssi Diff failed");
4748 goto fail;
4749 }
4750 roam_params->rssi_diff = nla_get_s32(
4751 tb[PARAM_ROAM_HISTERESYS]);
4752 hdd_debug("RSSI Diff (%d)",
4753 roam_params->rssi_diff);
4754 /* Parse and fetch Alert Rssi Threshold */
4755 if (!tb[PARAM_RSSI_TRIGGER]) {
4756 hdd_err("Alert Rssi Threshold failed");
4757 goto fail;
4758 }
4759 roam_params->alert_rssi_threshold = nla_get_u32(
4760 tb[PARAM_RSSI_TRIGGER]);
4761 hdd_debug("Alert RSSI Threshold (%d)",
4762 roam_params->alert_rssi_threshold);
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004763 sme_update_roam_params(mac_handle, vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004764 roam_params,
4765 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004766 break;
Srinivas Dasari0cc64372019-08-13 12:04:20 +05304767 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_LAZY_ROAM:
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004768 /* Parse and fetch Activate Good Rssi Roam */
4769 if (!tb[PARAM_ROAM_ENABLE]) {
4770 hdd_err("Activate Good Rssi Roam failed");
4771 goto fail;
4772 }
4773 roam_params->good_rssi_roam = nla_get_s32(
4774 tb[PARAM_ROAM_ENABLE]);
4775 hdd_debug("Activate Good Rssi Roam (%d)",
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004776 roam_params->good_rssi_roam);
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004777 sme_update_roam_params(mac_handle, vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004778 roam_params,
4779 REASON_ROAM_GOOD_RSSI_CHANGED);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004780 break;
Srinivas Dasari0cc64372019-08-13 12:04:20 +05304781 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PREFS:
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004782 ret = hdd_set_bssid_prefs(hdd_ctx, roam_params, tb, vdev_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004783 if (ret)
4784 goto fail;
4785 break;
Srinivas Dasari0cc64372019-08-13 12:04:20 +05304786 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID:
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004787 ret = hdd_set_blacklist_bssid(hdd_ctx, roam_params,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004788 tb, vdev_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004789 if (ret)
4790 goto fail;
4791 break;
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304792 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET:
4793 ret = hdd_set_roam_with_control_config(hdd_ctx, tb, vdev_id);
4794 if (ret)
4795 goto fail;
4796 break;
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05304797 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR:
4798 ret = hdd_clear_roam_control_config(hdd_ctx, tb, vdev_id);
4799 if (ret)
4800 goto fail;
4801 break;
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304802 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET:
4803 ret = hdd_get_roam_control_config(hdd_ctx, tb, vdev_id);
4804 if (ret)
4805 goto fail;
4806 break;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004807 }
4808
4809 return 0;
4810
4811fail:
4812 return -EINVAL;
4813}
4814
4815/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004816 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
4817 * @wiphy: The wiphy structure
4818 * @wdev: The wireless device
4819 * @data: Data passed by framework
4820 * @data_len: Parameters to be configured passed as data
4821 *
4822 * The roaming related parameters are configured by the framework
4823 * using this interface.
4824 *
4825 * Return: Return either success or failure code.
4826 */
4827static int
4828__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
4829 struct wireless_dev *wdev, const void *data, int data_len)
4830{
4831 struct net_device *dev = wdev->netdev;
Jeff Johnsonce2ba702017-10-02 13:30:24 -07004832 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -07004833 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004834 struct roam_ext_params *roam_params = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004835 int ret;
4836
Dustin Brownfdf17c12018-03-14 12:55:34 -07004837 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08004838
Anurag Chouhan6d760662016-02-20 16:05:43 +05304839 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004840 hdd_err("Command not allowed in FTM mode");
4841 return -EPERM;
4842 }
4843
Jeff Johnsonb8944722017-09-03 09:03:19 -07004844 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304845 if (ret)
4846 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004847
Jeff Johnsonb8944722017-09-03 09:03:19 -07004848 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05304849 hdd_err("Driver Modules are closed");
4850 return -EINVAL;
4851 }
4852
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004853 roam_params = qdf_mem_malloc(sizeof(*roam_params));
Min Liu74a1a502018-10-10 19:59:07 +08004854 if (!roam_params)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004855 return -ENOMEM;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004856
Jeff Johnsonb8944722017-09-03 09:03:19 -07004857 ret = hdd_set_ext_roam_params(hdd_ctx, data, data_len,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08004858 adapter->vdev_id, roam_params);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004859 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860 goto fail;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304861
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004862 if (roam_params)
4863 qdf_mem_free(roam_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004864 return 0;
4865fail:
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004866 if (roam_params)
4867 qdf_mem_free(roam_params);
4868
4869 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304871#undef PARAM_NUM_NW
4872#undef PARAM_SET_BSSID
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304873#undef PARAM_SET_BSSID_HINT
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004874#undef PARAM_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304875#undef PARAM_LIST_SSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004876#undef MAX_ROAMING_PARAM
4877#undef PARAM_NUM_BSSID
4878#undef PARAM_BSSID_PREFS
4879#undef PARAM_ROAM_BSSID
4880#undef PARAM_RSSI_MODIFIER
4881#undef PARAMS_NUM_BSSID
4882#undef PARAM_BSSID_PARAMS
4883#undef PARAM_A_BAND_BOOST_THLD
4884#undef PARAM_A_BAND_PELT_THLD
4885#undef PARAM_A_BAND_BOOST_FACTOR
4886#undef PARAM_A_BAND_PELT_FACTOR
4887#undef PARAM_A_BAND_MAX_BOOST
4888#undef PARAM_ROAM_HISTERESYS
4889#undef PARAM_RSSI_TRIGGER
4890#undef PARAM_ROAM_ENABLE
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304891
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004892
4893/**
4894 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
4895 * @wiphy: pointer to wireless wiphy structure.
4896 * @wdev: pointer to wireless_dev structure.
4897 * @data: Pointer to the data to be passed via vendor interface
4898 * @data_len:Length of the data to be passed
4899 *
4900 * Return: Return the Success or Failure code.
4901 */
4902static int
4903wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
4904 struct wireless_dev *wdev,
4905 const void *data,
4906 int data_len)
4907{
Dustin Browna09acf42018-11-08 12:32:26 +05304908 int errno;
4909 struct osif_vdev_sync *vdev_sync;
4910
4911 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
4912 if (errno)
4913 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914
Dustin Browna09acf42018-11-08 12:32:26 +05304915 errno = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004916 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917
Dustin Browna09acf42018-11-08 12:32:26 +05304918 osif_vdev_sync_op_stop(vdev_sync);
4919
4920 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004921}
4922
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304923#define PWR_SAVE_FAIL_CMD_INDEX \
4924 QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX
Jeff Johnsonb7fa2562018-07-02 08:36:17 -07004925
4926void hdd_chip_pwr_save_fail_detected_cb(hdd_handle_t hdd_handle,
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304927 struct chip_pwr_save_fail_detected_params
4928 *data)
4929{
Jeff Johnsonb7fa2562018-07-02 08:36:17 -07004930 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304931 struct sk_buff *skb;
4932 int flags = cds_get_gfp_flags();
4933
Dustin Brown491d54b2018-03-14 12:39:11 -07004934 hdd_enter();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304935
4936 if (wlan_hdd_validate_context(hdd_ctx))
4937 return;
4938
4939 if (!data) {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07004940 hdd_debug("data is null");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304941 return;
4942 }
4943
4944 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4945 NULL, NLMSG_HDRLEN +
4946 sizeof(data->failure_reason_code) +
4947 NLMSG_HDRLEN, PWR_SAVE_FAIL_CMD_INDEX,
4948 flags);
4949
4950 if (!skb) {
Dustin Brown5e89ef82018-03-14 11:50:23 -07004951 hdd_info("cfg80211_vendor_event_alloc failed");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304952 return;
4953 }
4954
Dustin Brownbacc48f2018-03-14 14:48:44 -07004955 hdd_debug("failure reason code: %u", data->failure_reason_code);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304956
4957 if (nla_put_u32(skb,
4958 QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON,
4959 data->failure_reason_code))
4960 goto fail;
4961
4962 cfg80211_vendor_event(skb, flags);
Dustin Browne74003f2018-03-14 12:51:58 -07004963 hdd_exit();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304964 return;
4965
4966fail:
4967 kfree_skb(skb);
4968}
4969#undef PWR_SAVE_FAIL_CMD_INDEX
4970
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004971static const struct nla_policy
4972wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
4973 +1] = {
4974 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
4975};
4976
4977/**
4978 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
4979 * @hdd_ctx: HDD context
4980 * @device_mode: device mode
4981 * Return: bool
4982 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004983static bool wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context *hdd_ctx,
Jeff Johnsonc1e62782017-11-09 09:50:17 -08004984 enum QDF_OPMODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004985{
Jeff Johnsone5006672017-08-29 14:39:02 -07004986 struct hdd_adapter *adapter;
Jeff Johnson87251032017-08-29 13:31:11 -07004987 struct hdd_ap_ctx *ap_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004988 struct hdd_station_ctx *sta_ctx;
Jingxiang Gece7c5472019-07-23 16:19:23 +08004989 uint8_t conn_info_channel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004990
Dustin Brown920397d2017-12-13 16:27:50 -08004991 hdd_for_each_adapter(hdd_ctx, adapter) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004992 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08004993 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004994 ap_ctx =
4995 WLAN_HDD_GET_AP_CTX_PTR(adapter);
4996
4997 /*
4998 * if there is SAP already running on DFS channel,
4999 * do not disable scan on dfs channels. Note that
5000 * with SAP on DFS, there cannot be conurrency on
5001 * single radio. But then we can have multiple
5002 * radios !!
5003 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07005004 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
Dustin Brown07901ec2018-09-07 11:02:41 -07005005 hdd_ctx->pdev,
Jeff Johnson01206862017-10-27 20:55:59 -07005006 ap_ctx->operating_channel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005007 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005008 return true;
5009 }
5010 }
5011
5012 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08005013 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005014 sta_ctx =
5015 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5016
Jingxiang Gece7c5472019-07-23 16:19:23 +08005017 conn_info_channel =
5018 wlan_reg_freq_to_chan(
5019 hdd_ctx->pdev,
Jingxiang Geae80dc62019-08-13 17:32:22 +08005020 sta_ctx->conn_info.chan_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005021 /*
5022 * if STA is already connected on DFS channel,
5023 * do not disable scan on dfs channels
5024 */
5025 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07005026 (CHANNEL_STATE_DFS ==
Dustin Brown07901ec2018-09-07 11:02:41 -07005027 wlan_reg_get_channel_state(hdd_ctx->pdev,
Jingxiang Gece7c5472019-07-23 16:19:23 +08005028 conn_info_channel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07005029 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005030 return true;
5031 }
5032 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005033 }
5034
5035 return false;
5036}
5037
5038/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005039 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005040 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005041 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005042 *
5043 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005044 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005045 * Fails the disable request if any device is active on a DFS channel.
5046 *
5047 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005049
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005050int wlan_hdd_enable_dfs_chan_scan(struct hdd_context *hdd_ctx,
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005051 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005052{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305053 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005054 bool err;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005055 mac_handle_t mac_handle;
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305056 bool enable_dfs_scan = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005057
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305058 ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
5059 &enable_dfs_scan);
5060
5061 if (enable_dfs_channels == enable_dfs_scan) {
Dustin Brown6a8d39b2018-08-14 15:27:26 -07005062 hdd_debug("DFS channels are already %s",
5063 enable_dfs_channels ? "enabled" : "disabled");
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005064 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005065 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005066
5067 if (!enable_dfs_channels) {
5068 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
5069 QDF_STA_MODE);
5070 if (err)
5071 return -EOPNOTSUPP;
5072
5073 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
5074 QDF_SAP_MODE);
5075 if (err)
5076 return -EOPNOTSUPP;
5077 }
5078
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305079 ucfg_scan_cfg_set_dfs_chan_scan_allowed(hdd_ctx->psoc,
5080 enable_dfs_channels);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005081
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005082 mac_handle = hdd_ctx->mac_handle;
5083 status = sme_enable_dfs_chan_scan(mac_handle, enable_dfs_channels);
Min Liu5eaf7242018-03-13 17:32:15 +08005084 if (QDF_IS_STATUS_ERROR(status)) {
5085 hdd_err("Failed to set DFS channel scan flag to %d",
5086 enable_dfs_channels);
5087 return qdf_status_to_os_return(status);
5088 }
5089
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005090 hdd_abort_mac_scan_all_adapters(hdd_ctx);
5091
5092 /* pass dfs channel status to regulatory component */
Dustin Brown07901ec2018-09-07 11:02:41 -07005093 status = ucfg_reg_enable_dfs_channels(hdd_ctx->pdev,
5094 enable_dfs_channels);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005095
5096 if (QDF_IS_STATUS_ERROR(status))
5097 hdd_err("Failed to %s DFS channels",
5098 enable_dfs_channels ? "enable" : "disable");
5099
5100 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005101}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005102
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005103/**
5104 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
5105 * @wiphy: corestack handler
5106 * @wdev: wireless device
5107 * @data: data
5108 * @data_len: data length
5109 * Return: success(0) or reason code for failure
5110 */
5111static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
5112 struct wireless_dev *wdev,
5113 const void *data,
5114 int data_len)
5115{
5116 struct net_device *dev = wdev->netdev;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005117 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005118 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
5119 int ret_val;
5120 uint32_t no_dfs_flag = 0;
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305121 bool enable_dfs_scan = true;
Dustin Brownfdf17c12018-03-14 12:55:34 -07005122 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005123
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005124 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305125 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005126 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005127
Dustin Brown4ea21db2018-01-05 14:13:17 -08005128 if (wlan_cfg80211_nla_parse(tb,
5129 QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
5130 data, data_len,
5131 wlan_hdd_set_no_dfs_flag_config_policy)) {
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005132 hdd_err("invalid attr");
5133 return -EINVAL;
5134 }
5135
5136 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
5137 hdd_err("attr dfs flag failed");
5138 return -EINVAL;
5139 }
5140
5141 no_dfs_flag = nla_get_u32(
5142 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
5143
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005144 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005145
5146 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07005147 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005148 return -EINVAL;
5149 }
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305150 ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
5151 &enable_dfs_scan);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005152
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305153 if (enable_dfs_scan) {
bings50112bb2018-12-21 15:51:51 +08005154 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
5155 } else {
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305156 if ((!no_dfs_flag) != enable_dfs_scan) {
bings50112bb2018-12-21 15:51:51 +08005157 hdd_err("DFS chan ini configured %d, no dfs flag: %d",
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305158 enable_dfs_scan,
bings50112bb2018-12-21 15:51:51 +08005159 no_dfs_flag);
5160 return -EINVAL;
5161 }
5162 }
5163
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005164 return ret_val;
5165}
5166
5167/**
5168 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
5169 *
5170 * @wiphy: wiphy device pointer
5171 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07005172 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005173 * @data_len: Buffer length
5174 *
5175 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
5176 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
5177 *
5178 * Return: EOK or other error codes.
5179 */
5180
5181static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
5182 struct wireless_dev *wdev,
5183 const void *data,
5184 int data_len)
5185{
Dustin Brown363b4792019-02-05 16:11:55 -08005186 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08005187 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05305188
Dustin Brown363b4792019-02-05 16:11:55 -08005189 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08005190 if (errno)
5191 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005192
Dustin Brownf0f00612019-01-31 16:02:24 -08005193 errno = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
5194 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005195
Dustin Brown363b4792019-02-05 16:11:55 -08005196 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05305197
Dustin Brownf0f00612019-01-31 16:02:24 -08005198 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199}
5200
Manikandan Mohan80dea792016-04-28 16:36:48 -07005201static const struct nla_policy
5202wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
5203 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
5204};
5205
5206/**
5207 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
5208 * @wiphy: wiphy device pointer
5209 * @wdev: wireless device pointer
5210 * @data: Vendor command data buffer
5211 * @data_len: Buffer length
5212 *
5213 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
5214 * setup WISA Mode features.
5215 *
5216 * Return: Success(0) or reason code for failure
5217 */
5218static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
5219 struct wireless_dev *wdev, const void *data, int data_len)
5220{
5221 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07005222 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005223 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005224 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
5225 struct sir_wisa_params wisa;
5226 int ret_val;
5227 QDF_STATUS status;
5228 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07005229 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
5230 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005231 mac_handle_t mac_handle;
Mohit Khannae1b86022019-04-12 10:04:57 -07005232 struct cdp_vdev *txrx_vdev = NULL;
Manikandan Mohan80dea792016-04-28 16:36:48 -07005233
Dustin Brownfdf17c12018-03-14 12:55:34 -07005234 hdd_enter_dev(dev);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005235 ret_val = wlan_hdd_validate_context(hdd_ctx);
5236 if (ret_val)
5237 goto err;
5238
5239 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5240 hdd_err("Command not allowed in FTM mode");
5241 return -EPERM;
5242 }
5243
Dustin Brown4ea21db2018-01-05 14:13:17 -08005244 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data,
5245 data_len, wlan_hdd_wisa_cmd_policy)) {
Manikandan Mohan80dea792016-04-28 16:36:48 -07005246 hdd_err("Invalid WISA cmd attributes");
5247 ret_val = -EINVAL;
5248 goto err;
5249 }
5250 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
5251 hdd_err("Invalid WISA mode");
5252 ret_val = -EINVAL;
5253 goto err;
5254 }
5255
5256 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005257 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005258 wisa.mode = wisa_mode;
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005259 wisa.vdev_id = adapter->vdev_id;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005260 mac_handle = hdd_ctx->mac_handle;
5261 status = sme_set_wisa_params(mac_handle, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07005262 if (!QDF_IS_STATUS_SUCCESS(status)) {
5263 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005264 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07005265 }
Mohit Khannae1b86022019-04-12 10:04:57 -07005266 if (QDF_IS_STATUS_SUCCESS(status) || !wisa_mode) {
5267 txrx_vdev = cdp_get_vdev_from_vdev_id(soc,
5268 (struct cdp_pdev *)pdev,
5269 adapter->vdev_id);
5270 if (!txrx_vdev)
5271 ret_val = -EINVAL;
5272 else
5273 cdp_set_wisa_mode(soc, txrx_vdev, wisa_mode);
5274 }
Manikandan Mohan80dea792016-04-28 16:36:48 -07005275err:
Dustin Browne74003f2018-03-14 12:51:58 -07005276 hdd_exit();
Manikandan Mohan80dea792016-04-28 16:36:48 -07005277 return ret_val;
5278}
5279
5280/**
5281 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
5282 * @wiphy: corestack handler
5283 * @wdev: wireless device
5284 * @data: data
5285 * @data_len: data length
5286 *
5287 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
5288 * setup WISA mode features.
5289 *
5290 * Return: Success(0) or reason code for failure
5291 */
5292static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
5293 struct wireless_dev *wdev,
5294 const void *data,
5295 int data_len)
5296{
Dustin Browna09acf42018-11-08 12:32:26 +05305297 int errno;
5298 struct osif_vdev_sync *vdev_sync;
5299
5300 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
5301 if (errno)
5302 return errno;
Manikandan Mohan80dea792016-04-28 16:36:48 -07005303
Dustin Browna09acf42018-11-08 12:32:26 +05305304 errno = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev,
5305 data, data_len);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005306
Dustin Browna09acf42018-11-08 12:32:26 +05305307 osif_vdev_sync_op_stop(vdev_sync);
5308
5309 return errno;
Manikandan Mohan80dea792016-04-28 16:36:48 -07005310}
5311
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05305312struct hdd_station_info *hdd_get_stainfo(struct hdd_station_info *astainfo,
5313 struct qdf_mac_addr mac_addr)
Will Huang496b36c2017-07-11 16:38:50 +08005314{
Jeff Johnson82155922017-09-30 16:54:14 -07005315 struct hdd_station_info *stainfo = NULL;
Will Huang496b36c2017-07-11 16:38:50 +08005316 int i;
5317
5318 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05305319 if (!qdf_mem_cmp(&astainfo[i].sta_mac,
Will Huang496b36c2017-07-11 16:38:50 +08005320 &mac_addr,
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05305321 QDF_MAC_ADDR_SIZE)) {
5322 stainfo = &astainfo[i];
5323 break;
5324 }
Will Huang496b36c2017-07-11 16:38:50 +08005325 }
5326
5327 return stainfo;
5328}
5329
Anurag Chouhan96919482016-07-13 16:36:57 +05305330/*
5331 * undef short names defined for get station command
5332 * used by __wlan_hdd_cfg80211_get_station_cmd()
5333 */
5334#undef STATION_INVALID
5335#undef STATION_INFO
5336#undef STATION_ASSOC_FAIL_REASON
Will Huang496b36c2017-07-11 16:38:50 +08005337#undef STATION_REMOTE
Anurag Chouhan96919482016-07-13 16:36:57 +05305338#undef STATION_MAX
Will Huang496b36c2017-07-11 16:38:50 +08005339#undef LINK_INFO_STANDARD_NL80211_ATTR
5340#undef AP_INFO_STANDARD_NL80211_ATTR
5341#undef INFO_ROAM_COUNT
5342#undef INFO_AKM
5343#undef WLAN802_11_MODE
5344#undef AP_INFO_HS20_INDICATION
5345#undef HT_OPERATION
5346#undef VHT_OPERATION
5347#undef INFO_ASSOC_FAIL_REASON
5348#undef REMOTE_MAX_PHY_RATE
5349#undef REMOTE_TX_PACKETS
5350#undef REMOTE_TX_BYTES
5351#undef REMOTE_RX_PACKETS
5352#undef REMOTE_RX_BYTES
5353#undef REMOTE_LAST_TX_RATE
5354#undef REMOTE_LAST_RX_RATE
5355#undef REMOTE_WMM
5356#undef REMOTE_SUPPORTED_MODE
5357#undef REMOTE_AMPDU
5358#undef REMOTE_TX_STBC
5359#undef REMOTE_RX_STBC
5360#undef REMOTE_CH_WIDTH
5361#undef REMOTE_SGI_ENABLE
5362#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
5363#undef REMOTE_PAD
5364#endif
Anurag Chouhan96919482016-07-13 16:36:57 +05305365
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005366#ifdef WLAN_FEATURE_ROAM_OFFLOAD
sheenam monga6e49e5c2019-04-04 12:49:04 +05305367
5368/**
5369 * hdd_get_roam_reason() - convert wmi roam reason to
5370 * enum qca_roam_reason
5371 * @roam_scan_trigger: wmi roam scan trigger ID
5372 *
5373 * Return: Meaningful qca_roam_reason from enum WMI_ROAM_TRIGGER_REASON_ID
5374 */
5375static enum qca_roam_reason hdd_get_roam_reason(uint16_t roam_scan_trigger)
5376{
5377 switch (roam_scan_trigger) {
5378 case WMI_ROAM_TRIGGER_REASON_PER:
5379 return QCA_ROAM_REASON_PER;
5380 case WMI_ROAM_TRIGGER_REASON_BMISS:
5381 return QCA_ROAM_REASON_BEACON_MISS;
5382 case WMI_ROAM_TRIGGER_REASON_LOW_RSSI:
5383 case WMI_ROAM_TRIGGER_REASON_BACKGROUND:
5384 return QCA_ROAM_REASON_POOR_RSSI;
5385 case WMI_ROAM_TRIGGER_REASON_HIGH_RSSI:
5386 return QCA_ROAM_REASON_BETTER_RSSI;
5387 case WMI_ROAM_TRIGGER_REASON_DENSE:
5388 return QCA_ROAM_REASON_CONGESTION;
5389 case WMI_ROAM_TRIGGER_REASON_FORCED:
5390 return QCA_ROAM_REASON_USER_TRIGGER;
5391 case WMI_ROAM_TRIGGER_REASON_BTM:
5392 return QCA_ROAM_REASON_BTM;
5393 case WMI_ROAM_TRIGGER_REASON_BSS_LOAD:
5394 return QCA_ROAM_REASON_BSS_LOAD;
5395 default:
5396 return QCA_ROAM_REASON_UNKNOWN;
5397 }
5398
5399 return QCA_ROAM_REASON_UNKNOWN;
5400}
5401
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005402/**
5403 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
5404 * @wiphy: pointer to wireless wiphy structure.
5405 * @wdev: pointer to wireless_dev structure.
5406 * @data: Pointer to the Key data
5407 * @data_len:Length of the data passed
5408 *
5409 * This is called when wlan driver needs to save the keys received via
5410 * vendor specific command.
5411 *
5412 * Return: Return the Success or Failure code.
5413 */
5414static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
5415 struct wireless_dev *wdev,
5416 const void *data, int data_len)
5417{
5418 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
5419 struct net_device *dev = wdev->netdev;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005420 struct hdd_adapter *hdd_adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5421 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005422 int status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005423 struct pmkid_mode_bits pmkid_modes;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005424 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005425
Dustin Brownfdf17c12018-03-14 12:55:34 -07005426 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005427
Anurag Chouhan6d760662016-02-20 16:05:43 +05305428 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005429 hdd_err("Command not allowed in FTM mode");
5430 return -EPERM;
5431 }
5432
Jeff Johnsond36fa332019-03-18 13:42:25 -07005433 if ((!data) || (data_len <= 0) ||
Hanumanth Reddy Pothula53874852018-03-08 19:57:49 +05305434 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005435 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005436 return -EINVAL;
5437 }
5438
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005439 hdd_ctx = WLAN_HDD_GET_CTX(hdd_adapter);
5440 if (!hdd_ctx) {
Jeff Johnson020db452016-06-29 14:37:26 -07005441 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005442 return -EINVAL;
5443 }
5444
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005445 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305446 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005447 return status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005448
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005449 hdd_get_pmkid_modes(hdd_ctx, &pmkid_modes);
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005450
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005451 mac_handle = hdd_ctx->mac_handle;
5452 sme_update_roam_key_mgmt_offload_enabled(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005453 hdd_adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005454 true, &pmkid_modes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305455 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
5456 qdf_mem_copy(local_pmk, data, data_len);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005457 sme_roam_set_psk_pmk(mac_handle, hdd_adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005458 local_pmk, data_len);
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +05305459 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005460 return 0;
5461}
5462
5463/**
5464 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
5465 * @wiphy: pointer to wireless wiphy structure.
5466 * @wdev: pointer to wireless_dev structure.
5467 * @data: Pointer to the Key data
5468 * @data_len:Length of the data passed
5469 *
5470 * This is called when wlan driver needs to save the keys received via
5471 * vendor specific command.
5472 *
5473 * Return: Return the Success or Failure code.
5474 */
5475static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
5476 struct wireless_dev *wdev,
5477 const void *data, int data_len)
5478{
Dustin Browna09acf42018-11-08 12:32:26 +05305479 int errno;
5480 struct osif_vdev_sync *vdev_sync;
5481
5482 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
5483 if (errno)
5484 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005485
Dustin Browna09acf42018-11-08 12:32:26 +05305486 errno = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev,
5487 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005488
Dustin Browna09acf42018-11-08 12:32:26 +05305489 osif_vdev_sync_op_stop(vdev_sync);
5490
5491 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005492}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08005493#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005494
5495static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
5496 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
5497 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
5498 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07005499 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005500};
5501
5502/**
5503 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
5504 * @wiphy: pointer to wireless wiphy structure.
5505 * @wdev: pointer to wireless_dev structure.
5506 * @data: Pointer to the data to be passed via vendor interface
5507 * @data_len:Length of the data to be passed
5508 *
5509 * This is called when wlan driver needs to send wifi driver related info
5510 * (driver/fw version) to the user space application upon request.
5511 *
5512 * Return: Return the Success or Failure code.
5513 */
5514static int
5515__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
5516 struct wireless_dev *wdev,
5517 const void *data, int data_len)
5518{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005519 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005520 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07005521 tSirVersionString driver_version;
5522 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005523 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07005524 struct sk_buff *reply_skb;
5525 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005526
Dustin Brownfdf17c12018-03-14 12:55:34 -07005527 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005528
Anurag Chouhan6d760662016-02-20 16:05:43 +05305529 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005530 hdd_err("Command not allowed in FTM mode");
5531 return -EPERM;
5532 }
5533
5534 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305535 if (status)
5536 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005537
Dustin Brown4ea21db2018-01-05 14:13:17 -08005538 if (wlan_cfg80211_nla_parse(tb_vendor,
5539 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
5540 data, data_len,
5541 qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07005542 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005543 return -EINVAL;
5544 }
5545
5546 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08005547 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07005548 strlcpy(driver_version, QWLAN_VERSIONSTR,
5549 sizeof(driver_version));
5550 skb_len += strlen(driver_version) + 1;
5551 count++;
5552 }
5553
5554 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005555 hdd_debug("Rcvd req for FW version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07005556 snprintf(firmware_version, sizeof(firmware_version),
Ashish Kumar Dhanotiyaeadb28b2019-06-28 14:34:19 +05305557 "FW:%d.%d.%d.%d.%d.%d HW:%s",
5558 hdd_ctx->fw_version_info.major_spid,
5559 hdd_ctx->fw_version_info.minor_spid,
5560 hdd_ctx->fw_version_info.siid,
5561 hdd_ctx->fw_version_info.rel_id,
5562 hdd_ctx->fw_version_info.crmid,
5563 hdd_ctx->fw_version_info.sub_id,
5564 hdd_ctx->target_hw_name);
Ryan Hsu7ac88852016-04-28 10:20:34 -07005565 skb_len += strlen(firmware_version) + 1;
5566 count++;
5567 }
5568
Rajeev Kumar Sirasanagandla551613d2018-05-16 17:21:01 +05305569 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
5570 hdd_debug("Rcvd req for Radio index");
5571 skb_len += sizeof(uint32_t);
5572 count++;
5573 }
5574
Ryan Hsu7ac88852016-04-28 10:20:34 -07005575 if (count == 0) {
5576 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005577 return -EINVAL;
5578 }
5579
Ryan Hsu7ac88852016-04-28 10:20:34 -07005580 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
5581 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
5582
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005583 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07005584 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005585 return -ENOMEM;
5586 }
5587
Ryan Hsu7ac88852016-04-28 10:20:34 -07005588 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
5589 if (nla_put_string(reply_skb,
5590 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
5591 driver_version))
5592 goto error_nla_fail;
5593 }
5594
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05305595 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07005596 if (nla_put_string(reply_skb,
5597 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
5598 firmware_version))
5599 goto error_nla_fail;
5600 }
5601
5602 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
5603 if (nla_put_u32(reply_skb,
5604 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
5605 hdd_ctx->radio_index))
5606 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005607 }
5608
5609 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07005610
5611error_nla_fail:
5612 hdd_err("nla put fail");
5613 kfree_skb(reply_skb);
5614 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005615}
5616
5617/**
5618 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
5619 * @wiphy: pointer to wireless wiphy structure.
5620 * @wdev: pointer to wireless_dev structure.
5621 * @data: Pointer to the data to be passed via vendor interface
5622 * @data_len:Length of the data to be passed
5623 *
5624 * This is called when wlan driver needs to send wifi driver related info
5625 * (driver/fw version) to the user space application upon request.
5626 *
5627 * Return: Return the Success or Failure code.
5628 */
5629static int
5630wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
5631 struct wireless_dev *wdev,
5632 const void *data, int data_len)
5633{
Dustin Brown363b4792019-02-05 16:11:55 -08005634 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08005635 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005636
Dustin Brown363b4792019-02-05 16:11:55 -08005637 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08005638 if (errno)
5639 return errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05305640
Dustin Brownf0f00612019-01-31 16:02:24 -08005641 errno = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005642
Dustin Brown363b4792019-02-05 16:11:55 -08005643 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08005644
5645 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005646}
5647
5648/**
5649 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
5650 * @wiphy: pointer to wireless wiphy structure.
5651 * @wdev: pointer to wireless_dev structure.
5652 * @data: Pointer to the data to be passed via vendor interface
5653 * @data_len:Length of the data to be passed
5654 *
5655 * This is called by userspace to know the supported logger features
5656 *
5657 * Return: Return the Success or Failure code.
5658 */
5659static int
5660__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
5661 struct wireless_dev *wdev,
5662 const void *data, int data_len)
5663{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005664 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005665 int status;
5666 uint32_t features;
5667 struct sk_buff *reply_skb = NULL;
5668
Dustin Brownfdf17c12018-03-14 12:55:34 -07005669 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005670
Anurag Chouhan6d760662016-02-20 16:05:43 +05305671 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005672 hdd_err("Command not allowed in FTM mode");
5673 return -EPERM;
5674 }
5675
5676 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305677 if (status)
5678 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005679
5680 features = 0;
5681
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005682 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
5683 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
5684 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
Srinivas Girigowdaa26eac02018-01-23 12:49:20 -08005685 features |= WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
Dundi Ravitejab189b742018-05-08 15:59:57 +05305686 features |= WIFI_LOGGER_PACKET_FATE_SUPPORTED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005687
5688 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5689 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
5690 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07005691 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005692 return -ENOMEM;
5693 }
5694
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005695 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005696 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
5697 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005698 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005699 kfree_skb(reply_skb);
5700 return -EINVAL;
5701 }
5702
5703 return cfg80211_vendor_cmd_reply(reply_skb);
5704}
5705
5706/**
5707 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
5708 * @wiphy: pointer to wireless wiphy structure.
5709 * @wdev: pointer to wireless_dev structure.
5710 * @data: Pointer to the data to be passed via vendor interface
5711 * @data_len:Length of the data to be passed
5712 *
5713 * This is called by userspace to know the supported logger features
5714 *
5715 * Return: Return the Success or Failure code.
5716 */
5717static int
5718wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
5719 struct wireless_dev *wdev,
5720 const void *data, int data_len)
5721{
Dustin Brown363b4792019-02-05 16:11:55 -08005722 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08005723 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05305724
Dustin Brown363b4792019-02-05 16:11:55 -08005725 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08005726 if (errno)
5727 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005728
Dustin Brownf0f00612019-01-31 16:02:24 -08005729 errno = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
5730 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005731
Dustin Brown363b4792019-02-05 16:11:55 -08005732 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05305733
Dustin Brownf0f00612019-01-31 16:02:24 -08005734 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005735}
5736
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305737#ifdef WLAN_FEATURE_GTK_OFFLOAD
5738void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05305739 uint8_t *kck_ptr, uint8_t kck_len,
5740 uint8_t *kek_ptr, uint32_t kek_len,
5741 uint8_t *replay_ctr, bool big_endian)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305742{
5743 struct hdd_station_ctx *hdd_sta_ctx;
5744 uint8_t *buf;
5745 int i;
5746 struct pmo_gtk_req *gtk_req = NULL;
Min Liu8c5d99e2018-09-10 17:18:44 +08005747 struct wlan_objmgr_vdev *vdev;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305748 QDF_STATUS status = QDF_STATUS_E_FAILURE;
5749
5750 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
Min Liu74a1a502018-10-10 19:59:07 +08005751 if (!gtk_req)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305752 return;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305753
5754 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05305755 if (kck_ptr) {
5756 if (kck_len > sizeof(gtk_req->kck)) {
5757 kck_len = sizeof(gtk_req->kck);
5758 QDF_ASSERT(0);
5759 }
5760 qdf_mem_copy(gtk_req->kck, kck_ptr, kck_len);
Yeshwanth Sriram Guntukae6313412019-08-06 14:18:33 +05305761 gtk_req->kck_len = kck_len;
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05305762 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305763
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08005764 if (kek_ptr) {
5765 /* paranoia */
5766 if (kek_len > sizeof(gtk_req->kek)) {
5767 kek_len = sizeof(gtk_req->kek);
5768 QDF_ASSERT(0);
5769 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305770 qdf_mem_copy(gtk_req->kek, kek_ptr, kek_len);
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08005771 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305772
Jeff Johnsone04b6992019-02-27 14:06:55 -08005773 qdf_copy_macaddr(&gtk_req->bssid, &hdd_sta_ctx->conn_info.bssid);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305774
5775 gtk_req->kek_len = kek_len;
gaurank kathpalia82a1b2b2018-07-10 16:49:10 +05305776 gtk_req->is_fils_connection = hdd_is_fils_connection(adapter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305777
5778 /* convert big to little endian since driver work on little endian */
5779 buf = (uint8_t *)&gtk_req->replay_counter;
5780 for (i = 0; i < 8; i++)
5781 buf[7 - i] = replay_ctr[i];
5782
Min Liu8c5d99e2018-09-10 17:18:44 +08005783 vdev = hdd_objmgr_get_vdev(adapter);
5784 if (!vdev)
5785 goto end;
5786 status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05305787 hdd_objmgr_put_vdev(vdev);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305788 if (status != QDF_STATUS_SUCCESS)
5789 hdd_err("Failed to cache GTK Offload");
5790
Min Liu8c5d99e2018-09-10 17:18:44 +08005791end:
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305792 qdf_mem_free(gtk_req);
5793}
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305794#endif
5795
Sridhar Selvaraje5260442017-08-19 10:12:03 +05305796#if defined(WLAN_FEATURE_FILS_SK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305797/**
5798 * wlan_hdd_add_fils_params_roam_auth_event() - Adds FILS params in roam auth
5799 * @skb: SK buffer
5800 * @roam_info: Roam info
5801 *
5802 * API adds fils params[pmk, pmkid, next sequence number] to roam auth event
5803 *
5804 * Return: zero on success, error code on failure
5805 */
Jeff Johnson172237b2017-11-07 15:32:59 -08005806static int
5807wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
5808 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305809{
5810 if (roam_info->pmk_len &&
5811 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK,
5812 roam_info->pmk_len, roam_info->pmk)) {
5813 hdd_err("pmk send fail");
5814 return -EINVAL;
5815 }
5816
5817 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID,
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -07005818 PMKID_LEN, roam_info->pmkid)) {
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305819 hdd_err("pmkid send fail");
5820 return -EINVAL;
5821 }
5822
Vignesh Viswanathan8da68cf2017-09-07 14:00:04 +05305823 hdd_debug("Update ERP Seq Num %d, Next ERP Seq Num %d",
5824 roam_info->update_erp_next_seq_num,
5825 roam_info->next_erp_seq_num);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305826 if (roam_info->update_erp_next_seq_num &&
5827 nla_put_u16(skb,
5828 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM,
5829 roam_info->next_erp_seq_num)) {
5830 hdd_err("ERP seq num send fail");
5831 return -EINVAL;
5832 }
5833
5834 return 0;
5835}
5836#else
Jeff Johnson172237b2017-11-07 15:32:59 -08005837static inline int
5838wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
5839 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305840{
5841 return 0;
5842}
5843#endif
5844
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08005845#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005846/**
5847 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05305848 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005849 * @bssid: pointer to bssid of roamed AP.
5850 * @req_rsn_ie: Pointer to request RSN IE
5851 * @req_rsn_len: Length of the request RSN IE
5852 * @rsp_rsn_ie: Pointer to response RSN IE
5853 * @rsp_rsn_len: Length of the response RSN IE
5854 * @roam_info_ptr: Pointer to the roaming related information
5855 *
5856 * This is called when wlan driver needs to send the roaming and
5857 * authorization information after roaming.
5858 *
5859 * The information that would be sent is the request RSN IE, response
5860 * RSN IE and BSSID of the newly roamed AP.
5861 *
5862 * If the Authorized status is authenticated, then additional parameters
5863 * like PTK's KCK and KEK and Replay Counter would also be passed to the
5864 * supplicant.
5865 *
5866 * The supplicant upon receiving this event would ignore the legacy
5867 * cfg80211_roamed call and use the entire information from this event.
5868 * The cfg80211_roamed should still co-exist since the kernel will
5869 * make use of the parameters even if the supplicant ignores it.
5870 *
5871 * Return: Return the Success or Failure code.
5872 */
Jeff Johnsone5006672017-08-29 14:39:02 -07005873int wlan_hdd_send_roam_auth_event(struct hdd_adapter *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005874 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
Jeff Johnson172237b2017-11-07 15:32:59 -08005875 uint32_t rsp_rsn_len, struct csr_roam_info *roam_info_ptr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005876{
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005877 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005878 struct sk_buff *skb = NULL;
Pragaspathi Thilagaraj7a1a08e2019-05-29 01:20:29 +05305879 enum csr_akm_type auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305880 uint32_t fils_params_len;
5881 int status;
sheenam monga6e49e5c2019-04-04 12:49:04 +05305882 enum qca_roam_reason hdd_roam_reason;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -07005883
Dustin Brown491d54b2018-03-14 12:39:11 -07005884 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005885
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005886 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005887 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005888
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005889 if (!roaming_offload_enabled(hdd_ctx) ||
5890 !roam_info_ptr->roamSynchInProgress)
Prashanth Bhattabfc25292015-11-05 11:16:21 -08005891 return 0;
5892
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305893 /*
5894 * PMK is sent from FW in Roam Synch Event for FILS Roaming.
5895 * In that case, add three more NL attributes.ie. PMK, PMKID
5896 * and ERP next sequence number. Add corresponding lengths
5897 * with 3 extra NL message headers for each of the
5898 * aforementioned params.
5899 */
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -07005900 fils_params_len = roam_info_ptr->pmk_len + PMKID_LEN +
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305901 sizeof(uint16_t) + (3 * NLMSG_HDRLEN);
5902
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005903 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05305904 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005905 ETH_ALEN + req_rsn_len + rsp_rsn_len +
5906 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305907 SIR_KCK_KEY_LEN + roam_info_ptr->kek_len +
sheenam monga6e49e5c2019-04-04 12:49:04 +05305908 sizeof(uint16_t) + sizeof(uint8_t) +
5909 (9 * NLMSG_HDRLEN) + fils_params_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005910 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
5911 GFP_KERNEL);
5912
5913 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07005914 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005915 return -EINVAL;
5916 }
5917
5918 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
5919 ETH_ALEN, bssid) ||
5920 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
5921 req_rsn_len, req_rsn_ie) ||
5922 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
5923 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005924 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005925 goto nla_put_failure;
5926 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005927 if (roam_info_ptr->synchAuthStatus ==
5928 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07005929 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08005930 if (nla_put_u8(skb,
5931 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
5932 hdd_err("nla put fail");
5933 goto nla_put_failure;
5934 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08005935 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
5936 /* if FT or CCKM connection: dont send replay counter */
5937 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
5938 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
Pragaspathi Thilagaraj96259b22019-02-15 01:08:27 +05305939 auth_type != eCSR_AUTH_TYPE_FT_SAE &&
5940 auth_type != eCSR_AUTH_TYPE_FT_SUITEB_EAP_SHA384 &&
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08005941 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
5942 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
5943 nla_put(skb,
5944 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
5945 SIR_REPLAY_CTR_LEN,
5946 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005947 hdd_err("non FT/non CCKM connection");
5948 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08005949 goto nla_put_failure;
5950 }
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05305951 if (roam_info_ptr->kek_len > SIR_KEK_KEY_LEN_FILS ||
5952 nla_put(skb,
Naveen Rawat14298b92015-11-25 16:27:41 -08005953 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05305954 roam_info_ptr->kck_len, roam_info_ptr->kck) ||
Naveen Rawat14298b92015-11-25 16:27:41 -08005955 nla_put(skb,
5956 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305957 roam_info_ptr->kek_len, roam_info_ptr->kek)) {
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05305958 hdd_err("nla put fail, kek_len %d",
5959 roam_info_ptr->kek_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005960 goto nla_put_failure;
5961 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305962
sheenam monga6e49e5c2019-04-04 12:49:04 +05305963 hdd_roam_reason =
5964 hdd_get_roam_reason(roam_info_ptr->roam_reason);
5965
5966 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON,
5967 hdd_roam_reason)) {
5968 hdd_err("roam reason send failure");
5969 goto nla_put_failure;
5970 }
5971
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305972 status = wlan_hdd_add_fils_params_roam_auth_event(skb,
5973 roam_info_ptr);
5974 if (status)
5975 goto nla_put_failure;
5976
5977 /*
5978 * Save the gtk rekey parameters in HDD STA context. They will
5979 * be used next time when host enables GTK offload and goes
5980 * into power save state.
5981 */
5982 wlan_hdd_save_gtk_offload_params(adapter, roam_info_ptr->kck,
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05305983 roam_info_ptr->kck_len,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305984 roam_info_ptr->kek,
5985 roam_info_ptr->kek_len,
5986 roam_info_ptr->replay_ctr,
5987 true);
5988 hdd_debug("roam_info_ptr->replay_ctr 0x%llx",
5989 *((uint64_t *)roam_info_ptr->replay_ctr));
5990
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005991 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07005992 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005993 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
5994 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005995 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005996 goto nla_put_failure;
5997 }
5998 }
5999
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05306000 hdd_debug("Auth Status = %d Subnet Change Status = %d",
6001 roam_info_ptr->synchAuthStatus,
6002 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08006003
6004 /*
6005 * Add subnet change status if subnet has changed
6006 * 0 = unchanged
6007 * 1 = changed
6008 * 2 = unknown
6009 */
6010 if (roam_info_ptr->subnet_change_status) {
6011 if (nla_put_u8(skb,
6012 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
6013 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006014 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08006015 goto nla_put_failure;
6016 }
6017 }
6018
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006019 cfg80211_vendor_event(skb, GFP_KERNEL);
6020 return 0;
6021
6022nla_put_failure:
6023 kfree_skb(skb);
6024 return -EINVAL;
6025}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08006026#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006027
Jeff Johnson91f90ff2018-11-16 07:53:37 -08006028#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
6029 ((1 << 26) | \
6030 (((probe_period) & 0x1fff) << 13) | \
6031 ((stay_period) & 0x1fff))
6032
6033#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
6034 ((1 << 27) | \
6035 ((snr_diff) & 0x1fff))
6036
6037#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
6038 ((1 << 28) | \
6039 ((probe_dwell_time) & 0x1fff))
6040
6041#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
6042 ((1 << 29) | \
6043 (((mgmt_snr_weight) & 0xff) << 16) | \
6044 (((data_snr_weight) & 0xff) << 8) | \
6045 ((ack_snr_weight) & 0xff))
6046
lifeng66831662017-05-19 16:01:35 +08006047#define RX_REORDER_TIMEOUT_VOICE \
6048 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE
6049#define RX_REORDER_TIMEOUT_VIDEO \
6050 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO
6051#define RX_REORDER_TIMEOUT_BESTEFFORT \
6052 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT
6053#define RX_REORDER_TIMEOUT_BACKGROUND \
6054 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND
6055#define RX_BLOCKSIZE_PEER_MAC \
6056 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC
6057#define RX_BLOCKSIZE_WINLIMIT \
6058 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006059static const struct nla_policy
6060wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
6061
6062 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
Sourav Mohapatra0dbdfb42019-03-19 14:31:20 +05306063 [QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED] = {
6064 .type = NLA_U8 },
6065 [QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS] = {.type = NLA_U8 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006066 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
6067 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Jeff Johnson79f6a602017-06-15 09:48:25 -07006068 [QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT] = {.type = NLA_U32},
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05306069 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05306070 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
6071 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006072 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
6073 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
6074 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
6075 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
6076 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08006077 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY] = {
6078 .type = NLA_U32 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05306079 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08006080 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
6081 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
Jeff Johnson91f90ff2018-11-16 07:53:37 -08006082 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
Jeff Johnson77177bc2018-11-16 08:14:20 -08006083 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME] = {
6084 .type = NLA_U32},
Jeff Johnson1350e622018-11-16 18:36:55 -08006085 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT] = {
6086 .type = NLA_U32},
6087 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT] = {
6088 .type = NLA_U32},
6089 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT] = {
6090 .type = NLA_U32},
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306091 [QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL] = {.type = NLA_U8},
lifeng66831662017-05-19 16:01:35 +08006092 [RX_REORDER_TIMEOUT_VOICE] = {.type = NLA_U32},
6093 [RX_REORDER_TIMEOUT_VIDEO] = {.type = NLA_U32},
6094 [RX_REORDER_TIMEOUT_BESTEFFORT] = {.type = NLA_U32},
6095 [RX_REORDER_TIMEOUT_BACKGROUND] = {.type = NLA_U32},
Jeff Johnson19a5a7e2017-06-15 14:51:26 -07006096 [RX_BLOCKSIZE_PEER_MAC] = {
6097 .type = NLA_UNSPEC,
6098 .len = QDF_MAC_ADDR_SIZE},
lifeng66831662017-05-19 16:01:35 +08006099 [RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32},
Mukul Sharma6398b252017-05-01 17:58:12 +05306100 [QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL] = {.type = NLA_U32 },
Poddar, Siddarth4b3f7312017-11-02 17:00:20 +05306101 [QCA_WLAN_VENDOR_ATTR_CONFIG_LRO] = {.type = NLA_U8 },
Jeff Johnson1feb8a62018-11-14 13:18:41 -08006102 [QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER] = {.type = NLA_U8 },
lifengd217d192017-05-09 19:44:16 +08006103 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA] = {.type = NLA_U32 },
6104 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN] = {.type = NLA_U32 },
6105 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST] = {.type = NLA_U32 },
6106 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL] = {.type = NLA_U32 },
Paul Zhang99fe8842017-12-08 14:43:46 +08006107 [QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL] = {.type = NLA_U16 },
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05306108 [QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT] = {.type = NLA_U8},
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07006109 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE] = {.type = NLA_U8 },
Abhishek Singh6454ad32017-12-20 10:42:21 +05306110 [QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] = {.type = NLA_U8},
Ashish Kumar Dhanotiya1e20bcc2018-06-15 11:28:51 +05306111 [QCA_WLAN_VENDOR_ATTR_CONFIG_GTX] = {.type = NLA_U8},
Paul Zhangc9dbaee2019-06-23 22:07:31 +08006112 [QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS] = {.type = NLA_U8},
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08006113 [QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY] = {.type = NLA_U32 },
6114 [QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST] = {
6115 .type = NLA_BINARY,
Srinivas Girigowdacf161402019-03-14 11:37:33 -07006116 .len = WLAN_MAX_IE_LEN + 2},
Srinivas Dasari37e37312019-06-30 23:50:24 +05306117 [QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES] = {
6118 .type = NLA_BINARY,
6119 .len = SIR_MAC_MAX_ADD_IE_LENGTH + 2},
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08006120
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006121};
6122
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006123static const struct nla_policy qca_wlan_vendor_twt_add_dialog_policy[
6124 QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1] = {
6125 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP] = {.type = NLA_U8 },
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05306126 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST] = {.type = NLA_FLAG },
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006127 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE] = {.type = NLA_U8 },
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05306128 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER] = {.type = NLA_FLAG },
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006129 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE] = {.type = NLA_U8 },
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05306130 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION] = {.type = NLA_FLAG },
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006131 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME] = {.type = NLA_U32 },
6132 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION] = {.type = NLA_U32 },
6133 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA] = {
6134 .type = NLA_U32 },
6135};
6136
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006137static const struct nla_policy
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08006138qca_wlan_vendor_attr_he_omi_tx_policy [QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX + 1] = {
6139 [QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS] = {.type = NLA_U8 },
6140 [QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW] = {.type = NLA_U8 },
6141 [QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE] = {.type = NLA_U8 },
6142 [QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS] = {.type = NLA_U8 },
Kiran Kumar Lokere49e3aff2019-02-06 17:00:48 -08006143 [QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE] = {.type = NLA_U8 },
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08006144};
6145
6146static const struct nla_policy
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006147wlan_hdd_wifi_test_config_policy[
6148 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1] = {
6149 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE] = {
6150 .type = NLA_U8},
6151 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ] = {
6152 .type = NLA_U8},
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08006153 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS] = {
6154 .type = NLA_U8},
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08006155 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ] = {
6156 .type = NLA_U8},
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08006157 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION] = {
6158 .type = NLA_U8},
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006159 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE] = {
6160 .type = NLA_U8},
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006161 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION] = {
6162 .type = NLA_U8},
6163 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID] = {
6164 .type = NLA_U8},
6165 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE] = {
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07006166 .type = NLA_U16},
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08006167 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK] = {
6168 .type = NLA_U8},
6169 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC] = {
6170 .type = NLA_U8},
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08006171 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF] = {
6172 .type = NLA_U8},
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07006173 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE] = {
6174 .type = NLA_U8},
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07006175 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS] = {
6176 .type = NLA_U8},
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07006177 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR] = {
6178 .type = NLA_U8},
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07006179 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AC] = {
6180 .type = NLA_U8},
6181 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA] = {
6182 .type = NLA_U8},
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07006183 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP] = {
6184 .type = NLA_U8},
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07006185 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_BW] = {
6186 .type = NLA_U8},
6187 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_NSS] = {
6188 .type = NLA_U8},
6189 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG] = {
6190 .type = NLA_FLAG},
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07006191 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU] = {
6192 .type = NLA_U8},
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08006193 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP] = {
6194 .type = NLA_U8},
6195 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX] = {
6196 .type = NLA_NESTED},
Kiran Kumar Lokereee205772018-09-27 00:27:27 -07006197 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU] = {
6198 .type = NLA_U8},
Kiran Kumar Lokere921b5a52019-02-24 21:53:20 -08006199 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS]
6200 = {.type = NLA_U8},
Kiran Kumar Lokerea1c29ec2019-02-25 18:19:00 -08006201 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT] = {
6202 .type = NLA_U8},
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006203 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP] = {
6204 .type = NLA_NESTED},
6205 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE] = {
6206 .type = NLA_NESTED},
6207 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT] = {
6208 .type = NLA_U8},
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006209};
6210
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006211/**
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306212 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
6213 * @hdd_ctx: HDD context
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306214 * @adapter: Pointer to HDD adapter
6215 * @ie_data: Pointer to Scan IEs buffer
6216 * @ie_len: Length of Scan IEs
6217 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306218 * This API is used to store the default scan ies received from
6219 * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
6220 *
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306221 * Return: 0 on success; error number otherwise
6222 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006223static int wlan_hdd_save_default_scan_ies(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07006224 struct hdd_adapter *adapter,
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306225 uint8_t *ie_data, uint16_t ie_len)
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306226{
Jeff Johnson37588942017-08-15 16:11:41 -07006227 struct hdd_scan_info *scan_info = &adapter->scan_info;
Wu Gao93816212018-08-31 16:49:54 +08006228 bool add_qcn_ie;
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306229
6230 if (!scan_info)
6231 return -EINVAL;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306232
6233 if (scan_info->default_scan_ies) {
6234 qdf_mem_free(scan_info->default_scan_ies);
6235 scan_info->default_scan_ies = NULL;
6236 }
6237
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306238 scan_info->default_scan_ies_len = ie_len;
Dustin Brown1dbefe62018-09-11 16:32:03 -07006239 ucfg_mlme_get_qcn_ie_support(hdd_ctx->psoc, &add_qcn_ie);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306240 if (add_qcn_ie)
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306241 ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306242
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306243 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306244 if (!scan_info->default_scan_ies) {
6245 scan_info->default_scan_ies_len = 0;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306246 return -ENOMEM;
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306247 }
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306248
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306249 qdf_mem_copy(scan_info->default_scan_ies, ie_data,
6250 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306251
6252 /* Add QCN IE if g_qcn_ie_support INI is enabled */
6253 if (add_qcn_ie)
Kiran Kumar Lokere89f01f02019-08-06 18:22:39 -07006254 sme_add_qcn_ie(hdd_ctx->mac_handle,
6255 scan_info->default_scan_ies,
6256 &scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306257
Abhishek Singh74d06cf2019-09-06 09:23:22 +05306258 hdd_debug("Saved default scan IE:len %d",
6259 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306260 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
6261 (uint8_t *) scan_info->default_scan_ies,
6262 scan_info->default_scan_ies_len);
6263
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306264 return 0;
6265}
6266
6267/**
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306268 * wlan_hdd_handle_restrict_offchan_config() -
6269 * Handle wifi configuration attribute :
6270 * QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL
6271 * @adapter: Pointer to HDD adapter
6272 * @restrict_offchan: Restrict offchannel setting done by
6273 * application
6274 *
6275 * Return: 0 on success; error number otherwise
6276 */
Jeff Johnsone5006672017-08-29 14:39:02 -07006277static int wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter *adapter,
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306278 u8 restrict_offchan)
6279{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006280 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonc1e62782017-11-09 09:50:17 -08006281 enum QDF_OPMODE dev_mode = adapter->device_mode;
Min Liu8c5d99e2018-09-10 17:18:44 +08006282 struct wlan_objmgr_vdev *vdev;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306283 int ret_val = 0;
6284
6285 if (!(dev_mode == QDF_SAP_MODE || dev_mode == QDF_P2P_GO_MODE)) {
6286 hdd_err("Invalid interface type:%d", dev_mode);
6287 return -EINVAL;
6288 }
Min Liu8c5d99e2018-09-10 17:18:44 +08006289 vdev = hdd_objmgr_get_vdev(adapter);
6290 if (!vdev)
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006291 return -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306292 if (restrict_offchan == 1) {
6293 enum policy_mgr_con_mode pmode =
6294 policy_mgr_convert_device_mode_to_qdf_type(dev_mode);
6295 int chan;
6296
Min Liu8c5d99e2018-09-10 17:18:44 +08006297 u32 vdev_id = wlan_vdev_get_id(vdev);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306298
Min Liu8c5d99e2018-09-10 17:18:44 +08006299 wlan_vdev_obj_lock(vdev);
6300 wlan_vdev_mlme_cap_set(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
6301 wlan_vdev_obj_unlock(vdev);
Dustin Brown76cd2932018-09-11 16:03:05 -07006302 chan = policy_mgr_get_channel(hdd_ctx->psoc, pmode,
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006303 &vdev_id);
6304 if (!chan ||
6305 wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, chan)) {
6306 hdd_err("unable to send avoid_freq");
6307 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306308 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006309 hdd_info("vdev %d mode %d dnbs enabled", vdev_id, dev_mode);
6310 } else if (restrict_offchan == 0) {
Min Liu8c5d99e2018-09-10 17:18:44 +08006311 wlan_vdev_obj_lock(vdev);
6312 wlan_vdev_mlme_cap_clear(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
6313 wlan_vdev_obj_unlock(vdev);
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006314 if (wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0)) {
6315 hdd_err("unable to clear avoid_freq");
6316 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306317 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006318 hdd_info("vdev mode %d dnbs disabled", dev_mode);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306319 } else {
6320 ret_val = -EINVAL;
6321 hdd_err("Invalid RESTRICT_OFFCHAN setting");
6322 }
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05306323 hdd_objmgr_put_vdev(vdev);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306324 return ret_val;
6325}
6326
6327/**
Jeff Johnson0dd687e2018-11-16 20:11:27 -08006328 * wlan_hdd_cfg80211_wifi_set_reorder_timeout() - set reorder timeout
6329 * @adapter: Pointer to HDD adapter
lifeng66831662017-05-19 16:01:35 +08006330 * @tb: array of pointer to struct nlattr
6331 *
6332 * Return: 0 on success; error number otherwise
6333 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006334static
Jeff Johnson0dd687e2018-11-16 20:11:27 -08006335int wlan_hdd_cfg80211_wifi_set_reorder_timeout(struct hdd_adapter *adapter,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006336 struct nlattr *tb[])
lifeng66831662017-05-19 16:01:35 +08006337{
Jeff Johnson0dd687e2018-11-16 20:11:27 -08006338 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Min Liuab6ed4f2018-01-09 13:13:57 +08006339 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08006340 QDF_STATUS qdf_status;
6341 struct sir_set_rx_reorder_timeout_val reorder_timeout;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006342 mac_handle_t mac_handle;
lifeng66831662017-05-19 16:01:35 +08006343
6344#define RX_TIMEOUT_VAL_MIN 10
6345#define RX_TIMEOUT_VAL_MAX 1000
6346
6347 if (tb[RX_REORDER_TIMEOUT_VOICE] ||
6348 tb[RX_REORDER_TIMEOUT_VIDEO] ||
6349 tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
6350 tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
6351
6352 /* if one is specified, all must be specified */
6353 if (!tb[RX_REORDER_TIMEOUT_VOICE] ||
6354 !tb[RX_REORDER_TIMEOUT_VIDEO] ||
6355 !tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
6356 !tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
6357 hdd_err("four AC timeout val are required MAC");
6358 return -EINVAL;
6359 }
6360
6361 reorder_timeout.rx_timeout_pri[0] = nla_get_u32(
6362 tb[RX_REORDER_TIMEOUT_VOICE]);
6363 reorder_timeout.rx_timeout_pri[1] = nla_get_u32(
6364 tb[RX_REORDER_TIMEOUT_VIDEO]);
6365 reorder_timeout.rx_timeout_pri[2] = nla_get_u32(
6366 tb[RX_REORDER_TIMEOUT_BESTEFFORT]);
6367 reorder_timeout.rx_timeout_pri[3] = nla_get_u32(
6368 tb[RX_REORDER_TIMEOUT_BACKGROUND]);
6369 /* timeout value is required to be in the rang 10 to 1000ms */
6370 if (reorder_timeout.rx_timeout_pri[0] >= RX_TIMEOUT_VAL_MIN &&
6371 reorder_timeout.rx_timeout_pri[0] <= RX_TIMEOUT_VAL_MAX &&
6372 reorder_timeout.rx_timeout_pri[1] >= RX_TIMEOUT_VAL_MIN &&
6373 reorder_timeout.rx_timeout_pri[1] <= RX_TIMEOUT_VAL_MAX &&
6374 reorder_timeout.rx_timeout_pri[2] >= RX_TIMEOUT_VAL_MIN &&
6375 reorder_timeout.rx_timeout_pri[2] <= RX_TIMEOUT_VAL_MAX &&
6376 reorder_timeout.rx_timeout_pri[3] >= RX_TIMEOUT_VAL_MIN &&
6377 reorder_timeout.rx_timeout_pri[3] <= RX_TIMEOUT_VAL_MAX) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006378 mac_handle = hdd_ctx->mac_handle;
6379 qdf_status = sme_set_reorder_timeout(mac_handle,
lifeng66831662017-05-19 16:01:35 +08006380 &reorder_timeout);
6381 if (qdf_status != QDF_STATUS_SUCCESS) {
6382 hdd_err("failed to set reorder timeout err %d",
6383 qdf_status);
6384 ret_val = -EPERM;
6385 }
6386 } else {
6387 hdd_err("one of the timeout value is not in range");
6388 ret_val = -EINVAL;
6389 }
6390 }
6391
6392 return ret_val;
6393}
6394
6395/**
Jeff Johnson339ede82018-11-16 20:27:52 -08006396 * wlan_hdd_cfg80211_wifi_set_rx_blocksize() - set rx blocksize
lifeng66831662017-05-19 16:01:35 +08006397 * @adapter: hdd adapter
6398 * @tb: array of pointer to struct nlattr
6399 *
6400 * Return: 0 on success; error number otherwise
6401 */
Jeff Johnson339ede82018-11-16 20:27:52 -08006402static int wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct hdd_adapter *adapter,
lifeng66831662017-05-19 16:01:35 +08006403 struct nlattr *tb[])
6404{
Jeff Johnson339ede82018-11-16 20:27:52 -08006405 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Min Liuab6ed4f2018-01-09 13:13:57 +08006406 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08006407 uint32_t set_value;
6408 QDF_STATUS qdf_status;
6409 struct sir_peer_set_rx_blocksize rx_blocksize;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006410 mac_handle_t mac_handle;
lifeng66831662017-05-19 16:01:35 +08006411
6412#define WINDOW_SIZE_VAL_MIN 1
6413#define WINDOW_SIZE_VAL_MAX 64
6414
6415 if (tb[RX_BLOCKSIZE_PEER_MAC] ||
6416 tb[RX_BLOCKSIZE_WINLIMIT]) {
6417
6418 /* if one is specified, both must be specified */
6419 if (!tb[RX_BLOCKSIZE_PEER_MAC] ||
6420 !tb[RX_BLOCKSIZE_WINLIMIT]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07006421 hdd_err("Both Peer MAC and windows limit required");
lifeng66831662017-05-19 16:01:35 +08006422 return -EINVAL;
6423 }
6424
6425 memcpy(&rx_blocksize.peer_macaddr,
6426 nla_data(tb[RX_BLOCKSIZE_PEER_MAC]),
6427 sizeof(rx_blocksize.peer_macaddr)),
6428
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006429 rx_blocksize.vdev_id = adapter->vdev_id;
lifeng66831662017-05-19 16:01:35 +08006430 set_value = nla_get_u32(tb[RX_BLOCKSIZE_WINLIMIT]);
6431 /* maximum window size is 64 */
6432 if (set_value >= WINDOW_SIZE_VAL_MIN &&
6433 set_value <= WINDOW_SIZE_VAL_MAX) {
6434 rx_blocksize.rx_block_ack_win_limit = set_value;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006435 mac_handle = hdd_ctx->mac_handle;
6436 qdf_status = sme_set_rx_set_blocksize(mac_handle,
lifeng66831662017-05-19 16:01:35 +08006437 &rx_blocksize);
6438 if (qdf_status != QDF_STATUS_SUCCESS) {
6439 hdd_err("failed to set aggr sizes err %d",
6440 qdf_status);
6441 ret_val = -EPERM;
6442 }
6443 } else {
6444 hdd_err("window size val is not in range");
6445 ret_val = -EINVAL;
6446 }
6447 }
6448
6449 return ret_val;
6450}
6451
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08006452static int hdd_config_access_policy(struct hdd_adapter *adapter,
6453 struct nlattr *tb[])
6454{
6455 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6456 struct nlattr *policy_attr =
6457 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY];
6458 struct nlattr *ielist_attr =
6459 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST];
6460 uint32_t access_policy;
Srinivas Girigowdacf161402019-03-14 11:37:33 -07006461 uint8_t ie[WLAN_MAX_IE_LEN + 2];
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08006462 QDF_STATUS status;
6463
6464 /* nothing to do if neither attribute is present */
6465 if (!ielist_attr && !policy_attr)
6466 return 0;
6467
6468 /* if one is present, both must be present */
6469 if (!ielist_attr || !policy_attr) {
6470 hdd_err("Missing attribute for %s",
6471 policy_attr ?
6472 "ACCESS_POLICY_IE_LIST" : "ACCESS_POLICY");
6473 return -EINVAL;
6474 }
6475
6476 /* validate the access policy */
6477 access_policy = nla_get_u32(policy_attr);
6478 switch (access_policy) {
6479 case QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED:
6480 case QCA_ACCESS_POLICY_DENY_UNLESS_LISTED:
6481 /* valid */
6482 break;
6483 default:
6484 hdd_err("Invalid value. access_policy %u", access_policy);
6485 return -EINVAL;
6486 }
6487
6488 /*
6489 * ie length is validated by the nla_policy. need to make a
Srinivas Girigowdacf161402019-03-14 11:37:33 -07006490 * copy since SME will always read WLAN_MAX_IE_LEN+2 bytes
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08006491 */
6492 nla_memcpy(ie, ielist_attr, sizeof(ie));
6493
6494 hdd_debug("calling sme_update_access_policy_vendor_ie");
6495 status = sme_update_access_policy_vendor_ie(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006496 adapter->vdev_id,
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08006497 ie, access_policy);
6498 if (QDF_IS_STATUS_ERROR(status))
6499 hdd_err("Failed to set vendor ie and access policy, %d",
6500 status);
6501
6502 return qdf_status_to_os_return(status);
6503}
6504
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08006505static int hdd_config_mpdu_aggregation(struct hdd_adapter *adapter,
6506 struct nlattr *tb[])
6507{
6508 struct nlattr *tx_attr =
6509 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION];
6510 struct nlattr *rx_attr =
6511 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION];
6512 uint8_t tx_size, rx_size;
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08006513 QDF_STATUS status;
6514
6515 /* nothing to do if neither attribute is present */
6516 if (!tx_attr && !rx_attr)
6517 return 0;
6518
6519 /* if one is present, both must be present */
6520 if (!tx_attr || !rx_attr) {
6521 hdd_err("Missing attribute for %s",
6522 tx_attr ? "RX" : "TX");
6523 return -EINVAL;
6524 }
6525
6526 tx_size = nla_get_u8(tx_attr);
6527 rx_size = nla_get_u8(rx_attr);
6528 if (!cfg_in_range(CFG_TX_AGGREGATION_SIZE, tx_size) ||
6529 !cfg_in_range(CFG_RX_AGGREGATION_SIZE, rx_size)) {
6530 hdd_err("TX %d RX %d MPDU aggr size not in range",
6531 tx_size, rx_size);
6532
6533 return -EINVAL;
6534 }
6535
Abhishek Ambure74709762019-05-27 19:43:26 +05306536 status = wma_set_tx_rx_aggr_size(adapter->vdev_id,
6537 tx_size,
6538 rx_size,
6539 WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU);
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08006540
6541 return qdf_status_to_os_return(status);
6542}
6543
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08006544static int hdd_config_ant_div_period(struct hdd_adapter *adapter,
6545 struct nlattr *tb[])
6546{
6547 struct nlattr *probe_attr =
6548 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD];
6549 struct nlattr *stay_attr =
6550 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD];
6551 uint32_t probe_period, stay_period, ant_div_usrcfg;
6552 int errno;
6553
6554 /* nothing to do if neither attribute is present */
6555 if (!probe_attr && !stay_attr)
6556 return 0;
6557
6558 /* if one is present, both must be present */
6559 if (!probe_attr || !stay_attr) {
6560 hdd_err("Missing attribute for %s",
6561 probe_attr ? "STAY" : "PROBE");
6562 return -EINVAL;
6563 }
6564
6565 probe_period = nla_get_u32(probe_attr);
6566 stay_period = nla_get_u32(stay_attr);
6567 ant_div_usrcfg = ANT_DIV_SET_PERIOD(probe_period, stay_period);
6568 hdd_debug("ant div set period: %x", ant_div_usrcfg);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006569 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08006570 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
6571 ant_div_usrcfg, PDEV_CMD);
6572 if (errno)
6573 hdd_err("Failed to set ant div period, %d", errno);
6574
6575 return errno;
6576}
6577
Jeff Johnson1350e622018-11-16 18:36:55 -08006578static int hdd_config_ant_div_snr_weight(struct hdd_adapter *adapter,
6579 struct nlattr *tb[])
6580{
6581 struct nlattr *mgmt_attr =
6582 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT];
6583 struct nlattr *data_attr =
6584 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT];
6585 struct nlattr *ack_attr =
6586 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT];
6587 uint32_t mgmt_snr, data_snr, ack_snr, ant_div_usrcfg;
6588 int errno;
6589
6590 /* nothing to do if none of the attributes are present */
6591 if (!mgmt_attr && !data_attr && !ack_attr)
6592 return 0;
6593
6594 /* if one is present, all must be present */
6595 if (!mgmt_attr || !data_attr || !ack_attr) {
6596 hdd_err("Missing attribute");
6597 return -EINVAL;
6598 }
6599
6600 mgmt_snr = nla_get_u32(mgmt_attr);
6601 data_snr = nla_get_u32(data_attr);
6602 ack_snr = nla_get_u32(ack_attr);
6603 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(mgmt_snr, data_snr, ack_snr);
6604 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006605 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson1350e622018-11-16 18:36:55 -08006606 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
6607 ant_div_usrcfg, PDEV_CMD);
6608 if (errno)
6609 hdd_err("Failed to set ant div weight, %d", errno);
6610
6611 return errno;
6612}
6613
Jeff Johnson7f4fd702018-11-14 11:19:52 -08006614static int hdd_config_fine_time_measurement(struct hdd_adapter *adapter,
6615 const struct nlattr *attr)
6616{
6617 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6618 uint32_t user_capability;
6619 uint32_t target_capability;
6620 uint32_t final_capability;
6621 QDF_STATUS status;
6622
6623 user_capability = nla_get_u32(attr);
6624 target_capability = hdd_ctx->fine_time_meas_cap_target;
6625 final_capability = user_capability & target_capability;
6626
6627 status = ucfg_mlme_set_fine_time_meas_cap(hdd_ctx->psoc,
6628 final_capability);
6629 if (QDF_IS_STATUS_ERROR(status)) {
6630 hdd_err("Unable to set value, status %d", status);
6631 return -EINVAL;
6632 }
6633
6634 sme_update_fine_time_measurement_capab(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006635 adapter->vdev_id,
Jeff Johnson7f4fd702018-11-14 11:19:52 -08006636 final_capability);
6637 ucfg_wifi_pos_set_ftm_cap(hdd_ctx->psoc, final_capability);
6638
6639 hdd_debug("user: 0x%x, target: 0x%x, final: 0x%x",
6640 user_capability, target_capability, final_capability);
6641
6642 return 0;
6643}
6644
Jeff Johnsonbcaeafb2018-11-14 12:14:24 -08006645static int hdd_config_modulated_dtim(struct hdd_adapter *adapter,
6646 const struct nlattr *attr)
6647{
6648 struct wlan_objmgr_vdev *vdev;
6649 uint32_t modulated_dtim;
6650 QDF_STATUS status;
6651
6652 modulated_dtim = nla_get_u32(attr);
6653
6654 vdev = hdd_objmgr_get_vdev(adapter);
6655 if (!vdev)
6656 return -EINVAL;
6657
6658 status = ucfg_pmo_config_modulated_dtim(vdev, modulated_dtim);
6659
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05306660 hdd_objmgr_put_vdev(vdev);
Jeff Johnsonbcaeafb2018-11-14 12:14:24 -08006661
6662 return qdf_status_to_os_return(status);
6663}
6664
Jeff Johnson6db91622018-11-14 12:33:28 -08006665static int hdd_config_listen_interval(struct hdd_adapter *adapter,
6666 const struct nlattr *attr)
6667{
6668 struct wlan_objmgr_vdev *vdev;
6669 uint32_t listen_interval;
6670 QDF_STATUS status;
6671
6672 listen_interval = nla_get_u32(attr);
6673 if (listen_interval > cfg_max(CFG_PMO_ENABLE_DYNAMIC_DTIM)) {
6674 hdd_err_rl("Invalid value for listen interval - %d",
6675 listen_interval);
6676 return -EINVAL;
6677 }
6678
6679 vdev = hdd_objmgr_get_vdev(adapter);
6680 if (!vdev)
6681 return -EINVAL;
6682
6683 status = ucfg_pmo_config_listen_interval(vdev, listen_interval);
6684
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05306685 hdd_objmgr_put_vdev(vdev);
Jeff Johnson6db91622018-11-14 12:33:28 -08006686
6687 return qdf_status_to_os_return(status);
6688}
6689
Jeff Johnson9381d032018-11-14 12:42:22 -08006690static int hdd_config_lro(struct hdd_adapter *adapter,
6691 const struct nlattr *attr)
6692{
6693 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6694 uint8_t enable_flag;
6695
6696 enable_flag = nla_get_u8(attr);
6697
6698 return hdd_lro_set_reset(hdd_ctx, adapter, enable_flag);
6699}
6700
Jeff Johnson3d4f64c2018-11-14 13:13:04 -08006701static int hdd_config_scan_enable(struct hdd_adapter *adapter,
6702 const struct nlattr *attr)
6703{
6704 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6705 uint8_t enable_flag;
6706
6707 enable_flag = nla_get_u8(attr);
6708 if (enable_flag)
6709 ucfg_scan_psoc_set_enable(hdd_ctx->psoc,
6710 REASON_USER_SPACE);
6711 else
6712 ucfg_scan_psoc_set_disable(hdd_ctx->psoc,
6713 REASON_USER_SPACE);
6714
6715 return 0;
6716}
6717
Jeff Johnson1feb8a62018-11-14 13:18:41 -08006718static int hdd_config_qpower(struct hdd_adapter *adapter,
6719 const struct nlattr *attr)
6720{
6721 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6722 uint8_t qpower;
6723
6724 qpower = nla_get_u8(attr);
6725
6726 return hdd_set_qpower_config(hdd_ctx, adapter, qpower);
6727}
6728
Jeff Johnsonf15ede02018-11-14 13:27:13 -08006729static int hdd_config_stats_avg_factor(struct hdd_adapter *adapter,
6730 const struct nlattr *attr)
6731{
6732 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6733 uint16_t stats_avg_factor;
6734 QDF_STATUS status;
6735
6736 stats_avg_factor = nla_get_u16(attr);
6737 status = sme_configure_stats_avg_factor(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006738 adapter->vdev_id,
Jeff Johnsonf15ede02018-11-14 13:27:13 -08006739 stats_avg_factor);
6740
6741 return qdf_status_to_os_return(status);
6742}
6743
Jeff Johnsonf3827502018-11-14 14:00:58 -08006744static int hdd_config_non_agg_retry(struct hdd_adapter *adapter,
6745 const struct nlattr *attr)
6746{
6747 uint8_t retry;
6748 int param_id;
6749
6750 retry = nla_get_u8(attr);
6751 retry = retry > CFG_NON_AGG_RETRY_MAX ?
6752 CFG_NON_AGG_RETRY_MAX : retry;
6753 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
6754
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006755 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnsonf3827502018-11-14 14:00:58 -08006756 retry, PDEV_CMD);
6757}
6758
Jeff Johnsonb9021002018-11-15 15:51:36 -08006759static int hdd_config_agg_retry(struct hdd_adapter *adapter,
6760 const struct nlattr *attr)
6761{
6762 uint8_t retry;
6763 int param_id;
6764
6765 retry = nla_get_u8(attr);
6766 retry = retry > CFG_AGG_RETRY_MAX ?
6767 CFG_AGG_RETRY_MAX : retry;
6768
6769 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
6770 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
6771 CFG_AGG_RETRY_MIN : retry;
6772 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
6773
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006774 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnsonb9021002018-11-15 15:51:36 -08006775 retry, PDEV_CMD);
6776}
6777
Jeff Johnson0e8259c2018-11-15 19:44:57 -08006778static int hdd_config_mgmt_retry(struct hdd_adapter *adapter,
6779 const struct nlattr *attr)
6780{
6781 uint8_t retry;
6782 int param_id;
6783
6784 retry = nla_get_u8(attr);
6785 retry = retry > CFG_MGMT_RETRY_MAX ?
6786 CFG_MGMT_RETRY_MAX : retry;
6787 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
6788
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006789 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson0e8259c2018-11-15 19:44:57 -08006790 retry, PDEV_CMD);
6791}
6792
Jeff Johnson6b48a2f2018-11-15 19:48:47 -08006793static int hdd_config_ctrl_retry(struct hdd_adapter *adapter,
6794 const struct nlattr *attr)
6795{
6796 uint8_t retry;
6797 int param_id;
6798
6799 retry = nla_get_u8(attr);
6800 retry = retry > CFG_CTRL_RETRY_MAX ?
6801 CFG_CTRL_RETRY_MAX : retry;
6802 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
6803
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006804 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson6b48a2f2018-11-15 19:48:47 -08006805 retry, PDEV_CMD);
6806}
6807
Jeff Johnson98214742018-11-15 19:56:37 -08006808static int hdd_config_propagation_delay(struct hdd_adapter *adapter,
6809 const struct nlattr *attr)
6810{
6811 uint8_t delay;
6812 uint32_t abs_delay;
6813 int param_id;
6814
6815 delay = nla_get_u8(attr);
6816 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
6817 CFG_PROPAGATION_DELAY_MAX : delay;
6818 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
6819 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
6820
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006821 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson98214742018-11-15 19:56:37 -08006822 abs_delay, PDEV_CMD);
6823}
6824
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08006825static int hdd_config_propagation_abs_delay(struct hdd_adapter *adapter,
6826 const struct nlattr *attr)
6827{
6828 uint32_t abs_delay;
6829 int param_id;
6830
6831 abs_delay = nla_get_u32(attr);
6832 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
6833
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006834 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08006835 abs_delay, PDEV_CMD);
6836}
6837
Jeff Johnson7c5e6dc2018-11-15 21:20:18 -08006838static int hdd_config_tx_fail_count(struct hdd_adapter *adapter,
6839 const struct nlattr *attr)
6840{
6841 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6842 uint32_t tx_fail_count;
6843 QDF_STATUS status;
6844
6845 tx_fail_count = nla_get_u32(attr);
6846 if (!tx_fail_count)
6847 return 0;
6848
6849 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006850 adapter->vdev_id,
Jeff Johnson7c5e6dc2018-11-15 21:20:18 -08006851 tx_fail_count);
6852 if (QDF_IS_STATUS_ERROR(status))
6853 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
6854 status);
6855
6856 return qdf_status_to_os_return(status);
6857}
6858
Jeff Johnson7766fd22018-11-15 21:52:37 -08006859static int hdd_config_channel_avoidance_ind(struct hdd_adapter *adapter,
6860 const struct nlattr *attr)
6861{
6862 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6863 uint8_t set_value;
6864
6865 set_value = nla_get_u8(attr);
6866 hdd_debug("set_value: %d", set_value);
6867
6868 return hdd_enable_disable_ca_event(hdd_ctx, set_value);
6869}
6870
Jeff Johnson47e2e842018-11-14 13:49:43 -08006871static int hdd_config_guard_time(struct hdd_adapter *adapter,
6872 const struct nlattr *attr)
6873{
6874 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6875 uint32_t guard_time;
6876 QDF_STATUS status;
6877
6878 guard_time = nla_get_u32(attr);
6879 status = sme_configure_guard_time(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006880 adapter->vdev_id,
Jeff Johnson47e2e842018-11-14 13:49:43 -08006881 guard_time);
6882
6883 return qdf_status_to_os_return(status);
6884}
6885
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006886static int hdd_config_scan_default_ies(struct hdd_adapter *adapter,
6887 const struct nlattr *attr)
6888{
6889 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6890 uint8_t *scan_ie;
6891 uint16_t scan_ie_len;
6892 QDF_STATUS status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006893 mac_handle_t mac_handle;
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006894
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006895 scan_ie_len = nla_len(attr);
6896 hdd_debug("IE len %d session %d device mode %d",
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006897 scan_ie_len, adapter->vdev_id, adapter->device_mode);
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006898
6899 if (!scan_ie_len) {
6900 hdd_err("zero-length IE prohibited");
6901 return -EINVAL;
6902 }
6903
6904 if (scan_ie_len > MAX_DEFAULT_SCAN_IE_LEN) {
6905 hdd_err("IE length %d exceeds max of %d",
6906 scan_ie_len, MAX_DEFAULT_SCAN_IE_LEN);
6907 return -EINVAL;
6908 }
6909
6910 scan_ie = nla_data(attr);
Jeff Johnson4933c3a2018-01-10 19:33:33 -08006911 if (!wlan_is_ie_valid(scan_ie, scan_ie_len)) {
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006912 hdd_err("Invalid default scan IEs");
6913 return -EINVAL;
6914 }
6915
6916 if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
6917 scan_ie, scan_ie_len))
6918 hdd_err("Failed to save default scan IEs");
6919
6920 if (adapter->device_mode == QDF_STA_MODE) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006921 mac_handle = hdd_ctx->mac_handle;
6922 status = sme_set_default_scan_ie(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006923 adapter->vdev_id, scan_ie,
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006924 scan_ie_len);
6925 if (QDF_STATUS_SUCCESS != status) {
6926 hdd_err("failed to set default scan IEs in sme: %d",
6927 status);
6928 return -EPERM;
6929 }
6930 }
6931
6932 return 0;
6933}
6934
Jeff Johnsonf9871e42018-11-15 22:24:06 -08006935static int hdd_config_ant_div_ena(struct hdd_adapter *adapter,
6936 const struct nlattr *attr)
6937{
6938 uint32_t antdiv_enable;
6939 int errno;
6940
6941 antdiv_enable = nla_get_u32(attr);
6942 hdd_debug("antdiv_enable: %d", antdiv_enable);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006943 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonf9871e42018-11-15 22:24:06 -08006944 WMI_PDEV_PARAM_ENA_ANT_DIV,
6945 antdiv_enable, PDEV_CMD);
6946 if (errno)
6947 hdd_err("Failed to set antdiv_enable, %d", errno);
6948
6949 return errno;
6950}
6951
Jeff Johnson91f90ff2018-11-16 07:53:37 -08006952static int hdd_config_ant_div_snr_diff(struct hdd_adapter *adapter,
6953 const struct nlattr *attr)
6954{
6955 uint32_t ant_div_snr_diff;
6956 uint32_t ant_div_usrcfg;
6957 int errno;
6958
6959 ant_div_snr_diff = nla_get_u32(attr);
6960 hdd_debug("snr diff: %x", ant_div_snr_diff);
6961
6962 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(ant_div_snr_diff);
6963 hdd_debug("usrcfg: %x", ant_div_usrcfg);
6964
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006965 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson91f90ff2018-11-16 07:53:37 -08006966 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
6967 ant_div_usrcfg, PDEV_CMD);
6968 if (errno)
6969 hdd_err("Failed to set snr diff, %d", errno);
6970
6971 return errno;
6972}
6973
Jeff Johnson77177bc2018-11-16 08:14:20 -08006974static int hdd_config_ant_div_probe_dwell_time(struct hdd_adapter *adapter,
6975 const struct nlattr *attr)
6976{
6977 uint32_t dwell_time;
6978 uint32_t ant_div_usrcfg;
6979 int errno;
6980
6981 dwell_time = nla_get_u32(attr);
6982 hdd_debug("dwell time: %x", dwell_time);
6983
6984 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(dwell_time);
6985 hdd_debug("usrcfg: %x", ant_div_usrcfg);
6986
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006987 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson77177bc2018-11-16 08:14:20 -08006988 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
6989 ant_div_usrcfg, PDEV_CMD);
6990 if (errno)
6991 hdd_err("Failed to set probe dwell time, %d", errno);
6992
6993 return errno;
6994}
6995
Jeff Johnsonaa172222018-11-16 09:16:11 -08006996static int hdd_config_ant_div_chain(struct hdd_adapter *adapter,
6997 const struct nlattr *attr)
6998{
6999 uint32_t antdiv_chain;
7000 int errno;
7001
7002 antdiv_chain = nla_get_u32(attr);
7003 hdd_debug("antdiv_chain: %d", antdiv_chain);
7004
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007005 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonaa172222018-11-16 09:16:11 -08007006 WMI_PDEV_PARAM_FORCE_CHAIN_ANT,
7007 antdiv_chain, PDEV_CMD);
7008 if (errno)
7009 hdd_err("Failed to set chain, %d", errno);
7010
7011 return errno;
7012}
7013
Jeff Johnsonef427ad2018-11-16 09:22:17 -08007014static int hdd_config_ant_div_selftest(struct hdd_adapter *adapter,
7015 const struct nlattr *attr)
7016{
7017 uint32_t antdiv_selftest;
7018 int errno;
7019
7020 antdiv_selftest = nla_get_u32(attr);
7021 hdd_debug("antdiv_selftest: %d", antdiv_selftest);
7022
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007023 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonef427ad2018-11-16 09:22:17 -08007024 WMI_PDEV_PARAM_ANT_DIV_SELFTEST,
7025 antdiv_selftest, PDEV_CMD);
7026 if (errno)
7027 hdd_err("Failed to set selftest, %d", errno);
7028
7029 return errno;
7030}
7031
Jeff Johnsonae21be82018-11-16 09:43:53 -08007032static int hdd_config_ant_div_selftest_intvl(struct hdd_adapter *adapter,
7033 const struct nlattr *attr)
7034{
7035 uint32_t antdiv_selftest_intvl;
7036 int errno;
7037
7038 antdiv_selftest_intvl = nla_get_u32(attr);
7039 hdd_debug("antdiv_selftest_intvl: %d", antdiv_selftest_intvl);
7040
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007041 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonae21be82018-11-16 09:43:53 -08007042 WMI_PDEV_PARAM_ANT_DIV_SELFTEST_INTVL,
7043 antdiv_selftest_intvl, PDEV_CMD);
7044 if (errno)
7045 hdd_err("Failed to set selftest interval, %d", errno);
7046
7047 return errno;
7048}
7049
Jeff Johnson3a25de82018-11-16 07:26:46 -08007050static int hdd_config_ignore_assoc_disallowed(struct hdd_adapter *adapter,
7051 const struct nlattr *attr)
7052{
7053 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7054 uint8_t ignore_assoc_disallowed;
7055
7056 ignore_assoc_disallowed = nla_get_u8(attr);
7057 hdd_debug("%u", ignore_assoc_disallowed);
7058 if ((ignore_assoc_disallowed < QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
7059 (ignore_assoc_disallowed > QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
7060 return -EINVAL;
7061
7062 sme_update_session_param(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007063 adapter->vdev_id,
Jeff Johnson3a25de82018-11-16 07:26:46 -08007064 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
7065 ignore_assoc_disallowed);
7066
7067 return 0;
7068}
7069
Jeff Johnson72dc91e2018-11-16 08:46:12 -08007070static int hdd_config_restrict_offchannel(struct hdd_adapter *adapter,
7071 const struct nlattr *attr)
7072{
7073 uint8_t restrict_offchan;
7074
7075 restrict_offchan = nla_get_u8(attr);
7076 hdd_debug("%u", restrict_offchan);
7077
7078 if (restrict_offchan > 1) {
7079 hdd_err("Invalid value %u", restrict_offchan);
7080 return -EINVAL;
7081 }
7082
7083 return wlan_hdd_handle_restrict_offchan_config(adapter,
7084 restrict_offchan);
7085}
7086
Jeff Johnson320feeb2018-11-16 10:14:24 -08007087static int hdd_config_total_beacon_miss_count(struct hdd_adapter *adapter,
7088 const struct nlattr *attr)
7089{
7090 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7091 uint8_t first_miss_count;
7092 uint8_t final_miss_count;
7093 uint8_t total_miss_count;
7094 QDF_STATUS status;
7095
7096 total_miss_count = nla_get_u8(attr);
7097 ucfg_mlme_get_roam_bmiss_first_bcnt(hdd_ctx->psoc,
7098 &first_miss_count);
7099 if (total_miss_count <= first_miss_count) {
7100 hdd_err("Total %u needs to exceed first %u",
7101 total_miss_count, first_miss_count);
7102 return -EINVAL;
7103 }
7104
7105 final_miss_count = total_miss_count - first_miss_count;
7106
7107 hdd_debug("First count %u, final count %u",
7108 first_miss_count, final_miss_count);
7109
7110 /*****
Jeff Johnson55d2ab42019-03-06 11:43:49 -08007111 * TODO: research why is 0 being passed for vdev id???
Jeff Johnson320feeb2018-11-16 10:14:24 -08007112 */
7113 status = sme_set_roam_bmiss_final_bcnt(hdd_ctx->mac_handle,
7114 0,
7115 final_miss_count);
7116 if (QDF_IS_STATUS_ERROR(status)) {
7117 hdd_err("Failed to set final count, status %u", status);
7118 return qdf_status_to_os_return(status);
7119 }
7120
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007121 status = sme_set_bmiss_bcnt(adapter->vdev_id,
Jeff Johnson320feeb2018-11-16 10:14:24 -08007122 first_miss_count,
7123 final_miss_count);
7124 if (QDF_IS_STATUS_ERROR(status))
7125 hdd_err("Failed to set count, status %u", status);
7126
7127 return qdf_status_to_os_return(status);
7128}
7129
Jeff Johnson2502ddd2018-11-16 10:59:30 -08007130static int hdd_config_latency_level(struct hdd_adapter *adapter,
7131 const struct nlattr *attr)
7132{
7133 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7134 uint16_t latency_level;
7135 QDF_STATUS status;
7136
7137 latency_level = nla_get_u16(attr);
7138 switch (latency_level) {
7139 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL:
7140 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE:
7141 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW:
7142 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW:
7143 /* valid values */
7144 break;
7145 default:
7146 hdd_err("Invalid value %u", latency_level);
7147 return -EINVAL;
7148 }
7149
7150 /* Map the latency value to the level which fw expected
7151 * 0 - normal, 1 - moderate, 2 - low, 3 - ultralow
7152 */
7153 latency_level = latency_level - 1;
7154 status = sme_set_wlm_latency_level(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007155 adapter->vdev_id,
Jeff Johnson2502ddd2018-11-16 10:59:30 -08007156 latency_level);
7157 if (QDF_IS_STATUS_ERROR(status))
7158 hdd_err("set latency level failed, %u", status);
7159
7160 return qdf_status_to_os_return(status);
7161}
7162
Jeff Johnson0a315912018-11-16 11:18:21 -08007163static int hdd_config_disable_fils(struct hdd_adapter *adapter,
7164 const struct nlattr *attr)
7165{
7166 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7167 uint8_t disable_fils;
7168 bool enabled;
7169 QDF_STATUS status;
7170
7171 /* ignore unless in STA mode */
7172 if (adapter->device_mode != QDF_STA_MODE)
7173 return 0;
7174
7175 disable_fils = nla_get_u8(attr);
7176 hdd_debug("%u", disable_fils);
7177
7178 enabled = !disable_fils;
7179 status = ucfg_mlme_set_fils_enabled_info(hdd_ctx->psoc, enabled);
7180 if (QDF_IS_STATUS_ERROR(status))
7181 hdd_err("could not set fils enabled info, %d", status);
7182
7183 status = ucfg_mlme_set_enable_bcast_probe_rsp(hdd_ctx->psoc, enabled);
7184 if (QDF_IS_STATUS_ERROR(status))
7185 hdd_err("could not set enable bcast probe resp info, %d",
7186 status);
7187
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007188 status = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson0a315912018-11-16 11:18:21 -08007189 WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE,
7190 !disable_fils, VDEV_CMD);
7191 if (QDF_IS_STATUS_ERROR(status))
7192 hdd_err("failed to set enable bcast probe resp, %d",
7193 status);
7194
7195 return qdf_status_to_os_return(status);
7196}
7197
Jeff Johnson0bdbb962018-11-16 11:42:10 -08007198static int hdd_config_rsn_ie(struct hdd_adapter *adapter,
7199 const struct nlattr *attr)
7200{
7201 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7202 bool override_enabled;
7203 uint8_t force_rsne_override;
7204
7205 /* ignore unless support explicitly enabled */
7206 ucfg_mlme_get_force_rsne_override(hdd_ctx->psoc, &override_enabled);
7207 if (!override_enabled)
7208 return 0;
7209
7210 force_rsne_override = nla_get_u8(attr);
7211 if (force_rsne_override > 1) {
7212 hdd_err("Invalid value %d", force_rsne_override);
7213 return -EINVAL;
7214 }
7215
7216 hdd_ctx->force_rsne_override = force_rsne_override;
7217 hdd_debug("force_rsne_override - %d", force_rsne_override);
7218
7219 return 0;
7220}
7221
Jeff Johnson7acca0d2018-11-16 11:53:18 -08007222static int hdd_config_gtx(struct hdd_adapter *adapter,
7223 const struct nlattr *attr)
7224{
7225 uint8_t config_gtx;
7226 int errno;
7227
7228 config_gtx = nla_get_u8(attr);
7229 if (config_gtx > 1) {
7230 hdd_err_rl("Invalid config_gtx value %d", config_gtx);
7231 return -EINVAL;
7232 }
7233
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007234 errno = sme_cli_set_command(adapter->vdev_id,
Jeff Johnson7acca0d2018-11-16 11:53:18 -08007235 WMI_VDEV_PARAM_GTX_ENABLE,
7236 config_gtx, VDEV_CMD);
7237 if (errno)
7238 hdd_err("Failed to set GTX, %d", errno);
7239
7240 return errno;
7241}
7242
lifeng66831662017-05-19 16:01:35 +08007243/**
Srinivas Dasari37e37312019-06-30 23:50:24 +05307244 * hdd_config_disconnect_ies() - Configure disconnect IEs
7245 * @adapter: Pointer to HDD adapter
7246 * @attr: array of pointer to struct nlattr
7247 *
7248 * Return: 0 on success; error number otherwise
7249 */
7250static int hdd_config_disconnect_ies(struct hdd_adapter *adapter,
7251 const struct nlattr *attr)
7252{
7253 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7254 QDF_STATUS status;
7255
7256 hdd_debug("IE len %u session %u device mode %u",
7257 nla_len(attr), adapter->vdev_id, adapter->device_mode);
7258 if (!nla_len(attr) ||
7259 nla_len(attr) > SIR_MAC_MAX_ADD_IE_LENGTH + 2 ||
7260 !wlan_is_ie_valid(nla_data(attr), nla_len(attr))) {
7261 hdd_err("Invalid disconnect IEs");
7262 return -EINVAL;
7263 }
7264
7265 status = sme_set_disconnect_ies(hdd_ctx->mac_handle,
7266 adapter->vdev_id,
7267 nla_data(attr),
7268 nla_len(attr));
7269 if (QDF_IS_STATUS_ERROR(status))
7270 hdd_err("Failed to set disconnect_ies");
7271
7272 return qdf_status_to_os_return(status);
7273}
7274
Paul Zhangc9dbaee2019-06-23 22:07:31 +08007275#ifdef WLAN_FEATURE_ELNA
7276/**
7277 * hdd_set_elna_bypass() - Set eLNA bypass
7278 * @adapter: Pointer to HDD adapter
7279 * @attr: Pointer to struct nlattr
7280 *
7281 * Return: 0 on success; error number otherwise
7282 */
7283static int hdd_set_elna_bypass(struct hdd_adapter *adapter,
7284 const struct nlattr *attr)
7285{
7286 int ret;
7287 struct wlan_objmgr_vdev *vdev;
7288
7289 vdev = hdd_objmgr_get_vdev(adapter);
7290 if (!vdev)
7291 return -EINVAL;
7292
7293 ret = os_if_fwol_set_elna_bypass(vdev, attr);
7294
7295 hdd_objmgr_put_vdev(vdev);
7296
7297 return ret;
7298}
7299#endif
7300
Srinivas Dasari37e37312019-06-30 23:50:24 +05307301/**
Jeff Johnsonb48efe22018-11-15 11:53:09 -08007302 * typedef independent_setter_fn - independent attribute handler
7303 * @adapter: The adapter being configured
7304 * @attr: The nl80211 attribute being applied
7305 *
7306 * Defines the signature of functions in the independent attribute vtable
7307 *
7308 * Return: 0 if the attribute was handled successfully, otherwise an errno
7309 */
7310typedef int (*independent_setter_fn)(struct hdd_adapter *adapter,
7311 const struct nlattr *attr);
7312
7313/**
7314 * struct independent_setters
7315 * @id: vendor attribute which this entry handles
7316 * @cb: callback function to invoke to process the attribute when present
7317 */
7318struct independent_setters {
7319 uint32_t id;
7320 independent_setter_fn cb;
7321};
7322
7323/* vtable for independent setters */
7324static const struct independent_setters independent_setters[] = {
Jeff Johnson522464b2018-11-15 13:07:26 -08007325 {QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES,
7326 hdd_config_scan_default_ies},
Jeff Johnson7f4fd702018-11-14 11:19:52 -08007327 {QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT,
7328 hdd_config_fine_time_measurement},
Jeff Johnsonbcaeafb2018-11-14 12:14:24 -08007329 {QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM,
7330 hdd_config_modulated_dtim},
Jeff Johnson6db91622018-11-14 12:33:28 -08007331 {QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL,
7332 hdd_config_listen_interval},
Jeff Johnson9381d032018-11-14 12:42:22 -08007333 {QCA_WLAN_VENDOR_ATTR_CONFIG_LRO,
7334 hdd_config_lro},
Jeff Johnson3d4f64c2018-11-14 13:13:04 -08007335 {QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE,
7336 hdd_config_scan_enable},
Jeff Johnson1feb8a62018-11-14 13:18:41 -08007337 {QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER,
7338 hdd_config_qpower},
Jeff Johnsonf15ede02018-11-14 13:27:13 -08007339 {QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR,
7340 hdd_config_stats_avg_factor},
Jeff Johnson47e2e842018-11-14 13:49:43 -08007341 {QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME,
7342 hdd_config_guard_time},
Jeff Johnsonf3827502018-11-14 14:00:58 -08007343 {QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY,
7344 hdd_config_non_agg_retry},
Jeff Johnsonb9021002018-11-15 15:51:36 -08007345 {QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY,
7346 hdd_config_agg_retry},
Jeff Johnson0e8259c2018-11-15 19:44:57 -08007347 {QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY,
7348 hdd_config_mgmt_retry},
Jeff Johnson6b48a2f2018-11-15 19:48:47 -08007349 {QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY,
7350 hdd_config_ctrl_retry},
Jeff Johnson98214742018-11-15 19:56:37 -08007351 {QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY,
7352 hdd_config_propagation_delay},
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08007353 {QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY,
7354 hdd_config_propagation_abs_delay},
Jeff Johnson7c5e6dc2018-11-15 21:20:18 -08007355 {QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT,
7356 hdd_config_tx_fail_count},
Jeff Johnson7766fd22018-11-15 21:52:37 -08007357 {QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND,
7358 hdd_config_channel_avoidance_ind},
Jeff Johnsonf9871e42018-11-15 22:24:06 -08007359 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA,
7360 hdd_config_ant_div_ena},
Jeff Johnson91f90ff2018-11-16 07:53:37 -08007361 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF,
7362 hdd_config_ant_div_snr_diff},
Jeff Johnson77177bc2018-11-16 08:14:20 -08007363 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME,
7364 hdd_config_ant_div_probe_dwell_time},
Jeff Johnsonaa172222018-11-16 09:16:11 -08007365 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN,
7366 hdd_config_ant_div_chain},
Jeff Johnsonef427ad2018-11-16 09:22:17 -08007367 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST,
7368 hdd_config_ant_div_selftest},
Jeff Johnsonae21be82018-11-16 09:43:53 -08007369 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL,
7370 hdd_config_ant_div_selftest_intvl},
Jeff Johnson3a25de82018-11-16 07:26:46 -08007371 {QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED,
7372 hdd_config_ignore_assoc_disallowed},
Jeff Johnson72dc91e2018-11-16 08:46:12 -08007373 {QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL,
7374 hdd_config_restrict_offchannel},
Jeff Johnson320feeb2018-11-16 10:14:24 -08007375 {QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT,
7376 hdd_config_total_beacon_miss_count},
Jeff Johnson2502ddd2018-11-16 10:59:30 -08007377 {QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL,
7378 hdd_config_latency_level},
Jeff Johnson0a315912018-11-16 11:18:21 -08007379 {QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS,
7380 hdd_config_disable_fils},
Jeff Johnson0bdbb962018-11-16 11:42:10 -08007381 {QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE,
7382 hdd_config_rsn_ie},
Jeff Johnson7acca0d2018-11-16 11:53:18 -08007383 {QCA_WLAN_VENDOR_ATTR_CONFIG_GTX,
7384 hdd_config_gtx},
Srinivas Dasari37e37312019-06-30 23:50:24 +05307385 {QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES,
7386 hdd_config_disconnect_ies},
Paul Zhangc9dbaee2019-06-23 22:07:31 +08007387#ifdef WLAN_FEATURE_ELNA
7388 {QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
7389 hdd_set_elna_bypass},
7390#endif
Jeff Johnsonb48efe22018-11-15 11:53:09 -08007391};
7392
Paul Zhangc9dbaee2019-06-23 22:07:31 +08007393#ifdef WLAN_FEATURE_ELNA
7394/**
7395 * hdd_get_elna_bypass() - Get eLNA bypass
7396 * @adapter: Pointer to HDD adapter
7397 * @skb: sk buffer to hold nl80211 attributes
7398 * @attr: Pointer to struct nlattr
7399 *
7400 * Return: 0 on success; error number otherwise
7401 */
7402static int hdd_get_elna_bypass(struct hdd_adapter *adapter,
7403 struct sk_buff *skb,
7404 const struct nlattr *attr)
7405{
7406 int ret;
7407 struct wlan_objmgr_vdev *vdev;
7408
7409 vdev = hdd_objmgr_get_vdev(adapter);
7410 if (!vdev)
7411 return -EINVAL;
7412
7413 ret = os_if_fwol_get_elna_bypass(vdev, skb, attr);
7414
7415 hdd_objmgr_put_vdev(vdev);
7416
7417 return ret;
7418}
7419#endif
7420
7421/**
7422 * typedef config_getter_fn - get configuration handler
7423 * @adapter: The adapter being configured
7424 * @skb: sk buffer to hold nl80211 attributes
7425 * @attr: The nl80211 attribute being applied
7426 *
7427 * Defines the signature of functions in the attribute vtable
7428 *
7429 * Return: 0 if the attribute was handled successfully, otherwise an errno
7430 */
7431typedef int (*config_getter_fn)(struct hdd_adapter *adapter,
7432 struct sk_buff *skb,
7433 const struct nlattr *attr);
7434
7435/**
7436 * struct config_getters
7437 * @id: vendor attribute which this entry handles
7438 * @cb: callback function to invoke to process the attribute when present
7439 */
7440struct config_getters {
7441 uint32_t id;
7442 size_t max_attr_len;
7443 config_getter_fn cb;
7444};
7445
7446/* vtable for config getters */
7447static const struct config_getters config_getters[] = {
7448#ifdef WLAN_FEATURE_ELNA
7449 {QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
7450 sizeof(uint8_t),
7451 hdd_get_elna_bypass},
7452#endif
7453};
7454
7455/**
7456 * hdd_get_configuration() - Handle get configuration
7457 * @adapter: adapter upon which the vendor command was received
7458 * @tb: parsed attribute array
7459 *
7460 * This is a table-driven function which dispatches attributes
7461 * in a QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION
7462 * vendor command.
7463 *
7464 * Return: 0 if there were no issues, otherwise errno of the last issue
7465 */
7466static int hdd_get_configuration(struct hdd_adapter *adapter,
7467 struct nlattr **tb)
7468{
7469 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7470 uint32_t i, id;
7471 unsigned long nl_buf_len = NLMSG_HDRLEN;
7472 struct sk_buff *skb;
7473 struct nlattr *attr;
7474 config_getter_fn cb;
7475 int errno = 0;
7476
7477 for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
7478 id = config_getters[i].id;
7479 attr = tb[id];
7480 if (!attr)
7481 continue;
7482
7483 nl_buf_len += NLA_HDRLEN +
7484 NLA_ALIGN(config_getters[i].max_attr_len);
7485 }
7486
7487 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7488 if (!skb) {
7489 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7490 return -ENOMEM;
7491 }
7492
7493 for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
7494 id = config_getters[i].id;
7495 attr = tb[id];
7496 if (!attr)
7497 continue;
7498
7499 cb = config_getters[i].cb;
7500 errno = cb(adapter, skb, attr);
7501 if (errno)
7502 break;
7503 }
7504
7505 if (errno) {
7506 hdd_err("Failed to get wifi configuration, errno = %d", errno);
7507 kfree_skb(skb);
7508 return -EINVAL;
7509 }
7510
7511 cfg80211_vendor_cmd_reply(skb);
7512
7513 return errno;
7514}
7515
Jeff Johnsonb48efe22018-11-15 11:53:09 -08007516/**
7517 * hdd_set_independent_configuration() - Handle independent attributes
7518 * @adapter: adapter upon which the vendor command was received
7519 * @tb: parsed attribute array
7520 *
7521 * This is a table-driven function which dispatches independent
7522 * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
7523 * vendor command. An attribute is considered independent if it
7524 * doesn't depend upon any other attributes
7525 *
7526 * Return: 0 if there were no issues, otherwise errno of the last issue
7527 */
7528static int hdd_set_independent_configuration(struct hdd_adapter *adapter,
7529 struct nlattr **tb)
7530{
7531 uint32_t i;
7532 uint32_t id;
7533 struct nlattr *attr;
7534 independent_setter_fn cb;
7535 int errno = 0;
7536 int ret;
7537
7538 for (i = 0; i < QDF_ARRAY_SIZE(independent_setters); i++) {
7539 id = independent_setters[i].id;
7540 attr = tb[id];
7541 if (!attr)
7542 continue;
7543
7544 cb = independent_setters[i].cb;
7545 ret = cb(adapter, attr);
7546 if (ret)
7547 errno = ret;
7548 }
7549
7550 return errno;
7551}
7552
7553/**
7554 * typedef interdependent_setter_fn - interdependent attribute handler
7555 * @adapter: The adapter being configured
7556 * @tb: The parsed nl80211 attributes being applied
7557 *
7558 * Defines the signature of functions in the interdependent attribute vtable
7559 *
7560 * Return: 0 if attributes were handled successfully, otherwise an errno
7561 */
7562typedef int (*interdependent_setter_fn)(struct hdd_adapter *adapter,
7563 struct nlattr **tb);
7564
7565/* vtable for interdependent setters */
7566static const interdependent_setter_fn interdependent_setters[] = {
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08007567 hdd_config_access_policy,
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08007568 hdd_config_mpdu_aggregation,
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08007569 hdd_config_ant_div_period,
Jeff Johnson1350e622018-11-16 18:36:55 -08007570 hdd_config_ant_div_snr_weight,
Jeff Johnson0dd687e2018-11-16 20:11:27 -08007571 wlan_hdd_cfg80211_wifi_set_reorder_timeout,
Jeff Johnson339ede82018-11-16 20:27:52 -08007572 wlan_hdd_cfg80211_wifi_set_rx_blocksize,
Jeff Johnsonb48efe22018-11-15 11:53:09 -08007573};
7574
7575/**
7576 * hdd_set_interdependent_configuration() - Handle interdependent attributes
7577 * @adapter: adapter upon which the vendor command was received
7578 * @tb: parsed attribute array
7579 *
7580 * This is a table-driven function which handles interdependent
7581 * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
7582 * vendor command. A set of attributes is considered interdependent if
7583 * they depend upon each other. In the typical case if one of the
7584 * attributes is present in the the attribute array, then all of the
7585 * attributes must be present.
7586 *
7587 * Return: 0 if there were no issues, otherwise errno of the last issue
7588 */
7589static int hdd_set_interdependent_configuration(struct hdd_adapter *adapter,
7590 struct nlattr **tb)
7591{
7592 uint32_t i;
7593 interdependent_setter_fn cb;
7594 int errno = 0;
7595 int ret;
7596
7597 for (i = 0; i < QDF_ARRAY_SIZE(interdependent_setters); i++) {
7598 cb = interdependent_setters[i];
7599 ret = cb(adapter, tb);
7600 if (ret)
7601 errno = ret;
7602 }
7603
7604 return errno;
7605}
7606
7607/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007608 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
7609 * vendor command
7610 *
7611 * @wiphy: wiphy device pointer
7612 * @wdev: wireless device pointer
7613 * @data: Vendor command data buffer
7614 * @data_len: Buffer length
7615 *
7616 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
7617 *
7618 * Return: Error code.
7619 */
7620static int
7621__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
7622 struct wireless_dev *wdev,
7623 const void *data,
7624 int data_len)
7625{
7626 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07007627 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007628 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007629 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
Jeff Johnsonb48efe22018-11-15 11:53:09 -08007630 int errno;
Jeff Johnson3b2abe92017-12-15 09:03:47 -08007631 int ret;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05307632
Dustin Brownfdf17c12018-03-14 12:55:34 -07007633 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08007634
Anurag Chouhan6d760662016-02-20 16:05:43 +05307635 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007636 hdd_err("Command not allowed in FTM mode");
7637 return -EPERM;
7638 }
7639
Jeff Johnsonb48efe22018-11-15 11:53:09 -08007640 errno = wlan_hdd_validate_context(hdd_ctx);
7641 if (errno)
7642 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007643
Dustin Brown4ea21db2018-01-05 14:13:17 -08007644 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
7645 data_len, wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007646 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007647 return -EINVAL;
7648 }
7649
Jeff Johnsonb48efe22018-11-15 11:53:09 -08007650 ret = hdd_set_independent_configuration(adapter, tb);
7651 if (ret)
7652 errno = ret;
7653
7654 ret = hdd_set_interdependent_configuration(adapter, tb);
7655 if (ret)
7656 errno = ret;
7657
Jeff Johnsonb48efe22018-11-15 11:53:09 -08007658 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007659}
7660
7661/**
7662 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
7663 * vendor command
7664 *
7665 * @wiphy: wiphy device pointer
7666 * @wdev: wireless device pointer
7667 * @data: Vendor command data buffer
7668 * @data_len: Buffer length
7669 *
7670 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
7671 *
7672 * Return: EOK or other error codes.
7673 */
7674static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
7675 struct wireless_dev *wdev,
7676 const void *data,
7677 int data_len)
7678{
Dustin Browna09acf42018-11-08 12:32:26 +05307679 int errno;
7680 struct osif_vdev_sync *vdev_sync;
7681
7682 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7683 if (errno)
7684 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007685
Dustin Browna09acf42018-11-08 12:32:26 +05307686 errno = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
7687 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007688
Dustin Browna09acf42018-11-08 12:32:26 +05307689 osif_vdev_sync_op_stop(vdev_sync);
7690
7691 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007692}
7693
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007694/**
Paul Zhangc9dbaee2019-06-23 22:07:31 +08007695 * __wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
7696 * vendor command
7697 * @wiphy: wiphy device pointer
7698 * @wdev: wireless device pointer
7699 * @data: Vendor command data buffer
7700 * @data_len: Buffer length
7701 *
7702 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
7703 *
7704 * Return: Error code.
7705 */
7706static int
7707__wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
7708 struct wireless_dev *wdev,
7709 const void *data,
7710 int data_len)
7711{
7712 struct net_device *dev = wdev->netdev;
7713 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7714 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
7715 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
7716 int errno;
7717 int ret;
7718
7719 hdd_enter_dev(dev);
7720
7721 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7722 hdd_err("Command not allowed in FTM mode");
7723 return -EPERM;
7724 }
7725
7726 errno = wlan_hdd_validate_context(hdd_ctx);
7727 if (errno)
7728 return errno;
7729
7730 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
7731 data_len, wlan_hdd_wifi_config_policy)) {
7732 hdd_err("invalid attr");
7733 return -EINVAL;
7734 }
7735
7736 ret = hdd_get_configuration(adapter, tb);
7737 if (ret)
7738 errno = ret;
7739
7740 return errno;
7741}
7742
7743/**
7744 * wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
7745 * vendor command
7746 *
7747 * @wiphy: wiphy device pointer
7748 * @wdev: wireless device pointer
7749 * @data: Vendor command data buffer
7750 * @data_len: Buffer length
7751 *
7752 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
7753 *
7754 * Return: EOK or other error codes.
7755 */
7756static int wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
7757 struct wireless_dev *wdev,
7758 const void *data,
7759 int data_len)
7760{
7761 int errno;
7762 struct osif_vdev_sync *vdev_sync;
7763
7764 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7765 if (errno)
7766 return errno;
7767
7768 errno = __wlan_hdd_cfg80211_wifi_configuration_get(wiphy, wdev,
7769 data, data_len);
7770
7771 osif_vdev_sync_op_stop(vdev_sync);
7772
7773 return errno;
7774}
7775
7776/**
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007777 * __wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
7778 * vendor command
7779 *
7780 * @wiphy: wiphy device pointer
7781 * @wdev: wireless device pointer
7782 * @data: Vendor command data buffer
7783 * @data_len: Buffer length
7784 *
7785 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
7786 *
7787 * Return: Error code.
7788 */
7789static int
7790__wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
Srinivas Girigowdaa19eafd2018-09-07 15:28:21 -07007791 struct wireless_dev *wdev, const void *data, int data_len)
7792{
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007793 struct net_device *dev = wdev->netdev;
7794 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7795 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
7796 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1];
7797 int ret_val = 0;
7798 uint8_t cfg_val = 0;
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08007799 uint8_t set_val = 0;
Jeff Johnson46b4f0e2019-03-08 10:48:35 -08007800 struct sme_config_params *sme_config;
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007801 bool update_sme_cfg = false;
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08007802 uint8_t tid = 0, ac;
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007803 uint16_t buff_size = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007804 mac_handle_t mac_handle;
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05307805 QDF_STATUS status;
7806 bool bval = false;
7807 uint8_t value = 0;
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +05307808 uint8_t wmm_mode = 0;
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07007809 uint32_t cmd_id;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007810
Dustin Brownfdf17c12018-03-14 12:55:34 -07007811 hdd_enter_dev(dev);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007812
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007813 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Min Liu74a1a502018-10-10 19:59:07 +08007814 if (!sme_config)
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007815 return -ENOMEM;
Min Liu74a1a502018-10-10 19:59:07 +08007816
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007817 mac_handle = hdd_ctx->mac_handle;
7818 sme_get_config_param(mac_handle, sme_config);
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007819
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007820 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7821 hdd_err("Command not allowed in FTM mode");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007822 ret_val = -EPERM;
7823 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007824 }
7825
7826 ret_val = wlan_hdd_validate_context(hdd_ctx);
7827 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007828 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007829
7830 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
7831 hdd_err("Driver Modules are closed, can not start logger");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007832 ret_val = -EINVAL;
7833 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007834 }
7835
7836 if (wlan_cfg80211_nla_parse(tb,
7837 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX,
7838 data, data_len, wlan_hdd_wifi_test_config_policy)) {
7839 hdd_err("invalid attr");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007840 ret_val = -EINVAL;
7841 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007842 }
7843
7844 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]) {
7845 cfg_val = nla_get_u8(tb[
7846 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]
7847 );
7848 hdd_debug("set addba accept req from peer value %d", cfg_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007849 ret_val = sme_set_addba_accept(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007850 cfg_val);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007851 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007852 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007853 }
7854
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08007855 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]) {
7856 cfg_val = nla_get_u8(tb[
7857 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]);
7858 hdd_debug("set HE MCS value 0x%0X", cfg_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007859 ret_val = sme_update_he_mcs(mac_handle, adapter->vdev_id,
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08007860 cfg_val);
7861 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007862 goto send_err;
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08007863 }
7864
Krunal Soni707eb782018-01-18 12:04:19 -08007865 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]) {
7866 cfg_val = nla_get_u8(tb[
7867 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]);
Krunal Soni707eb782018-01-18 12:04:19 -08007868 if (!cfg_val) {
Jeff Johnsone94ccd02019-04-02 15:02:56 -07007869 sme_config->csr_config.WMMSupportMode =
Krunal Soni707eb782018-01-18 12:04:19 -08007870 hdd_to_csr_wmm_mode(HDD_WMM_USER_MODE_NO_QOS);
7871 hdd_debug("wmm is disabled");
7872 } else {
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +05307873 status = ucfg_mlme_get_wmm_mode(hdd_ctx->psoc,
7874 &wmm_mode);
7875 if (!QDF_IS_STATUS_SUCCESS(status)) {
7876 hdd_err("Get wmm_mode failed");
7877 return QDF_STATUS_E_FAILURE;
7878 }
Jeff Johnsone94ccd02019-04-02 15:02:56 -07007879 sme_config->csr_config.WMMSupportMode =
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +05307880 hdd_to_csr_wmm_mode(wmm_mode);
Krunal Soni707eb782018-01-18 12:04:19 -08007881 hdd_debug("using wmm default value");
7882 }
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007883 update_sme_cfg = true;
Krunal Soni707eb782018-01-18 12:04:19 -08007884 }
7885
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08007886 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]) {
7887 cfg_val = nla_get_u8(tb[
7888 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]);
7889 if (cfg_val) {
7890 /*Auto BA mode*/
7891 set_val = 0;
7892 hdd_debug("BA operating mode is set to auto");
7893 } else {
7894 /*Manual BA mode*/
7895 set_val = 1;
7896 hdd_debug("BA operating mode is set to Manual");
7897 }
7898
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007899 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08007900 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
Kiran Kumar Lokere015f77f2018-04-24 18:25:28 -07007901 if (ret_val) {
7902 hdd_err("Set BA operating mode failed");
7903 goto send_err;
7904 }
7905 if (!cfg_val) {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007906 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere015f77f2018-04-24 18:25:28 -07007907 WMI_VDEV_PARAM_AMSDU_AGGREGATION_SIZE_OPTIMIZATION,
7908 0, VDEV_CMD);
7909 }
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08007910 }
7911
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08007912 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]) {
7913 cfg_val = nla_get_u8(tb[
7914 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]
7915 );
7916 if (cfg_val > HE_FRAG_LEVEL1)
7917 set_val = HE_FRAG_LEVEL1;
7918 else
7919 set_val = cfg_val;
7920
7921 hdd_debug("set HE fragmention to %d", set_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007922 ret_val = sme_update_he_frag_supp(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007923 adapter->vdev_id, set_val);
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08007924 }
7925
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007926 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]) {
7927 cfg_val = nla_get_u8(tb[
7928 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]);
Jeff Johnsone94ccd02019-04-02 15:02:56 -07007929 sme_config->csr_config.wep_tkip_in_he = cfg_val;
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007930 hdd_debug("Set WEP/TKIP allow in HE %d", cfg_val);
7931
7932 update_sme_cfg = true;
7933 }
7934
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007935 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]) {
7936 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]) {
7937 tid = nla_get_u8(tb[
7938 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]);
7939 } else {
7940 hdd_err("TID is not set for ADD/DEL BA cfg");
7941 ret_val = -EINVAL;
7942 goto send_err;
7943 }
7944 cfg_val = nla_get_u8(tb[
7945 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]);
7946 if (cfg_val == QCA_WLAN_ADD_BA) {
7947 if (tb[
7948 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE])
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07007949 buff_size = nla_get_u16(tb[
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007950 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007951 ret_val = sme_send_addba_req(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007952 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007953 tid, buff_size);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007954 } else if (cfg_val == QCA_WLAN_DELETE_BA) {
7955 } else {
7956 hdd_err("Invalid BA session cfg");
7957 ret_val = -EINVAL;
7958 goto send_err;
7959 }
7960 } else if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]) {
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07007961 buff_size = nla_get_u16(tb[
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007962 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
7963 hdd_debug("set buff size to %d for all tids", buff_size);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007964 ret_val = sme_set_ba_buff_size(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007965 adapter->vdev_id, buff_size);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007966 if (ret_val)
7967 goto send_err;
7968 if (buff_size > 64)
7969 /* Configure ADDBA req buffer size to 256 */
7970 set_val = 3;
7971 else
7972 /* Configure ADDBA req buffer size to 64 */
7973 set_val = 2;
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007974 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007975 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07007976 if (ret_val)
7977 hdd_err("Failed to set BA operating mode %d", set_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007978 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07007979 GEN_VDEV_PARAM_AMPDU,
7980 buff_size, GEN_CMD);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007981 }
7982
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08007983 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]) {
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07007984 int he_mcs_val;
Srinivas Girigowda50335342018-09-07 15:21:01 -07007985
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08007986 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]) {
7987 ac = nla_get_u8(tb[
7988 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]);
7989 } else {
7990 hdd_err("AC is not set for NO ACK policy config");
7991 ret_val = -EINVAL;
7992 goto send_err;
7993 }
7994 cfg_val = nla_get_u8(tb[
7995 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]);
7996 hdd_debug("Set NO_ACK to %d for ac %d", cfg_val, ac);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007997 ret_val = sme_set_no_ack_policy(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007998 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007999 cfg_val, ac);
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07008000 if (cfg_val) {
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308001 status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc,
8002 &bval);
8003 if (!QDF_IS_STATUS_SUCCESS(status))
8004 hdd_err("unable to get vht_enable2x2");
8005 if (bval)
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07008006 /*2x2 MCS 5 value*/
8007 he_mcs_val = 0x45;
8008 else
8009 /*1x1 MCS 5 value*/
8010 he_mcs_val = 0x25;
8011
8012 if (hdd_set_11ax_rate(adapter, he_mcs_val, NULL))
8013 hdd_err("HE MCS set failed, MCS val %0x",
8014 he_mcs_val);
8015 } else {
8016 if (hdd_set_11ax_rate(adapter, 0xFF, NULL))
8017 hdd_err("disable fixed rate failed");
8018 }
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08008019 }
8020
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08008021 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]) {
8022 cfg_val = nla_get_u8(tb[
8023 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]);
8024 hdd_debug("Set HE LTF to %d", cfg_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008025 ret_val = sme_set_auto_rate_he_ltf(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008026 adapter->vdev_id,
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08008027 cfg_val);
8028 if (ret_val)
8029 sme_err("Failed to set auto rate HE LTF");
8030
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008031 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08008032 WMI_VDEV_PARAM_HE_LTF,
8033 cfg_val, VDEV_CMD);
8034 if (ret_val)
8035 goto send_err;
8036 }
8037
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07008038 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]) {
8039 cfg_val = nla_get_u8(tb[
8040 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]);
8041 hdd_debug("Set Tx beamformee to %d", cfg_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008042 ret_val = sme_update_tx_bfee_supp(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008043 adapter->vdev_id,
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07008044 cfg_val);
8045 if (ret_val)
8046 sme_err("Failed to set Tx beamformee cap");
8047
8048 }
8049
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008050 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]) {
8051 cfg_val = nla_get_u8(tb[
8052 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]);
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308053 status = ucfg_mlme_cfg_get_vht_tx_bfee_ant_supp(hdd_ctx->psoc,
Abhinav Kumare057b412018-10-09 17:28:16 +05308054 &value);
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308055 if (!QDF_IS_STATUS_SUCCESS(status))
8056 hdd_err("unable to get tx_bfee_ant_supp");
8057
Kiran Kumar Lokerea67af052018-12-12 19:18:51 -08008058 if (!cfg_in_range(CFG_VHT_BEAMFORMEE_ANT_SUPP, cfg_val)) {
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008059 hdd_err("NSTS %d not supported, supp_val %d", cfg_val,
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308060 value);
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008061 ret_val = -ENOTSUPP;
8062 goto send_err;
8063 }
8064 hdd_debug("Set Tx beamformee NSTS to %d", cfg_val);
8065 ret_val = sme_update_tx_bfee_nsts(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008066 adapter->vdev_id,
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008067 cfg_val,
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308068 value);
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008069 if (ret_val)
8070 sme_err("Failed to set Tx beamformee cap");
8071
8072 }
8073
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008074 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]) {
8075 cfg_val = nla_get_u8(tb[
8076 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]);
8077 if (cfg_val) {
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07008078 hdd_debug("Set HE mac padding dur to %d", cfg_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008079 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008080 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
8081 0, VDEV_CMD);
8082 if (ret_val)
8083 hdd_err("MU_EDCA update disable failed");
8084 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
8085 sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
8086 if (sme_update_mu_edca_params(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008087 adapter->vdev_id))
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008088 hdd_err("Failed to send mu edca params");
8089 } else {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008090 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008091 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
8092 1, VDEV_CMD);
8093 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
8094 }
8095 ret_val = sme_update_he_trigger_frm_mac_pad(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008096 adapter->vdev_id,
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008097 cfg_val);
8098 if (ret_val)
8099 hdd_err("Failed to set Trig frame mac padding cap");
8100 }
8101
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07008102 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]) {
8103 cfg_val = nla_get_u8(tb[
8104 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]);
8105 if (cfg_val) {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008106 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07008107 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
8108 0, VDEV_CMD);
8109 if (ret_val)
8110 hdd_err("MU_EDCA update disable failed");
8111 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
8112 sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
8113 if (sme_update_mu_edca_params(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008114 adapter->vdev_id))
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07008115 hdd_err("Failed to send mu edca params");
8116 } else {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008117 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07008118 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
8119 1, VDEV_CMD);
8120 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
8121 }
8122 }
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07008123
8124 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]) {
8125 cfg_val = nla_get_u8(tb[
8126 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]);
8127 ret_val = sme_update_he_om_ctrl_supp(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008128 adapter->vdev_id,
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07008129 cfg_val);
8130 }
8131
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008132 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX;
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07008133 if (tb[cmd_id]) {
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008134 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX + 1];
8135 struct nlattr *curr_attr;
8136 int tmp, rc;
8137 nla_for_each_nested(curr_attr, tb[cmd_id], tmp) {
8138 rc = wlan_cfg80211_nla_parse(
8139 tb2, QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX,
8140 nla_data(curr_attr),
8141 nla_len(curr_attr),
8142 qca_wlan_vendor_attr_he_omi_tx_policy);
8143 if (rc) {
8144 hdd_err("Invalid ATTR");
8145 goto send_err;
8146 }
8147 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW;
8148 if (tb2[cmd_id]) {
8149 cfg_val = nla_get_u8(tb2[cmd_id]);
8150 ret_val = sme_set_he_om_ctrl_param(
8151 hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008152 adapter->vdev_id,
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008153 cmd_id, cfg_val);
8154 }
8155 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS;
8156 if (tb2[cmd_id]) {
8157 cfg_val = nla_get_u8(tb2[cmd_id]);
8158 ret_val = sme_set_he_om_ctrl_param(
8159 hdd_ctx->mac_handle,
8160 adapter->vdev_id,
8161 cmd_id, cfg_val);
8162 }
8163
8164 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE;
8165 if (tb2[cmd_id]) {
8166 cfg_val = nla_get_u8(tb2[cmd_id]);
8167 ret_val = sme_set_he_om_ctrl_param(
8168 hdd_ctx->mac_handle,
8169 adapter->vdev_id,
8170 cmd_id, cfg_val);
8171 }
8172
8173 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS;
8174 if (tb2[cmd_id]) {
8175 cfg_val = nla_get_u8(tb2[cmd_id]);
8176 ret_val = sme_set_he_om_ctrl_param(
8177 hdd_ctx->mac_handle,
8178 adapter->vdev_id,
8179 cmd_id, cfg_val);
8180 }
Kiran Kumar Lokere49e3aff2019-02-06 17:00:48 -08008181
8182 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE;
8183 if (tb2[cmd_id]) {
8184 cfg_val = nla_get_u8(tb2[cmd_id]);
8185 ret_val = sme_set_he_om_ctrl_param(
8186 hdd_ctx->mac_handle,
8187 adapter->vdev_id,
8188 cmd_id, cfg_val);
8189 }
8190
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008191 }
8192 if (ret_val) {
8193 sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
8194 goto send_err;
8195 }
8196 ret_val = sme_send_he_om_ctrl_update(hdd_ctx->mac_handle,
8197 adapter->vdev_id);
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07008198 }
8199
8200 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG])
8201 sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
8202
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07008203 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU;
8204 if (tb[cmd_id]) {
8205 cfg_val = nla_get_u8(tb[cmd_id]);
8206 hdd_debug("Configure Tx SU PPDU enable %d", cfg_val);
8207 if (cfg_val)
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008208 sme_config_su_ppdu_queue(adapter->vdev_id, true);
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07008209 else
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008210 sme_config_su_ppdu_queue(adapter->vdev_id, false);
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07008211 }
8212
Kiran Kumar Lokerea1c29ec2019-02-25 18:19:00 -08008213 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT;
8214 if (tb[cmd_id]) {
8215 cfg_val = nla_get_u8(tb[cmd_id]);
8216 hdd_debug("Configure 2G VHT support %d", cfg_val);
8217 ucfg_mlme_set_vht_for_24ghz(hdd_ctx->psoc,
8218 (cfg_val ? true : false));
8219 }
8220
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008221 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP;
8222 if (tb[cmd_id]) {
8223 cfg_val = nla_get_u8(tb[cmd_id]);
8224 hdd_debug("Configure +HTC_HE support %d", cfg_val);
8225 sme_update_he_htc_he_supp(hdd_ctx->mac_handle,
8226 adapter->vdev_id,
8227 (cfg_val ? true : false));
8228 }
8229
Kiran Kumar Lokere921b5a52019-02-24 21:53:20 -08008230 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS;
8231 if (tb[cmd_id]) {
8232 cfg_val = nla_get_u8(tb[cmd_id]);
8233 hdd_debug("Configure HE testbed defaults %d", cfg_val);
8234 if (!cfg_val)
8235 sme_reset_he_caps(hdd_ctx->mac_handle,
8236 adapter->vdev_id);
8237 else
8238 sme_set_he_testbed_def(hdd_ctx->mac_handle,
8239 adapter->vdev_id);
8240 }
8241
Kiran Kumar Lokereee205772018-09-27 00:27:27 -07008242 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU;
8243 if (tb[cmd_id]) {
8244 cfg_val = nla_get_u8(tb[cmd_id]);
8245 hdd_debug("Configure Action frame Tx in TB PPDU %d", cfg_val);
8246 sme_config_action_tx_in_tb_ppdu(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008247 adapter->vdev_id, cfg_val);
Kiran Kumar Lokereee205772018-09-27 00:27:27 -07008248 }
8249
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008250 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP]) {
8251 struct wmi_twt_add_dialog_param params = {0};
8252 struct hdd_station_ctx *hdd_sta_ctx =
8253 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8254 uint32_t wake_intvl_exp = 0, result = 0;
8255 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1];
8256 struct nlattr *twt_session;
8257 int tmp, rc;
8258
8259 if ((adapter->device_mode != QDF_STA_MODE &&
8260 adapter->device_mode != QDF_P2P_CLIENT_MODE) ||
8261 hdd_sta_ctx->conn_info.conn_state !=
8262 eConnectionState_Associated) {
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308263 hdd_err_rl("Invalid state, vdev %d mode %d state %d",
8264 adapter->vdev_id, adapter->device_mode,
8265 hdd_sta_ctx->conn_info.conn_state);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008266 goto send_err;
8267 }
8268
8269 qdf_mem_copy(params.peer_macaddr,
8270 hdd_sta_ctx->conn_info.bssid.bytes,
8271 QDF_MAC_ADDR_SIZE);
8272 params.vdev_id = adapter->vdev_id;
8273 params.dialog_id = 0;
8274
8275 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP;
8276 nla_for_each_nested(twt_session, tb[cmd_id], tmp) {
8277 rc = wlan_cfg80211_nla_parse(
8278 tb2, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX,
8279 nla_data(twt_session),
8280 nla_len(twt_session),
8281 qca_wlan_vendor_twt_add_dialog_policy);
8282 if (rc) {
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308283 hdd_err_rl("Invalid twt ATTR");
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008284 goto send_err;
8285 }
8286
8287 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308288 if (!tb2[cmd_id]) {
8289 hdd_err_rl("TWT_SETUP_WAKE_INTVL_EXP is must");
8290 goto send_err;
8291 }
8292 wake_intvl_exp = nla_get_u8(tb2[cmd_id]);
8293 if (wake_intvl_exp > TWT_SETUP_WAKE_INTVL_EXP_MAX) {
8294 hdd_err_rl("Invalid wake_intvl_exp %u > %u",
8295 wake_intvl_exp,
8296 TWT_SETUP_WAKE_INTVL_EXP_MAX);
8297 goto send_err;
8298 }
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008299
8300 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST;
8301 if (tb2[cmd_id])
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308302 params.flag_bcast = nla_get_flag(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008303
8304 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308305 if (!tb2[cmd_id]) {
8306 hdd_err_rl("TWT_SETUP_REQ_TYPE is must");
8307 goto send_err;
8308 }
8309 params.twt_cmd = nla_get_u8(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008310
8311 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER;
8312 if (tb2[cmd_id])
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308313 params.flag_trigger = nla_get_flag(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008314
8315 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308316 if (!tb2[cmd_id]) {
8317 hdd_err_rl("TWT_SETUP_FLOW_TYPE is must");
8318 goto send_err;
8319 }
8320 params.flag_flow_type = nla_get_u8(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008321
8322 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION;
8323 if (tb2[cmd_id])
8324 params.flag_protection =
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308325 nla_get_flag(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008326
8327 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME;
8328 if (tb2[cmd_id])
8329 params.sp_offset_us = nla_get_u32(tb2[cmd_id]);
8330
8331 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308332 if (!tb2[cmd_id]) {
8333 hdd_err_rl("TWT_SETUP_WAKE_DURATION is must");
8334 goto send_err;
8335 }
8336 params.wake_dura_us = 256 * nla_get_u32(tb2[cmd_id]);
8337 if (params.wake_dura_us > TWT_SETUP_WAKE_DURATION_MAX) {
8338 hdd_err_rl("Invalid wake_dura_us %u",
8339 params.wake_dura_us);
8340 goto send_err;
8341 }
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008342
8343 cmd_id =
8344 QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308345 if (!tb2[cmd_id]) {
8346 hdd_err_rl("SETUP_WAKE_INTVL_MANTISSA is must");
8347 goto send_err;
8348 }
8349 params.wake_intvl_mantis = nla_get_u32(tb2[cmd_id]);
8350 if (params.wake_intvl_mantis >
8351 TWT_SETUP_WAKE_INTVL_MANTISSA_MAX) {
8352 hdd_err_rl("Invalid wake_intvl_mantis %u",
8353 params.wake_dura_us);
8354 goto send_err;
8355 }
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008356
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308357 if (wake_intvl_exp && params.wake_intvl_mantis) {
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008358 result = 2 << (wake_intvl_exp - 1);
8359 if (result >
8360 (UINT_MAX / params.wake_intvl_mantis)) {
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308361 hdd_err_rl("Invalid exp %d mantissa %d",
8362 wake_intvl_exp,
8363 params.wake_intvl_mantis);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008364 goto send_err;
8365 }
8366 params.wake_intvl_us =
8367 params.wake_intvl_mantis * result;
8368 } else {
8369 params.wake_intvl_us = params.wake_intvl_mantis;
8370 }
8371
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008372 hdd_debug("twt: vdev %d, intvl_us %d, mantis %d",
8373 params.vdev_id, params.wake_intvl_us,
8374 params.wake_intvl_mantis);
8375 hdd_debug("twt: dura %d, offset %d, cmd %d",
8376 params.wake_dura_us, params.sp_offset_us,
8377 params.twt_cmd);
8378 hdd_debug("twt: bcast %d, trigger %d, type %d, prot %d",
8379 params.flag_bcast, params.flag_trigger,
8380 params.flag_flow_type,
8381 params.flag_protection);
8382
8383 ret_val = qdf_status_to_os_return(
8384 wma_twt_process_add_dialog(&params));
8385 if (ret_val)
8386 goto send_err;
8387 }
8388 }
8389
8390 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE]) {
8391 struct wmi_twt_del_dialog_param params = {0};
8392 struct hdd_station_ctx *hdd_sta_ctx =
8393 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8394
8395 if ((adapter->device_mode != QDF_STA_MODE &&
8396 adapter->device_mode != QDF_P2P_CLIENT_MODE) ||
8397 hdd_sta_ctx->conn_info.conn_state !=
8398 eConnectionState_Associated) {
8399 hdd_err("Invalid state, vdev %d mode %d state %d",
8400 adapter->vdev_id, adapter->device_mode,
8401 hdd_sta_ctx->conn_info.conn_state);
8402 goto send_err;
8403 }
8404 qdf_mem_copy(params.peer_macaddr,
8405 hdd_sta_ctx->conn_info.bssid.bytes,
8406 QDF_MAC_ADDR_SIZE);
8407 params.vdev_id = adapter->vdev_id;
8408 params.dialog_id = 0;
8409 hdd_debug("twt_terminate: vdev_id %d", params.vdev_id);
8410 ret_val = qdf_status_to_os_return(
8411 wma_twt_process_del_dialog(&params));
8412 if (ret_val)
8413 goto send_err;
8414 }
8415
8416 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT;
8417 if (tb[cmd_id]) {
8418 cfg_val = nla_get_u8(tb[cmd_id]);
8419 hdd_debug("twt_request: val %d", cfg_val);
8420 ret_val = sme_update_he_twt_req_support(hdd_ctx->mac_handle,
8421 adapter->vdev_id,
8422 cfg_val);
8423 }
8424
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008425 if (update_sme_cfg)
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008426 sme_update_config(mac_handle, sme_config);
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008427
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008428send_err:
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008429 qdf_mem_free(sme_config);
8430
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008431 return ret_val;
8432}
8433
8434/**
8435 * wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
8436 * vendor command
8437 *
8438 * @wiphy: wiphy device pointer
8439 * @wdev: wireless device pointer
8440 * @data: Vendor command data buffer
8441 * @data_len: Buffer length
8442 *
8443 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
8444 *
8445 * Return: EOK or other error codes.
8446 */
8447static int wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
8448 struct wireless_dev *wdev, const void *data, int data_len)
8449{
Dustin Browna09acf42018-11-08 12:32:26 +05308450 int errno;
8451 struct osif_vdev_sync *vdev_sync;
8452
8453 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
8454 if (errno)
8455 return errno;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008456
Dustin Browna09acf42018-11-08 12:32:26 +05308457 errno = __wlan_hdd_cfg80211_set_wifi_test_config(wiphy, wdev,
8458 data, data_len);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008459
Dustin Browna09acf42018-11-08 12:32:26 +05308460 osif_vdev_sync_op_stop(vdev_sync);
8461
8462 return errno;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008463}
8464
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008465static const struct
8466nla_policy
8467qca_wlan_vendor_wifi_logger_start_policy
8468[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
8469 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
8470 = {.type = NLA_U32 },
8471 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
8472 = {.type = NLA_U32 },
8473 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
8474 = {.type = NLA_U32 },
8475};
8476
8477/**
8478 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
8479 * or disable the collection of packet statistics from the firmware
8480 * @wiphy: WIPHY structure pointer
8481 * @wdev: Wireless device structure pointer
8482 * @data: Pointer to the data received
8483 * @data_len: Length of the data received
8484 *
8485 * This function enables or disables the collection of packet statistics from
8486 * the firmware
8487 *
8488 * Return: 0 on success and errno on failure
8489 */
8490static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
8491 struct wireless_dev *wdev,
8492 const void *data,
8493 int data_len)
8494{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308495 QDF_STATUS status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008496 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008497 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
Hanumanth Reddy Pothulae9af1162018-06-13 13:41:44 +05308498 struct sir_wifi_start_log start_log = { 0 };
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008499 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008500
Dustin Brownfdf17c12018-03-14 12:55:34 -07008501 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08008502
Anurag Chouhan6d760662016-02-20 16:05:43 +05308503 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008504 hdd_err("Command not allowed in FTM mode");
8505 return -EPERM;
8506 }
8507
8508 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308509 if (status)
8510 return status;
8511
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05308512 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
8513 hdd_err("Driver Modules are closed, can not start logger");
8514 return -EINVAL;
8515 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008516
Dustin Brown4ea21db2018-01-05 14:13:17 -08008517 if (wlan_cfg80211_nla_parse(tb,
8518 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
8519 data, data_len,
8520 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008521 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008522 return -EINVAL;
8523 }
8524
8525 /* Parse and fetch ring id */
8526 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008527 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008528 return -EINVAL;
8529 }
8530 start_log.ring_id = nla_get_u32(
8531 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008532 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008533
8534 /* Parse and fetch verbose level */
8535 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008536 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008537 return -EINVAL;
8538 }
8539 start_log.verbose_level = nla_get_u32(
8540 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008541 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008542
8543 /* Parse and fetch flag */
8544 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008545 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008546 return -EINVAL;
8547 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05308548 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008549 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008550
Hanumanth Reddy Pothulae9af1162018-06-13 13:41:44 +05308551 start_log.user_triggered = 1;
8552
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308553 /* size is buff size which can be set using iwpriv command*/
8554 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308555 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308556
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008557 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
8558
8559 if (start_log.ring_id == RING_ID_WAKELOCK) {
8560 /* Start/stop wakelock events */
8561 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
8562 cds_set_wakelock_logging(true);
8563 else
8564 cds_set_wakelock_logging(false);
8565 return 0;
8566 }
8567
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008568 mac_handle = hdd_ctx->mac_handle;
8569 status = sme_wifi_start_logger(mac_handle, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308570 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008571 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008572 status);
8573 return -EINVAL;
8574 }
8575 return 0;
8576}
8577
8578/**
8579 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
8580 * or disable the collection of packet statistics from the firmware
8581 * @wiphy: WIPHY structure pointer
8582 * @wdev: Wireless device structure pointer
8583 * @data: Pointer to the data received
8584 * @data_len: Length of the data received
8585 *
8586 * This function is used to enable or disable the collection of packet
8587 * statistics from the firmware
8588 *
8589 * Return: 0 on success and errno on failure
8590 */
8591static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
8592 struct wireless_dev *wdev,
8593 const void *data,
8594 int data_len)
8595{
Dustin Brown363b4792019-02-05 16:11:55 -08008596 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08008597 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05308598
Dustin Brown363b4792019-02-05 16:11:55 -08008599 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08008600 if (errno)
8601 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008602
Dustin Brownf0f00612019-01-31 16:02:24 -08008603 errno = __wlan_hdd_cfg80211_wifi_logger_start(wiphy, wdev,
8604 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008605
Dustin Brown363b4792019-02-05 16:11:55 -08008606 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05308607
Dustin Brownf0f00612019-01-31 16:02:24 -08008608 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008609}
8610
8611static const struct
8612nla_policy
8613qca_wlan_vendor_wifi_logger_get_ring_data_policy
8614[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
8615 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
8616 = {.type = NLA_U32 },
8617};
8618
8619/**
8620 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
8621 * @wiphy: WIPHY structure pointer
8622 * @wdev: Wireless device structure pointer
8623 * @data: Pointer to the data received
8624 * @data_len: Length of the data received
8625 *
8626 * This function is used to flush or retrieve the per packet statistics from
8627 * the driver
8628 *
8629 * Return: 0 on success and errno on failure
8630 */
8631static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
8632 struct wireless_dev *wdev,
8633 const void *data,
8634 int data_len)
8635{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308636 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008637 uint32_t ring_id;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008638 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008639 struct nlattr *tb
8640 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
8641
Dustin Brownfdf17c12018-03-14 12:55:34 -07008642 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08008643
Anurag Chouhan6d760662016-02-20 16:05:43 +05308644 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008645 hdd_err("Command not allowed in FTM mode");
8646 return -EPERM;
8647 }
8648
8649 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308650 if (status)
8651 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008652
Dustin Brown4ea21db2018-01-05 14:13:17 -08008653 if (wlan_cfg80211_nla_parse(tb,
8654 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
8655 data, data_len,
8656 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008657 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008658 return -EINVAL;
8659 }
8660
8661 /* Parse and fetch ring id */
8662 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008663 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008664 return -EINVAL;
8665 }
8666
8667 ring_id = nla_get_u32(
8668 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
8669
8670 if (ring_id == RING_ID_PER_PACKET_STATS) {
8671 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008672 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05308673 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
8674 /*
8675 * As part of DRIVER ring ID, flush both driver and fw logs.
8676 * For other Ring ID's driver doesn't have any rings to flush
8677 */
Dustin Brown5e89ef82018-03-14 11:50:23 -07008678 hdd_info("Bug report triggered by framework");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05308679
8680 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
8681 WLAN_LOG_INDICATOR_FRAMEWORK,
8682 WLAN_LOG_REASON_CODE_UNUSED,
8683 true, false);
8684 if (QDF_STATUS_SUCCESS != status) {
8685 hdd_err("Failed to trigger bug report");
8686 return -EINVAL;
8687 }
8688 } else {
8689 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
8690 WLAN_LOG_INDICATOR_FRAMEWORK,
Agrawal Ashishaff28982017-05-30 15:25:47 +05308691 WLAN_LOG_REASON_CODE_UNUSED,
8692 ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008693 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008694 return 0;
8695}
8696
8697/**
8698 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
8699 * @wiphy: WIPHY structure pointer
8700 * @wdev: Wireless device structure pointer
8701 * @data: Pointer to the data received
8702 * @data_len: Length of the data received
8703 *
8704 * This function is used to flush or retrieve the per packet statistics from
8705 * the driver
8706 *
8707 * Return: 0 on success and errno on failure
8708 */
8709static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
8710 struct wireless_dev *wdev,
8711 const void *data,
8712 int data_len)
8713{
Dustin Brown363b4792019-02-05 16:11:55 -08008714 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08008715 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05308716
Dustin Brown363b4792019-02-05 16:11:55 -08008717 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08008718 if (errno)
8719 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008720
Dustin Brownf0f00612019-01-31 16:02:24 -08008721 errno = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy, wdev,
8722 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008723
Dustin Brown363b4792019-02-05 16:11:55 -08008724 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08008725
8726 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008727}
8728
8729#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8730/**
8731 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
8732 * @hdd_ctx: HDD context
8733 * @request_id: [input] request id
8734 * @pattern_id: [output] pattern id
8735 *
8736 * This function loops through request id to pattern id array
8737 * if the slot is available, store the request id and return pattern id
8738 * if entry exists, return the pattern id
8739 *
8740 * Return: 0 on success and errno on failure
8741 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008742static int hdd_map_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008743 uint32_t request_id,
8744 uint8_t *pattern_id)
8745{
8746 uint32_t i;
8747
8748 mutex_lock(&hdd_ctx->op_ctx.op_lock);
8749 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
8750 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
8751 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
8752 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
8753 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
8754 return 0;
8755 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
8756 request_id) {
8757 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
8758 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
8759 return 0;
8760 }
8761 }
8762 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05308763 return -ENOBUFS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008764}
8765
8766/**
8767 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
8768 * @hdd_ctx: HDD context
8769 * @request_id: [input] request id
8770 * @pattern_id: [output] pattern id
8771 *
8772 * This function loops through request id to pattern id array
8773 * reset request id to 0 (slot available again) and
8774 * return pattern id
8775 *
8776 * Return: 0 on success and errno on failure
8777 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008778static int hdd_unmap_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008779 uint32_t request_id,
8780 uint8_t *pattern_id)
8781{
8782 uint32_t i;
8783
8784 mutex_lock(&hdd_ctx->op_ctx.op_lock);
8785 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
8786 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
8787 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
8788 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
8789 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
8790 return 0;
8791 }
8792 }
8793 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
8794 return -EINVAL;
8795}
8796
8797
8798/*
8799 * define short names for the global vendor params
8800 * used by __wlan_hdd_cfg80211_offloaded_packets()
8801 */
8802#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
8803#define PARAM_REQUEST_ID \
8804 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
8805#define PARAM_CONTROL \
8806 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
8807#define PARAM_IP_PACKET \
8808 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
8809#define PARAM_SRC_MAC_ADDR \
8810 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
8811#define PARAM_DST_MAC_ADDR \
8812 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
8813#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05308814#define PARAM_PROTO_TYPE \
8815 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008816
8817/**
8818 * wlan_hdd_add_tx_ptrn() - add tx pattern
8819 * @adapter: adapter pointer
8820 * @hdd_ctx: hdd context
8821 * @tb: nl attributes
8822 *
8823 * This function reads the NL attributes and forms a AddTxPtrn message
8824 * posts it to SME.
8825 *
8826 */
8827static int
Jeff Johnsone5006672017-08-29 14:39:02 -07008828wlan_hdd_add_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008829 struct nlattr **tb)
8830{
8831 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308832 QDF_STATUS status;
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05308833 uint32_t request_id, len;
8834 int32_t ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008835 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05308836 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008837 uint16_t eth_type = htons(ETH_P_IP);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008838 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008839
8840 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07008841 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008842 return -ENOTSUPP;
8843 }
8844
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308845 add_req = qdf_mem_malloc(sizeof(*add_req));
Min Liu74a1a502018-10-10 19:59:07 +08008846 if (!add_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008847 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008848
8849 /* Parse and fetch request Id */
8850 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008851 hdd_err("attr request id failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05308852 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008853 goto fail;
8854 }
8855
8856 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
8857 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07008858 hdd_err("request_id cannot be MAX");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05308859 ret = -EINVAL;
SaidiReddy Yenuga466b3ce2017-05-02 18:50:25 +05308860 goto fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008861 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008862 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008863
8864 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008865 hdd_err("attr period failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05308866 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008867 goto fail;
8868 }
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05308869
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008870 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008871 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008872 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07008873 hdd_err("Invalid interval zero, return failure");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05308874 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008875 goto fail;
8876 }
8877
8878 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008879 hdd_err("attr source mac address failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05308880 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008881 goto fail;
8882 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08008883 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05308884 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07008885 hdd_debug("input src mac address: "QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07008886 QDF_MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008887
Anurag Chouhanc5548422016-02-24 18:33:27 +05308888 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Jeff Johnson1e851a12017-10-28 14:36:12 -07008889 &adapter->mac_addr)) {
Srinivas Girigowda31896552015-11-18 22:59:52 -08008890 hdd_err("input src mac address and connected ap bssid are different");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05308891 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008892 goto fail;
8893 }
8894
8895 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008896 hdd_err("attr dst mac address failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05308897 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008898 goto fail;
8899 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05308900 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07008901 hdd_debug("input dst mac address: "QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07008902 QDF_MAC_ADDR_ARRAY(dst_addr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008903
8904 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008905 hdd_err("attr ip packet failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05308906 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008907 goto fail;
8908 }
8909 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008910 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008911
8912 if (add_req->ucPtrnSize < 0 ||
8913 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
8914 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008915 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008916 add_req->ucPtrnSize);
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05308917 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008918 goto fail;
8919 }
8920
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05308921 if (!tb[PARAM_PROTO_TYPE])
8922 eth_type = htons(ETH_P_IP);
8923 else
8924 eth_type = htons(nla_get_u16(tb[PARAM_PROTO_TYPE]));
8925
8926 hdd_debug("packet proto type: %u", eth_type);
8927
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008928 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308929 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05308930 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308931 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308932 QDF_MAC_ADDR_SIZE);
8933 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308934 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008935 len += 2;
8936
8937 /*
8938 * This is the IP packet, add 14 bytes Ethernet (802.3) header
8939 * ------------------------------------------------------------
8940 * | 14 bytes Ethernet (802.3) header | IP header and payload |
8941 * ------------------------------------------------------------
8942 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308943 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008944 nla_data(tb[PARAM_IP_PACKET]),
8945 add_req->ucPtrnSize);
8946 add_req->ucPtrnSize += len;
8947
8948 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
8949 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008950 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008951 goto fail;
8952 }
8953 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008954 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008955
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008956 mac_handle = hdd_ctx->mac_handle;
8957 status = sme_add_periodic_tx_ptrn(mac_handle, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308958 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008959 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05308960 ret = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008961 goto fail;
8962 }
8963
Dustin Browne74003f2018-03-14 12:51:58 -07008964 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008965
8966fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308967 qdf_mem_free(add_req);
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05308968 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008969}
8970
8971/**
8972 * wlan_hdd_del_tx_ptrn() - delete tx pattern
8973 * @adapter: adapter pointer
8974 * @hdd_ctx: hdd context
8975 * @tb: nl attributes
8976 *
8977 * This function reads the NL attributes and forms a DelTxPtrn message
8978 * posts it to SME.
8979 *
8980 */
8981static int
Jeff Johnsone5006672017-08-29 14:39:02 -07008982wlan_hdd_del_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008983 struct nlattr **tb)
8984{
8985 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308986 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008987 uint32_t request_id, ret;
8988 uint8_t pattern_id = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008989 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008990
8991 /* Parse and fetch request Id */
8992 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008993 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008994 return -EINVAL;
8995 }
8996 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
8997 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07008998 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008999 return -EINVAL;
9000 }
9001
9002 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
9003 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009004 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009005 return -EINVAL;
9006 }
9007
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309008 del_req = qdf_mem_malloc(sizeof(*del_req));
Min Liu74a1a502018-10-10 19:59:07 +08009009 if (!del_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009010 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009011
Jeff Johnson1e851a12017-10-28 14:36:12 -07009012 qdf_copy_macaddr(&del_req->mac_address, &adapter->mac_addr);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07009013 hdd_debug(QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07009014 QDF_MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009015 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009016 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009017 request_id, del_req->ucPtrnId);
9018
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009019 mac_handle = hdd_ctx->mac_handle;
9020 status = sme_del_periodic_tx_ptrn(mac_handle, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309021 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009022 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009023 goto fail;
9024 }
9025
Dustin Browne74003f2018-03-14 12:51:58 -07009026 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309027 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009028 return 0;
9029
9030fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309031 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009032 return -EINVAL;
9033}
9034
9035
9036/**
9037 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
9038 * @wiphy: Pointer to wireless phy
9039 * @wdev: Pointer to wireless device
9040 * @data: Pointer to data
9041 * @data_len: Data length
9042 *
9043 * Return: 0 on success, negative errno on failure
9044 */
9045static int
9046__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
9047 struct wireless_dev *wdev,
9048 const void *data,
9049 int data_len)
9050{
9051 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009052 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009053 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009054 struct nlattr *tb[PARAM_MAX + 1];
9055 uint8_t control;
9056 int ret;
9057 static const struct nla_policy policy[PARAM_MAX + 1] = {
9058 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
9059 [PARAM_CONTROL] = { .type = NLA_U32 },
9060 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309061 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009062 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309063 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009064 [PARAM_PERIOD] = { .type = NLA_U32 },
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05309065 [PARAM_PROTO_TYPE] = {.type = NLA_U16},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009066 };
9067
Dustin Brownfdf17c12018-03-14 12:55:34 -07009068 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009069
Anurag Chouhan6d760662016-02-20 16:05:43 +05309070 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009071 hdd_err("Command not allowed in FTM mode");
9072 return -EPERM;
9073 }
9074
9075 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309076 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009077 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009078
9079 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009080 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009081 return -ENOTSUPP;
9082 }
9083
Dustin Brown4ea21db2018-01-05 14:13:17 -08009084 if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009085 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009086 return -EINVAL;
9087 }
9088
9089 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009090 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009091 return -EINVAL;
9092 }
9093 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009094 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009095
9096 if (control == WLAN_START_OFFLOADED_PACKETS)
9097 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08009098 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009099 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08009100
9101 hdd_err("Invalid control: %d", control);
Jeff Johnson68755312017-02-10 11:46:55 -08009102 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009103}
9104
9105/*
9106 * done with short names for the global vendor params
9107 * used by __wlan_hdd_cfg80211_offloaded_packets()
9108 */
9109#undef PARAM_MAX
9110#undef PARAM_REQUEST_ID
9111#undef PARAM_CONTROL
9112#undef PARAM_IP_PACKET
9113#undef PARAM_SRC_MAC_ADDR
9114#undef PARAM_DST_MAC_ADDR
9115#undef PARAM_PERIOD
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05309116#undef PARAM_PROTO_TYPE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009117
9118/**
9119 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
9120 * @wiphy: wiphy structure pointer
9121 * @wdev: Wireless device structure pointer
9122 * @data: Pointer to the data received
9123 * @data_len: Length of @data
9124 *
9125 * Return: 0 on success; errno on failure
9126 */
9127static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
9128 struct wireless_dev *wdev,
9129 const void *data,
9130 int data_len)
9131{
Dustin Browna09acf42018-11-08 12:32:26 +05309132 int errno;
9133 struct osif_vdev_sync *vdev_sync;
9134
9135 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
9136 if (errno)
9137 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009138
Dustin Browna09acf42018-11-08 12:32:26 +05309139 errno = __wlan_hdd_cfg80211_offloaded_packets(wiphy, wdev,
9140 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009141
Dustin Browna09acf42018-11-08 12:32:26 +05309142 osif_vdev_sync_op_stop(vdev_sync);
9143
9144 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009145}
9146#endif
9147
Qiwei Cai1083f5b2018-07-02 19:10:11 +08009148#ifdef WLAN_NS_OFFLOAD
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309149static const struct nla_policy
9150ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
9151 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
9152};
9153
9154/**
9155 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
9156 * @wiphy: Pointer to wireless phy
9157 * @wdev: Pointer to wireless device
9158 * @data: Pointer to data
9159 * @data_len: Length of @data
9160 *
9161 * Return: 0 on success, negative errno on failure
9162 */
9163static int
9164__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
9165 struct wireless_dev *wdev,
9166 const void *data, int data_len)
9167{
9168 int status;
9169 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
Jeff Johnsonb8944722017-09-03 09:03:19 -07009170 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07009171 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009172 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309173
Dustin Brownfdf17c12018-03-14 12:55:34 -07009174 hdd_enter_dev(wdev->netdev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309175
Jeff Johnsonb8944722017-09-03 09:03:19 -07009176 status = wlan_hdd_validate_context(hdd_ctx);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309177 if (0 != status)
9178 return status;
Wu Gao66454f12018-09-26 19:55:41 +08009179
9180 if (!ucfg_pmo_is_ns_offloaded(hdd_ctx->psoc)) {
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309181 hdd_err("ND Offload not supported");
9182 return -EINVAL;
9183 }
9184
Wu Gao66454f12018-09-26 19:55:41 +08009185 if (!ucfg_pmo_is_active_mode_offloaded(hdd_ctx->psoc)) {
Mukul Sharma495df602017-09-25 14:52:18 +05309186 hdd_warn("Active mode offload is disabled");
9187 return -EINVAL;
9188 }
9189
Dustin Brown4ea21db2018-01-05 14:13:17 -08009190 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
9191 (struct nlattr *)data, data_len,
9192 ns_offload_set_policy)) {
9193 hdd_err("nla_parse failed");
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309194 return -EINVAL;
9195 }
9196
9197 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
9198 hdd_err("ND Offload flag attribute not present");
9199 return -EINVAL;
9200 }
9201
Jeff Johnsonb8944722017-09-03 09:03:19 -07009202 hdd_ctx->ns_offload_enable =
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309203 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
9204
Nachiket Kukadedbffab82017-04-25 19:26:02 +05309205 if (QDF_IBSS_MODE == adapter->device_mode) {
9206 hdd_debug("NS Offload is not supported in IBSS mode");
9207 return -EINVAL;
9208 }
9209
Dustin Brownd8279d22016-09-07 14:52:57 -07009210 /* update ns offload in case it is already enabled/disabled */
Jeff Johnsonb8944722017-09-03 09:03:19 -07009211 if (hdd_ctx->ns_offload_enable)
Mukul Sharma3ba26b82017-01-12 21:59:41 +05309212 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
9213 else
9214 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07009215
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309216 return 0;
9217}
9218
9219/**
9220 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
9221 * @wiphy: pointer to wireless wiphy structure.
9222 * @wdev: pointer to wireless_dev structure.
9223 * @data: Pointer to the data to be passed via vendor interface
9224 * @data_len:Length of the data to be passed
9225 *
9226 * Return: Return the Success or Failure code.
9227 */
9228static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
9229 struct wireless_dev *wdev,
9230 const void *data, int data_len)
9231{
Dustin Browna09acf42018-11-08 12:32:26 +05309232 int errno;
9233 struct osif_vdev_sync *vdev_sync;
9234
9235 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
9236 if (errno)
9237 return errno;
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309238
Dustin Browna09acf42018-11-08 12:32:26 +05309239 errno = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309240
Dustin Browna09acf42018-11-08 12:32:26 +05309241 osif_vdev_sync_op_stop(vdev_sync);
9242
9243 return errno;
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309244}
Qiwei Cai1083f5b2018-07-02 19:10:11 +08009245#endif /* WLAN_NS_OFFLOAD */
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309246
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309247/**
9248 * struct weighed_pcl: Preferred channel info
9249 * @freq: Channel frequency
9250 * @weight: Weightage of the channel
9251 * @flag: Validity of the channel in p2p negotiation
9252 */
9253struct weighed_pcl {
9254 u32 freq;
9255 u32 weight;
9256 u32 flag;
9257};
9258
Jeff Johnsondd7bd3e2017-06-05 13:25:24 -07009259static const struct nla_policy get_preferred_freq_list_policy
9260 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1] = {
9261 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE] = {
9262 .type = NLA_U32},
9263};
9264
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309265static uint32_t wlan_hdd_populate_weigh_pcl(
9266 struct policy_mgr_pcl_chan_weights *
9267 chan_weights,
9268 struct weighed_pcl *w_pcl,
9269 enum policy_mgr_con_mode intf_mode)
9270{
9271 int i, j;
9272 uint32_t chan_idx = 0;
9273 uint32_t set = 0;
9274 uint32_t pcl_len = chan_weights->pcl_len;
9275 uint32_t valid_weight;
9276
9277 /* convert channel number to frequency */
9278 for (i = 0; i < chan_weights->pcl_len; i++) {
9279 if (chan_weights->pcl_list[i] <=
9280 ARRAY_SIZE(hdd_channels_2_4_ghz))
9281 w_pcl[i].freq = ieee80211_channel_to_frequency(
9282 chan_weights->pcl_list[i],
9283 HDD_NL80211_BAND_2GHZ);
9284 else
9285 w_pcl[i].freq = ieee80211_channel_to_frequency(
9286 chan_weights->pcl_list[i],
9287 HDD_NL80211_BAND_5GHZ);
9288 w_pcl[i].weight = chan_weights->weight_list[i];
9289
9290 if (intf_mode == PM_SAP_MODE || intf_mode == PM_P2P_GO_MODE)
9291 w_pcl[i].flag = set | PCL_CHANNEL_SUPPORT_GO;
9292 else
9293 w_pcl[i].flag = set | PCL_CHANNEL_SUPPORT_CLI;
9294 }
9295 chan_idx = pcl_len;
Rajeev Kumar Sirasanagandla50b2c102019-07-18 19:27:49 +05309296 if (pcl_len && chan_weights->weight_list[pcl_len - 1] >
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309297 PCL_GROUPS_WEIGHT_DIFFERENCE)
9298 /* Set non-pcl channels weight 20 point less than the last PCL entry */
9299 valid_weight = chan_weights->weight_list[pcl_len - 1] -
9300 PCL_GROUPS_WEIGHT_DIFFERENCE;
9301 else
9302 valid_weight = 1;
9303
9304 /* Include rest of the valid channels */
9305 for (i = 0; i < chan_weights->saved_num_chan; i++) {
9306 for (j = 0; j < chan_weights->pcl_len; j++) {
9307 if (chan_weights->saved_chan_list[i] ==
9308 chan_weights->pcl_list[j])
9309 break;
9310 }
9311 if (j == chan_weights->pcl_len) {
9312 if (chan_weights->saved_chan_list[i] <=
9313 ARRAY_SIZE(hdd_channels_2_4_ghz))
9314 w_pcl[chan_idx].freq =
9315 ieee80211_channel_to_frequency(
9316 chan_weights->saved_chan_list[i],
9317 HDD_NL80211_BAND_2GHZ);
9318 else
9319 w_pcl[chan_idx].freq =
9320 ieee80211_channel_to_frequency(
9321 chan_weights->saved_chan_list[i],
9322 HDD_NL80211_BAND_5GHZ);
9323
9324 if (!chan_weights->weighed_valid_list[i]) {
9325 w_pcl[chan_idx].flag =
9326 set | PCL_CHANNEL_EXCLUDE_IN_GO_NEG;
9327 w_pcl[chan_idx].weight = 0;
9328 } else {
9329 if (intf_mode == PM_SAP_MODE ||
9330 intf_mode == PM_P2P_GO_MODE)
9331 w_pcl[chan_idx].flag =
9332 set | PCL_CHANNEL_SUPPORT_GO;
9333 else
9334 w_pcl[chan_idx].flag =
9335 set | PCL_CHANNEL_SUPPORT_CLI;
9336 w_pcl[chan_idx].weight = valid_weight;
9337 }
9338 chan_idx++;
9339 }
9340 }
9341 return chan_idx;
9342}
9343
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009344/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
9345 * @wiphy: Pointer to wireless phy
9346 * @wdev: Pointer to wireless device
9347 * @data: Pointer to data
9348 * @data_len: Data length
9349 *
9350 * This function return the preferred frequency list generated by the policy
9351 * manager.
9352 *
9353 * Return: success or failure code
9354 */
9355static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
9356 struct wireless_dev
9357 *wdev, const void *data,
9358 int data_len)
9359{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009360 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009361 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309362 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009363 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05309364 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08009365 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009366 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
9367 struct sk_buff *reply_skb;
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309368 struct weighed_pcl *w_pcl;
9369 struct nlattr *nla_attr, *channel;
9370 struct policy_mgr_pcl_chan_weights *chan_weights;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009371
Dustin Brownfdf17c12018-03-14 12:55:34 -07009372 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08009373
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009374 ret = wlan_hdd_validate_context(hdd_ctx);
9375 if (ret)
9376 return -EINVAL;
9377
Dustin Brown4ea21db2018-01-05 14:13:17 -08009378 if (wlan_cfg80211_nla_parse(tb,
9379 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
9380 data, data_len,
9381 get_preferred_freq_list_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009382 hdd_err("Invalid ATTR");
9383 return -EINVAL;
9384 }
9385
9386 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
9387 hdd_err("attr interface type failed");
9388 return -EINVAL;
9389 }
9390
9391 intf_mode = nla_get_u32(tb
9392 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
9393
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08009394 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009395 hdd_err("Invalid interface type");
9396 return -EINVAL;
9397 }
9398
9399 hdd_debug("Userspace requested pref freq list");
9400
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309401 chan_weights =
9402 qdf_mem_malloc(sizeof(struct policy_mgr_pcl_chan_weights));
9403 if (!chan_weights)
9404 return -ENOMEM;
9405
Dustin Brown76cd2932018-09-11 16:03:05 -07009406 status = policy_mgr_get_pcl(hdd_ctx->psoc,
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309407 intf_mode, chan_weights->pcl_list,
9408 &chan_weights->pcl_len,
9409 chan_weights->weight_list,
9410 QDF_ARRAY_SIZE(chan_weights->weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309411 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009412 hdd_err("Get pcl failed");
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309413 qdf_mem_free(chan_weights);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009414 return -EINVAL;
9415 }
gaurank kathpalia5aafb672019-06-24 17:11:15 +05309416 chan_weights->saved_num_chan = POLICY_MGR_MAX_CHANNEL_LIST;
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309417 sme_get_valid_channels(chan_weights->saved_chan_list,
9418 &chan_weights->saved_num_chan);
9419 policy_mgr_get_valid_chan_weights(hdd_ctx->psoc, chan_weights);
9420 w_pcl = qdf_mem_malloc(sizeof(struct weighed_pcl) * QDF_MAX_NUM_CHAN);
9421 if (!w_pcl) {
9422 qdf_mem_free(chan_weights);
9423 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009424 }
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309425 pcl_len = wlan_hdd_populate_weigh_pcl(chan_weights, w_pcl, intf_mode);
9426 qdf_mem_free(chan_weights);
9427
9428 for (i = 0; i < pcl_len; i++)
9429 freq_list[i] = w_pcl[i].freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009430
9431 /* send the freq_list back to supplicant */
9432 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309433 sizeof(u32) * pcl_len +
9434 sizeof(struct weighed_pcl) * pcl_len +
9435 NLMSG_HDRLEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009436
9437 if (!reply_skb) {
9438 hdd_err("Allocate reply_skb failed");
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309439 qdf_mem_free(w_pcl);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009440 return -EINVAL;
9441 }
9442
9443 if (nla_put_u32(reply_skb,
9444 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
9445 intf_mode) ||
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309446 nla_put(reply_skb,
9447 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
9448 sizeof(uint32_t) * pcl_len,
9449 freq_list)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009450 hdd_err("nla put fail");
9451 kfree_skb(reply_skb);
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309452 qdf_mem_free(w_pcl);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009453 return -EINVAL;
9454 }
9455
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309456 i = QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL;
9457 nla_attr = nla_nest_start(reply_skb, i);
9458
9459 if (!nla_attr) {
9460 hdd_err("nla nest start fail");
9461 kfree_skb(reply_skb);
9462 qdf_mem_free(w_pcl);
9463 return -EINVAL;
9464 }
9465
9466 for (i = 0; i < pcl_len; i++) {
9467 channel = nla_nest_start(reply_skb, i);
9468 if (!channel) {
9469 hdd_err("updating pcl list failed");
9470 kfree_skb(reply_skb);
9471 qdf_mem_free(w_pcl);
9472 return -EINVAL;
9473 }
9474 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FREQ,
9475 w_pcl[i].freq) ||
9476 nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
9477 w_pcl[i].weight) ||
9478 nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FLAG,
9479 w_pcl[i].flag)) {
9480 hdd_err("nla put fail");
9481 kfree_skb(reply_skb);
9482 qdf_mem_free(w_pcl);
9483 return -EINVAL;
9484 }
9485 nla_nest_end(reply_skb, channel);
9486 }
9487 nla_nest_end(reply_skb, nla_attr);
9488 qdf_mem_free(w_pcl);
9489
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009490 return cfg80211_vendor_cmd_reply(reply_skb);
9491}
9492
9493/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
9494 * @wiphy: Pointer to wireless phy
9495 * @wdev: Pointer to wireless device
9496 * @data: Pointer to data
9497 * @data_len: Data length
9498 *
9499 * This function return the preferred frequency list generated by the policy
9500 * manager.
9501 *
9502 * Return: success or failure code
9503 */
9504static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
9505 struct wireless_dev
9506 *wdev, const void *data,
9507 int data_len)
9508{
Dustin Brown363b4792019-02-05 16:11:55 -08009509 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08009510 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309511
Dustin Brown363b4792019-02-05 16:11:55 -08009512 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08009513 if (errno)
9514 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009515
Dustin Brownf0f00612019-01-31 16:02:24 -08009516 errno = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
9517 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009518
Dustin Brown363b4792019-02-05 16:11:55 -08009519 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309520
Dustin Brownf0f00612019-01-31 16:02:24 -08009521 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009522}
9523
Jeff Johnsone5f33ba2017-06-05 14:48:48 -07009524static const struct nla_policy set_probable_oper_channel_policy
9525 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1] = {
9526 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE] = {
9527 .type = NLA_U32},
9528 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ] = {
9529 .type = NLA_U32},
9530};
9531
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009532/**
9533 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
9534 * @wiphy: Pointer to wireless phy
9535 * @wdev: Pointer to wireless device
9536 * @data: Pointer to data
9537 * @data_len: Data length
9538 *
9539 * Return: 0 on success, negative errno on failure
9540 */
9541static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
9542 struct wireless_dev *wdev,
9543 const void *data,
9544 int data_len)
9545{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05309546 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009547 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009548 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009549 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08009550 enum policy_mgr_con_mode intf_mode;
Jeff Johnsone5f33ba2017-06-05 14:48:48 -07009551 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009552 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009553
Dustin Brownfdf17c12018-03-14 12:55:34 -07009554 hdd_enter_dev(ndev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08009555
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009556 ret = wlan_hdd_validate_context(hdd_ctx);
9557 if (ret)
9558 return ret;
9559
Dustin Brown4ea21db2018-01-05 14:13:17 -08009560 if (wlan_cfg80211_nla_parse(tb,
9561 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
9562 data, data_len,
9563 set_probable_oper_channel_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009564 hdd_err("Invalid ATTR");
9565 return -EINVAL;
9566 }
9567
9568 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
9569 hdd_err("attr interface type failed");
9570 return -EINVAL;
9571 }
9572
9573 intf_mode = nla_get_u32(tb
9574 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
9575
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08009576 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009577 hdd_err("Invalid interface type");
9578 return -EINVAL;
9579 }
9580
9581 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
9582 hdd_err("attr probable freq failed");
9583 return -EINVAL;
9584 }
9585
9586 channel_hint = cds_freq_to_chan(nla_get_u32(tb
9587 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
9588
9589 /* check pcl table */
Dustin Brown76cd2932018-09-11 16:03:05 -07009590 if (!policy_mgr_allow_concurrency(hdd_ctx->psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009591 channel_hint, HW_MODE_20_MHZ)) {
9592 hdd_err("Set channel hint failed due to concurrency check");
9593 return -EINVAL;
9594 }
9595
Krunal Soni09e55032016-06-07 10:06:55 -07009596 if (0 != wlan_hdd_check_remain_on_channel(adapter))
9597 hdd_warn("Remain On Channel Pending");
9598
Krunal Sonied3bc8e2018-01-26 12:13:34 -08009599 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, channel_hint,
9600 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
9601 hdd_err("Failed to change hw mode");
Krunal Soni3091bcc2016-06-23 12:28:21 -07009602 return -EINVAL;
9603 }
9604
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009605 return 0;
9606}
9607
9608/**
9609 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
9610 * @wiphy: Pointer to wireless phy
9611 * @wdev: Pointer to wireless device
9612 * @data: Pointer to data
9613 * @data_len: Data length
9614 *
9615 * Return: 0 on success, negative errno on failure
9616 */
9617static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
9618 struct wireless_dev *wdev,
9619 const void *data,
9620 int data_len)
9621{
Dustin Browna09acf42018-11-08 12:32:26 +05309622 int errno;
9623 struct osif_vdev_sync *vdev_sync;
9624
9625 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
9626 if (errno)
9627 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009628
Dustin Browna09acf42018-11-08 12:32:26 +05309629 errno = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
9630 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009631
Dustin Browna09acf42018-11-08 12:32:26 +05309632 osif_vdev_sync_op_stop(vdev_sync);
9633
9634 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009635}
9636
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309637static const struct
9638nla_policy
9639qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +05309640 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {
9641 .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309642};
9643
9644/**
9645 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
9646 * @wiphy: WIPHY structure pointer
9647 * @wdev: Wireless device structure pointer
9648 * @data: Pointer to the data received
9649 * @data_len: Length of the data received
9650 *
9651 * This function is used to get link properties like nss, rate flags and
9652 * operating frequency for the active connection with the given peer.
9653 *
9654 * Return: 0 on success and errno on failure
9655 */
9656static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
9657 struct wireless_dev *wdev,
9658 const void *data,
9659 int data_len)
9660{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009661 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309662 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009663 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson40dae4e2017-08-29 14:00:25 -07009664 struct hdd_station_ctx *hdd_sta_ctx;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309665 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05309666 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309667 uint32_t sta_id;
9668 struct sk_buff *reply_skb;
9669 uint32_t rate_flags = 0;
9670 uint8_t nss;
9671 uint8_t final_rate_flags = 0;
9672 uint32_t freq;
9673
Dustin Brownfdf17c12018-03-14 12:55:34 -07009674 hdd_enter_dev(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309675
Anurag Chouhan6d760662016-02-20 16:05:43 +05309676 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309677 hdd_err("Command not allowed in FTM mode");
9678 return -EPERM;
9679 }
9680
9681 if (0 != wlan_hdd_validate_context(hdd_ctx))
9682 return -EINVAL;
9683
Dustin Brown4ea21db2018-01-05 14:13:17 -08009684 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
9685 data_len, qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009686 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309687 return -EINVAL;
9688 }
9689
9690 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009691 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309692 adapter->device_mode);
9693 return -EINVAL;
9694 }
9695
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +05309696 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) < QDF_MAC_ADDR_SIZE) {
9697 hdd_err("Attribute peerMac is invalid for mode=%d",
9698 adapter->device_mode);
9699 return -EINVAL;
9700 }
9701
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309702 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05309703 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07009704 hdd_debug("peerMac="QDF_MAC_ADDR_STR" for device_mode:%d",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07009705 QDF_MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309706
Krunal Sonib4326f22016-03-10 13:05:51 -08009707 if (adapter->device_mode == QDF_STA_MODE ||
9708 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309709 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnsone7951512019-02-27 10:02:51 -08009710 if ((hdd_sta_ctx->conn_info.conn_state !=
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309711 eConnectionState_Associated) ||
Jeff Johnsone04b6992019-02-27 14:06:55 -08009712 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssid.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309713 peer_mac, QDF_MAC_ADDR_SIZE)) {
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07009714 hdd_err("Not Associated to mac "QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07009715 QDF_MAC_ADDR_ARRAY(peer_mac));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309716 return -EINVAL;
9717 }
9718
9719 nss = hdd_sta_ctx->conn_info.nss;
Jingxiang Geae80dc62019-08-13 17:32:22 +08009720 freq = hdd_sta_ctx->conn_info.chan_freq;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309721 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08009722 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
9723 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309724
9725 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07009726 if (adapter->sta_info[sta_id].in_use &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05309727 !qdf_is_macaddr_broadcast(
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07009728 &adapter->sta_info[sta_id].sta_mac) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309729 !qdf_mem_cmp(
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07009730 &adapter->sta_info[sta_id].sta_mac.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309731 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309732 break;
9733 }
9734
9735 if (WLAN_MAX_STA_COUNT == sta_id) {
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07009736 hdd_err("No active peer with mac="QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07009737 QDF_MAC_ADDR_ARRAY(peer_mac));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309738 return -EINVAL;
9739 }
9740
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07009741 nss = adapter->sta_info[sta_id].nss;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309742 freq = cds_chan_to_freq(
Jeff Johnson01206862017-10-27 20:55:59 -07009743 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operating_channel);
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07009744 rate_flags = adapter->sta_info[sta_id].rate_flags;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309745 } else {
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07009746 hdd_err("Not Associated! with mac "QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07009747 QDF_MAC_ADDR_ARRAY(peer_mac));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309748 return -EINVAL;
9749 }
9750
Naveen Rawatea1564b2018-05-17 15:56:11 -07009751 if (!(rate_flags & TX_RATE_LEGACY)) {
9752 if (rate_flags & TX_RATE_VHT80) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309753 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08009754#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309755 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08009756#endif
Naveen Rawatea1564b2018-05-17 15:56:11 -07009757 } else if (rate_flags & TX_RATE_VHT40) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309758 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08009759#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309760 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08009761#endif
Naveen Rawatea1564b2018-05-17 15:56:11 -07009762 } else if (rate_flags & TX_RATE_VHT20) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309763 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
9764 } else if (rate_flags &
Naveen Rawatea1564b2018-05-17 15:56:11 -07009765 (TX_RATE_HT20 | TX_RATE_HT40)) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309766 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08009767#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Naveen Rawatea1564b2018-05-17 15:56:11 -07009768 if (rate_flags & TX_RATE_HT40)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309769 final_rate_flags |=
9770 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08009771#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309772 }
9773
Naveen Rawatea1564b2018-05-17 15:56:11 -07009774 if (rate_flags & TX_RATE_SGI) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309775 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
9776 final_rate_flags |= RATE_INFO_FLAGS_MCS;
9777 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
9778 }
9779 }
9780
9781 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
9782 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
9783
Jeff Johnsond36fa332019-03-18 13:42:25 -07009784 if (!reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07009785 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309786 return -EINVAL;
9787 }
9788
9789 if (nla_put_u8(reply_skb,
9790 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
9791 nss) ||
9792 nla_put_u8(reply_skb,
9793 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
9794 final_rate_flags) ||
9795 nla_put_u32(reply_skb,
9796 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
9797 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009798 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309799 kfree_skb(reply_skb);
9800 return -EINVAL;
9801 }
9802
9803 return cfg80211_vendor_cmd_reply(reply_skb);
9804}
9805
9806/**
9807 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
9808 * properties.
9809 * @wiphy: WIPHY structure pointer
9810 * @wdev: Wireless device structure pointer
9811 * @data: Pointer to the data received
9812 * @data_len: Length of the data received
9813 *
9814 * This function is used to get link properties like nss, rate flags and
9815 * operating frequency for the active connection with the given peer.
9816 *
9817 * Return: 0 on success and errno on failure
9818 */
9819static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
9820 struct wireless_dev *wdev,
9821 const void *data,
9822 int data_len)
9823{
Dustin Browna09acf42018-11-08 12:32:26 +05309824 int errno;
9825 struct osif_vdev_sync *vdev_sync;
9826
9827 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
9828 if (errno)
9829 return errno;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309830
Dustin Browna09acf42018-11-08 12:32:26 +05309831 errno = __wlan_hdd_cfg80211_get_link_properties(wiphy, wdev,
9832 data, data_len);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309833
Dustin Browna09acf42018-11-08 12:32:26 +05309834 osif_vdev_sync_op_stop(vdev_sync);
9835
9836 return errno;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309837}
9838
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309839static const struct nla_policy
9840wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
9841 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
Ganesh Kondabattini099e6e82017-06-28 12:24:20 +05309842 [QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST] = {
9843 .type = NLA_NESTED },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309844};
9845
Agrawal Ashish65634612016-08-18 13:24:32 +05309846static const struct nla_policy
9847wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
9848 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
9849 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
9850};
9851
9852/**
9853 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
9854 * @wiphy: Pointer to wireless phy
9855 * @wdev: Pointer to wireless device
9856 * @data: Pointer to data
9857 * @data_len: Length of @data
9858 *
9859 * This function parses the incoming NL vendor command data attributes and
9860 * updates the SAP context about channel_hint and DFS mode.
9861 * If channel_hint is set, SAP will choose that channel
9862 * as operating channel.
9863 *
9864 * If DFS mode is enabled, driver will include DFS channels
9865 * in ACS else driver will skip DFS channels.
9866 *
9867 * Return: 0 on success, negative errno on failure
9868 */
9869static int
9870__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
9871 struct wireless_dev *wdev,
9872 const void *data, int data_len)
9873{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009874 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish65634612016-08-18 13:24:32 +05309875 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
9876 int ret;
9877 struct acs_dfs_policy *acs_policy;
9878 int mode = DFS_MODE_NONE;
9879 int channel_hint = 0;
9880
Dustin Brownfdf17c12018-03-14 12:55:34 -07009881 hdd_enter_dev(wdev->netdev);
Agrawal Ashish65634612016-08-18 13:24:32 +05309882
9883 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9884 hdd_err("Command not allowed in FTM mode");
9885 return -EINVAL;
9886 }
9887
9888 ret = wlan_hdd_validate_context(hdd_ctx);
9889 if (0 != ret)
9890 return ret;
9891
Dustin Brown4ea21db2018-01-05 14:13:17 -08009892 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
9893 data, data_len,
9894 wlan_hdd_set_acs_dfs_config_policy)) {
Agrawal Ashish65634612016-08-18 13:24:32 +05309895 hdd_err("invalid attr");
9896 return -EINVAL;
9897 }
9898
9899 acs_policy = &hdd_ctx->acs_policy;
9900 /*
9901 * SCM sends this attribute to restrict SAP from choosing
9902 * DFS channels from ACS.
9903 */
9904 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
9905 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
9906
9907 if (!IS_DFS_MODE_VALID(mode)) {
9908 hdd_err("attr acs dfs mode is not valid");
9909 return -EINVAL;
9910 }
9911 acs_policy->acs_dfs_mode = mode;
9912
9913 /*
9914 * SCM sends this attribute to provide an active channel,
9915 * to skip redundant ACS between drivers, and save driver start up time
9916 */
9917 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
9918 channel_hint = nla_get_u8(
9919 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
9920
9921 if (!IS_CHANNEL_VALID(channel_hint)) {
9922 hdd_err("acs channel is not valid");
9923 return -EINVAL;
9924 }
9925 acs_policy->acs_channel = channel_hint;
9926
9927 return 0;
9928}
9929
9930/**
9931 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
9932 * @wiphy: wiphy structure pointer
9933 * @wdev: Wireless device structure pointer
9934 * @data: Pointer to the data received
9935 * @data_len: Length of @data
9936 *
9937 * This function parses the incoming NL vendor command data attributes and
9938 * updates the SAP context about channel_hint and DFS mode.
9939 *
9940 * Return: 0 on success; errno on failure
9941 */
9942static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
9943 struct wireless_dev *wdev,
9944 const void *data, int data_len)
9945{
Dustin Brown363b4792019-02-05 16:11:55 -08009946 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08009947 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309948
Dustin Brown363b4792019-02-05 16:11:55 -08009949 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08009950 if (errno)
9951 return errno;
Agrawal Ashish65634612016-08-18 13:24:32 +05309952
Dustin Brownf0f00612019-01-31 16:02:24 -08009953 errno = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
Agrawal Ashish65634612016-08-18 13:24:32 +05309954
Dustin Brown363b4792019-02-05 16:11:55 -08009955 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309956
Dustin Brownf0f00612019-01-31 16:02:24 -08009957 return errno;
Agrawal Ashish65634612016-08-18 13:24:32 +05309958}
9959
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309960/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309961 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
9962 * @mode : cfg80211 dfs mode
9963 *
9964 * Return: return csr sta roam dfs mode else return NONE
9965 */
9966static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
9967 enum dfs_mode mode)
9968{
9969 switch (mode) {
9970 case DFS_MODE_ENABLE:
9971 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309972 case DFS_MODE_DISABLE:
9973 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309974 case DFS_MODE_DEPRIORITIZE:
9975 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309976 default:
9977 hdd_err("STA Roam policy dfs mode is NONE");
9978 return CSR_STA_ROAM_POLICY_NONE;
9979 }
9980}
9981
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05309982/*
9983 * hdd_get_sap_operating_band: Get current operating channel
9984 * for sap.
9985 * @hdd_ctx: hdd context
9986 *
9987 * Return : Corresponding band for SAP operating channel
9988 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009989uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05309990{
Jeff Johnsone5006672017-08-29 14:39:02 -07009991 struct hdd_adapter *adapter;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05309992 uint8_t operating_channel = 0;
9993 uint8_t sap_operating_band = 0;
Srinivas Girigowda576b2352017-08-25 14:44:26 -07009994
Dustin Brown920397d2017-12-13 16:27:50 -08009995 hdd_for_each_adapter(hdd_ctx, adapter) {
9996 if (adapter->device_mode != QDF_SAP_MODE)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05309997 continue;
Dustin Brown920397d2017-12-13 16:27:50 -08009998
Jeff Johnsonb9424862017-10-30 08:49:35 -07009999 operating_channel = adapter->session.ap.operating_channel;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010000 if (IS_24G_CH(operating_channel))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010001 sap_operating_band = BAND_2G;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010002 else if (IS_5G_CH(operating_channel))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010003 sap_operating_band = BAND_5G;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010004 else
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010005 sap_operating_band = BAND_ALL;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010006 }
Dustin Brown920397d2017-12-13 16:27:50 -080010007
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010008 return sap_operating_band;
10009}
10010
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010011static const struct nla_policy
10012wlan_hdd_set_sta_roam_config_policy[
10013QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
10014 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
10015 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
10016};
10017
10018/**
10019 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
10020 * for station connection or roaming.
10021 * @wiphy: Pointer to wireless phy
10022 * @wdev: Pointer to wireless device
10023 * @data: Pointer to data
10024 * @data_len: Length of @data
10025 *
10026 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
10027 * channels needs to be skipped in scanning or not.
10028 * If dfs_mode is disabled, driver will not scan DFS channels.
10029 * If skip_unsafe_channels is set, driver will skip unsafe channels
10030 * in Scanning.
10031 *
10032 * Return: 0 on success, negative errno on failure
10033 */
10034static int
10035__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
10036 struct wireless_dev *wdev,
10037 const void *data, int data_len)
10038{
10039 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010040 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010041 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010042 struct nlattr *tb[
10043 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
10044 int ret;
10045 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
10046 enum dfs_mode mode = DFS_MODE_NONE;
10047 bool skip_unsafe_channels = false;
10048 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010049 uint8_t sap_operating_band;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010050 mac_handle_t mac_handle;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010051
Dustin Brownfdf17c12018-03-14 12:55:34 -070010052 hdd_enter_dev(dev);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010053
10054 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10055 hdd_err("Command not allowed in FTM mode");
10056 return -EINVAL;
10057 }
10058
10059 ret = wlan_hdd_validate_context(hdd_ctx);
10060 if (0 != ret)
10061 return ret;
Dustin Brown4ea21db2018-01-05 14:13:17 -080010062 if (wlan_cfg80211_nla_parse(tb,
10063 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
10064 data, data_len,
10065 wlan_hdd_set_sta_roam_config_policy)) {
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010066 hdd_err("invalid attr");
10067 return -EINVAL;
10068 }
10069 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
10070 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
10071 if (!IS_DFS_MODE_VALID(mode)) {
10072 hdd_err("attr sta roam dfs mode policy is not valid");
10073 return -EINVAL;
10074 }
10075
10076 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
10077
10078 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
10079 skip_unsafe_channels = nla_get_u8(
10080 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010081 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010082 mac_handle = hdd_ctx->mac_handle;
10083 status = sme_update_sta_roam_policy(mac_handle, sta_roam_dfs_mode,
10084 skip_unsafe_channels,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080010085 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010086 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010087
10088 if (!QDF_IS_STATUS_SUCCESS(status)) {
10089 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
10090 return -EINVAL;
10091 }
10092 return 0;
10093}
10094
10095/**
10096 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
10097 * connection and roaming for station.
10098 * @wiphy: wiphy structure pointer
10099 * @wdev: Wireless device structure pointer
10100 * @data: Pointer to the data received
10101 * @data_len: Length of @data
10102 *
10103 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
10104 * channels needs to be skipped in scanning or not.
10105 * If dfs_mode is disabled, driver will not scan DFS channels.
10106 * If skip_unsafe_channels is set, driver will skip unsafe channels
10107 * in Scanning.
10108 * Return: 0 on success; errno on failure
10109 */
10110static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
10111 struct wireless_dev *wdev,
10112 const void *data, int data_len)
10113{
Dustin Browna09acf42018-11-08 12:32:26 +053010114 int errno;
10115 struct osif_vdev_sync *vdev_sync;
10116
10117 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
10118 if (errno)
10119 return errno;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010120
Dustin Browna09acf42018-11-08 12:32:26 +053010121 errno = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev,
10122 data, data_len);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010123
Dustin Browna09acf42018-11-08 12:32:26 +053010124 osif_vdev_sync_op_stop(vdev_sync);
10125
10126 return errno;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010127}
10128
Agrawal Ashish467dde42016-09-08 18:44:22 +053010129#ifdef FEATURE_WLAN_CH_AVOID
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010130
10131static int hdd_validate_avoid_freq_chanlist(
10132 struct hdd_context *hdd_ctx,
10133 struct ch_avoid_ind_type *channel_list)
10134{
10135 unsigned int range_idx, ch_idx;
10136 unsigned int unsafe_channel_index, unsafe_channel_count = 0;
10137 bool ch_found = false;
10138
10139 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
10140 (uint16_t)NUM_CHANNELS);
10141
10142 for (range_idx = 0; range_idx < channel_list->ch_avoid_range_cnt;
10143 range_idx++) {
10144 if ((channel_list->avoid_freq_range[range_idx].start_freq <
10145 CDS_24_GHZ_CHANNEL_1) ||
10146 (channel_list->avoid_freq_range[range_idx].end_freq >
10147 CDS_5_GHZ_CHANNEL_165) ||
10148 (channel_list->avoid_freq_range[range_idx].start_freq >
10149 channel_list->avoid_freq_range[range_idx].end_freq))
10150 continue;
10151
10152 for (ch_idx = channel_list->
10153 avoid_freq_range[range_idx].start_freq;
10154 ch_idx <= channel_list->
10155 avoid_freq_range[range_idx].end_freq;
10156 ch_idx++) {
Ashish Kumar Dhanotiyaaa9fdbb2018-12-14 15:29:14 +053010157 if (INVALID_CHANNEL == wlan_reg_get_chan_enum(ch_idx))
Ashish Kumar Dhanotiyabf00f822018-11-30 20:29:09 +053010158 continue;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010159 for (unsafe_channel_index = 0;
10160 unsafe_channel_index < unsafe_channel_count;
10161 unsafe_channel_index++) {
10162 if (ch_idx ==
10163 hdd_ctx->unsafe_channel_list[
10164 unsafe_channel_index]) {
Dustin Brown632af712018-03-14 15:03:55 -070010165 hdd_info("Duplicate channel %d",
10166 ch_idx);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010167 ch_found = true;
10168 break;
10169 }
10170 }
10171 if (!ch_found) {
10172 hdd_ctx->unsafe_channel_list[
10173 unsafe_channel_count++] = ch_idx;
10174 }
10175 ch_found = false;
10176 }
10177 }
10178 return unsafe_channel_count;
10179}
10180
Agrawal Ashish467dde42016-09-08 18:44:22 +053010181/**
10182 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
10183 * is on unsafe channel.
10184 * @wiphy: wiphy structure pointer
10185 * @wdev: Wireless device structure pointer
10186 * @data: Pointer to the data received
10187 * @data_len: Length of @data
10188 *
10189 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
10190 * on any of unsafe channels.
10191 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
10192 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
10193 *
10194 * Return: 0 on success; errno on failure
10195 */
10196static int
10197__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
10198 struct wireless_dev *wdev,
10199 const void *data, int data_len)
10200{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010201 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010202 int ret;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010203 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
Liangwei Dong6e1a2092017-08-30 16:29:06 +080010204 uint16_t *local_unsafe_list;
hqubf1b6182018-08-14 17:22:41 +080010205 uint16_t unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010206 uint16_t unsafe_channel_index, local_unsafe_list_count;
10207 struct ch_avoid_ind_type *channel_list;
Jeff Johnson2e60a142018-05-20 12:08:12 -070010208 enum QDF_GLOBAL_MODE curr_mode;
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +053010209 uint8_t num_args = 0;
hqubf1b6182018-08-14 17:22:41 +080010210 bool user_set_avoid_channel = true;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010211
Dustin Brownfdf17c12018-03-14 12:55:34 -070010212 hdd_enter_dev(wdev->netdev);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010213
10214 if (!qdf_ctx) {
Jeff Johnson6867ec32017-09-29 20:30:20 -070010215 hdd_err("qdf_ctx is NULL");
Agrawal Ashish467dde42016-09-08 18:44:22 +053010216 return -EINVAL;
10217 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010218 curr_mode = hdd_get_conparam();
10219 if (QDF_GLOBAL_FTM_MODE == curr_mode ||
10220 QDF_GLOBAL_MONITOR_MODE == curr_mode) {
10221 hdd_err("Command not allowed in FTM/MONITOR mode");
Agrawal Ashish467dde42016-09-08 18:44:22 +053010222 return -EINVAL;
10223 }
10224
10225 ret = wlan_hdd_validate_context(hdd_ctx);
10226 if (0 != ret)
10227 return ret;
hqubf1b6182018-08-14 17:22:41 +080010228 if (!data && data_len == 0) {
10229 hdd_debug("Userspace doesn't set avoid frequency channel list");
10230 user_set_avoid_channel = false;
10231 goto process_unsafe_channel;
10232 }
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +053010233 if (!data || data_len < (sizeof(channel_list->ch_avoid_range_cnt) +
10234 sizeof(struct ch_avoid_freq_type))) {
10235 hdd_err("Avoid frequency channel list empty");
10236 return -EINVAL;
10237 }
10238 num_args = (data_len - sizeof(channel_list->ch_avoid_range_cnt)) /
10239 sizeof(channel_list->avoid_freq_range[0].start_freq);
10240
10241 if (num_args < 2 || num_args > CH_AVOID_MAX_RANGE * 2 ||
10242 num_args % 2 != 0) {
10243 hdd_err("Invalid avoid frequency channel list");
10244 return -EINVAL;
10245 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010246
10247 channel_list = (struct ch_avoid_ind_type *)data;
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +053010248 if (channel_list->ch_avoid_range_cnt == 0 ||
10249 channel_list->ch_avoid_range_cnt > CH_AVOID_MAX_RANGE ||
10250 2 * channel_list->ch_avoid_range_cnt != num_args) {
10251 hdd_err("Invalid frequency range count %d",
10252 channel_list->ch_avoid_range_cnt);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010253 return -EINVAL;
10254 }
10255
hqubf1b6182018-08-14 17:22:41 +080010256process_unsafe_channel:
Liangwei Dong6e1a2092017-08-30 16:29:06 +080010257 ret = hdd_clone_local_unsafe_chan(hdd_ctx,
10258 &local_unsafe_list,
10259 &local_unsafe_list_count);
10260 if (0 != ret) {
10261 hdd_err("failed to clone the cur unsafe chan list");
10262 return ret;
10263 }
10264
Agrawal Ashish467dde42016-09-08 18:44:22 +053010265 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
10266 &(hdd_ctx->unsafe_channel_count),
10267 sizeof(hdd_ctx->unsafe_channel_list));
hqubf1b6182018-08-14 17:22:41 +080010268 if (user_set_avoid_channel) {
10269 hdd_ctx->unsafe_channel_count =
10270 hdd_validate_avoid_freq_chanlist(
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010271 hdd_ctx,
10272 channel_list);
hqubf1b6182018-08-14 17:22:41 +080010273 unsafe_channel_count = hdd_ctx->unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010274
hqubf1b6182018-08-14 17:22:41 +080010275 pld_set_wlan_unsafe_channel(qdf_ctx->dev,
10276 hdd_ctx->unsafe_channel_list,
10277 hdd_ctx->unsafe_channel_count);
10278 } else {
10279 unsafe_channel_count = QDF_MIN(
10280 (uint16_t)hdd_ctx->unsafe_channel_count,
10281 (uint16_t)NUM_CHANNELS);
10282 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010283
Agrawal Ashish467dde42016-09-08 18:44:22 +053010284 for (unsafe_channel_index = 0;
hqubf1b6182018-08-14 17:22:41 +080010285 unsafe_channel_index < unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010286 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010287 hdd_debug("Channel %d is not safe",
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010288 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010289 }
Liangwei Dong6e1a2092017-08-30 16:29:06 +080010290 if (hdd_local_unsafe_channel_updated(hdd_ctx, local_unsafe_list,
10291 local_unsafe_list_count))
10292 hdd_unsafe_channel_restart_sap(hdd_ctx);
10293 qdf_mem_free(local_unsafe_list);
10294
Agrawal Ashish467dde42016-09-08 18:44:22 +053010295 return 0;
10296}
10297
10298/**
10299 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
10300 * is on unsafe channel.
10301 * @wiphy: wiphy structure pointer
10302 * @wdev: Wireless device structure pointer
10303 * @data: Pointer to the data received
10304 * @data_len: Length of @data
10305 *
10306 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
10307 * on any of unsafe channels.
10308 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
10309 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
10310 *
10311 * Return: 0 on success; errno on failure
10312 */
10313static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
10314 struct wireless_dev *wdev,
10315 const void *data, int data_len)
10316{
Dustin Brown363b4792019-02-05 16:11:55 -080010317 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080010318 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010319
Dustin Brown363b4792019-02-05 16:11:55 -080010320 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080010321 if (errno)
10322 return errno;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010323
Dustin Brownf0f00612019-01-31 16:02:24 -080010324 errno = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010325
Dustin Brown363b4792019-02-05 16:11:55 -080010326 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010327
Dustin Brownf0f00612019-01-31 16:02:24 -080010328 return errno;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010329}
10330
10331#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010332/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010333 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
10334 * SAP is on unsafe channel.
10335 * @wiphy: wiphy structure pointer
10336 * @wdev: Wireless device structure pointer
10337 * @data: Pointer to the data received
10338 * @data_len: Length of @data
10339 *
10340 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
10341 * driver.
10342 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
10343 * will initiate restart of sap.
10344 *
10345 * Return: 0 on success; errno on failure
10346 */
10347static int
10348__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
10349 struct wireless_dev *wdev,
10350 const void *data, int data_len)
10351{
10352 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010353 struct hdd_adapter *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010354 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010355 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
10356 uint8_t config_channel = 0;
Jeff Johnson87251032017-08-29 13:31:11 -070010357 struct hdd_ap_ctx *ap_ctx;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010358 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053010359 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010360
Dustin Brown491d54b2018-03-14 12:39:11 -070010361 hdd_enter();
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010362
10363 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010364 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010365 return -EINVAL;
10366 }
10367
10368 ret = wlan_hdd_validate_context(hdd_ctx);
10369 if (0 != ret)
10370 return -EINVAL;
10371
Dustin Brown4ea21db2018-01-05 14:13:17 -080010372 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
10373 data, data_len,
10374 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010375 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010376 return -EINVAL;
10377 }
10378
10379 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
10380 if (!test_bit(SOFTAP_BSS_STARTED,
10381 &hostapd_adapter->event_flags)) {
10382 hdd_err("SAP is not started yet. Restart sap will be invalid");
10383 return -EINVAL;
10384 }
10385
10386 config_channel =
10387 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
10388
10389 if (!((IS_24G_CH(config_channel)) ||
10390 (IS_5G_CH(config_channel)))) {
10391 hdd_err("Channel %d is not valid to restart SAP",
10392 config_channel);
10393 return -ENOTSUPP;
10394 }
10395
10396 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -070010397 ap_ctx->sap_config.chan_freq = wlan_reg_chan_to_freq(
10398 hdd_ctx->pdev, config_channel);
Jeff Johnson91df29d2017-10-27 19:29:50 -070010399 ap_ctx->sap_config.ch_params.ch_width =
10400 ap_ctx->sap_config.ch_width_orig;
hqu73bccf22017-10-28 15:34:17 +080010401 ap_ctx->bss_stop_reason = BSS_STOP_DUE_TO_VENDOR_CONFIG_CHAN;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010402
Dustin Brown07901ec2018-09-07 11:02:41 -070010403 wlan_reg_set_channel_params(hdd_ctx->pdev,
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -070010404 config_channel,
10405 wlan_reg_freq_to_chan(hdd_ctx->pdev,
10406 ap_ctx->sap_config.sec_ch_freq),
Dustin Brown07901ec2018-09-07 11:02:41 -070010407 &ap_ctx->sap_config.ch_params);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010408
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080010409 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010410 }
10411
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053010412 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
10413 uint32_t freq_len, i;
10414 uint32_t *freq;
10415 uint8_t chans[QDF_MAX_NUM_CHAN];
10416
10417 hdd_debug("setting mandatory freq/chan list");
10418
10419 freq_len = nla_len(
10420 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
10421 sizeof(uint32_t);
10422
10423 if (freq_len > QDF_MAX_NUM_CHAN) {
10424 hdd_err("insufficient space to hold channels");
10425 return -ENOMEM;
10426 }
10427
10428 freq = nla_data(
10429 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
10430
10431 hdd_debug("freq_len=%d", freq_len);
10432
10433 for (i = 0; i < freq_len; i++) {
10434 chans[i] = ieee80211_frequency_to_channel(freq[i]);
10435 hdd_debug("freq[%d]=%d", i, freq[i]);
10436 }
10437
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010438 status = policy_mgr_set_sap_mandatory_channels(
Dustin Brown76cd2932018-09-11 16:03:05 -070010439 hdd_ctx->psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053010440 if (QDF_IS_STATUS_ERROR(status))
10441 return -EINVAL;
10442 }
10443
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010444 return 0;
10445}
10446
10447/**
10448 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
10449 * @wiphy: wiphy structure pointer
10450 * @wdev: Wireless device structure pointer
10451 * @data: Pointer to the data received
10452 * @data_len: Length of @data
10453 *
10454 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
10455 * driver.
10456 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
10457 * will initiate restart of sap.
10458 *
10459 * Return: 0 on success; errno on failure
10460 */
10461static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
10462 struct wireless_dev *wdev,
10463 const void *data, int data_len)
10464{
Dustin Browna09acf42018-11-08 12:32:26 +053010465 int errno;
10466 struct osif_vdev_sync *vdev_sync;
10467
10468 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
10469 if (errno)
10470 return errno;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010471
Dustin Browna09acf42018-11-08 12:32:26 +053010472 errno = __wlan_hdd_cfg80211_sap_configuration_set(wiphy, wdev,
10473 data, data_len);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010474
Dustin Browna09acf42018-11-08 12:32:26 +053010475 osif_vdev_sync_op_stop(vdev_sync);
10476
10477 return errno;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010478}
10479
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080010480/**
10481 * wlan_hdd_process_wake_lock_stats() - wrapper function to absract cp_stats
10482 * or legacy get_wake_lock_stats API.
10483 * @hdd_ctx: pointer to hdd_ctx
10484 *
10485 * Return: 0 on success; error number otherwise.
10486 */
10487static int wlan_hdd_process_wake_lock_stats(struct hdd_context *hdd_ctx)
10488{
Ashish Kumar Dhanotiya136bc8e2019-06-04 16:20:31 +053010489 return wlan_cfg80211_mc_cp_stats_get_wakelock_stats(hdd_ctx->psoc,
10490 hdd_ctx->wiphy);
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080010491}
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010492
10493/**
10494 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
10495 * @wiphy: wiphy pointer
10496 * @wdev: pointer to struct wireless_dev
10497 * @data: pointer to incoming NL vendor data
10498 * @data_len: length of @data
10499 *
10500 * This function parses the incoming NL vendor command data attributes and
10501 * invokes the SME Api and blocks on a completion variable.
10502 * WMA copies required data and invokes callback
10503 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
10504 *
10505 * Return: 0 on success; error number otherwise.
10506 */
10507static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
10508 struct wireless_dev *wdev,
10509 const void *data,
10510 int data_len)
10511{
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080010512 int ret;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010513 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010514
Dustin Brown491d54b2018-03-14 12:39:11 -070010515 hdd_enter();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010516
10517 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -070010518 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010519 return -EINVAL;
10520 }
10521
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080010522 ret = wlan_hdd_validate_context(hdd_ctx);
10523 if (0 != ret)
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010524 return -EINVAL;
10525
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080010526 ret = wlan_hdd_process_wake_lock_stats(hdd_ctx);
Dustin Browne74003f2018-03-14 12:51:58 -070010527 hdd_exit();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010528 return ret;
10529}
10530
10531/**
10532 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
10533 * @wiphy: wiphy pointer
10534 * @wdev: pointer to struct wireless_dev
10535 * @data: pointer to incoming NL vendor data
10536 * @data_len: length of @data
10537 *
10538 * This function parses the incoming NL vendor command data attributes and
10539 * invokes the SME Api and blocks on a completion variable.
10540 * WMA copies required data and invokes callback
10541 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
10542 *
10543 * Return: 0 on success; error number otherwise.
10544 */
10545static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
10546 struct wireless_dev *wdev,
10547 const void *data, int data_len)
10548{
Dustin Brown363b4792019-02-05 16:11:55 -080010549 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080010550 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010551
Dustin Brown363b4792019-02-05 16:11:55 -080010552 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080010553 if (errno)
10554 return errno;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010555
Dustin Brownf0f00612019-01-31 16:02:24 -080010556 errno = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev,
10557 data, data_len);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010558
Dustin Brown363b4792019-02-05 16:11:55 -080010559 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080010560
10561 return errno;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010562}
10563
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010564/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010565 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
10566 * @wiphy: wiphy structure pointer
10567 * @wdev: Wireless device structure pointer
10568 * @data: Pointer to the data received
10569 * @data_len: Length of @data
10570 *
10571 * This function reads wmi max bus size and fill in the skb with
10572 * NL attributes and send up the NL event.
10573 * Return: 0 on success; errno on failure
10574 */
10575static int
10576__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
10577 struct wireless_dev *wdev,
10578 const void *data, int data_len)
10579{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010580 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010581 int ret_val;
10582 struct sk_buff *skb;
10583 uint32_t nl_buf_len;
10584
Dustin Brown491d54b2018-03-14 12:39:11 -070010585 hdd_enter();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010586
10587 ret_val = wlan_hdd_validate_context(hdd_ctx);
10588 if (ret_val)
10589 return ret_val;
10590
10591 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10592 hdd_err("Command not allowed in FTM mode");
10593 return -EINVAL;
10594 }
10595
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010596 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010597
10598 nl_buf_len = NLMSG_HDRLEN;
10599 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
10600
10601 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
10602 if (!skb) {
10603 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
10604 return -ENOMEM;
10605 }
10606
10607 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
10608 hdd_ctx->wmi_max_len)) {
10609 hdd_err("nla put failure");
10610 goto nla_put_failure;
10611 }
10612
10613 cfg80211_vendor_cmd_reply(skb);
10614
Dustin Browne74003f2018-03-14 12:51:58 -070010615 hdd_exit();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010616
10617 return 0;
10618
10619nla_put_failure:
10620 kfree_skb(skb);
10621 return -EINVAL;
10622}
10623
10624/**
10625 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
10626 * @wiphy: wiphy structure pointer
10627 * @wdev: Wireless device structure pointer
10628 * @data: Pointer to the data received
10629 * @data_len: Length of @data
10630 *
10631 * Return: 0 on success; errno on failure
10632 */
10633static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
10634 struct wireless_dev *wdev,
10635 const void *data, int data_len)
10636{
Dustin Brown363b4792019-02-05 16:11:55 -080010637 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080010638 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010639
Dustin Brown363b4792019-02-05 16:11:55 -080010640 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080010641 if (errno)
10642 return errno;
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010643
Dustin Brownf0f00612019-01-31 16:02:24 -080010644 errno = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010645
Dustin Brown363b4792019-02-05 16:11:55 -080010646 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080010647
10648 return errno;
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010649}
10650
10651/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010652 *__wlan_hdd_cfg80211_setband() - set band
10653 * @wiphy: Pointer to wireless phy
10654 * @wdev: Pointer to wireless device
10655 * @data: Pointer to data
10656 * @data_len: Length of @data
10657 *
10658 * Return: 0 on success, negative errno on failure
10659 */
10660static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
10661 struct wireless_dev *wdev,
10662 const void *data, int data_len)
10663{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010664 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -070010665 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010666 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
10667 int ret;
10668 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
10669 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
10670
Dustin Brown491d54b2018-03-14 12:39:11 -070010671 hdd_enter();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010672
10673 ret = wlan_hdd_validate_context(hdd_ctx);
10674 if (ret)
10675 return ret;
10676
Dustin Brown4ea21db2018-01-05 14:13:17 -080010677 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
10678 data, data_len, policy)) {
Dustin Brownbacc48f2018-03-14 14:48:44 -070010679 hdd_err("Invalid ATTR");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010680 return -EINVAL;
10681 }
10682
10683 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -070010684 hdd_err("attr SETBAND_VALUE failed");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010685 return -EINVAL;
10686 }
10687
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -070010688 ret = hdd_reg_set_band(dev,
10689 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010690
Dustin Browne74003f2018-03-14 12:51:58 -070010691 hdd_exit();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010692 return ret;
10693}
10694
10695/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +053010696 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
10697 * @adapter: hdd adapter
10698 * @channel: channel number
10699 *
10700 * return: QDF status based on success or failure
10701 */
Jeff Johnsone5006672017-08-29 14:39:02 -070010702static QDF_STATUS wlan_hdd_validate_acs_channel(struct hdd_adapter *adapter,
Kapil Gupta94ca6f62016-12-11 18:43:12 +053010703 int channel, int chan_bw)
10704{
10705 if (QDF_STATUS_SUCCESS !=
10706 wlan_hdd_validate_operation_channel(adapter, channel))
10707 return QDF_STATUS_E_FAILURE;
10708 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
10709 channel,
10710 PHY_SINGLE_CHANNEL_CENTERED))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -070010711 hdd_info("channel %d is in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +053010712 return -EINVAL;
10713 }
10714
10715 if ((wlansap_is_channel_leaking_in_nol(
10716 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
10717 channel, chan_bw))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -070010718 hdd_info("channel %d is leaking in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +053010719 return -EINVAL;
10720 }
10721
10722 return 0;
10723
10724}
10725
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010726static void hdd_update_acs_sap_config(struct hdd_context *hdd_ctx,
Jeff Johnson8f8ceb92019-03-24 08:16:55 -070010727 struct sap_config *sap_config,
Kapil Gupta8878ad92017-02-13 11:56:04 +053010728 struct hdd_vendor_chan_info *channel_list)
10729{
Abhinav Kumarb074f2f2018-09-15 15:32:11 +053010730 uint8_t ch_width;
10731 QDF_STATUS status;
Wu Gaoed616a12019-01-16 15:19:21 +080010732 uint32_t channel_bonding_mode;
10733
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -070010734 sap_config->chan_freq = wlan_reg_chan_to_freq(hdd_ctx->pdev,
10735 channel_list->pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +053010736
10737 sap_config->ch_params.center_freq_seg0 =
10738 channel_list->vht_seg0_center_ch;
10739 sap_config->ch_params.center_freq_seg1 =
10740 channel_list->vht_seg1_center_ch;
10741
10742 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
10743 sap_config->ch_params.ch_width = channel_list->chan_width;
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -070010744 if (WLAN_REG_IS_5GHZ_CH_FREQ(sap_config->chan_freq)) {
Abhinav Kumarb074f2f2018-09-15 15:32:11 +053010745 status =
10746 ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
10747 &ch_width);
10748 if (!QDF_IS_STATUS_SUCCESS(status))
10749 hdd_err("Failed to set channel_width");
10750 sap_config->ch_width_orig = ch_width;
10751 } else {
Wu Gaoed616a12019-01-16 15:19:21 +080010752 ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
10753 &channel_bonding_mode);
10754 sap_config->ch_width_orig = channel_bonding_mode ?
10755 eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ;
Abhinav Kumarb074f2f2018-09-15 15:32:11 +053010756 }
Kapil Gupta8878ad92017-02-13 11:56:04 +053010757 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
10758 sap_config->acs_cfg.ch_width = channel_list->chan_width;
10759 sap_config->acs_cfg.vht_seg0_center_ch =
10760 channel_list->vht_seg0_center_ch;
10761 sap_config->acs_cfg.vht_seg1_center_ch =
10762 channel_list->vht_seg1_center_ch;
10763 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
10764}
10765
Jeff Johnsone5006672017-08-29 14:39:02 -070010766static int hdd_update_acs_channel(struct hdd_adapter *adapter, uint8_t reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +053010767 uint8_t channel_cnt,
10768 struct hdd_vendor_chan_info *channel_list)
10769{
Jeff Johnson8f8ceb92019-03-24 08:16:55 -070010770 struct sap_config *sap_config;
Jeff Johnson87251032017-08-29 13:31:11 -070010771 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010772 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Kapil Gupta8878ad92017-02-13 11:56:04 +053010773 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010774 mac_handle_t mac_handle;
Kapil Gupta8878ad92017-02-13 11:56:04 +053010775
Min Liuab6ed4f2018-01-09 13:13:57 +080010776 if (!channel_list) {
10777 hdd_err("channel_list is NULL");
10778 return -EINVAL;
10779 }
10780
Kapil Gupta8878ad92017-02-13 11:56:04 +053010781 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnsonb9424862017-10-30 08:49:35 -070010782 sap_config = &adapter->session.ap.sap_config;
Kapil Gupta8878ad92017-02-13 11:56:04 +053010783
10784 if (QDF_TIMER_STATE_RUNNING ==
Jeff Johnsonb9424862017-10-30 08:49:35 -070010785 qdf_mc_timer_get_current_state(&adapter->session.
Kapil Gupta8878ad92017-02-13 11:56:04 +053010786 ap.vendor_acs_timer)) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070010787 qdf_mc_timer_stop(&adapter->session.ap.vendor_acs_timer);
Kapil Gupta8878ad92017-02-13 11:56:04 +053010788 }
10789
Min Liuab6ed4f2018-01-09 13:13:57 +080010790 if (channel_list->pri_ch == 0) {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010791 /* Check mode, set default channel */
10792 channel_list->pri_ch = 6;
10793 /*
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010794 * sap_select_default_oper_chan(mac_handle,
Kapil Gupta8878ad92017-02-13 11:56:04 +053010795 * sap_config->acs_cfg.hw_mode);
10796 */
10797 }
10798
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010799 mac_handle = hdd_ctx->mac_handle;
Kapil Gupta8878ad92017-02-13 11:56:04 +053010800 switch (reason) {
10801 /* SAP init case */
10802 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
10803 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
10804 /* Update Hostapd */
10805 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
10806 break;
10807
10808 /* DFS detected on current channel */
10809 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
10810 wlan_sap_update_next_channel(
10811 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
10812 channel_list->pri_ch,
10813 channel_list->chan_width);
10814 status = sme_update_new_channel_event(
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010815 mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080010816 adapter->vdev_id);
Kapil Gupta8878ad92017-02-13 11:56:04 +053010817 break;
10818
10819 /* LTE coex event on current channel */
10820 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
10821 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
10822 sap_config->acs_cfg.ch_width = channel_list->chan_width;
Jeff Johnson91df29d2017-10-27 19:29:50 -070010823 hdd_ap_ctx->sap_config.ch_width_orig =
Kapil Gupta8878ad92017-02-13 11:56:04 +053010824 channel_list->chan_width;
Bala Venkatesh8b9bbde2019-07-03 16:25:16 +053010825 wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->vdev_id,
10826 CSA_REASON_LTE_COEX);
Min Liu2fef5792018-01-19 17:59:42 +080010827 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch,
10828 true);
Kapil Gupta8878ad92017-02-13 11:56:04 +053010829 break;
10830
10831 default:
10832 hdd_info("invalid reason for timer invoke");
10833 }
Dustin Browne74003f2018-03-14 12:51:58 -070010834 hdd_exit();
Min Liuab6ed4f2018-01-09 13:13:57 +080010835 return qdf_status_to_os_return(status);
Kapil Gupta8878ad92017-02-13 11:56:04 +053010836}
10837
10838/**
10839 * Define short name for vendor channel set config
10840 */
10841#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
Kapil Gupta8878ad92017-02-13 11:56:04 +053010842#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
10843#define SET_CHAN_PRIMARY_CHANNEL \
10844 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
10845#define SET_CHAN_SECONDARY_CHANNEL \
10846 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
10847#define SET_CHAN_SEG0_CENTER_CHANNEL \
10848 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
10849#define SET_CHAN_SEG1_CENTER_CHANNEL \
10850 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
10851#define SET_CHAN_CHANNEL_WIDTH \
10852 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
10853#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
Kapil Gupta63e75282017-05-18 20:55:10 +053010854#define SET_EXT_ACS_BAND QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND
Kapil Gupta8878ad92017-02-13 11:56:04 +053010855
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053010856static const struct nla_policy acs_chan_config_policy[SET_CHAN_MAX + 1] = {
10857 [SET_CHAN_REASON] = {.type = NLA_U8},
10858 [SET_CHAN_CHAN_LIST] = {.type = NLA_NESTED},
10859};
10860
10861static const struct nla_policy acs_chan_list_policy[SET_CHAN_MAX + 1] = {
10862 [SET_CHAN_PRIMARY_CHANNEL] = {.type = NLA_U8},
10863 [SET_CHAN_SECONDARY_CHANNEL] = {.type = NLA_U8},
10864 [SET_CHAN_SEG0_CENTER_CHANNEL] = {.type = NLA_U8},
10865 [SET_CHAN_SEG1_CENTER_CHANNEL] = {.type = NLA_U8},
10866 [SET_CHAN_CHANNEL_WIDTH] = {.type = NLA_U8},
10867 [SET_EXT_ACS_BAND] = {.type = NLA_U8},
10868};
10869
Kapil Gupta8878ad92017-02-13 11:56:04 +053010870/**
10871 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
10872 * @channel_list: pointer to hdd_vendor_chan_info
10873 * @reason: channel change reason
10874 * @channel_cnt: channel count
10875 * @data: data
10876 * @data_len: data len
10877 *
10878 * Return: 0 on success, negative errno on failure
10879 */
10880static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
10881 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
10882 const void *data, int data_len)
10883{
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053010884 int rem;
10885 uint32_t i = 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +053010886 struct nlattr *tb[SET_CHAN_MAX + 1];
10887 struct nlattr *tb2[SET_CHAN_MAX + 1];
10888 struct nlattr *curr_attr;
10889 struct hdd_vendor_chan_info *channel_list;
10890
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053010891 if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
10892 acs_chan_config_policy)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010893 hdd_err("Invalid ATTR");
10894 return -EINVAL;
10895 }
10896
10897 if (tb[SET_CHAN_REASON])
10898 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
10899
sheenam monga5440bdd2019-03-11 17:32:37 +053010900 if (!tb[SET_CHAN_CHAN_LIST]) {
10901 hdd_err("channel list empty");
10902 return -EINVAL;
10903 }
10904
Kapil Gupta63e75282017-05-18 20:55:10 +053010905 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem)
10906 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +053010907
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053010908 if (i > MAX_CHANNEL) {
10909 hdd_err("Error: Exceeded max channels: %u", MAX_CHANNEL);
10910 return -ENOMEM;
10911 }
10912
10913 *channel_cnt = (uint8_t)i;
Kapil Gupta63e75282017-05-18 20:55:10 +053010914
10915 if (i == 0)
10916 hdd_err("incorrect channel count");
Kapil Gupta8878ad92017-02-13 11:56:04 +053010917
10918 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
10919 (*channel_cnt));
Min Liu74a1a502018-10-10 19:59:07 +080010920 if (!channel_list)
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053010921 return -ENOMEM;
Kapil Gupta8878ad92017-02-13 11:56:04 +053010922
Kapil Gupta63e75282017-05-18 20:55:10 +053010923 i = 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +053010924 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053010925 if (wlan_cfg80211_nla_parse_nested(tb2, SET_CHAN_MAX,
10926 curr_attr,
10927 acs_chan_list_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -080010928 hdd_err("nla_parse failed");
Rajeev Kumar Sirasanagandla2feb4212019-03-14 22:15:02 +053010929 qdf_mem_free(channel_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +053010930 return -EINVAL;
10931 }
Kapil Gupta63e75282017-05-18 20:55:10 +053010932 if (tb2[SET_EXT_ACS_BAND]) {
10933 channel_list[i].band =
10934 nla_get_u8(tb2[SET_EXT_ACS_BAND]);
10935 }
Kapil Gupta8878ad92017-02-13 11:56:04 +053010936 /* Parse and Fetch allowed SSID list*/
10937 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
10938 channel_list[i].pri_ch =
10939 nla_get_u8(
10940 tb2[SET_CHAN_PRIMARY_CHANNEL]);
10941 }
10942 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
10943 channel_list[i].ht_sec_ch =
10944 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
10945 }
10946 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
10947 channel_list[i].vht_seg0_center_ch =
10948 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
10949 }
10950 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
10951 channel_list[i].vht_seg1_center_ch =
10952 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
10953 }
10954 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
10955 channel_list[i].chan_width =
10956 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
10957 }
Kapil Gupta63e75282017-05-18 20:55:10 +053010958 hdd_debug("index %d pri %d sec %d seg0 %d seg1 %d width %d",
Kapil Gupta8878ad92017-02-13 11:56:04 +053010959 i, channel_list[i].pri_ch,
10960 channel_list[i].ht_sec_ch,
10961 channel_list[i].vht_seg0_center_ch,
10962 channel_list[i].vht_seg1_center_ch,
10963 channel_list[i].chan_width);
10964 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +053010965 }
10966 *chan_list_ptr = channel_list;
10967
10968 return 0;
10969}
10970
10971/**
10972 * Undef short names for vendor set channel configuration
10973 */
10974#undef SET_CHAN_REASON
Kapil Gupta8878ad92017-02-13 11:56:04 +053010975#undef SET_CHAN_CHAN_LIST
10976#undef SET_CHAN_PRIMARY_CHANNEL
10977#undef SET_CHAN_SECONDARY_CHANNEL
10978#undef SET_CHAN_SEG0_CENTER_CHANNEL
10979#undef SET_CHAN_SEG1_CENTER_CHANNEL
10980#undef SET_CHAN_CHANNEL_WIDTH
10981#undef SET_CHAN_MAX
10982
10983/**
10984 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
10985 * @wiphy: Pointer to wireless phy
10986 * @wdev: Pointer to wireless device
10987 * @data: Pointer to data
10988 * @data_len: Length of @data
10989 *
10990 * Return: 0 on success, negative errno on failure
10991 */
10992static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
10993 struct wireless_dev *wdev,
10994 const void *data, int data_len)
10995{
10996 int ret_val;
10997 QDF_STATUS qdf_status;
10998 uint8_t channel_cnt = 0, reason = -1;
10999 struct hdd_vendor_chan_info *channel_list = NULL;
Jeff Johnsone5006672017-08-29 14:39:02 -070011000 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011001 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011002 struct hdd_vendor_chan_info *channel_list_ptr;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011003
Dustin Brown491d54b2018-03-14 12:39:11 -070011004 hdd_enter();
Kapil Gupta8878ad92017-02-13 11:56:04 +053011005
11006 ret_val = wlan_hdd_validate_context(hdd_ctx);
11007 if (ret_val)
11008 return ret_val;
11009
11010 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
11011 hdd_err("Command not allowed in FTM mode");
11012 return -EINVAL;
11013 }
11014
11015 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
11016 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
11017 else {
11018 hdd_err("already timeout happened for acs");
11019 return -EINVAL;
11020 }
11021
11022 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
11023 &channel_cnt, data, data_len);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011024 channel_list_ptr = channel_list;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011025 if (ret_val)
11026 return ret_val;
11027
11028 /* Validate channel to be set */
11029 while (channel_cnt && channel_list) {
11030 qdf_status = wlan_hdd_validate_acs_channel(adapter,
11031 channel_list->pri_ch,
11032 channel_list->chan_width);
11033 if (qdf_status == QDF_STATUS_SUCCESS)
11034 break;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011035 else if (channel_cnt == 1) {
11036 hdd_err("invalid channel %d received from app",
11037 channel_list->pri_ch);
11038 channel_list->pri_ch = 0;
11039 break;
11040 }
11041
Kapil Gupta8878ad92017-02-13 11:56:04 +053011042 channel_cnt--;
11043 channel_list++;
11044 }
Min Liuab6ed4f2018-01-09 13:13:57 +080011045
Kapil Gupta8878ad92017-02-13 11:56:04 +053011046 if ((channel_cnt <= 0) || !channel_list) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070011047 hdd_err("no available channel/chanlist %d/%pK", channel_cnt,
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011048 channel_list);
11049 qdf_mem_free(channel_list_ptr);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011050 return -EINVAL;
11051 }
11052
Min Liuab6ed4f2018-01-09 13:13:57 +080011053 hdd_debug("received primary channel as %d", channel_list->pri_ch);
11054
11055 ret_val = hdd_update_acs_channel(adapter, reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011056 channel_cnt, channel_list);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011057 qdf_mem_free(channel_list_ptr);
Min Liuab6ed4f2018-01-09 13:13:57 +080011058 return ret_val;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011059}
11060
11061/**
11062 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
11063 * @wiphy: Pointer to wireless phy
11064 * @wdev: Pointer to wireless device
11065 * @data: Pointer to data
11066 * @data_len: Length of @data
11067 *
11068 * Return: 0 on success, negative errno on failure
11069 */
11070static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
11071 struct wireless_dev *wdev,
11072 const void *data, int data_len)
11073{
Dustin Browna09acf42018-11-08 12:32:26 +053011074 int errno;
11075 struct osif_vdev_sync *vdev_sync;
11076
11077 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
11078 if (errno)
11079 return errno;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011080
Dustin Browna09acf42018-11-08 12:32:26 +053011081 errno = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev,
11082 data, data_len);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011083
Dustin Browna09acf42018-11-08 12:32:26 +053011084 osif_vdev_sync_op_stop(vdev_sync);
11085
11086 return errno;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011087}
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011088
11089/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011090 * wlan_hdd_cfg80211_setband() - Wrapper to setband
11091 * @wiphy: wiphy structure pointer
11092 * @wdev: Wireless device structure pointer
11093 * @data: Pointer to the data received
11094 * @data_len: Length of @data
11095 *
11096 * Return: 0 on success; errno on failure
11097 */
11098static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
11099 struct wireless_dev *wdev,
11100 const void *data, int data_len)
11101{
Dustin Browna09acf42018-11-08 12:32:26 +053011102 int errno;
11103 struct osif_vdev_sync *vdev_sync;
11104
11105 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
11106 if (errno)
11107 return errno;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011108
Dustin Browna09acf42018-11-08 12:32:26 +053011109 errno = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011110
Dustin Browna09acf42018-11-08 12:32:26 +053011111 osif_vdev_sync_op_stop(vdev_sync);
11112
11113 return errno;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011114}
11115
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011116/**
11117 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
11118 * @nl80211_value: Vendor command attribute value
11119 * @wmi_value: Pointer to return converted WMI return value
11120 *
11121 * Convert NL80211 vendor command value for SAR limit set to WMI value
11122 * Return: 0 on success, -1 on invalid value
11123 */
11124static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
11125 u32 *wmi_value)
11126{
11127 int ret = 0;
11128
11129 switch (nl80211_value) {
11130 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
11131 *wmi_value = WMI_SAR_FEATURE_OFF;
11132 break;
11133 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
11134 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
11135 break;
11136 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
11137 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
11138 break;
11139 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
11140 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
11141 break;
11142 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
11143 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
11144 break;
11145 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
11146 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
11147 break;
11148 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
11149 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
11150 break;
Kabilan Kannancaa85502018-04-13 18:04:58 -070011151 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0:
11152 *wmi_value = WMI_SAR_FEATURE_ON_SAR_V2_0;
11153 break;
11154
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011155 default:
11156 ret = -1;
11157 }
11158 return ret;
11159}
11160
Jeff Johnson354c20b2018-07-17 20:15:56 -070011161#ifdef WLAN_FEATURE_SARV1_TO_SARV2
11162/**
11163 * hdd_convert_sarv1_to_sarv2() - convert SAR V1 BDF reference to SAR V2
11164 * @hdd_ctx: The HDD global context
11165 * @tb: The parsed array of netlink attributes
11166 * @sar_limit_cmd: The WMI command to be filled
11167 *
11168 * This feature/function is designed to solve the following problem:
11169 * 1) Userspace application was written to use SARv1 BDF entries
11170 * 2) Product is configured with SAR V2 BDF entries
11171 *
11172 * So if this feature is enabled, and if the firmware is configured
11173 * with SAR V2 support, and if the incoming request is to enable a SAR
11174 * V1 BDF entry, then the WMI command is generated to actually
11175 * configure a SAR V2 BDF entry.
11176 *
11177 * Return: true if conversion was performed and @sar_limit_cmd is
11178 * ready to be sent to firmware. Otherwise false in which case the
11179 * normal parsing logic should be applied.
11180 */
11181
11182static bool
11183hdd_convert_sarv1_to_sarv2(struct hdd_context *hdd_ctx,
11184 struct nlattr *tb[],
11185 struct sar_limit_cmd_params *sar_limit_cmd)
11186{
11187 struct nlattr *attr;
11188 uint32_t bdf_index, set;
11189 struct sar_limit_cmd_row *row;
11190
11191 if (hdd_ctx->sar_version != SAR_VERSION_2) {
11192 hdd_debug("SAR version: %d", hdd_ctx->sar_version);
11193 return false;
11194 }
11195
11196 attr = tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE];
11197 if (!attr)
11198 return false;
11199
11200 bdf_index = nla_get_u32(attr);
11201
11202 if ((bdf_index >= QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0) &&
11203 (bdf_index <= QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4)) {
11204 set = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0;
11205 } else if (bdf_index == QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE) {
11206 set = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE;
11207 bdf_index = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0;
11208 } else {
11209 return false;
11210 }
11211
11212 /* Need two rows to hold the per-chain V2 power index
11213 * To disable SARv2 limit, send chain, num_limits_row and
11214 * power limit set to 0 (except power index 0xff)
11215 */
11216 row = qdf_mem_malloc(2 * sizeof(*row));
11217 if (!row)
11218 return false;
11219
11220 if (wlan_hdd_cfg80211_sar_convert_limit_set(
11221 set, &sar_limit_cmd->sar_enable)) {
11222 hdd_err("Failed to convert SAR limit to WMI value");
11223 return false;
11224 }
11225
11226 sar_limit_cmd->commit_limits = 1;
11227 sar_limit_cmd->num_limit_rows = 2;
11228 sar_limit_cmd->sar_limit_row_list = row;
11229 row[0].limit_value = bdf_index;
11230 row[1].limit_value = row[0].limit_value;
11231 row[0].chain_id = 0;
11232 row[1].chain_id = 1;
11233 row[0].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
11234 row[1].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
11235
11236 return true;
11237}
11238
11239#else /* WLAN_FEATURE_SARV1_TO_SARV2 */
Jeff Johnson354c20b2018-07-17 20:15:56 -070011240static bool
11241hdd_convert_sarv1_to_sarv2(struct hdd_context *hdd_ctx,
11242 struct nlattr *tb[],
11243 struct sar_limit_cmd_params *sar_limit_cmd)
11244{
11245 return false;
11246}
11247
11248#endif /* WLAN_FEATURE_SARV1_TO_SARV2 */
11249
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011250/**
11251 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
11252 * @nl80211_value: Vendor command attribute value
11253 * @wmi_value: Pointer to return converted WMI return value
11254 *
11255 * Convert NL80211 vendor command value for SAR BAND to WMI value
11256 * Return: 0 on success, -1 on invalid value
11257 */
11258static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
11259{
11260 int ret = 0;
11261
11262 switch (nl80211_value) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070011263 case HDD_NL80211_BAND_2GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011264 *wmi_value = WMI_SAR_2G_ID;
11265 break;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070011266 case HDD_NL80211_BAND_5GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011267 *wmi_value = WMI_SAR_5G_ID;
11268 break;
11269 default:
11270 ret = -1;
11271 }
11272 return ret;
11273}
11274
11275/**
11276 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
11277 * @nl80211_value: Vendor command attribute value
11278 * @wmi_value: Pointer to return converted WMI return value
11279 *
11280 * Convert NL80211 vendor command value for SAR Modulation to WMI value
11281 * Return: 0 on success, -1 on invalid value
11282 */
11283static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
11284 u32 *wmi_value)
11285{
11286 int ret = 0;
11287
11288 switch (nl80211_value) {
11289 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
11290 *wmi_value = WMI_SAR_MOD_CCK;
11291 break;
11292 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
11293 *wmi_value = WMI_SAR_MOD_OFDM;
11294 break;
11295 default:
11296 ret = -1;
11297 }
11298 return ret;
11299}
11300
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011301void hdd_store_sar_config(struct hdd_context *hdd_ctx,
11302 struct sar_limit_cmd_params *sar_limit_cmd)
11303{
11304 /* Free the previously stored sar_limit_cmd */
11305 wlan_hdd_free_sar_config(hdd_ctx);
11306
11307 hdd_ctx->sar_cmd_params = sar_limit_cmd;
11308}
11309
11310void wlan_hdd_free_sar_config(struct hdd_context *hdd_ctx)
11311{
11312 struct sar_limit_cmd_params *sar_limit_cmd;
11313
11314 if (!hdd_ctx->sar_cmd_params)
11315 return;
11316
11317 sar_limit_cmd = hdd_ctx->sar_cmd_params;
11318 hdd_ctx->sar_cmd_params = NULL;
11319 qdf_mem_free(sar_limit_cmd->sar_limit_row_list);
11320 qdf_mem_free(sar_limit_cmd);
11321}
11322
11323#define SAR_LIMITS_SAR_ENABLE QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE
11324#define SAR_LIMITS_NUM_SPECS QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS
11325#define SAR_LIMITS_SPEC QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC
11326#define SAR_LIMITS_SPEC_BAND QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND
11327#define SAR_LIMITS_SPEC_CHAIN QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN
11328#define SAR_LIMITS_SPEC_MODULATION \
11329 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION
11330#define SAR_LIMITS_SPEC_POWER_LIMIT \
11331 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT
11332#define SAR_LIMITS_SPEC_POWER_LIMIT_INDEX \
11333 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX
11334#define SAR_LIMITS_MAX QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX
11335
Jeff Johnsonb17a93c2017-06-02 12:26:55 -070011336static const struct nla_policy
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011337sar_limits_policy[SAR_LIMITS_MAX + 1] = {
11338 [SAR_LIMITS_SAR_ENABLE] = {.type = NLA_U32},
11339 [SAR_LIMITS_NUM_SPECS] = {.type = NLA_U32},
11340 [SAR_LIMITS_SPEC_BAND] = {.type = NLA_U32},
11341 [SAR_LIMITS_SPEC_CHAIN] = {.type = NLA_U32},
11342 [SAR_LIMITS_SPEC_MODULATION] = {.type = NLA_U32},
11343 [SAR_LIMITS_SPEC_POWER_LIMIT] = {.type = NLA_U32},
11344 [SAR_LIMITS_SPEC_POWER_LIMIT_INDEX] = {.type = NLA_U32},
Jeff Johnsonb17a93c2017-06-02 12:26:55 -070011345};
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011346
11347/**
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011348 * hdd_extract_sar_nested_attrs() - Extract nested SAR attribute
11349 * @spec: nested nla attribue
11350 * @row: output to hold extract nested attribute
11351 *
11352 * This function extracts nested SAR attribute one at a time which means
11353 * for each nested attribute this has to be invoked from
11354 * __wlan_hdd_set_sar_power_limits().
11355 *
11356 * Return: On success - 0
11357 * On Failure - Negative value
11358 */
11359static int hdd_extract_sar_nested_attrs(struct nlattr *spec[],
11360 struct sar_limit_cmd_row *row)
11361{
11362 uint32_t limit;
11363 uint32_t band;
11364 uint32_t modulation;
11365 int ret;
11366
11367 row->validity_bitmap = 0;
11368
11369 if (spec[SAR_LIMITS_SPEC_POWER_LIMIT]) {
11370 limit = nla_get_u32(spec[SAR_LIMITS_SPEC_POWER_LIMIT]);
11371 row->limit_value = limit;
11372 } else if (spec[SAR_LIMITS_SPEC_POWER_LIMIT_INDEX]) {
11373 limit = nla_get_u32(spec[SAR_LIMITS_SPEC_POWER_LIMIT_INDEX]);
11374 row->limit_value = limit;
11375 } else {
11376 hdd_err("SAR Spec does not have power limit or index value");
11377 return -EINVAL;
11378 }
11379
11380 if (spec[SAR_LIMITS_SPEC_BAND]) {
11381 band = nla_get_u32(spec[SAR_LIMITS_SPEC_BAND]);
11382 ret = wlan_hdd_cfg80211_sar_convert_band(band, &row->band_id);
11383 if (ret) {
11384 hdd_err("Invalid SAR Band attr");
11385 return ret;
11386 }
11387
11388 row->validity_bitmap |= WMI_SAR_BAND_ID_VALID_MASK;
11389 }
11390
11391 if (spec[SAR_LIMITS_SPEC_CHAIN]) {
11392 row->chain_id = nla_get_u32(spec[SAR_LIMITS_SPEC_CHAIN]);
11393 row->validity_bitmap |= WMI_SAR_CHAIN_ID_VALID_MASK;
11394 }
11395
11396 if (spec[SAR_LIMITS_SPEC_MODULATION]) {
11397 modulation = nla_get_u32(spec[SAR_LIMITS_SPEC_MODULATION]);
11398 ret = wlan_hdd_cfg80211_sar_convert_modulation(modulation,
11399 &row->mod_id);
11400 if (ret) {
11401 hdd_err("Invalid SAR Modulation attr");
11402 return ret;
11403 }
11404
11405 row->validity_bitmap |= WMI_SAR_MOD_ID_VALID_MASK;
11406 }
11407
11408 return 0;
11409}
11410
11411/**
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011412 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
11413 * @wiphy: Pointer to wireless phy
11414 * @wdev: Pointer to wireless device
11415 * @data: Pointer to data
11416 * @data_len: Length of @data
11417 *
11418 * This function is used to setup Specific Absorption Rate limit specs.
11419 *
11420 * Return: 0 on success, negative errno on failure
11421 */
11422static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
11423 struct wireless_dev *wdev,
11424 const void *data, int data_len)
11425{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011426 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011427 struct nlattr *spec[SAR_LIMITS_MAX + 1];
11428 struct nlattr *tb[SAR_LIMITS_MAX + 1];
11429 struct nlattr *spec_list;
11430 struct sar_limit_cmd_params *sar_limit_cmd;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011431 int ret = -EINVAL, i = 0, rem = 0;
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011432 QDF_STATUS status;
11433 uint32_t num_limit_rows = 0;
11434 struct sar_limit_cmd_row *row;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011435
Dustin Brown491d54b2018-03-14 12:39:11 -070011436 hdd_enter();
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011437
11438 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
11439 hdd_err("Command not allowed in FTM mode");
11440 return -EPERM;
11441 }
11442
11443 if (wlan_hdd_validate_context(hdd_ctx))
11444 return -EINVAL;
11445
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011446 if (wlan_cfg80211_nla_parse(tb, SAR_LIMITS_MAX, data, data_len,
11447 sar_limits_policy)) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011448 hdd_err("Invalid SAR attributes");
11449 return -EINVAL;
11450 }
11451
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011452 sar_limit_cmd = qdf_mem_malloc(sizeof(struct sar_limit_cmd_params));
11453 if (!sar_limit_cmd)
11454 return -ENOMEM;
11455
Jeff Johnson354c20b2018-07-17 20:15:56 -070011456 /* is special SAR V1 => SAR V2 logic enabled and applicable? */
Ashish Kumar Dhanotiya95498182019-04-29 13:59:20 +053011457 if (hdd_ctx->config->sar_version == 2 &&
11458 (hdd_convert_sarv1_to_sarv2(hdd_ctx, tb, sar_limit_cmd)))
Jeff Johnson354c20b2018-07-17 20:15:56 -070011459 goto send_sar_limits;
11460
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011461 /* Vendor command manadates all SAR Specs in single call */
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011462 sar_limit_cmd->commit_limits = 1;
11463 sar_limit_cmd->sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
11464 if (tb[SAR_LIMITS_SAR_ENABLE]) {
11465 uint32_t sar_enable = nla_get_u32(tb[SAR_LIMITS_SAR_ENABLE]);
11466 uint32_t *sar_ptr = &sar_limit_cmd->sar_enable;
11467
11468 ret = wlan_hdd_cfg80211_sar_convert_limit_set(sar_enable,
11469 sar_ptr);
11470 if (ret) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011471 hdd_err("Invalid SAR Enable attr");
11472 goto fail;
11473 }
11474 }
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011475
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011476 hdd_debug("attr sar sar_enable %d", sar_limit_cmd->sar_enable);
11477
11478 if (tb[SAR_LIMITS_NUM_SPECS]) {
11479 num_limit_rows = nla_get_u32(tb[SAR_LIMITS_NUM_SPECS]);
11480 hdd_debug("attr sar num_limit_rows %u", num_limit_rows);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011481 }
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011482
11483 if (num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011484 hdd_err("SAR Spec list exceed supported size");
11485 goto fail;
11486 }
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011487
11488 if (num_limit_rows == 0)
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011489 goto send_sar_limits;
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011490
11491 row = qdf_mem_malloc(sizeof(*row) * num_limit_rows);
11492 if (!row) {
11493 hdd_err("Failed to allocate memory for sar_limit_row_list");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011494 goto fail;
11495 }
11496
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011497 sar_limit_cmd->num_limit_rows = num_limit_rows;
11498 sar_limit_cmd->sar_limit_row_list = row;
11499
11500 if (!tb[SAR_LIMITS_SPEC]) {
11501 hdd_err("Invalid SAR specification list");
11502 goto fail;
11503 }
11504
11505 nla_for_each_nested(spec_list, tb[SAR_LIMITS_SPEC], rem) {
11506 if (i == num_limit_rows) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011507 hdd_warn("SAR Cmd has excess SPECs in list");
11508 break;
11509 }
11510
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011511 if (wlan_cfg80211_nla_parse(spec,
11512 SAR_LIMITS_MAX,
11513 nla_data(spec_list),
11514 nla_len(spec_list),
Dustin Brown4ea21db2018-01-05 14:13:17 -080011515 sar_limits_policy)) {
11516 hdd_err("nla_parse failed for SAR Spec list");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011517 goto fail;
11518 }
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011519
11520 ret = hdd_extract_sar_nested_attrs(spec, row);
11521 if (ret) {
11522 hdd_err("Failed to extract SAR nested attrs");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011523 goto fail;
11524 }
11525
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011526 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011527 i, row->band_id, row->chain_id, row->mod_id,
11528 row->limit_value, row->validity_bitmap);
11529
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011530 i++;
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011531 row++;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011532 }
11533
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011534 if (i < sar_limit_cmd->num_limit_rows) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011535 hdd_warn("SAR Cmd has less SPECs in list");
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011536 sar_limit_cmd->num_limit_rows = i;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011537 }
11538
11539send_sar_limits:
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011540 status = sme_set_sar_power_limits(hdd_ctx->mac_handle, sar_limit_cmd);
11541 if (QDF_IS_STATUS_ERROR(status)) {
11542 hdd_err("Failed to set sar power limits");
11543 goto fail;
11544 }
11545
11546 /* After SSR, the SAR configuration is lost. As SSR is hidden from
11547 * userland, this command will not come from userspace after a SSR. To
11548 * restore this configuration, save this in hdd context and restore
11549 * after re-init.
11550 */
11551 hdd_store_sar_config(hdd_ctx, sar_limit_cmd);
11552 return 0;
11553
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011554fail:
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011555 if (sar_limit_cmd) {
11556 qdf_mem_free(sar_limit_cmd->sar_limit_row_list);
11557 qdf_mem_free(sar_limit_cmd);
11558 }
11559
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011560 return ret;
11561}
11562
Sourav Mohapatra9036f652019-04-02 15:02:59 +053011563#undef SAR_LIMITS_SAR_ENABLE
11564#undef SAR_LIMITS_NUM_SPECS
11565#undef SAR_LIMITS_SPEC
11566#undef SAR_LIMITS_SPEC_BAND
11567#undef SAR_LIMITS_SPEC_CHAIN
11568#undef SAR_LIMITS_SPEC_MODULATION
11569#undef SAR_LIMITS_SPEC_POWER_LIMIT
11570#undef SAR_LIMITS_SPEC_POWER_LIMIT_INDEX
11571#undef SAR_LIMITS_MAX
11572
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011573/**
11574 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
11575 * @wiphy: Pointer to wireless phy
11576 * @wdev: Pointer to wireless device
11577 * @data: Pointer to data
11578 * @data_len: Length of @data
11579 *
11580 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
11581 *
11582 * Return: 0 on success, negative errno on failure
11583 */
11584static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
11585 struct wireless_dev *wdev,
11586 const void *data,
11587 int data_len)
11588{
Dustin Brown363b4792019-02-05 16:11:55 -080011589 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080011590 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053011591
Dustin Brown363b4792019-02-05 16:11:55 -080011592 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080011593 if (errno)
11594 return errno;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011595
Dustin Brownf0f00612019-01-31 16:02:24 -080011596 errno = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data, data_len);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011597
Dustin Brown363b4792019-02-05 16:11:55 -080011598 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053011599
Dustin Brownf0f00612019-01-31 16:02:24 -080011600 return errno;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011601}
11602
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011603static const struct
11604nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
11605 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
11606 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
11607 .len = QDF_MAC_ADDR_SIZE},
11608};
11609
Jeff Johnson43975142018-07-04 15:33:47 -070011610void wlan_hdd_rso_cmd_status_cb(hdd_handle_t hdd_handle,
11611 struct rso_cmd_status *rso_status)
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053011612{
Jeff Johnson43975142018-07-04 15:33:47 -070011613 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Jeff Johnsone5006672017-08-29 14:39:02 -070011614 struct hdd_adapter *adapter;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053011615
11616 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
11617 if (!adapter) {
11618 hdd_err("adapter NULL");
11619 return;
11620 }
11621
11622 adapter->lfr_fw_status.is_disabled = rso_status->status;
11623 complete(&adapter->lfr_fw_status.disable_lfr_event);
11624}
11625
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011626/**
11627 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
11628 * @wiphy: Pointer to wireless phy
11629 * @wdev: Pointer to wireless device
11630 * @data: Pointer to data
11631 * @data_len: Length of @data
11632 *
11633 * This function is used to enable/disable roaming using vendor commands
11634 *
11635 * Return: 0 on success, negative errno on failure
11636 */
11637static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
11638 struct wireless_dev *wdev,
11639 const void *data, int data_len)
11640{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011641 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011642 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070011643 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011644 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Abhishek Singh1f217ec2017-12-22 11:48:27 +053011645 uint32_t is_fast_roam_enabled;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011646 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +053011647 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053011648 unsigned long rc;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011649 struct hdd_station_ctx *hdd_sta_ctx =
11650 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
11651 mac_handle_t mac_handle;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011652
Dustin Brownfdf17c12018-03-14 12:55:34 -070011653 hdd_enter_dev(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011654
11655 ret = wlan_hdd_validate_context(hdd_ctx);
11656 if (0 != ret)
11657 return ret;
11658
11659 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
11660 hdd_err("Command not allowed in FTM mode");
11661 return -EINVAL;
11662 }
11663
Dustin Brown4ea21db2018-01-05 14:13:17 -080011664 ret = wlan_cfg80211_nla_parse(tb,
11665 QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
11666 qca_wlan_vendor_attr);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011667 if (ret) {
11668 hdd_err("Invalid ATTR");
11669 return -EINVAL;
11670 }
11671
11672 /* Parse and fetch Enable flag */
11673 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
11674 hdd_err("attr enable failed");
11675 return -EINVAL;
11676 }
11677
11678 is_fast_roam_enabled = nla_get_u32(
11679 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Abhishek Singh1f217ec2017-12-22 11:48:27 +053011680 hdd_debug("isFastRoamEnabled %d", is_fast_roam_enabled);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011681
11682 /* Update roaming */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011683 mac_handle = hdd_ctx->mac_handle;
Jeff Johnsoncf07c312019-02-04 13:53:29 -080011684 qdf_status = sme_config_fast_roaming(mac_handle, adapter->vdev_id,
Abhishek Singh1f217ec2017-12-22 11:48:27 +053011685 is_fast_roam_enabled);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +053011686 if (qdf_status != QDF_STATUS_SUCCESS)
11687 hdd_err("sme_config_fast_roaming failed with status=%d",
11688 qdf_status);
11689 ret = qdf_status_to_os_return(qdf_status);
11690
Jeff Johnsone7951512019-02-27 10:02:51 -080011691 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.conn_state &&
Abhishek Singh1f217ec2017-12-22 11:48:27 +053011692 QDF_IS_STATUS_SUCCESS(qdf_status) && !is_fast_roam_enabled) {
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +053011693
11694 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053011695 /*
11696 * wait only for LFR disable in fw as LFR enable
11697 * is always success
11698 */
11699 rc = wait_for_completion_timeout(
11700 &adapter->lfr_fw_status.disable_lfr_event,
11701 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
11702 if (!rc) {
11703 hdd_err("Timed out waiting for RSO CMD status");
11704 return -ETIMEDOUT;
11705 }
11706
11707 if (!adapter->lfr_fw_status.is_disabled) {
11708 hdd_err("Roam disable attempt in FW fails");
11709 return -EBUSY;
11710 }
11711 }
11712
Dustin Browne74003f2018-03-14 12:51:58 -070011713 hdd_exit();
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011714 return ret;
11715}
11716
11717/**
11718 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
11719 * @wiphy: Pointer to wireless phy
11720 * @wdev: Pointer to wireless device
11721 * @data: Pointer to data
11722 * @data_len: Length of @data
11723 *
11724 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
11725 *
11726 * Return: 0 on success, negative errno on failure
11727 */
11728static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
11729 struct wireless_dev *wdev,
11730 const void *data, int data_len)
11731{
Dustin Browna09acf42018-11-08 12:32:26 +053011732 int errno;
11733 struct osif_vdev_sync *vdev_sync;
11734
11735 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
11736 if (errno)
11737 return errno;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011738
Dustin Browna09acf42018-11-08 12:32:26 +053011739 errno = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev,
11740 data, data_len);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011741
Dustin Browna09acf42018-11-08 12:32:26 +053011742 osif_vdev_sync_op_stop(vdev_sync);
11743
11744 return errno;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011745}
11746
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011747/*
11748 * define short names for the global vendor params
11749 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
11750 */
11751#define STATS_SET_INVALID \
11752 QCA_ATTR_NUD_STATS_SET_INVALID
11753#define STATS_SET_START \
11754 QCA_ATTR_NUD_STATS_SET_START
11755#define STATS_GW_IPV4 \
11756 QCA_ATTR_NUD_STATS_GW_IPV4
11757#define STATS_SET_DATA_PKT_INFO \
11758 QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
11759#define STATS_SET_MAX \
11760 QCA_ATTR_NUD_STATS_SET_MAX
11761
11762const struct nla_policy
11763qca_wlan_vendor_set_nud_stats[STATS_SET_MAX + 1] = {
11764 [STATS_SET_START] = {.type = NLA_FLAG },
11765 [STATS_GW_IPV4] = {.type = NLA_U32 },
11766 [STATS_SET_DATA_PKT_INFO] = {.type = NLA_U32 },
11767};
11768
11769/* define short names for the global vendor params */
11770#define CONNECTIVITY_STATS_SET_INVALID \
11771 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
11772#define STATS_PKT_INFO_TYPE \
11773 QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
11774#define STATS_DNS_DOMAIN_NAME \
11775 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
11776#define STATS_SRC_PORT \
11777 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
11778#define STATS_DEST_PORT \
11779 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
11780#define STATS_DEST_IPV4 \
11781 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
11782#define STATS_DEST_IPV6 \
11783 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
11784#define CONNECTIVITY_STATS_SET_MAX \
11785 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
11786
11787const struct nla_policy
11788qca_wlan_vendor_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
11789 [STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
Sourav Mohapatraaaa0f882019-03-07 09:28:40 +053011790 [STATS_DNS_DOMAIN_NAME] = {.type = NLA_NUL_STRING,
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011791 .len = DNS_DOMAIN_NAME_MAX_LEN },
11792 [STATS_SRC_PORT] = {.type = NLA_U32 },
11793 [STATS_DEST_PORT] = {.type = NLA_U32 },
11794 [STATS_DEST_IPV4] = {.type = NLA_U32 },
11795 [STATS_DEST_IPV6] = {.type = NLA_BINARY,
11796 .len = ICMPv6_ADDR_LEN },
11797};
11798
11799/**
11800 * hdd_dns_unmake_name_query() - Convert an uncompressed DNS name to a
11801 * NUL-terminated string
11802 * @name: DNS name
11803 *
11804 * Return: Produce a printable version of a DNS name.
11805 */
11806static inline uint8_t *hdd_dns_unmake_name_query(uint8_t *name)
11807{
11808 uint8_t *p;
11809 unsigned int len;
11810
11811 p = name;
11812 while ((len = *p)) {
11813 *(p++) = '.';
11814 p += len;
11815 }
11816
11817 return name + 1;
11818}
11819
11820/**
11821 * hdd_dns_make_name_query() - Convert a standard NUL-terminated string
11822 * to DNS name
11823 * @string: Name as a NUL-terminated string
11824 * @buf: Buffer in which to place DNS name
11825 *
11826 * DNS names consist of "<length>element" pairs.
11827 *
11828 * Return: Byte following constructed DNS name
11829 */
Sourav Mohapatra47710c32018-11-30 16:27:05 +053011830static uint8_t *hdd_dns_make_name_query(const uint8_t *string,
11831 uint8_t *buf, uint8_t len)
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011832{
11833 uint8_t *length_byte = buf++;
11834 uint8_t c;
11835
Sourav Mohapatra47710c32018-11-30 16:27:05 +053011836 if (string[len - 1]) {
11837 hdd_debug("DNS name is not null terminated");
11838 return NULL;
11839 }
11840
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011841 while ((c = *(string++))) {
11842 if (c == '.') {
11843 *length_byte = buf - length_byte - 1;
11844 length_byte = buf;
11845 }
11846 *(buf++) = c;
11847 }
11848 *length_byte = buf - length_byte - 1;
11849 *(buf++) = '\0';
11850 return buf;
11851}
11852
11853/**
11854 * hdd_set_clear_connectivity_check_stats_info() - set/clear stats info
11855 * @adapter: Pointer to hdd adapter
11856 * @arp_stats_params: arp stats structure to be sent to FW
11857 * @tb: nl attribute
11858 * @is_set_stats: set/clear stats
11859 *
11860 *
11861 * Return: 0 on success, negative errno on failure
11862 */
11863static int hdd_set_clear_connectivity_check_stats_info(
11864 struct hdd_adapter *adapter,
11865 struct set_arp_stats_params *arp_stats_params,
11866 struct nlattr **tb, bool is_set_stats)
11867{
11868 struct nlattr *tb2[CONNECTIVITY_STATS_SET_MAX + 1];
11869 struct nlattr *curr_attr = NULL;
11870 int err = 0;
11871 uint32_t pkt_bitmap;
11872 int rem;
11873
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011874 /* Set NUD command for start tracking is received. */
11875 nla_for_each_nested(curr_attr,
11876 tb[STATS_SET_DATA_PKT_INFO],
11877 rem) {
11878
11879 if (wlan_cfg80211_nla_parse(tb2,
11880 CONNECTIVITY_STATS_SET_MAX,
11881 nla_data(curr_attr), nla_len(curr_attr),
11882 qca_wlan_vendor_set_connectivity_check_stats)) {
11883 hdd_err("nla_parse failed");
11884 err = -EINVAL;
11885 goto end;
11886 }
11887
11888 if (tb2[STATS_PKT_INFO_TYPE]) {
11889 pkt_bitmap = nla_get_u32(tb2[STATS_PKT_INFO_TYPE]);
11890 if (!pkt_bitmap) {
11891 hdd_err("pkt tracking bitmap is empty");
11892 err = -EINVAL;
11893 goto end;
11894 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053011895
11896 if (is_set_stats) {
11897 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
11898 arp_stats_params->flag = true;
11899 adapter->pkt_type_bitmap |=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011900 arp_stats_params->pkt_type_bitmap;
11901
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053011902 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
Srinivas Girigowda683726a2018-09-07 15:10:40 -070011903 if (!tb[STATS_GW_IPV4]) {
11904 hdd_err("GW ipv4 address is not present");
11905 err = -EINVAL;
11906 goto end;
11907 }
11908 arp_stats_params->ip_addr =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011909 nla_get_u32(tb[STATS_GW_IPV4]);
Srinivas Girigowda683726a2018-09-07 15:10:40 -070011910 arp_stats_params->pkt_type =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011911 WLAN_NUD_STATS_ARP_PKT_TYPE;
Srinivas Girigowda683726a2018-09-07 15:10:40 -070011912 adapter->track_arp_ip =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011913 arp_stats_params->ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011914 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053011915
11916 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
11917 uint8_t *domain_name;
11918
11919 if (!tb2[STATS_DNS_DOMAIN_NAME]) {
11920 hdd_err("DNS domain id is not present");
11921 err = -EINVAL;
11922 goto end;
11923 }
11924 domain_name = nla_data(
11925 tb2[STATS_DNS_DOMAIN_NAME]);
11926 adapter->track_dns_domain_len =
11927 nla_len(tb2[
11928 STATS_DNS_DOMAIN_NAME]);
Sourav Mohapatra47710c32018-11-30 16:27:05 +053011929 if (!hdd_dns_make_name_query(
11930 domain_name,
11931 adapter->dns_payload,
11932 adapter->track_dns_domain_len))
11933 adapter->track_dns_domain_len =
11934 0;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053011935 /* DNStracking isn't supported in FW. */
11936 arp_stats_params->pkt_type_bitmap &=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011937 ~CONNECTIVITY_CHECK_SET_DNS;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011938 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053011939
11940 if (pkt_bitmap &
11941 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
11942 if (!tb2[STATS_SRC_PORT] ||
11943 !tb2[STATS_DEST_PORT]) {
11944 hdd_err("Source/Dest port is not present");
11945 err = -EINVAL;
11946 goto end;
11947 }
11948 arp_stats_params->tcp_src_port =
11949 nla_get_u32(
11950 tb2[STATS_SRC_PORT]);
11951 arp_stats_params->tcp_dst_port =
11952 nla_get_u32(
11953 tb2[STATS_DEST_PORT]);
11954 adapter->track_src_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011955 arp_stats_params->tcp_src_port;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053011956 adapter->track_dest_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011957 arp_stats_params->tcp_dst_port;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011958 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053011959
11960 if (pkt_bitmap &
11961 CONNECTIVITY_CHECK_SET_ICMPV4) {
11962 if (!tb2[STATS_DEST_IPV4]) {
11963 hdd_err("destination ipv4 address to track ping packets is not present");
11964 err = -EINVAL;
11965 goto end;
11966 }
11967 arp_stats_params->icmp_ipv4 =
11968 nla_get_u32(
11969 tb2[STATS_DEST_IPV4]);
11970 adapter->track_dest_ipv4 =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011971 arp_stats_params->icmp_ipv4;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053011972 }
11973 } else {
11974 /* clear stats command received */
11975 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
11976 arp_stats_params->flag = false;
11977 adapter->pkt_type_bitmap &=
11978 (~arp_stats_params->pkt_type_bitmap);
11979
11980 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
11981 arp_stats_params->pkt_type =
11982 WLAN_NUD_STATS_ARP_PKT_TYPE;
11983 qdf_mem_zero(&adapter->hdd_stats.
11984 hdd_arp_stats,
11985 sizeof(adapter->hdd_stats.
11986 hdd_arp_stats));
11987 adapter->track_arp_ip = 0;
11988 }
11989
11990 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
11991 /* DNStracking isn't supported in FW. */
11992 arp_stats_params->pkt_type_bitmap &=
11993 ~CONNECTIVITY_CHECK_SET_DNS;
11994 qdf_mem_zero(&adapter->hdd_stats.
11995 hdd_dns_stats,
11996 sizeof(adapter->hdd_stats.
11997 hdd_dns_stats));
11998 qdf_mem_zero(adapter->dns_payload,
11999 adapter->track_dns_domain_len);
12000 adapter->track_dns_domain_len = 0;
12001 }
12002
12003 if (pkt_bitmap &
12004 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
12005 qdf_mem_zero(&adapter->hdd_stats.
12006 hdd_tcp_stats,
12007 sizeof(adapter->hdd_stats.
12008 hdd_tcp_stats));
12009 adapter->track_src_port = 0;
12010 adapter->track_dest_port = 0;
12011 }
12012
12013 if (pkt_bitmap &
12014 CONNECTIVITY_CHECK_SET_ICMPV4) {
12015 qdf_mem_zero(&adapter->hdd_stats.
12016 hdd_icmpv4_stats,
12017 sizeof(adapter->hdd_stats.
12018 hdd_icmpv4_stats));
12019 adapter->track_dest_ipv4 = 0;
12020 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012021 }
12022 } else {
12023 hdd_err("stats list empty");
12024 err = -EINVAL;
12025 goto end;
12026 }
12027 }
12028
12029end:
12030 return err;
12031}
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053012032
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012033static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
12034 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
12035 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
12036 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
12037 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
12038};
12039
12040/**
12041 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
12042 * @wiphy: Pointer to wireless phy
12043 * @wdev: Pointer to wireless device
12044 * @data: Pointer to data
12045 * @data_len: Length of @data
12046 *
12047 * Return: 0 on success, negative errno on failure
12048 */
12049static int
12050__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
12051 struct wireless_dev *wdev,
12052 const void *data,
12053 int data_len)
12054{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012055 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012056 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
12057 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
12058 struct nlattr *apth;
12059 int rem;
12060 int ret = 1;
12061 int print_idx = -1;
12062 int module_id = -1;
12063 int bit_mask = -1;
12064 int status;
12065
Dustin Brown491d54b2018-03-14 12:39:11 -070012066 hdd_enter();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012067
12068 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
12069 hdd_err("Command not allowed in FTM mode");
12070 return -EINVAL;
12071 }
12072
12073 ret = wlan_hdd_validate_context(hdd_ctx);
12074 if (ret != 0)
12075 return -EINVAL;
12076
12077 print_idx = qdf_get_pidx();
12078 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
12079 hdd_err("Invalid print controle object index");
12080 return -EINVAL;
12081 }
12082
Dustin Brown4ea21db2018-01-05 14:13:17 -080012083 if (wlan_cfg80211_nla_parse(tb1,
12084 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
12085 data, data_len,
12086 qca_wlan_vendor_set_trace_level_policy)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012087 hdd_err("Invalid attr");
12088 return -EINVAL;
12089 }
12090
12091 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
12092 hdd_err("attr trace level param failed");
12093 return -EINVAL;
12094 }
12095
12096 nla_for_each_nested(apth,
12097 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -080012098 if (wlan_cfg80211_nla_parse(tb2,
Ashish Kumar Dhanotiya69903252019-03-18 20:23:47 +053012099 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
12100 nla_data(apth), nla_len(apth),
12101 qca_wlan_vendor_set_trace_level_policy)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012102 hdd_err("Invalid attr");
12103 return -EINVAL;
12104 }
12105
12106 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
12107 hdd_err("attr Module ID failed");
12108 return -EINVAL;
12109 }
12110 module_id = nla_get_u32
12111 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
12112
12113 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
12114 hdd_err("attr Verbose mask failed");
12115 return -EINVAL;
12116 }
12117 bit_mask = nla_get_u32
12118 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
12119
12120 status = hdd_qdf_trace_enable(module_id, bit_mask);
12121
12122 if (status != 0)
12123 hdd_err("can not set verbose mask %d for the category %d",
12124 bit_mask, module_id);
12125 }
12126
Dustin Browne74003f2018-03-14 12:51:58 -070012127 hdd_exit();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012128 return ret;
12129}
12130
12131/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +053012132 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
12133 * @wiphy: Pointer to wireless phy
12134 * @wdev: Pointer to wireless device
12135 * @data: Pointer to data
12136 * @data_len: Length of @data
12137 *
12138 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
12139 *
12140 * Return: 0 on success, negative errno on failure
12141 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012142
12143static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
12144 struct wireless_dev *wdev,
12145 const void *data,
12146 int data_len)
12147{
Dustin Brown363b4792019-02-05 16:11:55 -080012148 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080012149 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053012150
Dustin Brown363b4792019-02-05 16:11:55 -080012151 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080012152 if (errno)
12153 return errno;
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012154
Dustin Brownf0f00612019-01-31 16:02:24 -080012155 errno = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev,
12156 data, data_len);
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012157
Dustin Brown363b4792019-02-05 16:11:55 -080012158 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053012159
Dustin Brownf0f00612019-01-31 16:02:24 -080012160 return errno;
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012161}
12162
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012163/**
12164 * __wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
12165 * @wiphy: pointer to wireless wiphy structure.
12166 * @wdev: pointer to wireless_dev structure.
12167 * @data: pointer to apfind configuration data.
12168 * @data_len: the length in byte of apfind data.
12169 *
12170 * This is called when wlan driver needs to send arp stats to
12171 * firmware.
12172 *
12173 * Return: An error code or 0 on success.
12174 */
12175static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
12176 struct wireless_dev *wdev,
12177 const void *data, int data_len)
12178{
12179 struct nlattr *tb[STATS_SET_MAX + 1];
12180 struct net_device *dev = wdev->netdev;
12181 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
12182 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012183 struct set_arp_stats_params arp_stats_params = {0};
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012184 int err = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012185 mac_handle_t mac_handle;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012186
Dustin Brown491d54b2018-03-14 12:39:11 -070012187 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012188
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053012189 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12190 hdd_err("Command not allowed in FTM mode");
12191 return -EINVAL;
12192 }
12193
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012194 err = wlan_hdd_validate_context(hdd_ctx);
12195 if (0 != err)
12196 return err;
12197
Jeff Johnson912b1bb2019-03-06 10:12:36 -080012198 if (adapter->vdev_id == WLAN_UMAC_VDEV_ID_MAX) {
12199 hdd_err("Invalid vdev id");
Yeshwanth Sriram Guntukad5aae7f2017-11-27 14:33:51 +053012200 return -EINVAL;
12201 }
12202
Poddar, Siddarthdf076672018-02-26 14:21:45 +053012203 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070012204 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053012205 return -EINVAL;
12206 }
12207
Jeff Johnson912b1bb2019-03-06 10:12:36 -080012208 err = wlan_cfg80211_nla_parse(tb, STATS_SET_MAX, data, data_len,
12209 qca_wlan_vendor_set_nud_stats);
12210 if (err) {
12211 hdd_err("STATS_SET_START ATTR");
12212 return err;
12213 }
12214
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012215 if (tb[STATS_SET_START]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012216 /* tracking is enabled for stats other than arp. */
12217 if (tb[STATS_SET_DATA_PKT_INFO]) {
12218 err = hdd_set_clear_connectivity_check_stats_info(
12219 adapter,
12220 &arp_stats_params, tb, true);
12221 if (err)
12222 return -EINVAL;
12223
12224 /*
12225 * if only tracking dns, then don't send
12226 * wmi command to FW.
12227 */
12228 if (!arp_stats_params.pkt_type_bitmap)
12229 return err;
12230 } else {
12231 if (!tb[STATS_GW_IPV4]) {
Dustin Browna2868622018-03-20 11:38:14 -070012232 hdd_err("STATS_SET_START CMD");
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012233 return -EINVAL;
12234 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012235
12236 arp_stats_params.pkt_type_bitmap =
12237 CONNECTIVITY_CHECK_SET_ARP;
12238 adapter->pkt_type_bitmap |=
12239 arp_stats_params.pkt_type_bitmap;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012240 arp_stats_params.flag = true;
12241 arp_stats_params.ip_addr =
12242 nla_get_u32(tb[STATS_GW_IPV4]);
12243 adapter->track_arp_ip = arp_stats_params.ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012244 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012245 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012246 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012247 /* clear stats command received. */
12248 if (tb[STATS_SET_DATA_PKT_INFO]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012249 err = hdd_set_clear_connectivity_check_stats_info(
12250 adapter,
12251 &arp_stats_params, tb, false);
12252 if (err)
12253 return -EINVAL;
12254
12255 /*
12256 * if only tracking dns, then don't send
12257 * wmi command to FW.
12258 */
12259 if (!arp_stats_params.pkt_type_bitmap)
12260 return err;
12261 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012262 arp_stats_params.pkt_type_bitmap =
12263 CONNECTIVITY_CHECK_SET_ARP;
12264 adapter->pkt_type_bitmap &=
12265 (~arp_stats_params.pkt_type_bitmap);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012266 arp_stats_params.flag = false;
12267 qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
12268 sizeof(adapter->hdd_stats.hdd_arp_stats));
12269 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
12270 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012271 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012272
Abhinav Kumar50d4dc72018-06-15 16:35:50 +053012273 hdd_debug("STATS_SET_START Received flag %d!", arp_stats_params.flag);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012274
Jeff Johnsoncf07c312019-02-04 13:53:29 -080012275 arp_stats_params.vdev_id = adapter->vdev_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012276
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012277 mac_handle = hdd_ctx->mac_handle;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012278 if (QDF_STATUS_SUCCESS !=
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012279 sme_set_nud_debug_stats(mac_handle, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070012280 hdd_err("STATS_SET_START CMD Failed!");
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012281 return -EINVAL;
12282 }
12283
Dustin Browne74003f2018-03-14 12:51:58 -070012284 hdd_exit();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012285
12286 return err;
12287}
12288
12289/**
12290 * wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
12291 * @wiphy: pointer to wireless wiphy structure.
12292 * @wdev: pointer to wireless_dev structure.
12293 * @data: pointer to apfind configuration data.
12294 * @data_len: the length in byte of apfind data.
12295 *
12296 * This is called when wlan driver needs to send arp stats to
12297 * firmware.
12298 *
12299 * Return: An error code or 0 on success.
12300 */
12301static int wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
12302 struct wireless_dev *wdev,
12303 const void *data, int data_len)
12304{
Dustin Browna09acf42018-11-08 12:32:26 +053012305 int errno;
12306 struct osif_vdev_sync *vdev_sync;
12307
12308 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
12309 if (errno)
12310 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012311
Dustin Browna09acf42018-11-08 12:32:26 +053012312 errno = __wlan_hdd_cfg80211_set_nud_stats(wiphy, wdev, data, data_len);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012313
Dustin Browna09acf42018-11-08 12:32:26 +053012314 osif_vdev_sync_op_stop(vdev_sync);
12315
12316 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012317}
12318
12319#undef STATS_SET_INVALID
12320#undef STATS_SET_START
12321#undef STATS_GW_IPV4
12322#undef STATS_SET_MAX
12323
12324/*
12325 * define short names for the global vendor params
12326 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
12327 */
12328#define STATS_GET_INVALID \
12329 QCA_ATTR_NUD_STATS_SET_INVALID
12330#define COUNT_FROM_NETDEV \
12331 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
12332#define COUNT_TO_LOWER_MAC \
12333 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
12334#define RX_COUNT_BY_LOWER_MAC \
12335 QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
12336#define COUNT_TX_SUCCESS \
12337 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
12338#define RSP_RX_COUNT_BY_LOWER_MAC \
12339 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
12340#define RSP_RX_COUNT_BY_UPPER_MAC \
12341 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
12342#define RSP_COUNT_TO_NETDEV \
12343 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
12344#define RSP_COUNT_OUT_OF_ORDER_DROP \
12345 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
12346#define AP_LINK_ACTIVE \
12347 QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
12348#define AP_LINK_DAD \
12349 QCA_ATTR_NUD_STATS_IS_DAD
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012350#define DATA_PKT_STATS \
12351 QCA_ATTR_NUD_STATS_DATA_PKT_STATS
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012352#define STATS_GET_MAX \
12353 QCA_ATTR_NUD_STATS_GET_MAX
12354
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012355#define CHECK_STATS_INVALID \
12356 QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
12357#define CHECK_STATS_PKT_TYPE \
12358 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
12359#define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
12360 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
12361#define CHECK_STATS_PKT_SRC_PORT \
12362 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
12363#define CHECK_STATS_PKT_DEST_PORT \
12364 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
12365#define CHECK_STATS_PKT_DEST_IPV4 \
12366 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
12367#define CHECK_STATS_PKT_DEST_IPV6 \
12368 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
12369#define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
12370 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
12371#define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
12372 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
12373#define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
12374 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
12375#define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
12376 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
12377#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
12378 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
12379#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
12380 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
12381#define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
12382 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
12383#define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
12384 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
12385#define CHECK_DATA_STATS_MAX \
12386 QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
12387
12388
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012389const struct nla_policy
12390qca_wlan_vendor_get_nud_stats[STATS_GET_MAX + 1] = {
12391 [COUNT_FROM_NETDEV] = {.type = NLA_U16 },
12392 [COUNT_TO_LOWER_MAC] = {.type = NLA_U16 },
12393 [RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
12394 [COUNT_TX_SUCCESS] = {.type = NLA_U16 },
12395 [RSP_RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
12396 [RSP_RX_COUNT_BY_UPPER_MAC] = {.type = NLA_U16 },
12397 [RSP_COUNT_TO_NETDEV] = {.type = NLA_U16 },
12398 [RSP_COUNT_OUT_OF_ORDER_DROP] = {.type = NLA_U16 },
12399 [AP_LINK_ACTIVE] = {.type = NLA_FLAG },
12400 [AP_LINK_DAD] = {.type = NLA_FLAG },
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012401 [DATA_PKT_STATS] = {.type = NLA_U16 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012402};
12403
12404/**
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012405 * hdd_populate_dns_stats_info() - send dns stats info to network stack
12406 * @adapter: pointer to adapter context
12407 * @skb: pointer to skb
12408 *
12409 *
12410 * Return: An error code or 0 on success.
12411 */
12412static int hdd_populate_dns_stats_info(struct hdd_adapter *adapter,
12413 struct sk_buff *skb)
12414{
12415 uint8_t *dns_query;
12416
12417 dns_query = qdf_mem_malloc(adapter->track_dns_domain_len + 1);
Min Liu74a1a502018-10-10 19:59:07 +080012418 if (!dns_query)
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012419 return -EINVAL;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012420
12421 qdf_mem_copy(dns_query, adapter->dns_payload,
12422 adapter->track_dns_domain_len);
12423
12424 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
12425 CONNECTIVITY_CHECK_SET_DNS) ||
12426 nla_put(skb, CHECK_STATS_PKT_DNS_DOMAIN_NAME,
12427 adapter->track_dns_domain_len,
12428 hdd_dns_unmake_name_query(dns_query)) ||
12429 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
12430 adapter->hdd_stats.hdd_dns_stats.tx_dns_req_count) ||
12431 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
12432 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
12433 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
12434 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
12435 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
12436 adapter->hdd_stats.hdd_dns_stats.tx_ack_cnt) ||
12437 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
12438 adapter->hdd_stats.hdd_dns_stats.rx_dns_rsp_count) ||
12439 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
12440 adapter->hdd_stats.hdd_dns_stats.rx_delivered) ||
12441 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
12442 adapter->hdd_stats.hdd_dns_stats.rx_host_drop)) {
12443 hdd_err("nla put fail");
12444 qdf_mem_free(dns_query);
12445 kfree_skb(skb);
12446 return -EINVAL;
12447 }
12448 qdf_mem_free(dns_query);
12449 return 0;
12450}
12451
12452/**
12453 * hdd_populate_tcp_stats_info() - send tcp stats info to network stack
12454 * @adapter: pointer to adapter context
12455 * @skb: pointer to skb
12456 * @pkt_type: tcp pkt type
12457 *
12458 * Return: An error code or 0 on success.
12459 */
12460static int hdd_populate_tcp_stats_info(struct hdd_adapter *adapter,
12461 struct sk_buff *skb,
12462 uint8_t pkt_type)
12463{
12464 switch (pkt_type) {
12465 case CONNECTIVITY_CHECK_SET_TCP_SYN:
12466 /* Fill info for tcp syn packets (tx packet) */
12467 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
12468 CONNECTIVITY_CHECK_SET_TCP_SYN) ||
12469 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
12470 adapter->track_src_port) ||
12471 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
12472 adapter->track_dest_port) ||
12473 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
12474 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_count) ||
12475 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
12476 adapter->hdd_stats.hdd_tcp_stats.
12477 tx_tcp_syn_host_fw_sent) ||
12478 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
12479 adapter->hdd_stats.hdd_tcp_stats.
12480 tx_tcp_syn_host_fw_sent) ||
12481 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
12482 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_ack_cnt)) {
12483 hdd_err("nla put fail");
12484 kfree_skb(skb);
12485 return -EINVAL;
12486 }
12487 break;
12488 case CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
12489 /* Fill info for tcp syn-ack packets (rx packet) */
12490 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
12491 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK) ||
12492 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
12493 adapter->track_src_port) ||
12494 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
12495 adapter->track_dest_port) ||
12496 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
12497 adapter->hdd_stats.hdd_tcp_stats.rx_fw_cnt) ||
12498 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
12499 adapter->hdd_stats.hdd_tcp_stats.
12500 rx_tcp_syn_ack_count) ||
12501 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
12502 adapter->hdd_stats.hdd_tcp_stats.rx_delivered) ||
12503 nla_put_u16(skb,
12504 CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
12505 adapter->hdd_stats.hdd_tcp_stats.rx_host_drop)) {
12506 hdd_err("nla put fail");
12507 kfree_skb(skb);
12508 return -EINVAL;
12509 }
12510 break;
12511 case CONNECTIVITY_CHECK_SET_TCP_ACK:
12512 /* Fill info for tcp ack packets (tx packet) */
12513 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
12514 CONNECTIVITY_CHECK_SET_TCP_ACK) ||
12515 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
12516 adapter->track_src_port) ||
12517 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
12518 adapter->track_dest_port) ||
12519 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
12520 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_count) ||
12521 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
12522 adapter->hdd_stats.hdd_tcp_stats.
12523 tx_tcp_ack_host_fw_sent) ||
12524 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
12525 adapter->hdd_stats.hdd_tcp_stats.
12526 tx_tcp_ack_host_fw_sent) ||
12527 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
12528 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_ack_cnt)) {
12529 hdd_err("nla put fail");
12530 kfree_skb(skb);
12531 return -EINVAL;
12532 }
12533 break;
12534 default:
12535 break;
12536 }
12537 return 0;
12538}
12539
12540/**
12541 * hdd_populate_icmpv4_stats_info() - send icmpv4 stats info to network stack
12542 * @adapter: pointer to adapter context
12543 * @skb: pointer to skb
12544 *
12545 *
12546 * Return: An error code or 0 on success.
12547 */
12548static int hdd_populate_icmpv4_stats_info(struct hdd_adapter *adapter,
12549 struct sk_buff *skb)
12550{
12551 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
12552 CONNECTIVITY_CHECK_SET_ICMPV4) ||
12553 nla_put_u32(skb, CHECK_STATS_PKT_DEST_IPV4,
12554 adapter->track_dest_ipv4) ||
12555 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
12556 adapter->hdd_stats.hdd_icmpv4_stats.tx_icmpv4_req_count) ||
12557 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
12558 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
12559 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
12560 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
12561 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
12562 adapter->hdd_stats.hdd_icmpv4_stats.tx_ack_cnt) ||
12563 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
12564 adapter->hdd_stats.hdd_icmpv4_stats.rx_fw_cnt) ||
12565 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
12566 adapter->hdd_stats.hdd_icmpv4_stats.rx_icmpv4_rsp_count) ||
12567 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
12568 adapter->hdd_stats.hdd_icmpv4_stats.rx_delivered) ||
12569 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
12570 adapter->hdd_stats.hdd_icmpv4_stats.rx_host_drop)) {
12571 hdd_err("nla put fail");
12572 kfree_skb(skb);
12573 return -EINVAL;
12574 }
12575 return 0;
12576}
12577
12578/**
12579 * hdd_populate_connectivity_check_stats_info() - send connectivity stats info
12580 * to network stack
12581 * @adapter: pointer to adapter context
12582 * @skb: pointer to skb
12583 *
12584 *
12585 * Return: An error code or 0 on success.
12586 */
12587
12588static int hdd_populate_connectivity_check_stats_info(
12589 struct hdd_adapter *adapter, struct sk_buff *skb)
12590{
12591 struct nlattr *connect_stats, *connect_info;
12592 uint32_t count = 0;
12593
12594 connect_stats = nla_nest_start(skb, DATA_PKT_STATS);
Jeff Johnsond36fa332019-03-18 13:42:25 -070012595 if (!connect_stats) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012596 hdd_err("nla_nest_start failed");
12597 return -EINVAL;
12598 }
12599
12600 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
12601 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070012602 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012603 hdd_err("nla_nest_start failed count %u", count);
12604 return -EINVAL;
12605 }
12606
12607 if (hdd_populate_dns_stats_info(adapter, skb))
12608 goto put_attr_fail;
12609 nla_nest_end(skb, connect_info);
12610 count++;
12611 }
12612
12613 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
12614 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070012615 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012616 hdd_err("nla_nest_start failed count %u", count);
12617 return -EINVAL;
12618 }
12619 if (hdd_populate_tcp_stats_info(adapter, skb,
12620 CONNECTIVITY_CHECK_SET_TCP_SYN))
12621 goto put_attr_fail;
12622 nla_nest_end(skb, connect_info);
12623 count++;
12624
12625 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070012626 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012627 hdd_err("nla_nest_start failed count %u", count);
12628 return -EINVAL;
12629 }
12630 if (hdd_populate_tcp_stats_info(adapter, skb,
12631 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK))
12632 goto put_attr_fail;
12633 nla_nest_end(skb, connect_info);
12634 count++;
12635
12636 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070012637 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012638 hdd_err("nla_nest_start failed count %u", count);
12639 return -EINVAL;
12640 }
12641 if (hdd_populate_tcp_stats_info(adapter, skb,
12642 CONNECTIVITY_CHECK_SET_TCP_ACK))
12643 goto put_attr_fail;
12644 nla_nest_end(skb, connect_info);
12645 count++;
12646 }
12647
12648 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ICMPV4) {
12649 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070012650 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012651 hdd_err("nla_nest_start failed count %u", count);
12652 return -EINVAL;
12653 }
12654
12655 if (hdd_populate_icmpv4_stats_info(adapter, skb))
12656 goto put_attr_fail;
12657 nla_nest_end(skb, connect_info);
12658 count++;
12659 }
12660
12661 nla_nest_end(skb, connect_stats);
12662 return 0;
12663
12664put_attr_fail:
12665 hdd_err("QCA_WLAN_VENDOR_ATTR put fail. count %u", count);
12666 return -EINVAL;
12667}
12668
12669
12670/**
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012671 * __wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
12672 * @wiphy: pointer to wireless wiphy structure.
12673 * @wdev: pointer to wireless_dev structure.
12674 * @data: pointer to apfind configuration data.
12675 * @data_len: the length in byte of apfind data.
12676 *
12677 * This is called when wlan driver needs to get arp stats to
12678 * firmware.
12679 *
12680 * Return: An error code or 0 on success.
12681 */
12682static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
12683 struct wireless_dev *wdev,
12684 const void *data, int data_len)
12685{
12686 int err = 0;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012687 struct net_device *dev = wdev->netdev;
12688 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
12689 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
12690 struct get_arp_stats_params arp_stats_params;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012691 mac_handle_t mac_handle;
Poddar, Siddarthdb568162017-07-27 18:16:38 +053012692 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012693 uint32_t pkt_type_bitmap;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012694 struct sk_buff *skb;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070012695 struct osif_request *request = NULL;
12696 static const struct osif_request_params params = {
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053012697 .priv_size = 0,
12698 .timeout_ms = WLAN_WAIT_TIME_NUD_STATS,
12699 };
12700 void *cookie = NULL;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012701
Dustin Brown491d54b2018-03-14 12:39:11 -070012702 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012703
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053012704 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12705 hdd_err("Command not allowed in FTM mode");
12706 return -EINVAL;
12707 }
12708
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012709 err = wlan_hdd_validate_context(hdd_ctx);
12710 if (0 != err)
12711 return err;
12712
Rajeev Kumar7f28e8a32017-08-23 15:41:30 -070012713 err = hdd_validate_adapter(adapter);
12714 if (err)
12715 return err;
12716
Poddar, Siddarthdf076672018-02-26 14:21:45 +053012717 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070012718 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053012719 return -EINVAL;
12720 }
12721
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070012722 request = osif_request_alloc(&params);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053012723 if (!request) {
12724 hdd_err("Request allocation failure");
12725 return -ENOMEM;
12726 }
12727
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070012728 cookie = osif_request_cookie(request);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053012729
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012730 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Jeff Johnsoncf07c312019-02-04 13:53:29 -080012731 arp_stats_params.vdev_id = adapter->vdev_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012732
Poddar, Siddarth762c5472018-03-20 14:55:35 +053012733 pkt_type_bitmap = adapter->pkt_type_bitmap;
12734
12735 /* send NUD failure event only when ARP tracking is enabled. */
jitiphil377bcc12018-10-05 19:46:08 +053012736 if (cdp_cfg_get(soc, cfg_dp_enable_data_stall) &&
Poddar, Siddarth762c5472018-03-20 14:55:35 +053012737 (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ARP))
Poddar, Siddarth37033032017-10-11 15:47:40 +053012738 cdp_post_data_stall_event(soc,
12739 DATA_STALL_LOG_INDICATOR_FRAMEWORK,
Poddar, Siddarthdb568162017-07-27 18:16:38 +053012740 DATA_STALL_LOG_NUD_FAILURE,
12741 0xFF, 0XFF,
12742 DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
12743
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012744 mac_handle = hdd_ctx->mac_handle;
12745 if (sme_set_nud_debug_stats_cb(mac_handle, hdd_get_nud_stats_cb,
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053012746 cookie) != QDF_STATUS_SUCCESS) {
12747 hdd_err("Setting NUD debug stats callback failure");
12748 err = -EINVAL;
12749 goto exit;
12750 }
12751
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012752 if (QDF_STATUS_SUCCESS !=
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012753 sme_get_nud_debug_stats(mac_handle, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070012754 hdd_err("STATS_SET_START CMD Failed!");
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053012755 err = -EINVAL;
12756 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012757 }
12758
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070012759 err = osif_request_wait_for_response(request);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053012760 if (err) {
12761 hdd_err("SME timedout while retrieving NUD stats");
12762 err = -ETIMEDOUT;
12763 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012764 }
12765
12766 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
12767 WLAN_NUD_STATS_LEN);
12768 if (!skb) {
12769 hdd_err("%s: cfg80211_vendor_cmd_alloc_reply_skb failed",
12770 __func__);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053012771 err = -ENOMEM;
12772 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012773 }
12774
12775 if (nla_put_u16(skb, COUNT_FROM_NETDEV,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053012776 adapter->hdd_stats.hdd_arp_stats.tx_arp_req_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012777 nla_put_u16(skb, COUNT_TO_LOWER_MAC,
12778 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
12779 nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053012780 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012781 nla_put_u16(skb, COUNT_TX_SUCCESS,
12782 adapter->hdd_stats.hdd_arp_stats.tx_ack_cnt) ||
12783 nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC,
12784 adapter->hdd_stats.hdd_arp_stats.rx_fw_cnt) ||
12785 nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053012786 adapter->hdd_stats.hdd_arp_stats.rx_arp_rsp_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012787 nla_put_u16(skb, RSP_COUNT_TO_NETDEV,
12788 adapter->hdd_stats.hdd_arp_stats.rx_delivered) ||
12789 nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP,
12790 adapter->hdd_stats.hdd_arp_stats.
12791 rx_host_drop_reorder)) {
12792 hdd_err("nla put fail");
12793 kfree_skb(skb);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053012794 err = -EINVAL;
12795 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012796 }
12797 if (adapter->con_status)
12798 nla_put_flag(skb, AP_LINK_ACTIVE);
12799 if (adapter->dad)
12800 nla_put_flag(skb, AP_LINK_DAD);
12801
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012802 /* ARP tracking is done above. */
12803 pkt_type_bitmap &= ~CONNECTIVITY_CHECK_SET_ARP;
12804
12805 if (pkt_type_bitmap) {
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053012806 if (hdd_populate_connectivity_check_stats_info(adapter, skb)) {
12807 err = -EINVAL;
12808 goto exit;
12809 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012810 }
12811
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012812 cfg80211_vendor_cmd_reply(skb);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053012813exit:
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070012814 osif_request_put(request);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012815 return err;
12816}
12817
12818/**
12819 * wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
12820 * @wiphy: pointer to wireless wiphy structure.
12821 * @wdev: pointer to wireless_dev structure.
12822 * @data: pointer to apfind configuration data.
12823 * @data_len: the length in byte of apfind data.
12824 *
12825 * This is called when wlan driver needs to get arp stats to
12826 * firmware.
12827 *
12828 * Return: An error code or 0 on success.
12829 */
12830static int wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
12831 struct wireless_dev *wdev,
12832 const void *data, int data_len)
12833{
Dustin Browna09acf42018-11-08 12:32:26 +053012834 int errno;
12835 struct osif_vdev_sync *vdev_sync;
12836
12837 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
12838 if (errno)
12839 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012840
Dustin Browna09acf42018-11-08 12:32:26 +053012841 errno = __wlan_hdd_cfg80211_get_nud_stats(wiphy, wdev, data, data_len);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012842
Dustin Browna09acf42018-11-08 12:32:26 +053012843 osif_vdev_sync_op_stop(vdev_sync);
12844
12845 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012846}
12847
12848#undef QCA_ATTR_NUD_STATS_SET_INVALID
12849#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
12850#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
12851#undef QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
12852#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
12853#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
12854#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
12855#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
12856#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
12857#undef QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
12858#undef QCA_ATTR_NUD_STATS_GET_MAX
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053012859
Jeff Johnsond0b6c7e2018-07-04 14:53:06 -070012860void hdd_bt_activity_cb(hdd_handle_t hdd_handle, uint32_t bt_activity)
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053012861{
Jeff Johnsond0b6c7e2018-07-04 14:53:06 -070012862 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053012863 int status;
12864
12865 status = wlan_hdd_validate_context(hdd_ctx);
12866 if (0 != status)
12867 return;
12868
12869 if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_ADD)
12870 hdd_ctx->bt_a2dp_active = 1;
12871 else if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_REMOVE)
12872 hdd_ctx->bt_a2dp_active = 0;
12873 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_ADD)
12874 hdd_ctx->bt_vo_active = 1;
12875 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_REMOVE)
12876 hdd_ctx->bt_vo_active = 0;
12877 else
12878 return;
12879
Dustin Brown76cd2932018-09-11 16:03:05 -070012880 ucfg_scan_set_bt_activity(hdd_ctx->psoc, hdd_ctx->bt_a2dp_active);
Srinivas Girigowda6598eea2017-07-06 19:26:19 -070012881 hdd_debug("a2dp_active: %d vo_active: %d", hdd_ctx->bt_a2dp_active,
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053012882 hdd_ctx->bt_vo_active);
12883}
12884
lifengd217d192017-05-09 19:44:16 +080012885struct chain_rssi_priv {
12886 struct chain_rssi_result chain_rssi;
12887};
12888
12889/**
12890 * hdd_get_chain_rssi_cb() - Callback function to get chain rssi
12891 * @context: opaque context originally passed to SME. HDD always passes
12892 * a cookie for the request context
12893 * @data: struct for get chain rssi
12894 *
12895 * This function receives the response/data from the lower layer and
12896 * checks to see if the thread is still waiting then post the results to
12897 * upper layer, if the request has timed out then ignore.
12898 *
12899 * Return: None
12900 */
12901static void hdd_get_chain_rssi_cb(void *context,
12902 struct chain_rssi_result *data)
12903{
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070012904 struct osif_request *request;
lifengd217d192017-05-09 19:44:16 +080012905 struct chain_rssi_priv *priv;
12906
Dustin Brown491d54b2018-03-14 12:39:11 -070012907 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080012908
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070012909 request = osif_request_get(context);
lifengd217d192017-05-09 19:44:16 +080012910 if (!request) {
12911 hdd_err("Obsolete request");
12912 return;
12913 }
12914
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070012915 priv = osif_request_priv(request);
lifengd217d192017-05-09 19:44:16 +080012916 priv->chain_rssi = *data;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070012917 osif_request_complete(request);
12918 osif_request_put(request);
lifengd217d192017-05-09 19:44:16 +080012919}
12920
12921/**
12922 * hdd_post_get_chain_rssi_rsp - send rsp to user space
12923 * @hdd_ctx: pointer to hdd context
12924 * @result: chain rssi result
12925 *
12926 * Return: 0 for success, non-zero for failure
12927 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012928static int hdd_post_get_chain_rssi_rsp(struct hdd_context *hdd_ctx,
lifengd217d192017-05-09 19:44:16 +080012929 struct chain_rssi_result *result)
12930{
12931 struct sk_buff *skb;
lifengd217d192017-05-09 19:44:16 +080012932
12933 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
lifengfe6c3e22018-04-03 12:10:04 +080012934 (sizeof(result->chain_rssi) + NLA_HDRLEN) +
stonez396a9732019-01-16 12:29:16 +080012935 (sizeof(result->chain_evm) + NLA_HDRLEN) +
lifengfe6c3e22018-04-03 12:10:04 +080012936 (sizeof(result->ant_id) + NLA_HDRLEN) +
12937 NLMSG_HDRLEN);
lifengd217d192017-05-09 19:44:16 +080012938
12939 if (!skb) {
12940 hdd_err("cfg80211_vendor_event_alloc failed");
12941 return -ENOMEM;
12942 }
12943
lifengfe6c3e22018-04-03 12:10:04 +080012944 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI,
stonez396a9732019-01-16 12:29:16 +080012945 sizeof(result->chain_rssi),
12946 result->chain_rssi)) {
12947 hdd_err("put fail");
12948 goto nla_put_failure;
12949 }
12950
12951 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_EVM,
12952 sizeof(result->chain_evm),
12953 result->chain_evm)) {
lifengd217d192017-05-09 19:44:16 +080012954 hdd_err("put fail");
12955 goto nla_put_failure;
12956 }
12957
lifengfe6c3e22018-04-03 12:10:04 +080012958 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO,
stonez396a9732019-01-16 12:29:16 +080012959 sizeof(result->ant_id),
12960 result->ant_id)) {
lifengfe6c3e22018-04-03 12:10:04 +080012961 hdd_err("put fail");
12962 goto nla_put_failure;
12963 }
12964
lifengd217d192017-05-09 19:44:16 +080012965 cfg80211_vendor_cmd_reply(skb);
12966 return 0;
12967
12968nla_put_failure:
12969 kfree_skb(skb);
12970 return -EINVAL;
12971}
12972
12973/**
12974 * __wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
12975 * @wiphy: wiphy pointer
12976 * @wdev: pointer to struct wireless_dev
12977 * @data: pointer to incoming NL vendor data
12978 * @data_len: length of @data
12979 *
12980 * Return: 0 on success; error number otherwise.
12981 */
12982static int __wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
12983 struct wireless_dev *wdev,
12984 const void *data,
12985 int data_len)
12986{
Jeff Johnsone5006672017-08-29 14:39:02 -070012987 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012988 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012989 mac_handle_t mac_handle;
lifengd217d192017-05-09 19:44:16 +080012990 struct get_chain_rssi_req_params req_msg;
12991 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
12992 QDF_STATUS status;
12993 int retval;
12994 void *cookie;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070012995 struct osif_request *request;
lifengd217d192017-05-09 19:44:16 +080012996 struct chain_rssi_priv *priv;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070012997 static const struct osif_request_params params = {
lifengd217d192017-05-09 19:44:16 +080012998 .priv_size = sizeof(*priv),
12999 .timeout_ms = WLAN_WAIT_TIME_STATS,
13000 };
13001
Dustin Brown491d54b2018-03-14 12:39:11 -070013002 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080013003
13004 retval = wlan_hdd_validate_context(hdd_ctx);
13005 if (0 != retval)
13006 return retval;
13007
Dustin Brown4ea21db2018-01-05 14:13:17 -080013008 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
13009 data, data_len, NULL)) {
lifengd217d192017-05-09 19:44:16 +080013010 hdd_err("Invalid ATTR");
13011 return -EINVAL;
13012 }
13013
13014 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
13015 hdd_err("attr mac addr failed");
13016 return -EINVAL;
13017 }
13018 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) !=
13019 QDF_MAC_ADDR_SIZE) {
13020 hdd_err("incorrect mac size");
13021 return -EINVAL;
13022 }
13023 memcpy(&req_msg.peer_macaddr,
13024 nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
13025 QDF_MAC_ADDR_SIZE);
Jeff Johnsoncf07c312019-02-04 13:53:29 -080013026 req_msg.session_id = adapter->vdev_id;
lifengd217d192017-05-09 19:44:16 +080013027
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013028 request = osif_request_alloc(&params);
lifengd217d192017-05-09 19:44:16 +080013029 if (!request) {
13030 hdd_err("Request allocation failure");
13031 return -ENOMEM;
13032 }
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013033 cookie = osif_request_cookie(request);
lifengd217d192017-05-09 19:44:16 +080013034
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013035 mac_handle = hdd_ctx->mac_handle;
13036 status = sme_get_chain_rssi(mac_handle,
13037 &req_msg,
13038 hdd_get_chain_rssi_cb,
13039 cookie);
lifengd217d192017-05-09 19:44:16 +080013040 if (QDF_STATUS_SUCCESS != status) {
13041 hdd_err("Unable to get chain rssi");
13042 retval = qdf_status_to_os_return(status);
13043 } else {
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013044 retval = osif_request_wait_for_response(request);
lifengd217d192017-05-09 19:44:16 +080013045 if (retval) {
13046 hdd_err("Target response timed out");
13047 } else {
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013048 priv = osif_request_priv(request);
lifengd217d192017-05-09 19:44:16 +080013049 retval = hdd_post_get_chain_rssi_rsp(hdd_ctx,
13050 &priv->chain_rssi);
13051 if (retval)
13052 hdd_err("Failed to post chain rssi");
13053 }
13054 }
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013055 osif_request_put(request);
lifengd217d192017-05-09 19:44:16 +080013056
Dustin Browne74003f2018-03-14 12:51:58 -070013057 hdd_exit();
lifengd217d192017-05-09 19:44:16 +080013058 return retval;
13059}
13060
13061/**
13062 * wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
13063 * @wiphy: wiphy pointer
13064 * @wdev: pointer to struct wireless_dev
13065 * @data: pointer to incoming NL vendor data
13066 * @data_len: length of @data
13067 *
13068 * Return: 0 on success; error number otherwise.
13069 */
13070static int wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
13071 struct wireless_dev *wdev,
13072 const void *data,
13073 int data_len)
13074{
Dustin Browna09acf42018-11-08 12:32:26 +053013075 int errno;
13076 struct osif_vdev_sync *vdev_sync;
13077
13078 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
13079 if (errno)
13080 return errno;
lifengd217d192017-05-09 19:44:16 +080013081
Dustin Browna09acf42018-11-08 12:32:26 +053013082 errno = __wlan_hdd_cfg80211_get_chain_rssi(wiphy, wdev, data, data_len);
lifengd217d192017-05-09 19:44:16 +080013083
Dustin Browna09acf42018-11-08 12:32:26 +053013084 osif_vdev_sync_op_stop(vdev_sync);
13085
13086 return errno;
lifengd217d192017-05-09 19:44:16 +080013087}
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013088
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053013089/**
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053013090 * wlan_hdd_fill_intf_info() - Fill skb buffer with interface info
13091 * @skb: Pointer to skb
13092 * @info: mac mode info
13093 * @index: attribute type index for nla_nest_start()
13094 *
13095 * Return : 0 on success and errno on failure
13096 */
13097static int wlan_hdd_fill_intf_info(struct sk_buff *skb,
13098 struct connection_info *info, int index)
13099{
13100 struct nlattr *attr;
13101 uint32_t freq;
13102 struct hdd_context *hdd_ctx;
13103 struct hdd_adapter *hdd_adapter;
13104
13105 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13106 if (!hdd_ctx)
13107 goto error;
13108
13109 hdd_adapter = hdd_get_adapter_by_vdev(hdd_ctx, info->vdev_id);
13110 if (!hdd_adapter)
13111 goto error;
13112
13113 attr = nla_nest_start(skb, index);
13114 if (!attr)
13115 goto error;
13116
13117 freq = sme_chn_to_freq(info->channel);
13118
13119 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX,
13120 hdd_adapter->dev->ifindex) ||
13121 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ, freq))
13122 goto error;
13123
13124 nla_nest_end(skb, attr);
13125
13126 return 0;
13127error:
13128 hdd_err("Fill buffer with interface info failed");
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053013129 return -EINVAL;
13130}
13131
13132/**
13133 * wlan_hdd_fill_mac_info() - Fill skb buffer with mac info
13134 * @skb: Pointer to skb
13135 * @info: mac mode info
13136 * @mac_id: MAC id
13137 * @conn_count: number of current connections
13138 *
13139 * Return : 0 on success and errno on failure
13140 */
13141static int wlan_hdd_fill_mac_info(struct sk_buff *skb,
13142 struct connection_info *info, uint32_t mac_id,
13143 uint32_t conn_count)
13144{
13145 struct nlattr *attr, *intf_attr;
13146 uint32_t band = 0, i = 0, j = 0;
13147 bool present = false;
13148
13149 while (i < conn_count) {
13150 if (info[i].mac_id == mac_id) {
13151 present = true;
13152 if (info[i].channel <= SIR_11B_CHANNEL_END)
13153 band |= 1 << NL80211_BAND_2GHZ;
13154 else if (info[i].channel <= SIR_11A_CHANNEL_END)
13155 band |= 1 << NL80211_BAND_5GHZ;
13156 }
13157 i++;
13158 }
13159
13160 if (!present)
13161 return 0;
13162
13163 i = 0;
13164 attr = nla_nest_start(skb, mac_id);
13165 if (!attr)
13166 goto error;
13167
13168 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID, mac_id) ||
13169 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND, band))
13170 goto error;
13171
13172 intf_attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO);
13173 if (!intf_attr)
13174 goto error;
13175
13176 while (i < conn_count) {
13177 if (info[i].mac_id == mac_id) {
13178 if (wlan_hdd_fill_intf_info(skb, &info[i], j))
13179 return -EINVAL;
13180 j++;
13181 }
13182 i++;
13183 }
13184
13185 nla_nest_end(skb, intf_attr);
13186
13187 nla_nest_end(skb, attr);
13188
13189 return 0;
13190error:
13191 hdd_err("Fill buffer with mac info failed");
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053013192 return -EINVAL;
13193}
13194
13195
13196int wlan_hdd_send_mode_change_event(void)
13197{
13198 int err;
13199 struct hdd_context *hdd_ctx;
13200 struct sk_buff *skb;
13201 struct nlattr *attr;
13202 struct connection_info info[MAX_NUMBER_OF_CONC_CONNECTIONS];
13203 uint32_t conn_count, mac_id;
13204
Dustin Brown491d54b2018-03-14 12:39:11 -070013205 hdd_enter();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053013206 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13207 if (!hdd_ctx) {
13208 hdd_err("HDD context is NULL");
13209 return -EINVAL;
13210 }
13211
13212 err = wlan_hdd_validate_context(hdd_ctx);
13213 if (0 != err)
13214 return err;
13215
Dustin Brown76cd2932018-09-11 16:03:05 -070013216 conn_count = policy_mgr_get_connection_info(hdd_ctx->psoc, info);
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053013217 if (!conn_count)
13218 return -EINVAL;
13219
13220 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
13221 (sizeof(uint32_t) * 4) *
13222 MAX_NUMBER_OF_CONC_CONNECTIONS + NLMSG_HDRLEN,
13223 QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX,
13224 GFP_KERNEL);
13225 if (!skb) {
13226 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
13227 return -ENOMEM;
13228 }
13229
13230 attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO);
13231 if (!attr) {
13232 hdd_err("nla_nest_start failed");
13233 kfree_skb(skb);
13234 return -EINVAL;
13235 }
13236
13237 for (mac_id = 0; mac_id < MAX_MAC; mac_id++) {
Lin Baifac77972018-07-05 19:51:49 +080013238 if (wlan_hdd_fill_mac_info(skb, info, mac_id, conn_count)) {
13239 kfree_skb(skb);
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053013240 return -EINVAL;
Lin Baifac77972018-07-05 19:51:49 +080013241 }
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053013242 }
13243
13244 nla_nest_end(skb, attr);
13245
13246 cfg80211_vendor_event(skb, GFP_KERNEL);
Dustin Browne74003f2018-03-14 12:51:58 -070013247 hdd_exit();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053013248
13249 return err;
13250}
13251
Ashish Kumar Dhanotiya1a720e72019-09-06 15:42:05 +053013252
13253/* Short name for QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS command */
13254
13255#define EXTSCAN_CONFIG_MAX \
13256 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
13257#define EXTSCAN_CONFIG_REQUEST_ID \
13258 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
13259#define EXTSCAN_CONFIG_WIFI_BAND \
13260 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND
13261#define ETCAN_CONFIG_MAX_CHANNELS \
13262QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS
13263#define EXTSCAN_RESULTS_NUM_CHANNELS \
13264 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS
13265#define EXTSCAN_RESULTS_CHANNELS \
13266 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS
13267
13268/**
13269 * hdd_remove_dsrc_channels () - remove dsrc chanels
13270 * @hdd_ctx: hdd context
13271 * @wiphy: Pointer to wireless phy
13272 * @chan_list: channel list
13273 * @num_channels: number of channels
13274 *
13275 * Return: none
13276 */
13277static void hdd_remove_dsrc_channels(struct hdd_context *hdd_ctx,
13278 struct wiphy *wiphy, uint32_t *chan_list,
13279 uint8_t *num_channels)
13280{
13281 uint8_t num_chan_temp = 0;
13282 int i;
13283
13284 for (i = 0; i < *num_channels; i++) {
13285 if (!wlan_reg_is_dsrc_chan(hdd_ctx->pdev,
13286 wlan_reg_freq_to_chan(
13287 hdd_ctx->pdev,
13288 chan_list[i]))) {
13289 chan_list[num_chan_temp] = chan_list[i];
13290 num_chan_temp++;
13291 }
13292 }
13293 *num_channels = num_chan_temp;
13294}
13295
13296/**
13297 * hdd_remove_passive_channels () - remove passive channels
13298 * @wiphy: Pointer to wireless phy
13299 * @chan_list: channel list
13300 * @num_channels: number of channels
13301 *
13302 * Return: none
13303 */
13304static void hdd_remove_passive_channels(struct wiphy *wiphy,
13305 uint32_t *chan_list,
13306 uint8_t *num_channels)
13307{
13308 uint8_t num_chan_temp = 0;
13309 int i, j, k;
13310
13311 for (i = 0; i < *num_channels; i++)
13312 for (j = 0; j < HDD_NUM_NL80211_BANDS; j++) {
13313 if (!wiphy->bands[j])
13314 continue;
13315 for (k = 0; k < wiphy->bands[j]->n_channels; k++) {
13316 if ((chan_list[i] ==
13317 wiphy->bands[j]->channels[k].center_freq)
13318 && (!(wiphy->bands[j]->channels[k].flags &
13319 IEEE80211_CHAN_PASSIVE_SCAN))
13320 ) {
13321 chan_list[num_chan_temp] = chan_list[i];
13322 num_chan_temp++;
13323 }
13324 }
13325 }
13326
13327 *num_channels = num_chan_temp;
13328}
13329
13330/**
13331 * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels
13332 * @wiphy: Pointer to wireless phy
13333 * @wdev: Pointer to wireless device
13334 * @data: Pointer to data
13335 * @data_len: Data length
13336 *
13337 * Return: none
13338 */
13339static int
13340__wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
13341 struct wireless_dev
13342 *wdev, const void *data,
13343 int data_len)
13344{
13345 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
13346 struct net_device *dev = wdev->netdev;
13347 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13348 uint32_t chan_list[CFG_VALID_CHANNEL_LIST_LEN] = {0};
13349 uint8_t num_channels = 0, i, buf[256] = {0};
13350 struct nlattr *tb[EXTSCAN_CONFIG_MAX +
13351 1];
13352 uint32_t requestId, maxChannels;
13353 tWifiBand wifi_band;
13354 QDF_STATUS status;
13355 struct sk_buff *reply_skb;
13356 int ret, len = 0;
13357
13358 /* ENTER_DEV() intentionally not used in a frequently invoked API */
13359
13360 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13361 hdd_err("Command not allowed in FTM mode");
13362 return -EPERM;
13363 }
13364
13365 ret = wlan_hdd_validate_context(hdd_ctx);
13366 if (0 != ret)
13367 return -EINVAL;
13368
13369 if (wlan_cfg80211_nla_parse(
13370 tb,
13371 EXTSCAN_CONFIG_MAX,
13372 data, data_len, wlan_hdd_extscan_config_policy)) {
13373 hdd_err("Invalid ATTR");
13374 return -EINVAL;
13375 }
13376
13377 /* Parse and fetch request Id */
13378 if (!tb[EXTSCAN_CONFIG_REQUEST_ID]) {
13379 hdd_err("attr request id failed");
13380 return -EINVAL;
13381 }
13382 requestId =
13383 nla_get_u32(tb
13384 [EXTSCAN_CONFIG_REQUEST_ID]);
13385
13386 /* Parse and fetch wifi band */
13387 if (!tb
13388 [EXTSCAN_CONFIG_WIFI_BAND]) {
13389 hdd_err("attr wifi band failed");
13390 return -EINVAL;
13391 }
13392 wifi_band =
13393 nla_get_u32(tb
13394 [EXTSCAN_CONFIG_WIFI_BAND]);
13395 if (!tb
13396 [ETCAN_CONFIG_MAX_CHANNELS]) {
13397 hdd_err("attr max channels failed");
13398 return -EINVAL;
13399 }
13400 maxChannels =
13401 nla_get_u32(tb
13402 [ETCAN_CONFIG_MAX_CHANNELS]);
13403
13404 if (maxChannels > CFG_VALID_CHANNEL_LIST_LEN) {
13405 hdd_err("Max channels %d exceeded Valid channel list len %d",
13406 maxChannels, CFG_VALID_CHANNEL_LIST_LEN);
13407 return -EINVAL;
13408 }
13409
13410 hdd_err("Req Id: %u Wifi band: %d Max channels: %d", requestId,
13411 wifi_band, maxChannels);
13412 status = sme_get_valid_channels_by_band(hdd_ctx->mac_handle,
13413 wifi_band, chan_list,
13414 &num_channels);
13415 if (QDF_STATUS_SUCCESS != status) {
13416 hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
13417 status);
13418 return -EINVAL;
13419 }
13420
13421 num_channels = QDF_MIN(num_channels, maxChannels);
13422
13423 hdd_remove_dsrc_channels(hdd_ctx, wiphy, chan_list, &num_channels);
13424 if ((QDF_SAP_MODE == adapter->device_mode) ||
13425 !strncmp(hdd_get_fwpath(), "ap", 2))
13426 hdd_remove_passive_channels(wiphy, chan_list,
13427 &num_channels);
13428
13429 hdd_debug("Number of channels: %d", num_channels);
13430 for (i = 0; i < num_channels; i++)
13431 len += scnprintf(buf + len, sizeof(buf) - len,
13432 "%u ", chan_list[i]);
13433
13434 hdd_debug("Channels: %s", buf);
13435
13436 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
13437 sizeof(u32) *
13438 num_channels +
13439 NLMSG_HDRLEN);
13440
13441 if (reply_skb) {
13442 if (nla_put_u32(
13443 reply_skb,
13444 EXTSCAN_RESULTS_NUM_CHANNELS,
13445 num_channels) ||
13446 nla_put(
13447 reply_skb,
13448 EXTSCAN_RESULTS_CHANNELS,
13449 sizeof(u32) * num_channels, chan_list)) {
13450 hdd_err("nla put fail");
13451 kfree_skb(reply_skb);
13452 return -EINVAL;
13453 }
13454 ret = cfg80211_vendor_cmd_reply(reply_skb);
13455 return ret;
13456 }
13457
13458 hdd_err("valid channels: buffer alloc fail");
13459 return -EINVAL;
13460}
13461
13462#undef EXTSCAN_CONFIG_MAX
13463#undef EXTSCAN_CONFIG_REQUEST_ID
13464#undef EXTSCAN_CONFIG_WIFI_BAND
13465#undef ETCAN_CONFIG_MAX_CHANNELS
13466#undef EXTSCAN_RESULTS_NUM_CHANNELS
13467#undef EXTSCAN_RESULTS_CHANNELS
13468
13469/**
13470 * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
13471 * @wiphy: Pointer to wireless phy
13472 * @wdev: Pointer to wireless device
13473 * @data: Pointer to data
13474 * @data_len: Data length
13475 *
13476 * Return: 0 on success, negative errno on failure
13477 */
13478static int wlan_hdd_cfg80211_extscan_get_valid_channels(
13479 struct wiphy *wiphy,
13480 struct wireless_dev *wdev,
13481 const void *data, int data_len)
13482{
13483 struct osif_psoc_sync *psoc_sync;
13484 int errno;
13485
13486 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
13487 if (errno)
13488 return errno;
13489
13490 errno = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev,
13491 data, data_len);
13492
13493 osif_psoc_sync_op_stop(psoc_sync);
13494
13495 return errno;
13496}
13497
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013498const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
13499 {
13500 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13501 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
13502 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +053013503 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013504 .doit = is_driver_dfs_capable
13505 },
Ashish Kumar Dhanotiya1a720e72019-09-06 15:42:05 +053013506 {
13507 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13508 .info.subcmd =
13509 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
13510 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13511 WIPHY_VENDOR_CMD_NEED_NETDEV |
13512 WIPHY_VENDOR_CMD_NEED_RUNNING,
13513 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
13514 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013515
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013516#ifdef WLAN_FEATURE_STATS_EXT
13517 {
13518 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13519 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
13520 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13521 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
13522 .doit = wlan_hdd_cfg80211_stats_ext_request
13523 },
13524#endif
13525#ifdef FEATURE_WLAN_EXTSCAN
13526 {
13527 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13528 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
13529 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13530 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
13531 .doit = wlan_hdd_cfg80211_extscan_start
13532 },
13533 {
13534 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13535 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
13536 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13537 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
13538 .doit = wlan_hdd_cfg80211_extscan_stop
13539 },
13540 {
13541 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013542 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
13543 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13544 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
13545 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
13546 },
13547 {
13548 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13549 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
13550 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13551 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
13552 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
13553 },
13554 {
13555 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13556 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
13557 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13558 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
13559 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
13560 },
13561 {
13562 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13563 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
13564 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13565 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
13566 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
13567 },
13568 {
13569 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13570 .info.subcmd =
13571 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
13572 .flags =
13573 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
13574 WIPHY_VENDOR_CMD_NEED_RUNNING,
13575 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
13576 },
13577 {
13578 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13579 .info.subcmd =
13580 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
13581 .flags =
13582 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
13583 WIPHY_VENDOR_CMD_NEED_RUNNING,
13584 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
13585 },
13586 {
13587 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13588 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
13589 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13590 WIPHY_VENDOR_CMD_NEED_NETDEV |
13591 WIPHY_VENDOR_CMD_NEED_RUNNING,
13592 .doit = wlan_hdd_cfg80211_set_epno_list
13593 },
13594#endif /* FEATURE_WLAN_EXTSCAN */
13595
13596#ifdef WLAN_FEATURE_LINK_LAYER_STATS
13597 {
13598 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13599 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
13600 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13601 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
13602 .doit = wlan_hdd_cfg80211_ll_stats_clear
13603 },
13604
13605 {
13606 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13607 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
13608 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13609 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
13610 .doit = wlan_hdd_cfg80211_ll_stats_set
13611 },
13612
13613 {
13614 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13615 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
13616 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13617 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
13618 .doit = wlan_hdd_cfg80211_ll_stats_get
13619 },
13620#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
13621#ifdef FEATURE_WLAN_TDLS
13622 {
13623 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13624 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
13625 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13626 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
13627 .doit = wlan_hdd_cfg80211_exttdls_enable
13628 },
13629 {
13630 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13631 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
13632 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13633 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
13634 .doit = wlan_hdd_cfg80211_exttdls_disable
13635 },
13636 {
13637 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13638 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
13639 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
13640 .doit = wlan_hdd_cfg80211_exttdls_get_status
13641 },
13642#endif
13643 {
13644 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13645 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
13646 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
13647 .doit = wlan_hdd_cfg80211_get_supported_features
13648 },
13649 {
13650 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13651 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053013652 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13653 WIPHY_VENDOR_CMD_NEED_NETDEV |
13654 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013655 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
13656 },
Qiwei Caie689a262018-07-26 15:50:22 +080013657
13658 FEATURE_CONCURRENCY_MATRIX_VENDOR_COMMANDS
13659
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660 {
13661 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13662 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
13663 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053013664 WIPHY_VENDOR_CMD_NEED_NETDEV |
13665 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013666 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
13667 },
Manikandan Mohan80dea792016-04-28 16:36:48 -070013668 {
13669 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13670 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
13671 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053013672 WIPHY_VENDOR_CMD_NEED_NETDEV |
13673 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -070013674 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
13675 },
Qiwei Caie689a262018-07-26 15:50:22 +080013676
13677 FEATURE_STATION_INFO_VENDOR_COMMANDS
13678
Anurag Chouhan96919482016-07-13 16:36:57 +053013679 {
13680 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013681 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
13682 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13683 WIPHY_VENDOR_CMD_NEED_NETDEV |
13684 WIPHY_VENDOR_CMD_NEED_RUNNING,
13685 .doit = wlan_hdd_cfg80211_do_acs
13686 },
13687
13688 {
13689 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13690 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
13691 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13692 WIPHY_VENDOR_CMD_NEED_NETDEV,
13693 .doit = wlan_hdd_cfg80211_get_features
13694 },
13695#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13696 {
13697 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13698 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
13699 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13700 WIPHY_VENDOR_CMD_NEED_NETDEV |
13701 WIPHY_VENDOR_CMD_NEED_RUNNING,
13702 .doit = wlan_hdd_cfg80211_keymgmt_set_key
13703 },
13704#endif
13705#ifdef FEATURE_WLAN_EXTSCAN
13706 {
13707 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13708 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
13709 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13710 WIPHY_VENDOR_CMD_NEED_NETDEV |
13711 WIPHY_VENDOR_CMD_NEED_RUNNING,
13712 .doit = wlan_hdd_cfg80211_set_passpoint_list
13713 },
13714 {
13715 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13716 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
13717 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13718 WIPHY_VENDOR_CMD_NEED_NETDEV |
13719 WIPHY_VENDOR_CMD_NEED_RUNNING,
13720 .doit = wlan_hdd_cfg80211_reset_passpoint_list
13721 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013722#endif /* FEATURE_WLAN_EXTSCAN */
13723 {
13724 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13725 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
13726 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13727 WIPHY_VENDOR_CMD_NEED_NETDEV,
13728 .doit = wlan_hdd_cfg80211_get_wifi_info
13729 },
13730 {
13731 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13732 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
13733 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13734 WIPHY_VENDOR_CMD_NEED_NETDEV |
13735 WIPHY_VENDOR_CMD_NEED_RUNNING,
13736 .doit = wlan_hdd_cfg80211_wifi_configuration_set
13737 },
13738 {
13739 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Paul Zhangc9dbaee2019-06-23 22:07:31 +080013740 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION,
13741 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13742 WIPHY_VENDOR_CMD_NEED_NETDEV |
13743 WIPHY_VENDOR_CMD_NEED_RUNNING,
13744 .doit = wlan_hdd_cfg80211_wifi_configuration_get
13745 },
13746 {
13747 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -080013748 .info.subcmd =
13749 QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION,
13750 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13751 WIPHY_VENDOR_CMD_NEED_NETDEV |
13752 WIPHY_VENDOR_CMD_NEED_RUNNING,
13753 .doit = wlan_hdd_cfg80211_set_wifi_test_config
13754 },
13755
13756 {
13757 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013758 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
13759 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053013760 WIPHY_VENDOR_CMD_NEED_NETDEV |
13761 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013762 .doit = wlan_hdd_cfg80211_set_ext_roam_params
13763 },
13764 {
13765 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13766 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
13767 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053013768 WIPHY_VENDOR_CMD_NEED_NETDEV |
13769 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013770 .doit = wlan_hdd_cfg80211_wifi_logger_start
13771 },
13772 {
13773 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13774 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
13775 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053013776 WIPHY_VENDOR_CMD_NEED_NETDEV |
13777 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013778 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
13779 },
13780 {
13781 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13782 .info.subcmd =
13783 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
13784 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13785 WIPHY_VENDOR_CMD_NEED_NETDEV |
13786 WIPHY_VENDOR_CMD_NEED_RUNNING,
13787 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
13788 },
13789 {
13790 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13791 .info.subcmd =
13792 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
13793 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13794 WIPHY_VENDOR_CMD_NEED_NETDEV |
13795 WIPHY_VENDOR_CMD_NEED_RUNNING,
13796 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
13797 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070013798#ifdef WLAN_FEATURE_TSF
13799 {
13800 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13801 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
13802 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13803 WIPHY_VENDOR_CMD_NEED_NETDEV |
13804 WIPHY_VENDOR_CMD_NEED_RUNNING,
13805 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
13806 },
13807#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013808#ifdef FEATURE_WLAN_TDLS
13809 {
13810 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13811 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
13812 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13813 WIPHY_VENDOR_CMD_NEED_NETDEV |
13814 WIPHY_VENDOR_CMD_NEED_RUNNING,
13815 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
13816 },
13817#endif
13818#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
13819 {
13820 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13821 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
13822 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13823 WIPHY_VENDOR_CMD_NEED_NETDEV |
13824 WIPHY_VENDOR_CMD_NEED_RUNNING,
13825 .doit = wlan_hdd_cfg80211_offloaded_packets
13826 },
13827#endif
Qiwei Caie689a262018-07-26 15:50:22 +080013828 FEATURE_RSSI_MONITOR_VENDOR_COMMANDS
Paul Zhangda2970b2019-06-23 18:16:38 +080013829 FEATURE_OEM_DATA_VENDOR_COMMANDS
Paul Zhang37185672019-05-14 11:20:14 +080013830 FEATURE_INTEROP_ISSUES_AP_VENDOR_COMMANDS
Qiwei Caie689a262018-07-26 15:50:22 +080013831
Qiwei Cai1083f5b2018-07-02 19:10:11 +080013832#ifdef WLAN_NS_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013833 {
13834 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053013835 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
13836 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13837 WIPHY_VENDOR_CMD_NEED_NETDEV |
13838 WIPHY_VENDOR_CMD_NEED_RUNNING,
13839 .doit = wlan_hdd_cfg80211_set_ns_offload
13840 },
Qiwei Cai1083f5b2018-07-02 19:10:11 +080013841#endif /* WLAN_NS_OFFLOAD */
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053013842 {
13843 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013844 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
13845 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Sourav Mohapatra412ceb92018-03-07 18:41:16 +053013846 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013847 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
13848 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013849 {
13850 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13851 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
13852 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13853 WIPHY_VENDOR_CMD_NEED_NETDEV |
13854 WIPHY_VENDOR_CMD_NEED_RUNNING,
13855 .doit = wlan_hdd_cfg80211_vendor_scan
13856 },
13857
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053013858 /* Vendor abort scan */
13859 {
13860 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13861 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
13862 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13863 WIPHY_VENDOR_CMD_NEED_NETDEV |
13864 WIPHY_VENDOR_CMD_NEED_RUNNING,
13865 .doit = wlan_hdd_vendor_abort_scan
13866 },
13867
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013868 /* OCB commands */
13869 {
13870 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13871 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
13872 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13873 WIPHY_VENDOR_CMD_NEED_NETDEV |
13874 WIPHY_VENDOR_CMD_NEED_RUNNING,
13875 .doit = wlan_hdd_cfg80211_ocb_set_config
13876 },
13877 {
13878 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13879 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
13880 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13881 WIPHY_VENDOR_CMD_NEED_NETDEV |
13882 WIPHY_VENDOR_CMD_NEED_RUNNING,
13883 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
13884 },
13885 {
13886 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13887 .info.subcmd =
13888 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
13889 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13890 WIPHY_VENDOR_CMD_NEED_NETDEV |
13891 WIPHY_VENDOR_CMD_NEED_RUNNING,
13892 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
13893 },
13894 {
13895 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13896 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
13897 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13898 WIPHY_VENDOR_CMD_NEED_NETDEV |
13899 WIPHY_VENDOR_CMD_NEED_RUNNING,
13900 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
13901 },
13902 {
13903 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13904 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
13905 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13906 WIPHY_VENDOR_CMD_NEED_NETDEV |
13907 WIPHY_VENDOR_CMD_NEED_RUNNING,
13908 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
13909 },
13910 {
13911 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13912 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
13913 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13914 WIPHY_VENDOR_CMD_NEED_NETDEV |
13915 WIPHY_VENDOR_CMD_NEED_RUNNING,
13916 .doit = wlan_hdd_cfg80211_dcc_get_stats
13917 },
13918 {
13919 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13920 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
13921 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13922 WIPHY_VENDOR_CMD_NEED_NETDEV |
13923 WIPHY_VENDOR_CMD_NEED_RUNNING,
13924 .doit = wlan_hdd_cfg80211_dcc_clear_stats
13925 },
13926 {
13927 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13928 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
13929 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13930 WIPHY_VENDOR_CMD_NEED_NETDEV |
13931 WIPHY_VENDOR_CMD_NEED_RUNNING,
13932 .doit = wlan_hdd_cfg80211_dcc_update_ndl
13933 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053013934 {
13935 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13936 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
13937 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13938 WIPHY_VENDOR_CMD_NEED_NETDEV |
13939 WIPHY_VENDOR_CMD_NEED_RUNNING,
13940 .doit = wlan_hdd_cfg80211_get_link_properties
13941 },
Qiwei Caie689a262018-07-26 15:50:22 +080013942
13943 FEATURE_OTA_TEST_VENDOR_COMMANDS
13944
Ravi Joshideb5a8d2015-11-09 19:11:43 -080013945#ifdef FEATURE_LFR_SUBNET_DETECTION
13946 {
13947 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13948 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
13949 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13950 WIPHY_VENDOR_CMD_NEED_NETDEV |
13951 WIPHY_VENDOR_CMD_NEED_RUNNING,
13952 .doit = wlan_hdd_cfg80211_set_gateway_params
13953 },
13954#endif /* FEATURE_LFR_SUBNET_DETECTION */
Qiwei Caie689a262018-07-26 15:50:22 +080013955
13956 FEATURE_TX_POWER_VENDOR_COMMANDS
13957
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053013958#ifdef FEATURE_WLAN_APF
Arun Khandavalli2476ef52016-04-26 20:19:43 +053013959 {
13960 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13961 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
13962 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13963 WIPHY_VENDOR_CMD_NEED_NETDEV |
13964 WIPHY_VENDOR_CMD_NEED_RUNNING,
Nachiket Kukadee547a482018-05-22 16:43:30 +053013965 .doit = wlan_hdd_cfg80211_apf_offload
Arun Khandavalli2476ef52016-04-26 20:19:43 +053013966 },
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053013967#endif /* FEATURE_WLAN_APF */
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053013968 {
13969 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053013970 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
13971 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13972 WIPHY_VENDOR_CMD_NEED_NETDEV |
13973 WIPHY_VENDOR_CMD_NEED_RUNNING,
13974 .doit = wlan_hdd_cfg80211_acs_dfs_mode
13975 },
13976 {
13977 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053013978 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
13979 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13980 WIPHY_VENDOR_CMD_NEED_NETDEV |
13981 WIPHY_VENDOR_CMD_NEED_RUNNING,
13982 .doit = wlan_hdd_cfg80211_sta_roam_policy
13983 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053013984#ifdef FEATURE_WLAN_CH_AVOID
13985 {
13986 .info.vendor_id = QCA_NL80211_VENDOR_ID,
13987 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
13988 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13989 WIPHY_VENDOR_CMD_NEED_NETDEV |
13990 WIPHY_VENDOR_CMD_NEED_RUNNING,
13991 .doit = wlan_hdd_cfg80211_avoid_freq
13992 },
13993#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053013994 {
13995 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053013996 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
13997 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
13998 WIPHY_VENDOR_CMD_NEED_NETDEV |
13999 WIPHY_VENDOR_CMD_NEED_RUNNING,
14000 .doit = wlan_hdd_cfg80211_sap_configuration_set
14001 },
Qiwei Caie689a262018-07-26 15:50:22 +080014002
14003 FEATURE_P2P_LISTEN_OFFLOAD_VENDOR_COMMANDS
14004
14005 FEATURE_SAP_COND_CHAN_SWITCH_VENDOR_COMMANDS
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053014006 {
14007 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14008 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
14009 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14010 WIPHY_VENDOR_CMD_NEED_NETDEV |
14011 WIPHY_VENDOR_CMD_NEED_RUNNING,
14012 .doit = wlan_hdd_cfg80211_get_wakelock_stats
14013 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053014014 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053014015 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14016 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
14017 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14018 WIPHY_VENDOR_CMD_NEED_NETDEV |
14019 WIPHY_VENDOR_CMD_NEED_RUNNING,
14020 .doit = wlan_hdd_cfg80211_get_bus_size
14021 },
14022 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053014023 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14024 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
14025 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14026 WIPHY_VENDOR_CMD_NEED_NETDEV |
14027 WIPHY_VENDOR_CMD_NEED_RUNNING,
14028 .doit = wlan_hdd_cfg80211_update_vendor_channel
14029 },
14030 {
bingsd09dea32017-03-17 10:08:26 +080014031 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053014032 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
14033 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14034 WIPHY_VENDOR_CMD_NEED_NETDEV |
14035 WIPHY_VENDOR_CMD_NEED_RUNNING,
14036 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053014037 },
14038 {
14039 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14040 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
14041 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14042 WIPHY_VENDOR_CMD_NEED_NETDEV |
14043 WIPHY_VENDOR_CMD_NEED_RUNNING,
14044 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053014045 },
14046#ifdef WLAN_FEATURE_DISA
14047 {
14048 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14049 .info.subcmd =
14050 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
14051 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14052 WIPHY_VENDOR_CMD_NEED_NETDEV |
14053 WIPHY_VENDOR_CMD_NEED_RUNNING,
14054 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
14055 },
14056#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070014057#ifdef FEATURE_WLAN_TDLS
14058 {
14059 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14060 .info.subcmd =
14061 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
14062 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14063 WIPHY_VENDOR_CMD_NEED_NETDEV |
14064 WIPHY_VENDOR_CMD_NEED_RUNNING,
14065 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080014066 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070014067#endif
Qiwei Caie689a262018-07-26 15:50:22 +080014068 FEATURE_SAR_LIMITS_VENDOR_COMMANDS
Abhinav Kumardbbfd2c2019-05-07 12:22:06 +053014069 BCN_RECV_FEATURE_VENDOR_COMMANDS
Qiwei Caie689a262018-07-26 15:50:22 +080014070
Jeff Johnson8c83f132017-12-18 16:41:37 -080014071 {
14072 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080014073 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
14074 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14075 WIPHY_VENDOR_CMD_NEED_RUNNING,
14076 .doit = wlan_hdd_cfg80211_set_sar_power_limits
14077 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053014078 {
14079 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14080 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
14081 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14082 WIPHY_VENDOR_CMD_NEED_NETDEV |
14083 WIPHY_VENDOR_CMD_NEED_RUNNING,
14084 .doit = wlan_hdd_cfg80211_set_trace_level
14085 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080014086 {
14087 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14088 .info.subcmd =
14089 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
14090 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14091 WIPHY_VENDOR_CMD_NEED_NETDEV |
14092 WIPHY_VENDOR_CMD_NEED_RUNNING,
14093 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
14094 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053014095 {
14096 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14097 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET,
14098 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14099 WIPHY_VENDOR_CMD_NEED_NETDEV |
14100 WIPHY_VENDOR_CMD_NEED_RUNNING,
14101 .doit = wlan_hdd_cfg80211_set_nud_stats
14102 },
14103 {
14104 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14105 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
14106 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14107 WIPHY_VENDOR_CMD_NEED_NETDEV |
14108 WIPHY_VENDOR_CMD_NEED_RUNNING,
14109 .doit = wlan_hdd_cfg80211_get_nud_stats
14110 },
Qiwei Caie689a262018-07-26 15:50:22 +080014111
14112 FEATURE_BSS_TRANSITION_VENDOR_COMMANDS
Sandeep Puligilla063a4342018-01-10 02:50:14 -080014113 FEATURE_SPECTRAL_SCAN_VENDOR_COMMANDS
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080014114 FEATURE_11AX_VENDOR_COMMANDS
lifengd217d192017-05-09 19:44:16 +080014115
14116 {
14117 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14118 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI,
14119 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14120 WIPHY_VENDOR_CMD_NEED_NETDEV |
14121 WIPHY_VENDOR_CMD_NEED_RUNNING,
14122 .doit = wlan_hdd_cfg80211_get_chain_rssi
14123 },
Qiwei Caie689a262018-07-26 15:50:22 +080014124
14125 FEATURE_ACTIVE_TOS_VENDOR_COMMANDS
Nachiket Kukadea6a70a92018-10-09 20:07:21 +053014126 FEATURE_NAN_VENDOR_COMMANDS
Qun Zhangef655622019-02-25 10:48:10 +080014127 FEATURE_FW_STATE_COMMANDS
Jiani Liua5f17222019-03-04 16:22:33 +080014128 FEATURE_COEX_CONFIG_COMMANDS
stonez2d686482019-03-12 14:54:26 +080014129 FEATURE_MPTA_HELPER_COMMANDS
guangde4853c402019-05-06 15:54:04 +080014130 FEATURE_HW_CAPABILITY_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014131};
14132
Dustin Brown92bd8382018-10-31 15:49:46 -070014133struct hdd_context *hdd_cfg80211_wiphy_alloc(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014134{
14135 struct wiphy *wiphy;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070014136 struct hdd_context *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080014137
Dustin Brown491d54b2018-03-14 12:39:11 -070014138 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014139
Dustin Brown92bd8382018-10-31 15:49:46 -070014140 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, sizeof(*hdd_ctx));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014141 if (!wiphy) {
Dustin Brown92bd8382018-10-31 15:49:46 -070014142 hdd_err("failed to allocate wiphy!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014143 return NULL;
14144 }
14145
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080014146 hdd_ctx = wiphy_priv(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080014147 hdd_ctx->wiphy = wiphy;
14148
14149 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014150}
14151
Jeff Johnson459d2732019-03-02 10:13:25 -080014152int wlan_hdd_cfg80211_update_band(struct hdd_context *hdd_ctx,
14153 struct wiphy *wiphy,
14154 enum band_info new_band)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014155{
14156 int i, j;
Jeff Johnson9cb757b2019-03-11 15:29:02 -070014157 enum channel_state channel_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014158
Dustin Brown491d54b2018-03-14 12:39:11 -070014159 hdd_enter();
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070014160
14161 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014162
Jeff Johnsond36fa332019-03-18 13:42:25 -070014163 if (!wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014164 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014165
14166 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
14167 struct ieee80211_supported_band *band = wiphy->bands[i];
14168
Jeff Johnson9cb757b2019-03-11 15:29:02 -070014169 channel_state = wlan_reg_get_channel_state(
Dustin Brown07901ec2018-09-07 11:02:41 -070014170 hdd_ctx->pdev,
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070014171 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014172
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070014173 if (HDD_NL80211_BAND_2GHZ == i &&
Jeff Johnson459d2732019-03-02 10:13:25 -080014174 BAND_5G == new_band) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014175 /* 5G only */
14176#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
14177 /* Enable Social channels for P2P */
14178 if (WLAN_HDD_IS_SOCIAL_CHANNEL
14179 (band->channels[j].center_freq)
14180 && CHANNEL_STATE_ENABLE ==
Jeff Johnson9cb757b2019-03-11 15:29:02 -070014181 channel_state)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014182 band->channels[j].flags &=
14183 ~IEEE80211_CHAN_DISABLED;
14184 else
14185#endif
14186 band->channels[j].flags |=
14187 IEEE80211_CHAN_DISABLED;
14188 continue;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070014189 } else if (HDD_NL80211_BAND_5GHZ == i &&
Jeff Johnson459d2732019-03-02 10:13:25 -080014190 BAND_2G == new_band) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014191 /* 2G only */
14192 band->channels[j].flags |=
14193 IEEE80211_CHAN_DISABLED;
14194 continue;
14195 }
14196
Jeff Johnson9cb757b2019-03-11 15:29:02 -070014197 if (CHANNEL_STATE_DISABLE != channel_state)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014198 band->channels[j].flags &=
14199 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200 }
14201 }
14202 return 0;
14203}
14204
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053014205#if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \
14206 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
14207static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
14208{
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +053014209 wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
14210 wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053014211}
14212#else
14213static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
14214{
14215}
14216#endif
14217
Peng Xuacfdda12017-02-06 16:15:38 -080014218#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053014219
Liangwei Dong3abfe8f2018-09-20 02:25:44 -040014220#if defined(CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME) || \
14221 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
14222/**
14223 * wlan_hdd_cfg80211_action_frame_randomization_init() - Randomize SA of MA
14224 * frames
14225 * @wiphy: Pointer to wiphy
14226 *
14227 * This function is used to indicate the support of source mac address
14228 * randomization of management action frames
14229 *
14230 * Return: None
14231 */
14232static void
14233wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
14234{
14235 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA);
14236}
14237#else
14238static void
14239wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
14240{
14241}
14242#endif
14243
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053014244#if defined(WLAN_FEATURE_FILS_SK) && \
14245 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
14246 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053014247static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
14248{
14249 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
14250}
14251#else
14252static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
14253{
14254}
14255#endif
14256
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053014257#if defined (CFG80211_SCAN_DBS_CONTROL_SUPPORT) || \
14258 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
14259static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
14260{
14261 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
14262 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
14263 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
14264}
14265#else
14266static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
14267{
14268}
14269#endif
14270
Veerendranath Jakkam62fedb92019-03-20 16:32:17 +053014271#if defined(CFG80211_SCAN_OCE_CAPABILITY_SUPPORT) || \
14272 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
14273static void wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy *wiphy)
14274{
14275 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME);
14276 wiphy_ext_feature_set(wiphy,
14277 NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP);
14278 wiphy_ext_feature_set(wiphy,
14279 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE);
14280 wiphy_ext_feature_set(
14281 wiphy, NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION);
14282}
14283#else
14284static void wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy *wiphy)
14285{
14286}
14287#endif
14288
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053014289#if defined(WLAN_FEATURE_SAE) && \
14290 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053014291/**
14292 * wlan_hdd_cfg80211_set_wiphy_sae_feature() - Indicates support of SAE feature
14293 * @wiphy: Pointer to wiphy
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053014294 *
14295 * This function is used to indicate the support of SAE
14296 *
14297 * Return: None
14298 */
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080014299static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053014300{
Manikandan Mohand350c192018-11-29 14:01:12 -080014301 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Manikandan Mohand350c192018-11-29 14:01:12 -080014302
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080014303 if (ucfg_fwol_get_sae_enable(hdd_ctx->psoc))
Manikandan Mohan5dba1c72019-01-07 16:57:03 -080014304 wiphy->features |= NL80211_FEATURE_SAE;
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053014305}
14306#else
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080014307static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053014308{
14309}
14310#endif
14311
Peng Xu8e8b0392018-04-30 11:32:34 -070014312#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
14313 defined(CFG80211_DFS_OFFLOAD_BACKPORT)
14314static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
14315{
14316 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
14317}
14318#else
14319static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
14320{
14321 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
14322}
14323#endif
14324
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070014325#ifdef WLAN_FEATURE_DSRC
14326static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
14327 int *num_ch, int *ch_len)
14328{
14329 *num_ch = QDF_ARRAY_SIZE(hdd_channels_dot11p);
14330 *ch_len = sizeof(hdd_channels_dot11p);
14331}
14332
14333static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
14334{
14335 if (!ch_arr_len)
14336 return;
14337 qdf_mem_copy(ch_ptr, &hdd_channels_dot11p[0], ch_arr_len);
14338}
14339
14340static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
14341 int *num_ch, int *ch_len)
14342{
14343 *num_ch = 0;
14344 *ch_len = 0;
14345}
14346
14347static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
14348{
14349}
14350
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053014351/**
14352 * wlan_hdd_populate_srd_chan_info() - Populate SRD chan info in hdd context
14353 * @hdd_ctx: pointer to hdd context
14354 * @index: SRD channel beginning index in chan_info of @hdd_ctx
14355 *
14356 * Return: Number of SRD channels populated
14357 */
14358static uint32_t
14359wlan_hdd_populate_srd_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
14360{
14361 return 0;
14362}
14363
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070014364#else
14365
14366static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
14367 int *num_ch, int *ch_len)
14368{
14369 *num_ch = 0;
14370 *ch_len = 0;
14371}
14372
14373static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
14374{
14375}
14376
14377static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
14378 int *num_ch, int *ch_len)
14379{
14380 *num_ch = QDF_ARRAY_SIZE(hdd_etsi13_srd_ch);
14381 *ch_len = sizeof(hdd_etsi13_srd_ch);
14382}
14383
14384static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
14385{
14386 if (!ch_arr_len)
14387 return;
14388 qdf_mem_copy(ch_ptr, &hdd_etsi13_srd_ch[0], ch_arr_len);
14389}
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053014390
14391/**
14392 * wlan_hdd_populate_srd_chan_info() - Populate SRD chan info in hdd context
14393 * @hdd_ctx: pointer to hdd context
14394 * @index: SRD channel beginning index in chan_info of @hdd_ctx
14395 *
14396 * Return: Number of SRD channels populated
14397 */
14398static uint32_t
14399wlan_hdd_populate_srd_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
14400{
14401 uint32_t num_srd_ch, i;
14402 struct scan_chan_info *chan_info;
14403
14404 num_srd_ch = QDF_ARRAY_SIZE(hdd_etsi13_srd_ch);
14405 chan_info = hdd_ctx->chan_info;
14406
14407 for (i = 0; i < num_srd_ch; i++)
14408 chan_info[index + i].freq = hdd_etsi13_srd_ch[i].center_freq;
14409
14410 return num_srd_ch;
14411}
14412
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070014413#endif
14414
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053014415#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
14416static QDF_STATUS
14417wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx)
14418{
14419 hdd_ctx->iftype_data_2g =
14420 qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_2g));
14421
14422 if (!hdd_ctx->iftype_data_2g) {
14423 hdd_err("mem alloc failed for 2g iftype data");
14424 return QDF_STATUS_E_NOMEM;
14425 }
14426 hdd_ctx->iftype_data_5g =
14427 qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_5g));
14428
14429 if (!hdd_ctx->iftype_data_5g) {
14430 hdd_err("mem alloc failed for 5g iftype data");
14431 qdf_mem_free(hdd_ctx->iftype_data_2g);
14432 hdd_ctx->iftype_data_2g = NULL;
14433 return QDF_STATUS_E_NOMEM;
14434 }
14435
14436 return QDF_STATUS_SUCCESS;
14437}
14438#else
14439static inline QDF_STATUS
14440wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx)
14441{
14442 return QDF_STATUS_SUCCESS;
14443}
14444#endif
14445
14446#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
14447static void
14448wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx)
14449{
14450 qdf_mem_free(hdd_ctx->iftype_data_5g);
14451 qdf_mem_free(hdd_ctx->iftype_data_2g);
14452 hdd_ctx->iftype_data_5g = NULL;
14453 hdd_ctx->iftype_data_2g = NULL;
14454}
14455#else
14456static inline void
14457wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx)
14458{
14459}
14460#endif
14461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014462/*
14463 * FUNCTION: wlan_hdd_cfg80211_init
14464 * This function is called by hdd_wlan_startup()
14465 * during initialization.
14466 * This function is used to initialize and register wiphy structure.
14467 */
14468int wlan_hdd_cfg80211_init(struct device *dev,
Jeff Johnson30f5bba2019-03-08 11:58:08 -080014469 struct wiphy *wiphy, struct hdd_config *config)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014470{
Jeff Johnsonb8944722017-09-03 09:03:19 -070014471 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053014472 uint32_t *cipher_suites;
Dustin Brown491d54b2018-03-14 12:39:11 -070014473 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014474
14475 /* Now bind the underlying wlan device with wiphy */
14476 set_wiphy_dev(wiphy, dev);
14477
14478 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
14479
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014480 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
14481 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
14482 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
14483#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
14484 | WIPHY_FLAG_4ADDR_STATION
14485#endif
14486 | WIPHY_FLAG_OFFCHAN_TX;
14487
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014488#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
14489 wiphy->wowlan = &wowlan_support_cfg80211_init;
14490#else
14491 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
14492 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
14493 wiphy->wowlan.pattern_min_len = 1;
14494 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
14495#endif
14496
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014497#ifdef FEATURE_WLAN_TDLS
14498 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
14499 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
14500#endif
14501
14502 wiphy->features |= NL80211_FEATURE_HT_IBSS;
14503
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014504#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
14505 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
14506#endif
14507
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053014508 wlan_hdd_cfg80211_set_wiphy_scan_flags(wiphy);
14509
Pragaspathi Thilagaraj24789d32018-12-10 22:28:03 +053014510 wlan_scan_cfg80211_add_connected_pno_support(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014511
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014512 wiphy->max_scan_ssids = MAX_SCAN_SSID;
14513
14514 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
14515
14516 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
14517
Arun Khandavallifae92942016-08-01 13:31:08 +053014518 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
14519 | BIT(NL80211_IFTYPE_ADHOC)
14520 | BIT(NL80211_IFTYPE_P2P_CLIENT)
14521 | BIT(NL80211_IFTYPE_P2P_GO)
14522 | BIT(NL80211_IFTYPE_AP)
14523 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014524
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014525
Abhishek Singhf512bf32016-05-04 16:47:46 +053014526 /*
14527 * In case of static linked driver at the time of driver unload,
14528 * module exit doesn't happens. Module cleanup helps in cleaning
14529 * of static memory.
14530 * If driver load happens statically, at the time of driver unload,
14531 * wiphy flags don't get reset because of static memory.
14532 * It's better not to store channel in static memory.
Qun Zhang043635a2019-02-27 15:19:29 +080014533 * The memory is for channels of struct wiphy and shouldn't be
14534 * released during stop modules. So if it's allocated in active
14535 * domain, the memory leak detector would catch the leak during
14536 * stop modules. To avoid this,alloc in init domain in advance.
Abhishek Singhf512bf32016-05-04 16:47:46 +053014537 */
Qun Zhang043635a2019-02-27 15:19:29 +080014538 hdd_ctx->channels_2ghz = qdf_mem_malloc(band_2_ghz_channels_size);
14539 if (!hdd_ctx->channels_2ghz) {
14540 hdd_err("Not enough memory to allocate channels");
Abhishek Singhf512bf32016-05-04 16:47:46 +053014541 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014542 }
Qun Zhang043635a2019-02-27 15:19:29 +080014543 hdd_ctx->channels_5ghz = qdf_mem_malloc(band_5_ghz_chanenls_size);
14544 if (!hdd_ctx->channels_5ghz)
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053014545 goto mem_fail_5g;
14546
14547 if (QDF_IS_STATUS_ERROR(wlan_hdd_iftype_data_alloc(hdd_ctx)))
14548 goto mem_fail_iftype_data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014549
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014550 /*Initialise the supported cipher suite details */
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080014551 if (ucfg_fwol_get_gcmp_enable(hdd_ctx->psoc)) {
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053014552 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites) +
14553 sizeof(hdd_gcmp_cipher_suits));
Min Liu74a1a502018-10-10 19:59:07 +080014554 if (!cipher_suites)
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053014555 goto mem_fail_cipher_suites;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053014556 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites) +
14557 QDF_ARRAY_SIZE(hdd_gcmp_cipher_suits);
14558 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
14559 sizeof(hdd_cipher_suites));
14560 qdf_mem_copy(cipher_suites + QDF_ARRAY_SIZE(hdd_cipher_suites),
14561 &hdd_gcmp_cipher_suits,
14562 sizeof(hdd_gcmp_cipher_suits));
14563 } else {
14564 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites));
Min Liu74a1a502018-10-10 19:59:07 +080014565 if (!cipher_suites)
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053014566 goto mem_fail_cipher_suites;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053014567 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites);
14568 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
14569 sizeof(hdd_cipher_suites));
14570 }
14571 wiphy->cipher_suites = cipher_suites;
14572 cipher_suites = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014573 /*signal strength in mBm (100*dBm) */
14574 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
14575 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
14576
Anurag Chouhan6d760662016-02-20 16:05:43 +053014577 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014578 wiphy->n_vendor_commands =
14579 ARRAY_SIZE(hdd_wiphy_vendor_commands);
14580 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
14581
14582 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
14583 wiphy->n_vendor_events =
14584 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
14585 }
14586
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014587#ifdef QCA_HT_2040_COEX
14588 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
14589#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053014590 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080014591
hangtian821d12d2019-06-11 11:53:50 +080014592 wiphy->features |= NL80211_FEATURE_VIF_TXPOWER;
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053014593#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) || \
wadesonga75734c2017-02-07 16:03:25 +080014594 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
14595 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
14596 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
14597 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
14598#endif
14599
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014600 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080014601 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Liangwei Dong3abfe8f2018-09-20 02:25:44 -040014602 wlan_hdd_cfg80211_action_frame_randomization_init(wiphy);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014603
Dustin Browne74003f2018-03-14 12:51:58 -070014604 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014605 return 0;
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053014606
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053014607mem_fail_cipher_suites:
14608 wlan_hdd_iftype_data_mem_free(hdd_ctx);
14609mem_fail_iftype_data:
14610 qdf_mem_free(hdd_ctx->channels_5ghz);
14611 hdd_ctx->channels_5ghz = NULL;
14612mem_fail_5g:
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053014613 hdd_err("Not enough memory to allocate channels");
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053014614 qdf_mem_free(hdd_ctx->channels_2ghz);
14615 hdd_ctx->channels_2ghz = NULL;
14616
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053014617 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014618}
14619
Abhishek Singhf512bf32016-05-04 16:47:46 +053014620/**
Yingying Tang80e15f32016-09-27 18:23:01 +080014621 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
14622 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053014623 *
14624 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053014625 * memory allocated in wlan_hdd_cfg80211_init also
14626 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053014627 *
14628 * Return: void
14629 */
14630void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
14631{
14632 int i;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053014633 const uint32_t *cipher_suites;
Qun Zhang043635a2019-02-27 15:19:29 +080014634 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +053014635
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070014636 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Jeff Johnsond36fa332019-03-18 13:42:25 -070014637 if (wiphy->bands[i] &&
Qun Zhang043635a2019-02-27 15:19:29 +080014638 (wiphy->bands[i]->channels))
Abhishek Singhf512bf32016-05-04 16:47:46 +053014639 wiphy->bands[i]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053014640 }
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053014641 wlan_hdd_iftype_data_mem_free(hdd_ctx);
Qun Zhang043635a2019-02-27 15:19:29 +080014642 qdf_mem_free(hdd_ctx->channels_5ghz);
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053014643 qdf_mem_free(hdd_ctx->channels_2ghz);
Qun Zhang043635a2019-02-27 15:19:29 +080014644 hdd_ctx->channels_2ghz = NULL;
14645 hdd_ctx->channels_5ghz = NULL;
Amar Singhal5cccafe2017-02-15 12:42:58 -080014646
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053014647 cipher_suites = wiphy->cipher_suites;
14648 wiphy->cipher_suites = NULL;
14649 wiphy->n_cipher_suites = 0;
14650 qdf_mem_free((uint32_t *)cipher_suites);
14651 cipher_suites = NULL;
Abhishek Singh3e6172f2016-05-04 16:56:48 +053014652 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053014653}
14654
Yingying Tang80e15f32016-09-27 18:23:01 +080014655/**
14656 * wlan_hdd_update_band_cap() - update capabilities for supported bands
14657 * @hdd_ctx: HDD context
14658 *
14659 * this function will update capabilities for supported bands
14660 *
14661 * Return: void
14662 */
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053014663static void wlan_hdd_update_ht_cap(struct hdd_context *hdd_ctx)
Yingying Tang80e15f32016-09-27 18:23:01 +080014664{
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053014665 struct mlme_ht_capabilities_info ht_cap_info = {0};
Yingying Tang80e15f32016-09-27 18:23:01 +080014666 QDF_STATUS status;
Wu Gaoed616a12019-01-16 15:19:21 +080014667 uint32_t channel_bonding_mode;
Rajeev Kumar Sirasanagandla7dee7fe2019-08-05 15:55:19 +053014668 struct ieee80211_supported_band *band_2g;
14669 struct ieee80211_supported_band *band_5g;
Yingying Tang80e15f32016-09-27 18:23:01 +080014670
Dustin Brown76cd2932018-09-11 16:03:05 -070014671 status = ucfg_mlme_get_ht_cap_info(hdd_ctx->psoc, &ht_cap_info);
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053014672 if (QDF_STATUS_SUCCESS != status)
Yingying Tang80e15f32016-09-27 18:23:01 +080014673 hdd_err("could not get HT capability info");
Yingying Tang80e15f32016-09-27 18:23:01 +080014674
Rajeev Kumar Sirasanagandla7dee7fe2019-08-05 15:55:19 +053014675 band_2g = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ];
14676 band_5g = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ];
14677
14678 if (band_2g) {
14679 if (ht_cap_info.tx_stbc)
14680 band_2g->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
14681
14682 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
14683 band_2g->vht_cap.vht_supported = 0;
14684 band_2g->vht_cap.cap = 0;
14685 }
14686
14687 if (!ht_cap_info.short_gi_20_mhz)
14688 band_2g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Yingying Tang80e15f32016-09-27 18:23:01 +080014689 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080014690
Rajeev Kumar Sirasanagandla7dee7fe2019-08-05 15:55:19 +053014691 if (band_5g) {
14692 if (ht_cap_info.tx_stbc)
14693 band_5g->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
14694
14695 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
14696 band_5g->vht_cap.vht_supported = 0;
14697 band_5g->vht_cap.cap = 0;
14698 }
14699
14700 if (!ht_cap_info.short_gi_20_mhz)
14701 band_5g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
14702
14703 if (!ht_cap_info.short_gi_40_mhz)
14704 band_5g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
14705
14706 ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc,
14707 &channel_bonding_mode);
14708 if (!channel_bonding_mode)
14709 band_5g->ht_cap.cap &=
14710 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080014711 }
Yingying Tang80e15f32016-09-27 18:23:01 +080014712}
14713
Vignesh Viswanathanf97cc112018-10-03 19:17:07 +053014714/**
14715 * wlan_hdd_update_band_cap_in_wiphy() - update channel flags based on band cap
14716 * @hdd_ctx: HDD context
14717 *
14718 * This function updates the channel flags based on the band capability set
14719 * in the MLME CFG
14720 *
14721 * Return: void
14722 */
14723static void wlan_hdd_update_band_cap_in_wiphy(struct hdd_context *hdd_ctx)
14724{
14725 int i, j;
14726 uint8_t band_capability;
14727 QDF_STATUS status;
14728 struct ieee80211_supported_band *band;
14729
14730 status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
14731 if (QDF_IS_STATUS_ERROR(status)) {
14732 hdd_err("Failed to get MLME Band Capability");
14733 return;
14734 }
14735
14736 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Jeff Johnsond36fa332019-03-18 13:42:25 -070014737 if (!hdd_ctx->wiphy->bands[i])
Vignesh Viswanathanf97cc112018-10-03 19:17:07 +053014738 continue;
14739
14740 for (j = 0; j < hdd_ctx->wiphy->bands[i]->n_channels; j++) {
14741 band = hdd_ctx->wiphy->bands[i];
14742
14743 if (HDD_NL80211_BAND_2GHZ == i &&
14744 BAND_5G == band_capability) {
14745 /* 5G only */
14746#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
14747 /* Enable social channels for P2P */
14748 if (WLAN_HDD_IS_SOCIAL_CHANNEL
14749 (band->channels[j].center_freq))
14750 band->channels[j].flags &=
14751 ~IEEE80211_CHAN_DISABLED;
14752 else
14753#endif
14754 band->channels[j].flags |=
14755 IEEE80211_CHAN_DISABLED;
14756 continue;
14757 } else if (HDD_NL80211_BAND_5GHZ == i &&
14758 BAND_2G == band_capability) {
14759 /* 2G only */
14760 band->channels[j].flags |=
14761 IEEE80211_CHAN_DISABLED;
14762 continue;
14763 }
14764 }
14765 }
14766}
14767
Wu Gao1ab05582018-11-08 16:22:49 +080014768#ifdef FEATURE_WLAN_ESE
14769/**
14770 * wlan_hdd_update_lfr_wiphy() - update LFR flag based on configures
14771 * @hdd_ctx: HDD context
14772 *
14773 * This function updates the LFR flag based on LFR configures
14774 *
14775 * Return: void
14776 */
14777static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
14778{
14779 bool fast_transition_enabled;
14780 bool lfr_enabled;
14781 bool ese_enabled;
14782
14783 ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
14784 &fast_transition_enabled);
14785 ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
14786 ucfg_mlme_is_ese_enabled(hdd_ctx->psoc, &ese_enabled);
14787 if (fast_transition_enabled || lfr_enabled || ese_enabled)
14788 hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
14789}
14790#else
14791static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
14792{
14793 bool fast_transition_enabled;
14794 bool lfr_enabled;
14795
14796 ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
14797 &fast_transition_enabled);
14798 ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
14799 if (fast_transition_enabled || lfr_enabled)
14800 hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
14801}
14802#endif
14803
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014804/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053014805 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014806 * initialization. In wlan_hdd_cfg80211_init, only the
14807 * default values will be initialized. The final initialization
14808 * of all required members can be done here.
14809 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070014810void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014811{
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053014812 int value;
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053014813 bool fils_enabled, mac_spoofing_enabled;
Srinivas Dasarib264fec2019-05-21 18:56:25 +053014814 bool dfs_master_capable = true, is_oce_sta_enabled = false;
Karthik Kantamneni2231a232018-09-11 15:45:55 +053014815 QDF_STATUS status;
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053014816 struct wiphy *wiphy = hdd_ctx->wiphy;
14817 uint8_t allow_mcc_go_diff_bi = 0, enable_mcc = 0;
Yingying Tang80e15f32016-09-27 18:23:01 +080014818
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053014819 if (!wiphy) {
14820 hdd_err("Invalid wiphy");
14821 return;
14822 }
Dustin Brown05d81302018-09-11 16:49:22 -070014823 ucfg_mlme_get_sap_max_peers(hdd_ctx->psoc, &value);
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053014824 hdd_ctx->wiphy->max_ap_assoc_sta = value;
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053014825 wlan_hdd_update_ht_cap(hdd_ctx);
Vignesh Viswanathanf97cc112018-10-03 19:17:07 +053014826 wlan_hdd_update_band_cap_in_wiphy(hdd_ctx);
Wu Gao1ab05582018-11-08 16:22:49 +080014827 wlan_hdd_update_lfr_wiphy(hdd_ctx);
Karthik Kantamneni2231a232018-09-11 15:45:55 +053014828
14829 fils_enabled = 0;
Dustin Brown05d81302018-09-11 16:49:22 -070014830 status = ucfg_mlme_get_fils_enabled_info(hdd_ctx->psoc,
Karthik Kantamneni2231a232018-09-11 15:45:55 +053014831 &fils_enabled);
14832 if (QDF_IS_STATUS_ERROR(status))
14833 hdd_err("could not get fils enabled info");
14834 if (fils_enabled)
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053014835 wlan_hdd_cfg80211_set_wiphy_fils_feature(wiphy);
Arif Hussain88d1fdd2018-09-26 16:12:24 -070014836
14837 status = ucfg_mlme_get_dfs_master_capability(hdd_ctx->psoc,
14838 &dfs_master_capable);
14839 if (QDF_IS_STATUS_SUCCESS(status) && dfs_master_capable)
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053014840 wlan_hdd_cfg80211_set_dfs_offload_feature(wiphy);
Srinivas Dasarib264fec2019-05-21 18:56:25 +053014841
14842 status = ucfg_mlme_get_oce_sta_enabled_info(hdd_ctx->psoc,
14843 &is_oce_sta_enabled);
14844 if (QDF_IS_STATUS_ERROR(status))
14845 hdd_err("could not get OCE STA enable info");
14846 if (is_oce_sta_enabled)
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053014847 wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(wiphy);
14848
14849 wlan_hdd_cfg80211_set_wiphy_sae_feature(wiphy);
14850
14851 if (QDF_STATUS_SUCCESS !=
14852 ucfg_policy_mgr_get_allow_mcc_go_diff_bi(hdd_ctx->psoc,
14853 &allow_mcc_go_diff_bi))
14854 hdd_err("can't get mcc_go_diff_bi value, use default");
14855
14856 if (QDF_STATUS_SUCCESS !=
14857 ucfg_mlme_get_mcc_feature(hdd_ctx->psoc, &enable_mcc))
14858 hdd_err("can't get enable_mcc value, use default");
14859
14860 if (hdd_ctx->config->advertise_concurrent_operation) {
14861 if (enable_mcc) {
14862 int i;
14863
14864 for (i = 0;
14865 i < ARRAY_SIZE(wlan_hdd_iface_combination);
14866 i++) {
14867 if (!allow_mcc_go_diff_bi)
14868 wlan_hdd_iface_combination[i].
14869 beacon_int_infra_match = true;
14870 }
14871 }
14872 wiphy->n_iface_combinations =
14873 ARRAY_SIZE(wlan_hdd_iface_combination);
14874 wiphy->iface_combinations = wlan_hdd_iface_combination;
14875 }
14876
14877 mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
14878 if (mac_spoofing_enabled)
14879 wlan_hdd_cfg80211_scan_randomization_init(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014880}
14881
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080014882/**
14883 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
14884 * @cfg: hdd cfg
14885 *
14886 * this function update 11n mode in hdd cfg
14887 *
14888 * Return: void
14889 */
Sandeep Puligilla34618782019-01-04 17:42:42 -080014890void wlan_hdd_update_11n_mode(struct hdd_context *hdd_ctx)
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080014891{
Sandeep Puligilla34618782019-01-04 17:42:42 -080014892 struct hdd_config *cfg = hdd_ctx->config;
14893
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080014894 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014895 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080014896 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014897 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080014898 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
14899 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
14900 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
Sandeep Puligilla34618782019-01-04 17:42:42 -080014901 ucfg_mlme_set_sap_11ac_override(hdd_ctx->psoc, 0);
14902 ucfg_mlme_set_go_11ac_override(hdd_ctx->psoc, 0);
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080014903 }
14904 }
14905}
14906
Qun Zhang043635a2019-02-27 15:19:29 +080014907QDF_STATUS wlan_hdd_update_wiphy_supported_band(struct hdd_context *hdd_ctx)
14908{
14909 int len_5g_ch, num_ch;
14910 int num_dsrc_ch, len_dsrc_ch, num_srd_ch, len_srd_ch;
Varuneshwar Petlozu3a18e852019-07-23 15:13:26 +053014911 bool is_vht_for_24ghz = false;
14912 QDF_STATUS status;
Qun Zhang043635a2019-02-27 15:19:29 +080014913 struct hdd_config *cfg = hdd_ctx->config;
14914 struct wiphy *wiphy = hdd_ctx->wiphy;
14915
tinlin5d3721d2019-06-03 16:13:20 +080014916 if (wiphy->registered)
14917 return QDF_STATUS_SUCCESS;
14918
Ashish Kumar Dhanotiya34507e02019-06-12 12:53:59 +053014919 if (hdd_is_2g_supported(hdd_ctx)) {
14920 if (!hdd_ctx->channels_2ghz)
14921 return QDF_STATUS_E_NOMEM;
14922 wiphy->bands[HDD_NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
14923 wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels =
14924 hdd_ctx->channels_2ghz;
14925 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels,
14926 &hdd_channels_2_4_ghz[0],
14927 sizeof(hdd_channels_2_4_ghz));
Varuneshwar Petlozu3a18e852019-07-23 15:13:26 +053014928
14929 status = ucfg_mlme_get_vht_for_24ghz(hdd_ctx->psoc,
14930 &is_vht_for_24ghz);
14931 if (QDF_IS_STATUS_ERROR(status))
14932 hdd_err("could not get VHT capability");
14933
14934 if (is_vht_for_24ghz &&
14935 sme_is_feature_supported_by_fw(DOT11AC))
14936 wlan_hdd_band_2_4_ghz.vht_cap.vht_supported = 1;
Ashish Kumar Dhanotiya34507e02019-06-12 12:53:59 +053014937 }
Qun Zhang043635a2019-02-27 15:19:29 +080014938 if (!hdd_is_5g_supported(hdd_ctx) ||
14939 (eHDD_DOT11_MODE_11b == cfg->dot11Mode) ||
14940 (eHDD_DOT11_MODE_11g == cfg->dot11Mode) ||
14941 (eHDD_DOT11_MODE_11b_ONLY == cfg->dot11Mode) ||
14942 (eHDD_DOT11_MODE_11g_ONLY == cfg->dot11Mode))
14943 return QDF_STATUS_SUCCESS;
14944
14945 if (!hdd_ctx->channels_5ghz)
14946 return QDF_STATUS_E_NOMEM;
14947 wiphy->bands[HDD_NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
14948 wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels = hdd_ctx->channels_5ghz;
14949 wlan_hdd_get_num_dsrc_ch_and_len(cfg, &num_dsrc_ch, &len_dsrc_ch);
14950 wlan_hdd_get_num_srd_ch_and_len(cfg, &num_srd_ch, &len_srd_ch);
14951 num_ch = QDF_ARRAY_SIZE(hdd_channels_5_ghz) + num_dsrc_ch + num_srd_ch;
14952 len_5g_ch = sizeof(hdd_channels_5_ghz);
14953
14954 wiphy->bands[HDD_NL80211_BAND_5GHZ]->n_channels = num_ch;
14955 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels,
14956 &hdd_channels_5_ghz[0], len_5g_ch);
14957 if (num_dsrc_ch)
14958 wlan_hdd_copy_dsrc_ch((char *)wiphy->bands[
14959 HDD_NL80211_BAND_5GHZ]->channels +
14960 len_5g_ch, len_dsrc_ch);
14961 if (num_srd_ch)
14962 wlan_hdd_copy_srd_ch((char *)wiphy->bands[
14963 HDD_NL80211_BAND_5GHZ]->channels +
14964 len_5g_ch, len_srd_ch);
14965
14966 return QDF_STATUS_SUCCESS;
14967}
14968
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014969/* In this function we are registering wiphy. */
14970int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
14971{
Dustin Brown491d54b2018-03-14 12:39:11 -070014972 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014973 /* Register our wiphy dev with cfg80211 */
14974 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070014975 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014976 return -EIO;
14977 }
14978
Dustin Browne74003f2018-03-14 12:51:58 -070014979 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014980 return 0;
14981}
14982
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014983/* This function registers for all frame which supplicant is interested in */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014984int wlan_hdd_cfg80211_register_frames(struct hdd_adapter *adapter)
Wu Gao84d120c2017-03-24 18:46:00 +080014985{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014986 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
Wu Gao84d120c2017-03-24 18:46:00 +080014987 /* Register for all P2P action, public action etc frames */
14988 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053014989 QDF_STATUS status;
Wu Gao84d120c2017-03-24 18:46:00 +080014990
Dustin Brown491d54b2018-03-14 12:39:11 -070014991 hdd_enter();
Sourav Mohapatraa0943922018-11-21 21:26:29 +053014992 if (adapter->device_mode == QDF_FTM_MODE) {
14993 hdd_info("No need to register frames in FTM mode");
14994 return 0;
14995 }
Wu Gao84d120c2017-03-24 18:46:00 +080014996
14997 /* Register frame indication call back */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014998 status = sme_register_mgmt_frame_ind_callback(mac_handle,
14999 hdd_indicate_mgmt_frame);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015000 if (status != QDF_STATUS_SUCCESS) {
15001 hdd_err("Failed to register hdd_indicate_mgmt_frame");
15002 goto ret_status;
15003 }
Wu Gao84d120c2017-03-24 18:46:00 +080015004
Wu Gao84d120c2017-03-24 18:46:00 +080015005 /* Right now we are registering these frame when driver is getting
15006 * initialized. Once we will move to 2.6.37 kernel, in which we have
15007 * frame register ops, we will move this code as a part of that
15008 */
15009
15010 /* GAS Initial Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015011 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15012 (uint8_t *) GAS_INITIAL_REQ,
15013 GAS_INITIAL_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015014 if (status != QDF_STATUS_SUCCESS) {
15015 hdd_err("Failed to register GAS_INITIAL_REQ");
15016 goto ret_status;
15017 }
Wu Gao84d120c2017-03-24 18:46:00 +080015018
15019 /* GAS Initial Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015020 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15021 (uint8_t *) GAS_INITIAL_RSP,
15022 GAS_INITIAL_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015023 if (status != QDF_STATUS_SUCCESS) {
15024 hdd_err("Failed to register GAS_INITIAL_RSP");
15025 goto dereg_gas_initial_req;
15026 }
Wu Gao84d120c2017-03-24 18:46:00 +080015027
15028 /* GAS Comeback Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015029 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15030 (uint8_t *) GAS_COMEBACK_REQ,
15031 GAS_COMEBACK_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015032 if (status != QDF_STATUS_SUCCESS) {
15033 hdd_err("Failed to register GAS_COMEBACK_REQ");
15034 goto dereg_gas_initial_rsp;
15035 }
Wu Gao84d120c2017-03-24 18:46:00 +080015036
15037 /* GAS Comeback Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015038 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15039 (uint8_t *) GAS_COMEBACK_RSP,
15040 GAS_COMEBACK_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015041 if (status != QDF_STATUS_SUCCESS) {
15042 hdd_err("Failed to register GAS_COMEBACK_RSP");
15043 goto dereg_gas_comeback_req;
15044 }
Wu Gao84d120c2017-03-24 18:46:00 +080015045
15046 /* WNM BSS Transition Request frame */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015047 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15048 (uint8_t *) WNM_BSS_ACTION_FRAME,
15049 WNM_BSS_ACTION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015050 if (status != QDF_STATUS_SUCCESS) {
15051 hdd_err("Failed to register WNM_BSS_ACTION_FRAME");
15052 goto dereg_gas_comeback_rsp;
15053 }
Wu Gao84d120c2017-03-24 18:46:00 +080015054
15055 /* WNM-Notification */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080015056 status = sme_register_mgmt_frame(mac_handle, adapter->vdev_id, type,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015057 (uint8_t *) WNM_NOTIFICATION_FRAME,
15058 WNM_NOTIFICATION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015059 if (status != QDF_STATUS_SUCCESS) {
15060 hdd_err("Failed to register WNM_NOTIFICATION_FRAME");
15061 goto dereg_wnm_bss_action_frm;
15062 }
15063
Dustin Brown237baee2018-05-10 13:22:18 -070015064 return 0;
15065
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015066dereg_wnm_bss_action_frm:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015067 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15068 (uint8_t *) WNM_BSS_ACTION_FRAME,
15069 WNM_BSS_ACTION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015070dereg_gas_comeback_rsp:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015071 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15072 (uint8_t *) GAS_COMEBACK_RSP,
15073 GAS_COMEBACK_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015074dereg_gas_comeback_req:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015075 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15076 (uint8_t *) GAS_COMEBACK_REQ,
15077 GAS_COMEBACK_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015078dereg_gas_initial_rsp:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015079 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15080 (uint8_t *) GAS_INITIAL_RSP,
15081 GAS_INITIAL_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015082dereg_gas_initial_req:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015083 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15084 (uint8_t *) GAS_INITIAL_REQ,
15085 GAS_INITIAL_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015086ret_status:
15087 return qdf_status_to_os_return(status);
Wu Gao84d120c2017-03-24 18:46:00 +080015088}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015089
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015090void wlan_hdd_cfg80211_deregister_frames(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015091{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015092 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
15093 /* Deregister for all P2P action, public action etc frames */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015094 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
15095
Dustin Brown491d54b2018-03-14 12:39:11 -070015096 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015097
15098 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015099 * initialized. Once we will move to 2.6.37 kernel, in which we have
15100 * frame register ops, we will move this code as a part of that
15101 */
15102
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015103 /* GAS Initial Request */
15104
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015105 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015106 (uint8_t *) GAS_INITIAL_REQ,
15107 GAS_INITIAL_REQ_SIZE);
15108
15109 /* GAS Initial Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015110 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015111 (uint8_t *) GAS_INITIAL_RSP,
15112 GAS_INITIAL_RSP_SIZE);
15113
15114 /* GAS Comeback Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015115 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015116 (uint8_t *) GAS_COMEBACK_REQ,
15117 GAS_COMEBACK_REQ_SIZE);
15118
15119 /* GAS Comeback Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015120 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015121 (uint8_t *) GAS_COMEBACK_RSP,
15122 GAS_COMEBACK_RSP_SIZE);
15123
15124 /* P2P Public Action */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015125 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015126 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
15127 P2P_PUBLIC_ACTION_FRAME_SIZE);
15128
15129 /* P2P Action */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015130 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015131 (uint8_t *) P2P_ACTION_FRAME,
15132 P2P_ACTION_FRAME_SIZE);
15133
15134 /* WNM-Notification */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080015135 sme_deregister_mgmt_frame(mac_handle, adapter->vdev_id, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015136 (uint8_t *) WNM_NOTIFICATION_FRAME,
15137 WNM_NOTIFICATION_FRAME_SIZE);
15138}
15139
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015140#if defined(FEATURE_WLAN_WAPI) && !defined(CRYPTO_SET_KEY_CONVERGED)
Sourav Mohapatrad21fc6b2018-06-01 11:31:14 +053015141static void wlan_hdd_cfg80211_set_key_wapi(struct hdd_adapter *adapter,
15142 uint8_t key_index,
15143 const uint8_t *mac_addr,
15144 const uint8_t *key,
Jeff Johnson7d70e4f2019-03-23 11:18:59 -070015145 int key_len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015146{
Jeff Johnson89515092019-03-23 10:52:04 -070015147 tCsrRoamSetKey set_key;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015148 QDF_STATUS status;
Jeff Johnson29c78672019-02-26 21:05:53 -080015149 uint32_t roam_id = INVALID_ROAM_ID;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015150 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015151
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015152 hdd_debug("Device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070015153 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015154
Jeff Johnson7d70e4f2019-03-23 11:18:59 -070015155 qdf_mem_zero(&set_key, sizeof(set_key));
15156 set_key.keyId = key_index;
15157 set_key.encType = eCSR_ENCRYPT_TYPE_WPI;
15158 set_key.keyDirection = eSIR_TX_RX;
15159 set_key.paeRole = 0;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015160 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson89515092019-03-23 10:52:04 -070015161 qdf_set_macaddr_broadcast(&set_key.peerMac);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015162 else
Jeff Johnson7d70e4f2019-03-23 11:18:59 -070015163 qdf_mem_copy(set_key.peerMac.bytes, mac_addr,
15164 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015165
Jeff Johnson7d70e4f2019-03-23 11:18:59 -070015166 set_key.keyLength = key_len;
15167 memcpy(set_key.Key, key, key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015168
Jeff Johnson7d70e4f2019-03-23 11:18:59 -070015169 hdd_debug("WAPI KEY LENGTH:0x%04x", key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015170
Jeff Johnson7d70e4f2019-03-23 11:18:59 -070015171 mac_handle = hdd_adapter_get_mac_handle(adapter);
15172 status = sme_roam_set_key(mac_handle, adapter->vdev_id,
15173 &set_key, &roam_id);
15174 if (status != QDF_STATUS_SUCCESS)
15175 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015176}
15177#endif /* FEATURE_WLAN_WAPI */
15178
Krunal Soni364e0872017-05-10 21:24:34 -070015179bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
15180{
Naveen Rawat08db88f2017-09-08 15:07:48 -070015181 const uint8_t *vendor_ie;
Krunal Soni364e0872017-05-10 21:24:34 -070015182
15183 if (length < 2) {
15184 hdd_debug("bss size is less than expected");
15185 return true;
15186 }
15187 if (!ies) {
15188 hdd_debug("invalid IE pointer");
15189 return true;
15190 }
Naveen Rawat08db88f2017-09-08 15:07:48 -070015191 vendor_ie = wlan_get_vendor_ie_ptr_from_oui(VENDOR1_AP_OUI_TYPE,
Krunal Soni364e0872017-05-10 21:24:34 -070015192 VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
15193 if (vendor_ie) {
15194 hdd_debug("AP can't support immediate powersave. defer it");
15195 return false;
15196 }
15197 return true;
15198}
15199
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015200/*
15201 * FUNCTION: wlan_hdd_validate_operation_channel
15202 * called by wlan_hdd_cfg80211_start_bss() and
15203 * wlan_hdd_set_channel()
15204 * This function validates whether given channel is part of valid
15205 * channel list.
15206 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015207QDF_STATUS wlan_hdd_validate_operation_channel(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015208 int channel)
15209{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015210 uint32_t num_ch = 0;
Tushnim Bhattacharyyad1d0db92019-08-30 13:50:15 -070015211 uint32_t valid_ch[CFG_VALID_CHANNEL_LIST_LEN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015212 u32 indx = 0;
Jeff Johnson603ef852019-03-11 15:23:30 -070015213 bool is_valid_channel = false;
15214 uint8_t count;
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053015215 QDF_STATUS status;
15216 bool value;
15217 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015218
Wu Gao0821b0d2019-01-11 17:31:11 +080015219 num_ch = CFG_VALID_CHANNEL_LIST_LEN;
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053015220 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown05d81302018-09-11 16:49:22 -070015221 status = ucfg_mlme_get_sap_allow_all_channels(hdd_ctx->psoc, &value);
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053015222 if (status != QDF_STATUS_SUCCESS)
15223 hdd_err("Unable to fetch sap allow all channels");
15224 if (value) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015225 /* Validate the channel */
Amar Singhal2e4cccc2019-08-06 12:47:18 -070015226 for (count = CHAN_ENUM_2412; count <= CHAN_ENUM_5865; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070015227 if (channel == WLAN_REG_CH_NUM(count)) {
Jeff Johnson603ef852019-03-11 15:23:30 -070015228 is_valid_channel = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015229 break;
15230 }
15231 }
Jeff Johnson603ef852019-03-11 15:23:30 -070015232 if (!is_valid_channel) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015233 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015234 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015235 }
15236 } else {
Tushnim Bhattacharyyad1d0db92019-08-30 13:50:15 -070015237 ucfg_mlme_get_valid_channel_freq_list(hdd_ctx->psoc, valid_ch,
15238 &num_ch);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015239 for (indx = 0; indx < num_ch; indx++) {
Tushnim Bhattacharyyad1d0db92019-08-30 13:50:15 -070015240 if (channel ==
15241 wlan_reg_freq_to_chan(hdd_ctx->pdev, valid_ch[indx]))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015242 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015243 }
15244
15245 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015246 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015247 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015248 }
15249 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015250 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015251
15252}
15253
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015254static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
15255 struct net_device *dev,
15256 struct bss_parameters *params)
15257{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015258 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
15259 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015260 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053015261 QDF_STATUS qdf_ret_status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015262 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015263
Dustin Brown491d54b2018-03-14 12:39:11 -070015264 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015265
Anurag Chouhan6d760662016-02-20 16:05:43 +053015266 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070015267 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015268 return -EINVAL;
15269 }
15270
Jeff Johnson48363022019-02-24 16:26:51 -080015271 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015272 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015273
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053015274 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
15275 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080015276 adapter->vdev_id, params->ap_isolate);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053015277
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015278 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Dustin Brown458027c2018-10-19 12:26:27 -070015279 qdf_opmode_str(adapter->device_mode),
15280 adapter->device_mode, params->ap_isolate);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015281
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015282 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070015283 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015284 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015285 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015286
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015287 if (!(adapter->device_mode == QDF_SAP_MODE ||
15288 adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015289 return -EOPNOTSUPP;
15290 }
15291
15292 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015293 * want to update this parameter
15294 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015295 if (-1 != params->ap_isolate) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070015296 adapter->session.ap.disable_intrabss_fwd =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015297 !!params->ap_isolate;
15298
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015299 mac_handle = hdd_ctx->mac_handle;
15300 qdf_ret_status = sme_ap_disable_intra_bss_fwd(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080015301 adapter->vdev_id,
Jeff Johnsonb9424862017-10-30 08:49:35 -070015302 adapter->session.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015303 ap.
Jeff Johnson82ceb082017-10-27 14:52:42 -070015304 disable_intrabss_fwd);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015305 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015306 ret = -EINVAL;
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +053015307
Dustin Brown07901ec2018-09-07 11:02:41 -070015308 ucfg_ipa_set_ap_ibss_fwd(hdd_ctx->pdev,
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +053015309 adapter->session.ap.
15310 disable_intrabss_fwd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015311 }
15312
Dustin Browne74003f2018-03-14 12:51:58 -070015313 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015314 return ret;
15315}
15316
Krunal Soni8c37e322016-02-03 16:08:37 -080015317/**
Dustin Brown56377e12018-10-10 17:04:04 -070015318 * hdd_change_adapter_mode() - change @adapter's operating mode to @new_mode
15319 * @adapter: the adapter to change modes on
15320 * @new_mode: the new operating mode to change to
Krunal Soni8c37e322016-02-03 16:08:37 -080015321 *
Dustin Brown56377e12018-10-10 17:04:04 -070015322 * Return: Errno
Krunal Soni8c37e322016-02-03 16:08:37 -080015323 */
Dustin Brown56377e12018-10-10 17:04:04 -070015324static int hdd_change_adapter_mode(struct hdd_adapter *adapter,
15325 enum QDF_OPMODE new_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015326{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015327 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown56377e12018-10-10 17:04:04 -070015328 struct net_device *netdev = adapter->dev;
Krunal Soni8c37e322016-02-03 16:08:37 -080015329 struct hdd_config *config = hdd_ctx->config;
Jeff Johnson20227a92018-03-13 09:41:05 -070015330 struct csr_roam_profile *roam_profile;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053015331 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015332
Dustin Brown491d54b2018-03-14 12:39:11 -070015333 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015334
Krunal Soni8c37e322016-02-03 16:08:37 -080015335 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Dustin Brown56377e12018-10-10 17:04:04 -070015336 hdd_warn("Can't change interface: ACS in progress");
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070015337 return -EBUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015338 }
15339
Dustin Browndb2a8be2017-12-20 11:49:56 -080015340 hdd_stop_adapter(hdd_ctx, adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080015341 hdd_deinit_adapter(hdd_ctx, adapter, true);
Dustin Brown194aeca2018-10-12 15:37:36 -070015342 adapter->device_mode = new_mode;
Jeff Johnsonb9424862017-10-30 08:49:35 -070015343 memset(&adapter->session, 0, sizeof(adapter->session));
Dustin Brown56377e12018-10-10 17:04:04 -070015344 hdd_set_station_ops(netdev);
Jeff Johnson20227a92018-03-13 09:41:05 -070015345
15346 roam_profile = hdd_roam_profile(adapter);
15347 roam_profile->pAddIEScan = adapter->scan_info.scan_add_ie.addIEdata;
Dustin Brown56377e12018-10-10 17:04:04 -070015348 roam_profile->nAddIEScanLength = adapter->scan_info.scan_add_ie.length;
15349
15350 if (new_mode == QDF_IBSS_MODE) {
Krunal Sonib51eec72017-11-20 21:53:01 -080015351 status = hdd_start_station_adapter(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070015352 roam_profile->BSSType = eCSR_BSS_TYPE_START_IBSS;
15353 roam_profile->phyMode =
Krunal Soni8c37e322016-02-03 16:08:37 -080015354 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
15355 }
Dustin Brown56377e12018-10-10 17:04:04 -070015356
Dustin Browne74003f2018-03-14 12:51:58 -070015357 hdd_exit();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070015358
15359 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015360}
15361
15362static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
15363 struct net_device *dev,
15364 struct bss_parameters *params)
15365{
Dustin Brown1d31b082018-11-22 14:41:20 +053015366 int errno;
15367 struct osif_vdev_sync *vdev_sync;
15368
15369 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
15370 if (errno)
15371 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015372
Dustin Brown1d31b082018-11-22 14:41:20 +053015373 errno = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015374
Dustin Brown1d31b082018-11-22 14:41:20 +053015375 osif_vdev_sync_op_stop(vdev_sync);
15376
15377 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015378}
15379
Dustin Brown63fe4922018-10-12 15:02:26 -070015380static bool hdd_is_client_mode(enum QDF_OPMODE mode)
15381{
15382 switch (mode) {
15383 case QDF_STA_MODE:
15384 case QDF_P2P_CLIENT_MODE:
15385 case QDF_P2P_DEVICE_MODE:
15386 case QDF_IBSS_MODE:
15387 return true;
15388 default:
15389 return false;
15390 }
15391}
15392
15393static bool hdd_is_ap_mode(enum QDF_OPMODE mode)
15394{
15395 switch (mode) {
15396 case QDF_SAP_MODE:
15397 case QDF_P2P_GO_MODE:
15398 return true;
15399 default:
15400 return false;
15401 }
15402}
15403
15404/**
Rajeev Kumar98edb772016-01-19 12:42:19 -080015405 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
15406 * @wiphy: Pointer to the wiphy structure
15407 * @ndev: Pointer to the net device
15408 * @type: Interface type
15409 * @flags: Flags for change interface
15410 * @params: Pointer to change interface parameters
15411 *
15412 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015413 */
15414static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
15415 struct net_device *ndev,
15416 enum nl80211_iftype type,
15417 u32 *flags,
15418 struct vif_params *params)
15419{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015420 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070015421 struct hdd_context *hdd_ctx;
Dustin Brown56377e12018-10-10 17:04:04 -070015422 bool iff_up = ndev->flags & IFF_UP;
15423 enum QDF_OPMODE new_mode;
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053015424 bool ap_random_bssid_enabled;
Dustin Brown56377e12018-10-10 17:04:04 -070015425 QDF_STATUS status;
Dustin Brown63fe4922018-10-12 15:02:26 -070015426 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015427
Dustin Brown491d54b2018-03-14 12:39:11 -070015428 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015429
Dustin Brown63fe4922018-10-12 15:02:26 -070015430 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
Jeff Johnson77848112016-06-29 14:52:06 -070015431 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015432 return -EINVAL;
15433 }
15434
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015435 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown2ab5a972018-10-09 17:19:37 -070015436 errno = wlan_hdd_validate_context(hdd_ctx);
15437 if (errno)
15438 return errno;
Nachiket Kukade08b9f292017-11-17 18:27:37 +053015439
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053015440 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
15441 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080015442 adapter->vdev_id, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015443
Dustin Brown56377e12018-10-10 17:04:04 -070015444 status = hdd_nl_to_qdf_iface_type(type, &new_mode);
15445 if (QDF_IS_STATUS_ERROR(status))
15446 return qdf_status_to_os_return(status);
15447
Dustin Brown194aeca2018-10-12 15:37:36 -070015448 /* A userspace issue leads to it sending a 'change to station mode'
15449 * request on a "p2p" device, expecting the driver do execute a 'change
15450 * to p2p-device mode' request instead. The (unfortunate) work around
15451 * here is implemented by overriding the new mode if the net_device name
15452 * starts with "p2p" and the requested mode was station.
15453 */
15454 if (strnstr(ndev->name, "p2p", 3) && new_mode == QDF_STA_MODE)
15455 new_mode = QDF_P2P_DEVICE_MODE;
15456
Dustin Brown56377e12018-10-10 17:04:04 -070015457 hdd_debug("Changing mode for '%s' from %s to %s",
15458 ndev->name,
15459 qdf_opmode_str(adapter->device_mode),
15460 qdf_opmode_str(new_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015461
Rajeev Kumar473f9af2019-04-05 14:25:56 -070015462 errno = hdd_trigger_psoc_idle_restart(hdd_ctx);
Dustin Brown2ab5a972018-10-09 17:19:37 -070015463 if (errno) {
Dustin Brown3ecc8782018-09-19 16:37:13 -070015464 hdd_err("Failed to restart psoc; errno:%d", errno);
Arun Khandavallifae92942016-08-01 13:31:08 +053015465 return -EINVAL;
15466 }
15467
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015468 /* Reset the current device mode bit mask */
Dustin Brown2ab5a972018-10-09 17:19:37 -070015469 policy_mgr_clear_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015470
Dustin Brown63fe4922018-10-12 15:02:26 -070015471 if (hdd_is_client_mode(adapter->device_mode)) {
15472 if (hdd_is_client_mode(new_mode)) {
Visweswara Tanukub5a61242019-03-26 12:24:13 +053015473 if (new_mode == QDF_IBSS_MODE) {
15474 hdd_deregister_hl_netdev_fc_timer(adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015475 hdd_deregister_tx_flow_control(adapter);
Visweswara Tanukub5a61242019-03-26 12:24:13 +053015476 }
Dustin Brown56377e12018-10-10 17:04:04 -070015477
15478 errno = hdd_change_adapter_mode(adapter, new_mode);
Liangwei Dong4d35cad2018-11-02 02:38:50 -040015479 if (errno) {
15480 hdd_err("change intf mode fail %d", errno);
15481 goto err;
15482 }
Dustin Brown63fe4922018-10-12 15:02:26 -070015483 } else if (hdd_is_ap_mode(new_mode)) {
15484 if (new_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015485 wlan_hdd_cancel_existing_remain_on_channel
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015486 (adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015487
Dustin Browndb2a8be2017-12-20 11:49:56 -080015488 hdd_stop_adapter(hdd_ctx, adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015489 hdd_deinit_adapter(hdd_ctx, adapter, true);
Dustin Brown2ab5a972018-10-09 17:19:37 -070015490 memset(&adapter->session, 0, sizeof(adapter->session));
Dustin Brown56377e12018-10-10 17:04:04 -070015491 adapter->device_mode = new_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015492
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053015493 status = ucfg_mlme_get_ap_random_bssid_enable(
15494 hdd_ctx->psoc,
15495 &ap_random_bssid_enabled);
15496 if (QDF_IS_STATUS_ERROR(status))
15497 return qdf_status_to_os_return(status);
15498
Dustin Brown2ab5a972018-10-09 17:19:37 -070015499 if (adapter->device_mode == QDF_SAP_MODE &&
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053015500 ap_random_bssid_enabled) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015501 /* To meet Android requirements create
15502 * a randomized MAC address of the
15503 * form 02:1A:11:Fx:xx:xx
15504 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015505 get_random_bytes(&ndev->dev_addr[3], 3);
15506 ndev->dev_addr[0] = 0x02;
15507 ndev->dev_addr[1] = 0x1A;
15508 ndev->dev_addr[2] = 0x11;
15509 ndev->dev_addr[3] |= 0xF0;
Dustin Brown2ab5a972018-10-09 17:19:37 -070015510 memcpy(adapter->mac_addr.bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015511 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015512 pr_info("wlan: Generated HotSpot BSSID "
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070015513 QDF_MAC_ADDR_STR "\n",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070015514 QDF_MAC_ADDR_ARRAY(ndev->dev_addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015515 }
15516
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015517 hdd_set_ap_ops(adapter->dev);
Dustin Brown63fe4922018-10-12 15:02:26 -070015518 } else {
Dustin Brown56377e12018-10-10 17:04:04 -070015519 hdd_err("Changing to device mode '%s' is not supported",
15520 qdf_opmode_str(new_mode));
Liangwei Dong4d35cad2018-11-02 02:38:50 -040015521 errno = -EOPNOTSUPP;
15522 goto err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015523 }
Dustin Brown63fe4922018-10-12 15:02:26 -070015524 } else if (hdd_is_ap_mode(adapter->device_mode)) {
15525 if (hdd_is_client_mode(new_mode)) {
Dustin Brown56377e12018-10-10 17:04:04 -070015526 errno = hdd_change_adapter_mode(adapter, new_mode);
Liangwei Dong4d35cad2018-11-02 02:38:50 -040015527 if (errno) {
15528 hdd_err("change mode fail %d", errno);
15529 goto err;
15530 }
Dustin Brown63fe4922018-10-12 15:02:26 -070015531 } else if (hdd_is_ap_mode(new_mode)) {
Dustin Brown56377e12018-10-10 17:04:04 -070015532 adapter->device_mode = new_mode;
15533
Dustin Brown63fe4922018-10-12 15:02:26 -070015534 /* avoid starting the adapter, since it never stopped */
15535 iff_up = false;
15536 } else {
Dustin Brown56377e12018-10-10 17:04:04 -070015537 hdd_err("Changing to device mode '%s' is not supported",
15538 qdf_opmode_str(new_mode));
Liangwei Dong4d35cad2018-11-02 02:38:50 -040015539 errno = -EOPNOTSUPP;
15540 goto err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015541 }
15542 } else {
Dustin Brown56377e12018-10-10 17:04:04 -070015543 hdd_err("Changing from device mode '%s' is not supported",
15544 qdf_opmode_str(adapter->device_mode));
Liangwei Dong4d35cad2018-11-02 02:38:50 -040015545 errno = -EOPNOTSUPP;
15546 goto err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015547 }
Dustin Brown56377e12018-10-10 17:04:04 -070015548
Dustin Brown63fe4922018-10-12 15:02:26 -070015549 /* restart the adapter if it was up before the change iface request */
15550 if (iff_up) {
15551 errno = hdd_start_adapter(adapter);
15552 if (errno) {
15553 hdd_err("Failed to start adapter");
Liangwei Dong4d35cad2018-11-02 02:38:50 -040015554 errno = -EINVAL;
15555 goto err;
Dustin Brown63fe4922018-10-12 15:02:26 -070015556 }
15557 }
15558
15559 ndev->ieee80211_ptr->iftype = type;
Liangwei Dong4d35cad2018-11-02 02:38:50 -040015560 hdd_lpass_notify_mode_change(adapter);
15561err:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015562 /* Set bitmask based on updated value */
Dustin Brown2ab5a972018-10-09 17:19:37 -070015563 policy_mgr_set_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015564
Dustin Browne74003f2018-03-14 12:51:58 -070015565 hdd_exit();
Dustin Brown2ab5a972018-10-09 17:19:37 -070015566
Liangwei Dong4d35cad2018-11-02 02:38:50 -040015567 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015568}
15569
Dustin Brown0e1e1622019-01-17 11:00:22 -080015570static int _wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
15571 struct net_device *net_dev,
15572 enum nl80211_iftype type,
15573 u32 *flags,
15574 struct vif_params *params)
15575{
15576 int errno;
15577 struct osif_vdev_sync *vdev_sync;
15578
15579 errno = osif_vdev_sync_trans_start(net_dev, &vdev_sync);
15580 if (errno)
15581 return errno;
15582
Dustin Brown0e1e1622019-01-17 11:00:22 -080015583 errno = __wlan_hdd_cfg80211_change_iface(wiphy, net_dev, type,
15584 flags, params);
Dustin Brown0e1e1622019-01-17 11:00:22 -080015585
15586 osif_vdev_sync_trans_stop(vdev_sync);
15587
15588 return errno;
15589}
15590
Dustin Brown9ed30a52017-08-16 13:59:38 -070015591#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
Rajeev Kumar98edb772016-01-19 12:42:19 -080015592/**
15593 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
15594 * @wiphy: Pointer to the wiphy structure
15595 * @ndev: Pointer to the net device
15596 * @type: Interface type
15597 * @flags: Flags for change interface
15598 * @params: Pointer to change interface parameters
15599 *
15600 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015601 */
15602static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
15603 struct net_device *ndev,
15604 enum nl80211_iftype type,
15605 u32 *flags,
15606 struct vif_params *params)
15607{
Dustin Brown0e1e1622019-01-17 11:00:22 -080015608 return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
15609 flags, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015610}
Dustin Brown9ed30a52017-08-16 13:59:38 -070015611#else
15612static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
15613 struct net_device *ndev,
15614 enum nl80211_iftype type,
15615 struct vif_params *params)
15616{
Dustin Brown0e1e1622019-01-17 11:00:22 -080015617 return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
Dustin Brown9ed30a52017-08-16 13:59:38 -070015618 &params->flags, params);
Dustin Brown9ed30a52017-08-16 13:59:38 -070015619}
15620#endif /* KERNEL_VERSION(4, 12, 0) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015621
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053015622QDF_STATUS wlan_hdd_send_sta_authorized_event(
15623 struct hdd_adapter *adapter,
15624 struct hdd_context *hdd_ctx,
15625 const struct qdf_mac_addr *mac_addr)
15626{
15627 struct sk_buff *vendor_event;
15628 QDF_STATUS status;
15629 struct nl80211_sta_flag_update sta_flags;
15630
15631 hdd_enter();
15632 if (!hdd_ctx) {
15633 hdd_err("HDD context is null");
15634 return QDF_STATUS_E_INVAL;
15635 }
15636
15637 vendor_event =
15638 cfg80211_vendor_event_alloc(
15639 hdd_ctx->wiphy, &adapter->wdev, sizeof(sta_flags) +
15640 QDF_MAC_ADDR_SIZE + NLMSG_HDRLEN,
15641 QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX,
15642 GFP_KERNEL);
15643 if (!vendor_event) {
15644 hdd_err("cfg80211_vendor_event_alloc failed");
15645 return QDF_STATUS_E_FAILURE;
15646 }
15647
Ashish Kumar Dhanotiya0dd9b8b2019-06-04 20:21:06 +053015648 qdf_mem_zero(&sta_flags, sizeof(sta_flags));
15649
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053015650 sta_flags.mask |= BIT(NL80211_STA_FLAG_AUTHORIZED);
15651 sta_flags.set = true;
15652
15653 status = nla_put(vendor_event,
15654 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS,
15655 sizeof(struct nl80211_sta_flag_update),
15656 &sta_flags);
15657 if (status) {
15658 hdd_err("STA flag put fails");
15659 kfree_skb(vendor_event);
15660 return QDF_STATUS_E_FAILURE;
15661 }
15662 status = nla_put(vendor_event,
15663 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR,
15664 QDF_MAC_ADDR_SIZE, mac_addr->bytes);
15665 if (status) {
15666 hdd_err("STA MAC put fails");
15667 kfree_skb(vendor_event);
15668 return QDF_STATUS_E_FAILURE;
15669 }
15670
15671 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
15672
15673 hdd_exit();
15674 return QDF_STATUS_SUCCESS;
15675}
15676
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015677/**
15678 * __wlan_hdd_change_station() - change station
15679 * @wiphy: Pointer to the wiphy structure
15680 * @dev: Pointer to the net device.
15681 * @mac: bssid
15682 * @params: Pointer to station parameters
15683 *
15684 * Return: 0 for success, error number on failure.
15685 */
15686#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15687static int __wlan_hdd_change_station(struct wiphy *wiphy,
15688 struct net_device *dev,
15689 const uint8_t *mac,
15690 struct station_parameters *params)
15691#else
15692static int __wlan_hdd_change_station(struct wiphy *wiphy,
15693 struct net_device *dev,
15694 uint8_t *mac,
15695 struct station_parameters *params)
15696#endif
15697{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015698 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015699 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070015700 struct hdd_context *hdd_ctx;
Jeff Johnsond377dce2017-10-04 10:32:42 -070015701 struct hdd_station_ctx *sta_ctx;
Vignesh Viswanathan597d9012018-07-06 15:26:08 +053015702 struct hdd_ap_ctx *ap_ctx;
Jeff Johnsonf31df632019-03-23 11:53:28 -070015703 struct qdf_mac_addr sta_macaddr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015704 int ret;
15705
Dustin Brown491d54b2018-03-14 12:39:11 -070015706 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015707
Anurag Chouhan6d760662016-02-20 16:05:43 +053015708 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070015709 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015710 return -EINVAL;
15711 }
15712
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053015713 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
15714 TRACE_CODE_HDD_CHANGE_STATION,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080015715 adapter->vdev_id, params->listen_interval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015716
Jeff Johnson48363022019-02-24 16:26:51 -080015717 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015718 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015719
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015720 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070015721 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015722 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015723 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015724
Jeff Johnsond377dce2017-10-04 10:32:42 -070015725 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015726
Jeff Johnsonf31df632019-03-23 11:53:28 -070015727 qdf_mem_copy(sta_macaddr.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015728
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015729 if ((adapter->device_mode == QDF_SAP_MODE) ||
15730 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015731 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
Vignesh Viswanathan597d9012018-07-06 15:26:08 +053015732 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
15733 /*
15734 * For Encrypted SAP session, this will be done as
15735 * part of eSAP_STA_SET_KEY_EVENT
15736 */
15737 if (ap_ctx->encryption_type !=
15738 eCSR_ENCRYPT_TYPE_NONE) {
15739 hdd_debug("Encrypt type %d, not setting peer authorized now",
15740 ap_ctx->encryption_type);
15741 return 0;
15742 }
15743
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015744 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015745 hdd_softap_change_sta_state(adapter,
Jeff Johnsonf31df632019-03-23 11:53:28 -070015746 &sta_macaddr,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080015747 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015748
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015749 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015750 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015751 return -EINVAL;
15752 }
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053015753 status = wlan_hdd_send_sta_authorized_event(
15754 adapter,
15755 hdd_ctx,
Jeff Johnsonf31df632019-03-23 11:53:28 -070015756 &sta_macaddr);
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053015757 if (status != QDF_STATUS_SUCCESS) {
15758 return -EINVAL;
15759 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015760 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015761 } else if ((adapter->device_mode == QDF_STA_MODE) ||
15762 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015763 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud1a28462017-09-06 22:55:48 +080015764#if defined(FEATURE_WLAN_TDLS)
Min Liu8c5d99e2018-09-10 17:18:44 +080015765 struct wlan_objmgr_vdev *vdev;
15766
15767 vdev = hdd_objmgr_get_vdev(adapter);
15768 if (!vdev)
15769 return -EINVAL;
15770 ret = wlan_cfg80211_tdls_update_peer(vdev, mac, params);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053015771 hdd_objmgr_put_vdev(vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015772#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080015773 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015774 }
Dustin Browne74003f2018-03-14 12:51:58 -070015775 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015776 return ret;
15777}
15778
15779/**
15780 * wlan_hdd_change_station() - cfg80211 change station handler function
15781 * @wiphy: Pointer to the wiphy structure
15782 * @dev: Pointer to the net device.
15783 * @mac: bssid
15784 * @params: Pointer to station parameters
15785 *
15786 * This is the cfg80211 change station handler function which invokes
15787 * the internal function @__wlan_hdd_change_station with
15788 * SSR protection.
15789 *
15790 * Return: 0 for success, error number on failure.
15791 */
15792#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
15793static int wlan_hdd_change_station(struct wiphy *wiphy,
15794 struct net_device *dev,
15795 const u8 *mac,
15796 struct station_parameters *params)
15797#else
15798static int wlan_hdd_change_station(struct wiphy *wiphy,
15799 struct net_device *dev,
15800 u8 *mac,
15801 struct station_parameters *params)
15802#endif
15803{
Dustin Brown1d31b082018-11-22 14:41:20 +053015804 int errno;
15805 struct osif_vdev_sync *vdev_sync;
15806
15807 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
15808 if (errno)
15809 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015810
Dustin Brown1d31b082018-11-22 14:41:20 +053015811 errno = __wlan_hdd_change_station(wiphy, dev, mac, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015812
Dustin Brown1d31b082018-11-22 14:41:20 +053015813 osif_vdev_sync_op_stop(vdev_sync);
15814
15815 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015816}
15817
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015818#ifdef CRYPTO_SET_KEY_CONVERGED
15819#ifdef FEATURE_WLAN_ESE
15820static bool hdd_is_krk_enc_type(uint32_t cipher_type)
15821{
15822 if (cipher_type == WLAN_CIPHER_SUITE_KRK)
15823 return true;
15824
15825 return false;
15826}
15827#else
15828static bool hdd_is_krk_enc_type(uint32_t cipher_type)
15829{
15830 return false;
15831}
15832#endif
15833
15834#if defined(FEATURE_WLAN_ESE) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
15835static bool hdd_is_btk_enc_type(uint32_t cipher_type)
15836{
15837 if (cipher_type == WLAN_CIPHER_SUITE_BTK)
15838 return true;
15839
15840 return false;
15841}
15842#else
15843static bool hdd_is_btk_enc_type(uint32_t cipher_type)
15844{
15845 return false;
15846}
15847#endif
15848#endif
15849
15850#ifdef CRYPTO_SET_KEY_CONVERGED
Abhishek Ambure68677462019-09-13 12:44:26 +053015851#ifdef QCA_IBSS_SUPPORT
15852/**
15853 * wlan_hdd_add_key_ibss() - API to add IBSS key
15854 * @adapter: Pointer to adapter
15855 * @pairwise: need to add key pairwise
15856 * @key_index: key index
15857 * @mac_addr: Pointer to mac_addr
15858 * @params: Pointer to key params
15859 * @key_already_installed: pointer to key already installed state
15860 *
15861 * This API will add IBSS key for given mac address.
15862 *
15863 * Return: 0 for success, error number on failure.
15864 */
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015865static int wlan_hdd_add_key_ibss(struct hdd_adapter *adapter,
15866 bool pairwise, u8 key_index,
15867 const u8 *mac_addr, struct key_params *params,
15868 bool *key_already_installed)
15869{
15870 struct wlan_objmgr_vdev *vdev;
15871 int errno;
15872
15873 if (pairwise)
15874 return 0;
15875 /* if a key is already installed, block all subsequent ones */
15876 if (adapter->session.station.ibss_enc_key_installed) {
15877 hdd_debug("IBSS key installed already");
15878 *key_already_installed = true;
15879 return 0;
15880 }
15881 /*Set the group key */
15882 vdev = hdd_objmgr_get_vdev(adapter);
15883 if (!vdev)
15884 return -EINVAL;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080015885 errno = wlan_cfg80211_crypto_add_key(vdev, WLAN_CRYPTO_KEY_TYPE_GROUP,
15886 key_index);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015887 if (errno) {
15888 hdd_err("add_ibss_key failed, errno: %d", errno);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053015889 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015890 return errno;
15891 }
15892 /* Save the keys here and call set_key for setting
15893 * the PTK after peer joins the IBSS network
15894 */
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080015895 wlan_cfg80211_store_key(vdev, key_index, WLAN_CRYPTO_KEY_TYPE_UNICAST,
15896 mac_addr, params);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053015897 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015898 adapter->session.station.ibss_enc_key_installed = 1;
15899
15900 return 0;
15901}
Abhishek Ambure68677462019-09-13 12:44:26 +053015902#else
15903/**
15904 * wlan_hdd_add_key_ibss() - API to add IBSS key
15905 * @adapter: Pointer to adapter
15906 * @pairwise: need to add key pairwise
15907 * @key_index: key index
15908 * @mac_addr: Pointer to mac_addr
15909 * @params: Pointer to key params
15910 * @key_already_installed: pointer to key already installed state
15911 *
15912 * This function is dummy
15913 *
15914 * Return: 0
15915 */
15916static inline int
15917wlan_hdd_add_key_ibss(struct hdd_adapter *adapter,
15918 bool pairwise, u8 key_index,
15919 const u8 *mac_addr, struct key_params *params,
15920 bool *key_already_installed)
15921{
15922 return 0;
15923}
15924#endif
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015925
15926static int wlan_hdd_add_key_sap(struct hdd_adapter *adapter,
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080015927 bool pairwise, u8 key_index,
15928 enum wlan_crypto_cipher_type cipher)
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015929{
15930 struct wlan_objmgr_vdev *vdev;
15931 int errno = 0;
15932 struct hdd_hostapd_state *hostapd_state =
15933 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
15934
15935 vdev = hdd_objmgr_get_vdev(adapter);
15936 if (!vdev)
15937 return -EINVAL;
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080015938 if (hostapd_state->bss_state == BSS_START) {
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080015939 errno =
15940 wlan_cfg80211_crypto_add_key(vdev, (pairwise ?
15941 WLAN_CRYPTO_KEY_TYPE_UNICAST :
15942 WLAN_CRYPTO_KEY_TYPE_GROUP),
15943 key_index);
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080015944 if (!errno)
15945 wma_update_set_key(adapter->vdev_id, pairwise,
15946 key_index, cipher);
15947 }
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053015948 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015949
15950 return errno;
15951}
15952
15953static int wlan_hdd_add_key_sta(struct hdd_adapter *adapter,
15954 bool pairwise, u8 key_index,
15955 mac_handle_t mac_handle, bool *ft_mode)
15956{
15957 struct wlan_objmgr_vdev *vdev;
15958 struct hdd_station_ctx *sta_ctx =
15959 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15960 int errno;
15961 QDF_STATUS status;
15962
15963 if (!pairwise) {
15964 /* set group key */
15965 if (sta_ctx->roam_info.defer_key_complete) {
15966 hdd_debug("Perform Set key Complete");
15967 hdd_perform_roam_set_key_complete(adapter);
15968 }
15969 }
15970 /* The supplicant may attempt to set the PTK once
15971 * pre-authentication is done. Save the key in the
15972 * UMAC and include it in the ADD BSS request
15973 */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080015974 status = sme_check_ft_status(mac_handle, adapter->vdev_id);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015975 if (status == QDF_STATUS_SUCCESS) {
15976 *ft_mode = true;
15977 return 0;
15978 }
15979 vdev = hdd_objmgr_get_vdev(adapter);
15980 if (!vdev)
15981 return -EINVAL;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080015982 errno = wlan_cfg80211_crypto_add_key(vdev, (pairwise ?
15983 WLAN_CRYPTO_KEY_TYPE_UNICAST :
15984 WLAN_CRYPTO_KEY_TYPE_GROUP),
15985 key_index);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053015986 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015987 if (!errno && adapter->send_mode_change) {
15988 wlan_hdd_send_mode_change_event();
15989 adapter->send_mode_change = false;
15990 }
15991
15992 return errno;
15993}
15994
15995static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
15996 struct net_device *ndev,
15997 u8 key_index, bool pairwise,
15998 const u8 *mac_addr,
15999 struct key_params *params)
16000{
16001 struct hdd_context *hdd_ctx;
16002 mac_handle_t mac_handle;
16003 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
16004 struct wlan_objmgr_vdev *vdev;
16005 bool key_already_installed = false, ft_mode = false;
16006 enum wlan_crypto_cipher_type cipher;
16007 int errno;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016008 struct qdf_mac_addr mac_address;
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016009
16010 hdd_enter();
16011
16012 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16013 hdd_err("Command not allowed in FTM mode");
16014 return -EINVAL;
16015 }
16016
Jeff Johnson48363022019-02-24 16:26:51 -080016017 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016018 return -EINVAL;
16019
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016020 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
16021 TRACE_CODE_HDD_CFG80211_ADD_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016022 adapter->vdev_id, params->key_len);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016023
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016024 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16025 errno = wlan_hdd_validate_context(hdd_ctx);
16026 if (errno)
16027 return errno;
16028
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016029 hdd_debug("converged Device_mode %s(%d) index %d, pairwise %d",
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016030 qdf_opmode_str(adapter->device_mode),
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016031 adapter->device_mode, key_index, pairwise);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016032 mac_handle = hdd_ctx->mac_handle;
16033
16034 if (hdd_is_btk_enc_type(params->cipher))
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016035 return sme_add_key_btk(mac_handle, adapter->vdev_id,
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016036 params->key, params->key_len);
16037 if (hdd_is_krk_enc_type(params->cipher))
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016038 return sme_add_key_krk(mac_handle, adapter->vdev_id,
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016039 params->key, params->key_len);
16040
16041 vdev = hdd_objmgr_get_vdev(adapter);
16042 if (!vdev)
16043 return -EINVAL;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016044 if (!pairwise && ((adapter->device_mode == QDF_STA_MODE) ||
16045 (adapter->device_mode == QDF_P2P_CLIENT_MODE))) {
16046 qdf_mem_copy(mac_address.bytes,
Jeff Johnsone04b6992019-02-27 14:06:55 -080016047 adapter->session.station.conn_info.bssid.bytes,
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016048 QDF_MAC_ADDR_SIZE);
16049 } else {
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016050 if (mac_addr)
16051 qdf_mem_copy(mac_address.bytes, mac_addr,
16052 QDF_MAC_ADDR_SIZE);
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016053 }
16054 errno = wlan_cfg80211_store_key(vdev, key_index,
16055 (pairwise ?
16056 WLAN_CRYPTO_KEY_TYPE_UNICAST :
16057 WLAN_CRYPTO_KEY_TYPE_GROUP),
16058 mac_address.bytes, params);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053016059 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016060 if (errno)
16061 return errno;
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016062 cipher = osif_nl_to_crypto_cipher_type(params->cipher);
Abhishek Singhf880a7d2019-04-29 14:51:11 +053016063 if (pairwise)
16064 wma_set_peer_ucast_cipher(mac_address.bytes, cipher);
16065
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016066 switch (adapter->device_mode) {
16067 case QDF_IBSS_MODE:
16068 errno = wlan_hdd_add_key_ibss(adapter, pairwise, key_index,
16069 mac_addr, params,
16070 &key_already_installed);
16071 if (key_already_installed)
16072 return 0;
16073 break;
16074 case QDF_SAP_MODE:
16075 case QDF_P2P_GO_MODE:
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016076 errno = wlan_hdd_add_key_sap(adapter, pairwise,
16077 key_index, cipher);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016078 break;
16079 case QDF_STA_MODE:
16080 case QDF_P2P_CLIENT_MODE:
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016081 errno = wlan_hdd_add_key_sta(adapter, pairwise, key_index,
16082 mac_handle, &ft_mode);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016083 if (ft_mode)
16084 return 0;
16085 break;
16086 default:
16087 break;
16088 }
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016089 if (!errno && (adapter->device_mode != QDF_SAP_MODE))
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016090 wma_update_set_key(adapter->vdev_id, pairwise, key_index,
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016091 cipher);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016092 hdd_exit();
16093
16094 return errno;
16095}
16096#else /* !CRYPTO_SET_KEY_CONVERGED */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016097/*
16098 * FUNCTION: __wlan_hdd_cfg80211_add_key
16099 * This function is used to initialize the key information
16100 */
16101static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
16102 struct net_device *ndev,
16103 u8 key_index, bool pairwise,
16104 const u8 *mac_addr,
16105 struct key_params *params)
16106{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016107 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson89515092019-03-23 10:52:04 -070016108 tCsrRoamSetKey set_key;
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016109 int errno;
Jeff Johnson29c78672019-02-26 21:05:53 -080016110 uint32_t roam_id = INVALID_ROAM_ID;
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016111 QDF_STATUS status;
Jeff Johnsonb8944722017-09-03 09:03:19 -070016112 struct hdd_context *hdd_ctx;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016113 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016114
Dustin Brown491d54b2018-03-14 12:39:11 -070016115 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016116
Anurag Chouhan6d760662016-02-20 16:05:43 +053016117 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016118 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016119 return -EINVAL;
16120 }
16121
Jeff Johnson48363022019-02-24 16:26:51 -080016122 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016123 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016124
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016125 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
16126 TRACE_CODE_HDD_CFG80211_ADD_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016127 adapter->vdev_id, params->key_len);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016128
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016129 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016130 errno = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016131
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016132 if (errno)
16133 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016134
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016135 hdd_debug("Device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070016136 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016137
16138 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016139 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016140
16141 return -EINVAL;
16142 }
16143
16144 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016145 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016146
16147 return -EINVAL;
16148 }
16149
Srinivas Girigowdacf161402019-03-14 11:37:33 -070016150 if (WLAN_CRYPTO_RSC_SIZE < params->seq_len) {
Jeff Johnsonb05f4fd2017-10-18 15:08:21 -070016151 hdd_err("Invalid seq length %d", params->seq_len);
16152
16153 return -EINVAL;
16154 }
16155
16156 hdd_debug("key index %d, key length %d, seq length %d",
16157 key_index, params->key_len, params->seq_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016158
16159 /*extract key idx, key len and key */
Jeff Johnson89515092019-03-23 10:52:04 -070016160 qdf_mem_zero(&set_key, sizeof(tCsrRoamSetKey));
16161 set_key.keyId = key_index;
16162 set_key.keyLength = params->key_len;
16163 qdf_mem_copy(&set_key.Key[0], params->key, params->key_len);
16164 qdf_mem_copy(&set_key.keyRsc[0], params->seq, params->seq_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016165
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016166 mac_handle = hdd_ctx->mac_handle;
16167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016168 switch (params->cipher) {
16169 case WLAN_CIPHER_SUITE_WEP40:
Jeff Johnson89515092019-03-23 10:52:04 -070016170 set_key.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016171 break;
16172
16173 case WLAN_CIPHER_SUITE_WEP104:
Jeff Johnson89515092019-03-23 10:52:04 -070016174 set_key.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016175 break;
16176
16177 case WLAN_CIPHER_SUITE_TKIP:
16178 {
Jeff Johnson675072b2019-03-23 11:47:35 -070016179 u8 *key = &set_key.Key[0];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016180
Jeff Johnson89515092019-03-23 10:52:04 -070016181 set_key.encType = eCSR_ENCRYPT_TYPE_TKIP;
Jeff Johnson675072b2019-03-23 11:47:35 -070016182 qdf_mem_zero(key, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016183
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016184 /* Supplicant sends the 32bytes key in this order
16185 *
16186 * |--------------|----------|----------|
16187 * | Tk1 |TX-MIC | RX Mic |
16188 * |--------------|----------|----------|
16189 * <---16bytes---><--8bytes--><--8bytes-->
16190 *
16191 * Sme expects the 32 bytes key to be in the below order
16192 *
16193 * |--------------|----------|----------|
16194 * | Tk1 |RX-MIC | TX Mic |
16195 * |--------------|----------|----------|
16196 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016197 */
16198 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnson675072b2019-03-23 11:47:35 -070016199 qdf_mem_copy(key, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016200
16201 /*Copy the rx mic first */
Jeff Johnson675072b2019-03-23 11:47:35 -070016202 qdf_mem_copy(&key[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016203
16204 /*Copy the tx mic */
Jeff Johnson675072b2019-03-23 11:47:35 -070016205 qdf_mem_copy(&key[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016206
16207 break;
16208 }
16209
16210 case WLAN_CIPHER_SUITE_CCMP:
Jeff Johnson89515092019-03-23 10:52:04 -070016211 set_key.encType = eCSR_ENCRYPT_TYPE_AES;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016212 break;
16213
16214#ifdef FEATURE_WLAN_WAPI
16215 case WLAN_CIPHER_SUITE_SMS4:
16216 {
Jeff Johnson89515092019-03-23 10:52:04 -070016217 qdf_mem_zero(&set_key, sizeof(tCsrRoamSetKey));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016218 wlan_hdd_cfg80211_set_key_wapi(adapter, key_index,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016219 mac_addr, params->key,
16220 params->key_len);
16221 return 0;
16222 }
16223#endif
16224
16225#ifdef FEATURE_WLAN_ESE
16226 case WLAN_CIPHER_SUITE_KRK:
Jeff Johnson89515092019-03-23 10:52:04 -070016227 set_key.encType = eCSR_ENCRYPT_TYPE_KRK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016228 break;
16229#ifdef WLAN_FEATURE_ROAM_OFFLOAD
16230 case WLAN_CIPHER_SUITE_BTK:
Jeff Johnson89515092019-03-23 10:52:04 -070016231 set_key.encType = eCSR_ENCRYPT_TYPE_BTK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016232 break;
16233#endif
16234#endif
16235
16236#ifdef WLAN_FEATURE_11W
16237 case WLAN_CIPHER_SUITE_AES_CMAC:
Jeff Johnson89515092019-03-23 10:52:04 -070016238 set_key.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016239 break;
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +053016240#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
16241 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
Jeff Johnson89515092019-03-23 10:52:04 -070016242 set_key.encType = eCSR_ENCRYPT_TYPE_AES_GMAC_128;
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +053016243 break;
16244 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
Jeff Johnson89515092019-03-23 10:52:04 -070016245 set_key.encType = eCSR_ENCRYPT_TYPE_AES_GMAC_256;
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +053016246 break;
16247#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016248#endif
Mukul Sharma05504ac2017-06-08 12:35:53 +053016249 case WLAN_CIPHER_SUITE_GCMP:
Jeff Johnson89515092019-03-23 10:52:04 -070016250 set_key.encType = eCSR_ENCRYPT_TYPE_AES_GCMP;
Mukul Sharma05504ac2017-06-08 12:35:53 +053016251 break;
16252 case WLAN_CIPHER_SUITE_GCMP_256:
Jeff Johnson89515092019-03-23 10:52:04 -070016253 set_key.encType = eCSR_ENCRYPT_TYPE_AES_GCMP_256;
Mukul Sharma05504ac2017-06-08 12:35:53 +053016254 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016255
16256 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016257 hdd_err("Unsupported cipher type: %u", params->cipher);
Jeff Johnson89515092019-03-23 10:52:04 -070016258 qdf_mem_zero(&set_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016259 return -EOPNOTSUPP;
16260 }
16261
Jeff Johnson89515092019-03-23 10:52:04 -070016262 hdd_debug("encryption type %d", set_key.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016263
16264 if (!pairwise) {
16265 /* set group key */
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070016266 hdd_debug("setting Broadcast key");
Jeff Johnson89515092019-03-23 10:52:04 -070016267 set_key.keyDirection = eSIR_RX_ONLY;
16268 qdf_set_macaddr_broadcast(&set_key.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016269 } else {
16270 /* set pairwise key */
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070016271 hdd_debug("setting pairwise key");
Jeff Johnson89515092019-03-23 10:52:04 -070016272 set_key.keyDirection = eSIR_TX_RX;
16273 qdf_mem_copy(set_key.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016274 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016275 if ((QDF_IBSS_MODE == adapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016276 /* if a key is already installed, block all subsequent ones */
Jeff Johnsonb9424862017-10-30 08:49:35 -070016277 if (adapter->session.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016278 hdd_debug("IBSS key installed already");
Jeff Johnson89515092019-03-23 10:52:04 -070016279 qdf_mem_zero(&set_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016280 return 0;
16281 }
16282
Jeff Johnson89515092019-03-23 10:52:04 -070016283 set_key.keyDirection = eSIR_TX_RX;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016284 /*Set the group key */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016285 status = sme_roam_set_key(mac_handle,
Jeff Johnson89515092019-03-23 10:52:04 -070016286 adapter->vdev_id, &set_key, &roam_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016287
16288 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016289 hdd_err("sme_roam_set_key failed, status: %d", status);
Jeff Johnson89515092019-03-23 10:52:04 -070016290 qdf_mem_zero(&set_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016291 return -EINVAL;
16292 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016293 /* Save the keys here and call sme_roam_set_key for setting
16294 * the PTK after peer joins the IBSS network
16295 */
Jeff Johnsonb9424862017-10-30 08:49:35 -070016296 qdf_mem_copy(&adapter->session.station.ibss_enc_key,
Jeff Johnson89515092019-03-23 10:52:04 -070016297 &set_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016298
Jeff Johnsonb9424862017-10-30 08:49:35 -070016299 adapter->session.station.ibss_enc_key_installed = 1;
Jeff Johnson89515092019-03-23 10:52:04 -070016300 qdf_mem_zero(&set_key, sizeof(tCsrRoamSetKey));
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016301 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016302 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016303 if ((adapter->device_mode == QDF_SAP_MODE) ||
16304 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053016305 struct hdd_hostapd_state *hostapd_state =
16306 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
16307 struct hdd_ap_ctx *ap_ctx =
16308 WLAN_HDD_GET_AP_CTX_PTR(adapter);
16309
Jeff Johnson0f9f87b2017-10-28 09:21:06 -070016310 if (hostapd_state->bss_state == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070016311 status = wlansap_set_key_sta(
Jeff Johnson89515092019-03-23 10:52:04 -070016312 WLAN_HDD_GET_SAP_CTX_PTR(adapter), &set_key);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016313 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016314 hdd_err("wlansap_set_key_sta failed status: %d",
16315 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016316 }
16317 }
16318
Jeff Johnson413c15f2017-10-27 18:56:35 -070016319 /* Save the key in ap ctx for use on START_BSS and restart */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016320 if (pairwise ||
Jeff Johnson89515092019-03-23 10:52:04 -070016321 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == set_key.encType ||
16322 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == set_key.encType)
16323 qdf_mem_copy(&ap_ctx->wep_key[key_index], &set_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016324 sizeof(tCsrRoamSetKey));
16325 else
Jeff Johnson89515092019-03-23 10:52:04 -070016326 qdf_mem_copy(&ap_ctx->group_key, &set_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016327 sizeof(tCsrRoamSetKey));
16328
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016329 } else if ((adapter->device_mode == QDF_STA_MODE) ||
16330 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Jeff Johnsond377dce2017-10-04 10:32:42 -070016331 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016332 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016333 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016334
16335 if (!pairwise) {
16336 /* set group key */
Jeff Johnsonaf2ae4b2017-11-01 11:38:50 -070016337 if (sta_ctx->roam_info.defer_key_complete) {
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070016338 hdd_debug("Perform Set key Complete");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016339 hdd_perform_roam_set_key_complete(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016340 }
16341 }
16342
Jeff Johnson20227a92018-03-13 09:41:05 -070016343 roam_profile = hdd_roam_profile(adapter);
16344 roam_profile->Keys.KeyLength[key_index] = params->key_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016345
Jeff Johnson20227a92018-03-13 09:41:05 -070016346 roam_profile->Keys.defaultIndex = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016347
Jeff Johnson20227a92018-03-13 09:41:05 -070016348 qdf_mem_copy(&roam_profile->Keys.KeyMaterial[key_index][0],
16349 params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016350
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070016351 hdd_debug("Set key for peerMac "QDF_MAC_ADDR_STR" direction %d",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070016352 QDF_MAC_ADDR_ARRAY(set_key.peerMac.bytes),
16353 set_key.keyDirection);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016354
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016355 /* The supplicant may attempt to set the PTK once
16356 * pre-authentication is done. Save the key in the
16357 * UMAC and include it in the ADD BSS request
16358 */
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016359 status = sme_ft_update_key(mac_handle,
Jeff Johnson89515092019-03-23 10:52:04 -070016360 adapter->vdev_id, &set_key);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016361 if (status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016362 hdd_debug("Update PreAuth Key success");
Jeff Johnson89515092019-03-23 10:52:04 -070016363 qdf_mem_zero(&set_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016364 return 0;
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016365 } else if (status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016366 hdd_err("Update PreAuth Key failed");
Jeff Johnson89515092019-03-23 10:52:04 -070016367 qdf_mem_zero(&set_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016368 return -EINVAL;
16369 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016370
16371 /* issue set key request to SME */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016372 status = sme_roam_set_key(mac_handle,
Jeff Johnson89515092019-03-23 10:52:04 -070016373 adapter->vdev_id, &set_key,
Jeff Johnson29c78672019-02-26 21:05:53 -080016374 &roam_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016375
16376 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016377 hdd_err("sme_roam_set_key failed, status: %d", status);
Jeff Johnson89515092019-03-23 10:52:04 -070016378 qdf_mem_zero(&set_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016379 return -EINVAL;
16380 }
16381
Yeshwanth Sriram Guntuka4fe30bd2018-06-13 11:41:42 +053016382 if (adapter->send_mode_change) {
16383 wlan_hdd_send_mode_change_event();
16384 adapter->send_mode_change = false;
16385 }
16386
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016387 /* in case of IBSS as there was no information
16388 * available about WEP keys during IBSS join, group
Jeff Johnson5e19a942018-05-06 15:37:39 -070016389 * key initialized with NULL key, so re-initialize
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016390 * group key with correct value
16391 */
Jeff Johnson20227a92018-03-13 09:41:05 -070016392 if ((eCSR_BSS_TYPE_START_IBSS == roam_profile->BSSType) &&
Jeff Johnson37ecea42018-03-18 17:54:40 -070016393 !((HDD_AUTH_KEY_MGMT_802_1X ==
16394 (sta_ctx->auth_key_mgmt & HDD_AUTH_KEY_MGMT_802_1X))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016395 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
Jeff Johnson96e33512019-02-27 15:10:21 -080016396 sta_ctx->conn_info.auth_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016397 )
16398 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
16399 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
16400 )
16401 ) {
Jeff Johnson89515092019-03-23 10:52:04 -070016402 set_key.keyDirection = eSIR_RX_ONLY;
16403 qdf_set_macaddr_broadcast(&set_key.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016404
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070016405 hdd_debug("Set key peerMac "QDF_MAC_ADDR_STR" direction %d",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070016406 QDF_MAC_ADDR_ARRAY(set_key.peerMac.bytes),
Jeff Johnson89515092019-03-23 10:52:04 -070016407 set_key.keyDirection);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016408
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016409 status = sme_roam_set_key(mac_handle,
Jeff Johnson89515092019-03-23 10:52:04 -070016410 adapter->vdev_id, &set_key,
Jeff Johnson29c78672019-02-26 21:05:53 -080016411 &roam_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016412
16413 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016414 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Jeff Johnson89515092019-03-23 10:52:04 -070016415 qdf_mem_zero(&set_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016416 return -EINVAL;
16417 }
16418 }
16419 }
Jeff Johnson89515092019-03-23 10:52:04 -070016420 qdf_mem_zero(&set_key, sizeof(tCsrRoamSetKey));
Dustin Browne74003f2018-03-14 12:51:58 -070016421 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016422 return 0;
16423}
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016424#endif /* CRYPTO_SET_KEY_CONVERGED */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016425
16426static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
16427 struct net_device *ndev,
16428 u8 key_index, bool pairwise,
16429 const u8 *mac_addr,
16430 struct key_params *params)
16431{
Dustin Brown1d31b082018-11-22 14:41:20 +053016432 int errno;
16433 struct osif_vdev_sync *vdev_sync;
16434
16435 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
16436 if (errno)
16437 return errno;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070016438
Dustin Brown1d31b082018-11-22 14:41:20 +053016439 errno = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
16440 mac_addr, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016441
Dustin Brown1d31b082018-11-22 14:41:20 +053016442 osif_vdev_sync_op_stop(vdev_sync);
16443
16444 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016445}
16446
16447/*
16448 * FUNCTION: __wlan_hdd_cfg80211_get_key
16449 * This function is used to get the key information
16450 */
16451static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
16452 struct net_device *ndev,
16453 u8 key_index, bool pairwise,
16454 const u8 *mac_addr, void *cookie,
16455 void (*callback)(void *cookie,
16456 struct key_params *)
16457 )
16458{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016459 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070016460 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016461 struct key_params params;
16462
Dustin Brown491d54b2018-03-14 12:39:11 -070016463 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016464
Anurag Chouhan6d760662016-02-20 16:05:43 +053016465 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016466 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016467 return -EINVAL;
16468 }
16469
Jeff Johnson48363022019-02-24 16:26:51 -080016470 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Jiachao Wud58cfc92017-12-27 14:15:23 +080016471 return -EINVAL;
Jiachao Wud58cfc92017-12-27 14:15:23 +080016472
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016473 hdd_debug("Device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070016474 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016475
16476 memset(&params, 0, sizeof(params));
16477
16478 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016479 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016480 return -EINVAL;
16481 }
16482
Nachiket Kukaded9152832017-10-16 16:18:22 +053016483 if ((adapter->device_mode == QDF_SAP_MODE) ||
16484 (adapter->device_mode == QDF_P2P_GO_MODE)) {
16485 struct hdd_ap_ctx *ap_ctx =
16486 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016487
Nachiket Kukaded9152832017-10-16 16:18:22 +053016488 roam_profile =
16489 wlan_sap_get_roam_profile(ap_ctx->sap_context);
16490 } else {
Jeff Johnson20227a92018-03-13 09:41:05 -070016491 roam_profile = hdd_roam_profile(adapter);
Nachiket Kukaded9152832017-10-16 16:18:22 +053016492 }
16493
Jeff Johnsond36fa332019-03-18 13:42:25 -070016494 if (!roam_profile) {
Jiachao Wud58cfc92017-12-27 14:15:23 +080016495 hdd_err("Get roam profile failed!");
16496 return -EINVAL;
16497 }
16498
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016499 switch (roam_profile->EncryptionType.encryptionType[0]) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016500 case eCSR_ENCRYPT_TYPE_NONE:
16501 params.cipher = IW_AUTH_CIPHER_NONE;
16502 break;
16503
16504 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
16505 case eCSR_ENCRYPT_TYPE_WEP40:
16506 params.cipher = WLAN_CIPHER_SUITE_WEP40;
16507 break;
16508
16509 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
16510 case eCSR_ENCRYPT_TYPE_WEP104:
16511 params.cipher = WLAN_CIPHER_SUITE_WEP104;
16512 break;
16513
16514 case eCSR_ENCRYPT_TYPE_TKIP:
16515 params.cipher = WLAN_CIPHER_SUITE_TKIP;
16516 break;
16517
16518 case eCSR_ENCRYPT_TYPE_AES:
16519 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
16520 break;
Mukul Sharma05504ac2017-06-08 12:35:53 +053016521 case eCSR_ENCRYPT_TYPE_AES_GCMP:
16522 params.cipher = WLAN_CIPHER_SUITE_GCMP;
16523 break;
16524 case eCSR_ENCRYPT_TYPE_AES_GCMP_256:
16525 params.cipher = WLAN_CIPHER_SUITE_GCMP_256;
16526 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016527 default:
16528 params.cipher = IW_AUTH_CIPHER_NONE;
16529 break;
16530 }
16531
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016532 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
16533 TRACE_CODE_HDD_CFG80211_GET_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016534 adapter->vdev_id, params.cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016535
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016536 params.key_len = roam_profile->Keys.KeyLength[key_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016537 params.seq_len = 0;
16538 params.seq = NULL;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016539 params.key = &roam_profile->Keys.KeyMaterial[key_index][0];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016540 callback(cookie, &params);
16541
Dustin Browne74003f2018-03-14 12:51:58 -070016542 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016543 return 0;
16544}
16545
16546static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
16547 struct net_device *ndev,
16548 u8 key_index, bool pairwise,
16549 const u8 *mac_addr, void *cookie,
16550 void (*callback)(void *cookie,
16551 struct key_params *)
16552 )
16553{
Dustin Brown1d31b082018-11-22 14:41:20 +053016554 int errno;
16555 struct osif_vdev_sync *vdev_sync;
16556
16557 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
16558 if (errno)
16559 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016560
Dustin Brown1d31b082018-11-22 14:41:20 +053016561 errno = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
16562 mac_addr, cookie, callback);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016563
Dustin Brown1d31b082018-11-22 14:41:20 +053016564 osif_vdev_sync_op_stop(vdev_sync);
16565
16566 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016567}
16568
16569/**
16570 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
16571 * @wiphy: wiphy interface context
16572 * @ndev: pointer to net device
16573 * @key_index: Key index used in 802.11 frames
16574 * @unicast: true if it is unicast key
16575 * @multicast: true if it is multicast key
16576 *
16577 * This function is required for cfg80211_ops API.
16578 * It is used to delete the key information
16579 * Underlying hardware implementation does not have API to delete the
16580 * encryption key. It is automatically deleted when the peer is
16581 * removed. Hence this function currently does nothing.
16582 * Future implementation may interprete delete key operation to
16583 * replacing the key with a random junk value, effectively making it
16584 * useless.
16585 *
16586 * Return: status code, always 0.
16587 */
16588
16589static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
16590 struct net_device *ndev,
16591 u8 key_index,
16592 bool pairwise, const u8 *mac_addr)
16593{
Dustin Browne74003f2018-03-14 12:51:58 -070016594 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016595 return 0;
16596}
16597
16598/**
16599 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
16600 * @wiphy: Pointer to wiphy structure.
16601 * @dev: Pointer to net_device structure.
16602 * @key_index: key index
16603 * @pairwise: pairwise
16604 * @mac_addr: mac address
16605 *
16606 * This is the cfg80211 delete key handler function which invokes
16607 * the internal function @__wlan_hdd_cfg80211_del_key with
16608 * SSR protection.
16609 *
16610 * Return: 0 for success, error number on failure.
16611 */
16612static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
16613 struct net_device *dev,
16614 u8 key_index,
16615 bool pairwise, const u8 *mac_addr)
16616{
Dustin Brown1d31b082018-11-22 14:41:20 +053016617 int errno;
16618 struct osif_vdev_sync *vdev_sync;
16619
16620 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
16621 if (errno)
16622 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016623
Dustin Brown1d31b082018-11-22 14:41:20 +053016624 errno = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
16625 pairwise, mac_addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016626
Dustin Brown1d31b082018-11-22 14:41:20 +053016627 osif_vdev_sync_op_stop(vdev_sync);
16628
16629 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016630}
16631
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016632#ifndef CRYPTO_SET_KEY_CONVERGED
Hu Wangc3148842017-06-20 19:03:29 +080016633#ifdef FEATURE_WLAN_WAPI
Jeff Johnsonb1959842019-02-27 13:04:04 -080016634static bool hdd_is_wapi_enc_type(eCsrEncryptionType encrypt_type)
Hu Wangc3148842017-06-20 19:03:29 +080016635{
Jeff Johnsonb1959842019-02-27 13:04:04 -080016636 if (encrypt_type == eCSR_ENCRYPT_TYPE_WPI)
Hu Wangc3148842017-06-20 19:03:29 +080016637 return true;
16638
16639 return false;
16640}
16641#else
Jeff Johnsonb1959842019-02-27 13:04:04 -080016642static bool hdd_is_wapi_enc_type(eCsrEncryptionType encrypt_type)
Hu Wangc3148842017-06-20 19:03:29 +080016643{
16644 return false;
16645}
16646#endif
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016647#endif
Hu Wangc3148842017-06-20 19:03:29 +080016648
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016649#ifdef CRYPTO_SET_KEY_CONVERGED
16650static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
16651 struct net_device *ndev,
16652 u8 key_index,
16653 bool unicast, bool multicast)
16654{
16655 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
16656 struct hdd_context *hdd_ctx;
16657 struct qdf_mac_addr bssid = QDF_MAC_ADDR_BCAST_INIT;
16658 struct hdd_station_ctx *sta_ctx;
16659 struct wlan_crypto_key *crypto_key;
16660 int ret;
16661 QDF_STATUS status;
16662
16663 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16664 hdd_err("Command not allowed in FTM mode");
16665 return -EINVAL;
16666 }
16667
Jeff Johnson48363022019-02-24 16:26:51 -080016668 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016669 return -EINVAL;
16670
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016671 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
16672 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016673 adapter->vdev_id, key_index);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016674
16675 hdd_debug("Device_mode %s(%d) key_index = %d",
16676 qdf_opmode_str(adapter->device_mode),
16677 adapter->device_mode, key_index);
16678
16679 if (CSR_MAX_NUM_KEY <= key_index) {
16680 hdd_err("Invalid key index: %d", key_index);
16681 return -EINVAL;
16682 }
16683
16684 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16685 ret = wlan_hdd_validate_context(hdd_ctx);
16686
16687 if (0 != ret)
16688 return ret;
16689 crypto_key = wlan_crypto_get_key(adapter->vdev, key_index);
16690 hdd_debug("unicast %d, cipher %d", unicast, crypto_key->cipher_type);
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016691 if (!IS_WEP_CIPHER(crypto_key->cipher_type))
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016692 return 0;
16693 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16694 if (unicast)
16695 status =
16696 wlan_cfg80211_set_default_key(adapter->vdev, key_index,
Jeff Johnsone04b6992019-02-27 14:06:55 -080016697 &sta_ctx->conn_info.bssid);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016698 else
16699 status = wlan_cfg80211_set_default_key(adapter->vdev, key_index,
16700 &bssid);
16701 if (QDF_STATUS_SUCCESS != status) {
16702 hdd_err("ret fail status %d", ret);
16703 return -EINVAL;
16704 }
16705 if ((adapter->device_mode == QDF_STA_MODE) ||
16706 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016707 ret =
16708 wlan_cfg80211_crypto_add_key(adapter->vdev, (unicast ?
16709 WLAN_CRYPTO_KEY_TYPE_UNICAST :
16710 WLAN_CRYPTO_KEY_TYPE_GROUP),
16711 key_index);
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016712 wma_update_set_key(adapter->vdev_id, unicast, key_index,
16713 crypto_key->cipher_type);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016714 }
16715
16716 return ret;
16717}
16718#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016719/*
16720 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
16721 * This function is used to set the default tx key index
16722 */
16723static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
16724 struct net_device *ndev,
16725 u8 key_index,
16726 bool unicast, bool multicast)
16727{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016728 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016729 struct hdd_context *hdd_ctx;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016730 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016731 int status;
16732
Dustin Brown491d54b2018-03-14 12:39:11 -070016733 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016734
Anurag Chouhan6d760662016-02-20 16:05:43 +053016735 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016736 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016737 return -EINVAL;
16738 }
16739
Jeff Johnson48363022019-02-24 16:26:51 -080016740 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016741 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016742
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016743 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
16744 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016745 adapter->vdev_id, key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016746
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016747 hdd_debug("Device_mode %s(%d) key_index = %d",
Dustin Brown458027c2018-10-19 12:26:27 -070016748 qdf_opmode_str(adapter->device_mode),
16749 adapter->device_mode, key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016750
16751 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016752 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016753 return -EINVAL;
16754 }
16755
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016756 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016757 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016758
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016759 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016760 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016761
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016762 mac_handle = hdd_ctx->mac_handle;
16763
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016764 if ((adapter->device_mode == QDF_STA_MODE) ||
16765 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053016766 struct hdd_station_ctx *sta_ctx =
16767 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016768 struct csr_roam_profile *roam_profile;
16769
16770 roam_profile = hdd_roam_profile(adapter);
Nachiket Kukaded9152832017-10-16 16:18:22 +053016771
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016772 if ((eCSR_ENCRYPT_TYPE_TKIP !=
Jeff Johnsonb1959842019-02-27 13:04:04 -080016773 sta_ctx->conn_info.uc_encrypt_type) &&
Hu Wangc3148842017-06-20 19:03:29 +080016774 !hdd_is_wapi_enc_type(
Jeff Johnsonb1959842019-02-27 13:04:04 -080016775 sta_ctx->conn_info.uc_encrypt_type) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016776 (eCSR_ENCRYPT_TYPE_AES !=
Jeff Johnsonb1959842019-02-27 13:04:04 -080016777 sta_ctx->conn_info.uc_encrypt_type) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053016778 (eCSR_ENCRYPT_TYPE_AES_GCMP !=
Jeff Johnsonb1959842019-02-27 13:04:04 -080016779 sta_ctx->conn_info.uc_encrypt_type) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053016780 (eCSR_ENCRYPT_TYPE_AES_GCMP_256 !=
Jeff Johnsonb1959842019-02-27 13:04:04 -080016781 sta_ctx->conn_info.uc_encrypt_type)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016782 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016783 * then update the default key index
16784 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016785
Jeff Johnson89515092019-03-23 10:52:04 -070016786 tCsrRoamSetKey set_key;
Jeff Johnson29c78672019-02-26 21:05:53 -080016787 uint32_t roam_id = INVALID_ROAM_ID;
Jeff Johnson25e452b2019-03-23 11:51:16 -070016788 tCsrKeys *keys = &roam_profile->Keys;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016789
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016790 hdd_debug("Default tx key index %d", key_index);
Jeff Johnson25e452b2019-03-23 11:51:16 -070016791 keys->defaultIndex = (u8) key_index;
Jeff Johnson89515092019-03-23 10:52:04 -070016792 qdf_mem_zero(&set_key, sizeof(tCsrRoamSetKey));
16793 set_key.keyId = key_index;
Jeff Johnson25e452b2019-03-23 11:51:16 -070016794 set_key.keyLength = keys->KeyLength[key_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016795
Jeff Johnson89515092019-03-23 10:52:04 -070016796 qdf_mem_copy(&set_key.Key[0],
Jeff Johnson25e452b2019-03-23 11:51:16 -070016797 &keys->KeyMaterial[key_index][0],
16798 keys->KeyLength[key_index]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016799
Jeff Johnson89515092019-03-23 10:52:04 -070016800 set_key.keyDirection = eSIR_TX_RX;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016801
Jeff Johnson89515092019-03-23 10:52:04 -070016802 qdf_copy_macaddr(&set_key.peerMac,
Jeff Johnsone04b6992019-02-27 14:06:55 -080016803 &sta_ctx->conn_info.bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016804
Jeff Johnson25e452b2019-03-23 11:51:16 -070016805 if (keys->KeyLength[key_index] ==
Srinivas Girigowdacf161402019-03-14 11:37:33 -070016806 WLAN_CRYPTO_KEY_WEP40_LEN &&
Jeff Johnson20227a92018-03-13 09:41:05 -070016807 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016808 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016809 /* In the case of dynamic wep
16810 * supplicant hardcodes DWEP type to
16811 * eCSR_ENCRYPT_TYPE_WEP104 even
16812 * though ap is configured for WEP-40
16813 * encryption. In this canse the key
16814 * length is 5 but the encryption type
16815 * is 104 hence checking the key
Jeff Johnsonfe8e9492018-05-06 15:40:52 -070016816 * length(5) and encryption type(104)
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016817 * and switching encryption type to 40
16818 */
Jeff Johnson20227a92018-03-13 09:41:05 -070016819 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016820 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
Jeff Johnson20227a92018-03-13 09:41:05 -070016821 roam_profile->mcEncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016822 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
16823 }
16824
Jeff Johnson89515092019-03-23 10:52:04 -070016825 set_key.encType =
Jeff Johnson20227a92018-03-13 09:41:05 -070016826 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016827 encryptionType[0];
16828
16829 /* Issue set key request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016830 status = sme_roam_set_key(mac_handle,
Jeff Johnson89515092019-03-23 10:52:04 -070016831 adapter->vdev_id, &set_key,
Jeff Johnson29c78672019-02-26 21:05:53 -080016832 &roam_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016833
16834 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016835 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016836 status);
16837 return -EINVAL;
16838 }
16839 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016840 } else if (QDF_SAP_MODE == adapter->device_mode) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053016841 struct hdd_ap_ctx *ap_ctx =
16842 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnson61b5e982018-03-15 11:33:31 -070016843 struct csr_roam_profile *profile =
Nachiket Kukaded9152832017-10-16 16:18:22 +053016844 wlan_sap_get_roam_profile(ap_ctx->sap_context);
16845
16846 if (!profile) {
16847 hdd_err("Failed to get SAP Roam Profile");
16848 return -EINVAL;
16849 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016850 /* In SoftAp mode setting key direction for default mode */
16851 if ((eCSR_ENCRYPT_TYPE_TKIP !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053016852 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053016853 (eCSR_ENCRYPT_TYPE_AES !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053016854 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053016855 (eCSR_ENCRYPT_TYPE_AES_GCMP !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053016856 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053016857 (eCSR_ENCRYPT_TYPE_AES_GCMP_256 !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053016858 profile->EncryptionType.encryptionType[0])) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016859 /* Saving key direction for default key index to TX default */
Nachiket Kukaded9152832017-10-16 16:18:22 +053016860 ap_ctx->wep_key[key_index].keyDirection =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016861 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016862 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053016863 key_index);
Nachiket Kukaded9152832017-10-16 16:18:22 +053016864 ap_ctx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016865 }
16866 }
16867
Dustin Browne74003f2018-03-14 12:51:58 -070016868 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016869 return status;
16870}
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016871#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016872
16873static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
16874 struct net_device *ndev,
16875 u8 key_index,
16876 bool unicast, bool multicast)
16877{
Dustin Brown1d31b082018-11-22 14:41:20 +053016878 int errno;
16879 struct osif_vdev_sync *vdev_sync;
16880
16881 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
16882 if (errno)
16883 return errno;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -070016884
Dustin Brown1d31b082018-11-22 14:41:20 +053016885 errno = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index,
16886 unicast, multicast);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016887
Dustin Brown1d31b082018-11-22 14:41:20 +053016888 osif_vdev_sync_op_stop(vdev_sync);
16889
16890 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016891}
16892
Abhishek Singh85283ae2019-03-08 12:00:51 +053016893void wlan_hdd_cfg80211_unlink_bss(struct hdd_adapter *adapter,
Ashish Kumar Dhanotiya3d8b0ae2019-07-10 20:55:56 +053016894 tSirMacAddr bssid, uint8_t *ssid,
16895 uint8_t ssid_len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016896{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016897 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016898 struct wireless_dev *wdev = dev->ieee80211_ptr;
16899 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016900
Ashish Kumar Dhanotiya3d8b0ae2019-07-10 20:55:56 +053016901 __wlan_cfg80211_unlink_bss_list(wiphy, bssid, ssid, ssid_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016902}
16903
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016904#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053016905static inline int
16906wlan_hdd_get_frame_len(struct bss_description *bss_desc)
16907{
16908 return GET_IE_LEN_IN_BSS(bss_desc->length) + sizeof(qcom_ie_age);
16909}
16910
16911static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053016912 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053016913{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016914 qcom_ie_age *qie_age = NULL;
Nachiket Kukade348ede72017-04-28 16:34:24 +053016915
16916 /*
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053016917 * GPS Requirement: need age ie per entry. Using vendor specific.
16918 * Assuming this is the last IE, copy at the end
Nachiket Kukade348ede72017-04-28 16:34:24 +053016919 */
Abhishek Singhf1c16762018-03-07 10:48:46 +053016920 *ie_length -= sizeof(qcom_ie_age);
16921 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + *ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016922 qie_age->element_id = QCOM_VENDOR_IE_ID;
16923 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
16924 qie_age->oui_1 = QCOM_OUI1;
16925 qie_age->oui_2 = QCOM_OUI2;
16926 qie_age->oui_3 = QCOM_OUI3;
16927 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053016928 /*
16929 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
16930 * all bss related timestamp is in units of ms. Due to this when scan
16931 * results are sent to lowi the scan age is high.To address this,
16932 * send age in units of 1/10 ms.
16933 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053016934 qie_age->age = (uint32_t)(qdf_mc_timer_get_system_time() -
16935 bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016936 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070016937 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
16938 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070016939 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
16940 sizeof(qie_age->seq_ctrl));
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053016941}
16942#else
16943static inline int
16944wlan_hdd_get_frame_len(struct bss_description *bss_desc)
16945{
16946 return GET_IE_LEN_IN_BSS(bss_desc->length);
16947}
16948static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053016949 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053016950{
16951}
16952#endif /* WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016953
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053016954
16955struct cfg80211_bss *
16956wlan_hdd_inform_bss_frame(struct hdd_adapter *adapter,
16957 struct bss_description *bss_desc)
16958{
16959 struct wireless_dev *wdev = adapter->dev->ieee80211_ptr;
16960 struct wiphy *wiphy = wdev->wiphy;
Abhishek Singhf1c16762018-03-07 10:48:46 +053016961 uint32_t ie_length = wlan_hdd_get_frame_len(bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053016962 const char *ie =
16963 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
Will Huang65d64252019-07-16 17:57:42 +080016964 uint32_t i;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053016965 struct cfg80211_bss *bss_status = NULL;
16966 struct hdd_context *hdd_ctx;
16967 struct timespec ts;
16968 struct hdd_config *cfg_param;
16969 struct wlan_cfg80211_inform_bss bss_data = {0};
16970
16971 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16972 /*
16973 * wlan_hdd_validate_context should not be used here, In validate ctx
16974 * start_modules_in_progress or stop_modules_in_progress is validated,
16975 * If the start_modules_in_progress is set to true means the interface
16976 * is not UP yet if the stop_modules_in_progress means that interface
16977 * is already down. So in both the two scenario's driver should not be
16978 * informing bss to kernel. Hence removing the validate context.
16979 */
16980
16981 if (!hdd_ctx || !hdd_ctx->config) {
16982 hdd_debug("HDD context is Null");
16983 return NULL;
16984 }
16985
16986 if (cds_is_driver_recovering() ||
16987 cds_is_load_or_unload_in_progress()) {
16988 hdd_debug("Recovery or load/unload in progress. State: 0x%x",
16989 cds_get_driver_state());
16990 return NULL;
16991 }
16992
16993 cfg_param = hdd_ctx->config;
16994 bss_data.frame_len = ie_length + offsetof(struct ieee80211_mgmt,
16995 u.probe_resp.variable);
16996 bss_data.mgmt = qdf_mem_malloc(bss_data.frame_len);
Min Liu74a1a502018-10-10 19:59:07 +080016997 if (!bss_data.mgmt)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053016998 return NULL;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053016999
17000 memcpy(bss_data.mgmt->bssid, bss_desc->bssId, ETH_ALEN);
17001
17002 /* Android does not want the timestamp from the frame.
17003 * Instead it wants a monotonic increasing value
17004 */
17005 get_monotonic_boottime(&ts);
17006 bss_data.mgmt->u.probe_resp.timestamp =
17007 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
17008
17009 bss_data.mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
17010 bss_data.mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
17011
Abhishek Singhf1c16762018-03-07 10:48:46 +053017012 wlan_hdd_add_age_ie(bss_data.mgmt, &ie_length, bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017013
17014 memcpy(bss_data.mgmt->u.probe_resp.variable, ie, ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017015 if (bss_desc->fProbeRsp) {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017016 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017017 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
17018 } else {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017019 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017020 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
17021 }
17022
Will Huang65d64252019-07-16 17:57:42 +080017023 bss_data.chan = ieee80211_get_channel(wiphy, bss_desc->chan_freq);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017024 if (!bss_data.chan) {
Will Huang65d64252019-07-16 17:57:42 +080017025 hdd_err("chan pointer is NULL, chan freq: %d",
17026 bss_desc->chan_freq);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017027 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017028 return NULL;
17029 }
17030
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017031 /*
17032 * Based on .ini configuration, raw rssi can be reported for bss.
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070017033 * Raw rssi is typically used for estimating power.
17034 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017035 bss_data.rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070017036 bss_desc->rssi;
17037
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017038 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017039 bss_data.rssi = QDF_MIN(bss_data.rssi, 0) * 100;
17040
17041 bss_data.boottime_ns = bss_desc->scansystimensec;
17042
17043 /* Set all per chain rssi as invalid */
17044 for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++)
Yeshwanth Sriram Guntuka14ab04c2018-09-21 15:06:49 +053017045 bss_data.per_chain_rssi[i] = WLAN_INVALID_PER_CHAIN_RSSI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017046
Ashish Kumar Dhanotiya3d8b0ae2019-07-10 20:55:56 +053017047 hdd_debug("BSSID: " QDF_MAC_ADDR_STR " Channel:%d RSSI:%d TSF %u seq %d is_prob_resp %d",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070017048 QDF_MAC_ADDR_ARRAY(bss_data.mgmt->bssid),
Abhishek Singhef6f38c2018-12-20 13:51:29 +053017049 bss_data.chan->center_freq, (int)(bss_data.rssi / 100),
17050 bss_desc->timeStamp[0], ((bss_desc->seq_ctrl.seqNumHi <<
Ashish Kumar Dhanotiya3d8b0ae2019-07-10 20:55:56 +053017051 HIGH_SEQ_NUM_OFFSET) | bss_desc->seq_ctrl.seqNumLo),
17052 bss_desc->fProbeRsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017053
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017054 bss_status = wlan_cfg80211_inform_bss_frame_data(wiphy, &bss_data);
Jeff Johnsonb8944722017-09-03 09:03:19 -070017055 hdd_ctx->beacon_probe_rsp_cnt_per_scan++;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017056 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017057 return bss_status;
17058}
17059
17060/**
17061 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017062 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017063 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017064 *
17065 * This function is used to update the BSS data base of CFG8011
17066 *
17067 * Return: struct cfg80211_bss pointer
17068 */
Jeff Johnson172237b2017-11-07 15:32:59 -080017069struct cfg80211_bss *
17070wlan_hdd_cfg80211_update_bss_db(struct hdd_adapter *adapter,
17071 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017072{
17073 tCsrRoamConnectedProfile roamProfile;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017074 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017075 struct cfg80211_bss *bss = NULL;
17076
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017077 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017078 sme_roam_get_connect_profile(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017079 &roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017080
Pragaspathi Thilagaraj96742ae2019-05-29 00:49:33 +053017081 if (roamProfile.bss_desc) {
17082 bss = wlan_hdd_inform_bss_frame(adapter, roamProfile.bss_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017083
Jeff Johnsond36fa332019-03-18 13:42:25 -070017084 if (!bss)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017085 hdd_debug("wlan_hdd_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017086
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080017087 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017088 } else {
Pragaspathi Thilagaraj96742ae2019-05-29 00:49:33 +053017089 hdd_err("roamProfile.bss_desc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017090 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017091 return bss;
17092}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017093
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017094/**
17095 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017096 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017097 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017098 * @index: Index
17099 * @preauth: Preauth flag
17100 *
17101 * This function is used to notify the supplicant of a new PMKSA candidate.
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017102 * PMK value is notified to supplicant whether PMK caching or OKC is enabled
17103 * in firmware or not. Supplicant needs this value becaue it uses PMK caching
17104 * by default.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017105 *
17106 * Return: 0 for success, non-zero for failure
17107 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017108int wlan_hdd_cfg80211_pmksa_candidate_notify(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080017109 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017110 int index, bool preauth)
17111{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017112 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017113
Dustin Brown491d54b2018-03-14 12:39:11 -070017114 hdd_enter();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017115 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017116
Jeff Johnsond36fa332019-03-18 13:42:25 -070017117 if (!roam_info) {
Jeff Johnsonfd060852017-10-04 10:50:51 -070017118 hdd_err("roam_info is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017119 return -EINVAL;
17120 }
17121
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070017122 hdd_info(QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017123 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnsonfd060852017-10-04 10:50:51 -070017124 roam_info->bssid.bytes,
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017125 preauth, GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017126 return 0;
17127}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017128
17129#ifdef FEATURE_WLAN_LFR_METRICS
17130/**
17131 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017132 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017133 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017134 *
17135 * 802.11r/LFR metrics reporting function to report preauth initiation
17136 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017137 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017138 */
17139#define MAX_LFR_METRICS_EVENT_LENGTH 100
Jeff Johnson172237b2017-11-07 15:32:59 -080017140QDF_STATUS
17141wlan_hdd_cfg80211_roam_metrics_preauth(struct hdd_adapter *adapter,
17142 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017143{
17144 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17145 union iwreq_data wrqu;
17146
Dustin Brown491d54b2018-03-14 12:39:11 -070017147 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017148
Jeff Johnsond36fa332019-03-18 13:42:25 -070017149 if (!adapter) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017150 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017151 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017152 }
17153
17154 /* create the event */
17155 memset(&wrqu, 0, sizeof(wrqu));
17156 memset(metrics_notification, 0, sizeof(metrics_notification));
17157
17158 wrqu.data.pointer = metrics_notification;
17159 wrqu.data.length = scnprintf(metrics_notification,
17160 sizeof(metrics_notification),
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070017161 "QCOM: LFR_PREAUTH_INIT " QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070017162 QDF_MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017163
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017164 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017165 metrics_notification);
17166
Dustin Browne74003f2018-03-14 12:51:58 -070017167 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017168
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017169 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017170}
17171
17172/**
17173 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017174 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017175 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017176 * @preauth_status: Preauth status
17177 *
17178 * 802.11r/LFR metrics reporting function to report handover initiation
17179 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017180 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017181 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017182QDF_STATUS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017183wlan_hdd_cfg80211_roam_metrics_preauth_status(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080017184 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017185 bool preauth_status)
17186{
17187 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17188 union iwreq_data wrqu;
17189
Dustin Brown491d54b2018-03-14 12:39:11 -070017190 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017191
Jeff Johnsond36fa332019-03-18 13:42:25 -070017192 if (!adapter) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017193 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017194 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017195 }
17196
17197 /* create the event */
17198 memset(&wrqu, 0, sizeof(wrqu));
17199 memset(metrics_notification, 0, sizeof(metrics_notification));
17200
17201 scnprintf(metrics_notification, sizeof(metrics_notification),
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070017202 "QCOM: LFR_PREAUTH_STATUS " QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070017203 QDF_MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017204
17205 if (1 == preauth_status)
17206 strlcat(metrics_notification, " true",
17207 sizeof(metrics_notification));
17208 else
17209 strlcat(metrics_notification, " false",
17210 sizeof(metrics_notification));
17211
17212 wrqu.data.pointer = metrics_notification;
17213 wrqu.data.length = strlen(metrics_notification);
17214
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017215 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017216 metrics_notification);
17217
Dustin Browne74003f2018-03-14 12:51:58 -070017218 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017219
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017220 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017221}
17222
17223/**
17224 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017225 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017226 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017227 *
17228 * 802.11r/LFR metrics reporting function to report handover initiation
17229 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017230 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017231 */
Jeff Johnson172237b2017-11-07 15:32:59 -080017232QDF_STATUS
17233wlan_hdd_cfg80211_roam_metrics_handover(struct hdd_adapter *adapter,
17234 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017235{
17236 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17237 union iwreq_data wrqu;
17238
Dustin Brown491d54b2018-03-14 12:39:11 -070017239 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017240
Jeff Johnsond36fa332019-03-18 13:42:25 -070017241 if (!adapter) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017242 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017243 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017244 }
17245
17246 /* create the event */
17247 memset(&wrqu, 0, sizeof(wrqu));
17248 memset(metrics_notification, 0, sizeof(metrics_notification));
17249
17250 wrqu.data.pointer = metrics_notification;
17251 wrqu.data.length = scnprintf(metrics_notification,
17252 sizeof(metrics_notification),
17253 "QCOM: LFR_PREAUTH_HANDOVER "
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070017254 QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070017255 QDF_MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017256
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017257 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017258 metrics_notification);
17259
Dustin Browne74003f2018-03-14 12:51:58 -070017260 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017261
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017262 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017263}
17264#endif
17265
Nirav Shah73713f72018-05-17 14:50:41 +053017266#ifdef FEATURE_MONITOR_MODE_SUPPORT
17267static
17268void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
wadesongc48ea292019-08-07 16:40:02 +080017269 uint32_t op_freq,
Nirav Shah73713f72018-05-17 14:50:41 +053017270 struct ch_params *ch_params)
17271{
17272 struct hdd_station_ctx *station_ctx =
17273 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17274 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
17275 enum hdd_dot11_mode hdd_dot11_mode;
17276 uint8_t ini_dot11_mode =
17277 (WLAN_HDD_GET_CTX(adapter))->config->dot11Mode;
17278
17279 hdd_debug("Dot11Mode is %u", ini_dot11_mode);
17280 switch (ini_dot11_mode) {
17281 case eHDD_DOT11_MODE_AUTO:
17282 case eHDD_DOT11_MODE_11ax:
17283 case eHDD_DOT11_MODE_11ax_ONLY:
17284 if (sme_is_feature_supported_by_fw(DOT11AX))
17285 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
17286 else if (sme_is_feature_supported_by_fw(DOT11AC))
17287 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
17288 else
17289 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17290 break;
17291 case eHDD_DOT11_MODE_11ac:
17292 case eHDD_DOT11_MODE_11ac_ONLY:
17293 if (sme_is_feature_supported_by_fw(DOT11AC))
17294 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
17295 else
17296 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17297 break;
17298 case eHDD_DOT11_MODE_11n:
17299 case eHDD_DOT11_MODE_11n_ONLY:
17300 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17301 break;
17302 default:
17303 hdd_dot11_mode = ini_dot11_mode;
17304 break;
17305 }
17306 ch_info->channel_width = ch_params->ch_width;
17307 ch_info->phy_mode =
17308 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
wadesongc48ea292019-08-07 16:40:02 +080017309 ch_info->freq = op_freq;
Nirav Shah73713f72018-05-17 14:50:41 +053017310 ch_info->cb_mode = ch_params->ch_width;
wadesong59e727c2019-07-25 13:52:06 +080017311 hdd_debug("ch_info width %d, phymode %d channel freq %d",
Nirav Shah73713f72018-05-17 14:50:41 +053017312 ch_info->channel_width, ch_info->phy_mode,
wadesong59e727c2019-07-25 13:52:06 +080017313 ch_info->freq);
Nirav Shah73713f72018-05-17 14:50:41 +053017314}
17315#else
17316static
17317void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
wadesongc48ea292019-08-07 16:40:02 +080017318 uint32_t op_freq,
Nirav Shah73713f72018-05-17 14:50:41 +053017319 struct ch_params *ch_params)
17320{
17321}
17322#endif
17323
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017324/**
17325 * hdd_select_cbmode() - select channel bonding mode
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017326 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017327 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017328 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017329 *
17330 * Return: none
17331 */
wadesongc48ea292019-08-07 16:40:02 +080017332void hdd_select_cbmode(struct hdd_adapter *adapter, uint8_t op_chan,
17333 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017334{
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017335 uint8_t sec_ch = 0;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017336 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Chaoli Zhou75b062f2018-06-11 12:36:54 +080017337 struct hdd_station_ctx *station_ctx =
17338 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17339 eConnectionState connstate;
17340 bool cbmode_select = false;
wadesongc48ea292019-08-07 16:40:02 +080017341 uint32_t op_freq = wlan_reg_chan_to_freq(hdd_ctx->pdev, op_chan);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017342
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017343 /*
17344 * CDS api expects secondary channel for calculating
17345 * the channel params
17346 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017347 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
wadesongc48ea292019-08-07 16:40:02 +080017348 (WLAN_REG_IS_24GHZ_CH(op_chan))) {
17349 if (op_chan >= 1 && op_chan <= 5)
17350 sec_ch = op_chan + 4;
17351 else if (op_chan >= 6 && op_chan <= 13)
17352 sec_ch = op_chan - 4;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017353 }
17354
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017355 /* This call decides required channel bonding mode */
wadesongc48ea292019-08-07 16:40:02 +080017356 wlan_reg_set_channel_params(hdd_ctx->pdev, op_chan,
Dustin Brown07901ec2018-09-07 11:02:41 -070017357 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017358
Chaoli Zhou75b062f2018-06-11 12:36:54 +080017359 if (adapter->device_mode == QDF_STA_MODE &&
Pragaspathi Thilagaraja8893752019-02-06 19:58:59 +053017360 ucfg_mlme_is_change_channel_bandwidth_enabled(hdd_ctx->psoc)) {
Jeff Johnsone7951512019-02-27 10:02:51 -080017361 connstate = station_ctx->conn_info.conn_state;
Chaoli Zhou75b062f2018-06-11 12:36:54 +080017362 if (!(eConnectionState_Associated == connstate ||
17363 eConnectionState_Connecting == connstate)) {
17364 cbmode_select = true;
17365 }
17366 }
17367
17368 if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE || cbmode_select)
wadesongc48ea292019-08-07 16:40:02 +080017369 hdd_mon_select_cbmode(adapter, op_freq, ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017370}
17371
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017372/**
17373 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
17374 * @adapter: STA adapter
17375 * @roam_profile: STA roam profile
17376 *
17377 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
17378 *
17379 * Return: false if sta-sap conc is not allowed, else return true
17380 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070017381static
17382bool wlan_hdd_handle_sap_sta_dfs_conc(struct hdd_adapter *adapter,
17383 struct csr_roam_profile *roam_profile)
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017384{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070017385 struct hdd_context *hdd_ctx;
Jeff Johnsone5006672017-08-29 14:39:02 -070017386 struct hdd_adapter *ap_adapter;
Jeff Johnson87251032017-08-29 13:31:11 -070017387 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070017388 struct hdd_hostapd_state *hostapd_state;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017389 uint8_t channel = 0;
17390 QDF_STATUS status;
17391
17392 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17393 if (!hdd_ctx) {
17394 hdd_err("HDD context is NULL");
17395 return true;
17396 }
17397
17398 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
17399 /* probably no sap running, no handling required */
Jeff Johnsond36fa332019-03-18 13:42:25 -070017400 if (!ap_adapter)
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017401 return true;
17402
17403 /*
17404 * sap is not in started state, so it is fine to go ahead with sta.
17405 * if sap is currently doing CAC then don't allow sta to go further.
17406 */
17407 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
17408 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
17409 return true;
17410
17411 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
17412 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
17413 return false;
17414 }
17415
17416 /*
17417 * log and return error, if we allow STA to go through, we don't
17418 * know what is going to happen better stop sta connection
17419 */
17420 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
Jeff Johnsond36fa332019-03-18 13:42:25 -070017421 if (!hdd_ap_ctx) {
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017422 hdd_err("AP context not found");
17423 return false;
17424 }
17425
17426 /* sap is on non-dfs channel, nothing to handle */
Dustin Brown07901ec2018-09-07 11:02:41 -070017427 if (!wlan_reg_is_dfs_ch(hdd_ctx->pdev,
Jeff Johnson01206862017-10-27 20:55:59 -070017428 hdd_ap_ctx->operating_channel)) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017429 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017430 return true;
17431 }
17432 /*
17433 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053017434 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017435 */
Dustin Brown76cd2932018-09-11 16:03:05 -070017436 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017437 roam_profile, &channel);
17438
Nitesh Shah59774522016-09-16 15:14:21 +053017439 /*
17440 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
17441 * channels for roaming case.
17442 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017443 if (WLAN_REG_IS_24GHZ_CH(channel)) {
17444 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053017445 return true;
17446 }
17447
17448 /*
Jeff Johnsondcf84ce2017-10-05 09:26:24 -070017449 * If channel is 0 or DFS or LTE unsafe then better to call pcl and
Tushnim Bhattacharyya9a929992017-06-18 00:59:09 -070017450 * find out the best channel. If channel is non-dfs 5 GHz then
17451 * better move SAP to STA's channel to make scc, so we have room
17452 * for 3port MCC scenario.
Nitesh Shah59774522016-09-16 15:14:21 +053017453 */
Dustin Brown07901ec2018-09-07 11:02:41 -070017454 if (!channel || wlan_reg_is_dfs_ch(hdd_ctx->pdev, channel) ||
Dustin Brown76cd2932018-09-11 16:03:05 -070017455 !policy_mgr_is_safe_channel(hdd_ctx->psoc, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017456 channel = policy_mgr_get_nondfs_preferred_channel(
Dustin Brown76cd2932018-09-11 16:03:05 -070017457 hdd_ctx->psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017458
17459 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
17460 qdf_event_reset(&hostapd_state->qdf_event);
Bala Venkatesh8b9bbde2019-07-03 16:25:16 +053017461 wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, ap_adapter->vdev_id,
17462 CSA_REASON_STA_CONNECT_DFS_TO_NON_DFS);
17463
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017464 status = wlansap_set_channel_change_with_csa(
17465 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
Jeff Johnson91df29d2017-10-27 19:29:50 -070017466 hdd_ap_ctx->sap_config.ch_width_orig, false);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017467
17468 if (QDF_STATUS_SUCCESS != status) {
17469 hdd_err("Set channel with CSA IE failed, can't allow STA");
17470 return false;
17471 }
17472
17473 /*
17474 * wait here for SAP to finish the channel switch. When channel
17475 * switch happens, SAP sends few beacons with CSA_IE. After
17476 * successfully Transmission of those beacons, it will move its
17477 * state from started to disconnected and move to new channel.
17478 * once it moves to new channel, sap again moves its state
17479 * machine from disconnected to started and set this event.
17480 * wait for 10 secs to finish this.
17481 */
Nachiket Kukade0396b732017-11-14 16:35:16 +053017482 status = qdf_wait_for_event_completion(&hostapd_state->qdf_event, 10000);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017483 if (!QDF_IS_STATUS_SUCCESS(status)) {
17484 hdd_err("wait for qdf_event failed, STA not allowed!!");
17485 return false;
17486 }
17487
17488 return true;
17489}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017490
Abhishek Singhcfb44482017-03-10 12:42:37 +053017491#ifdef WLAN_FEATURE_11W
17492/**
17493 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
17494 * @roam_profile: pointer to roam profile
17495 *
17496 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
17497 * or pmf=2 is an explicit configuration in the supplicant
17498 * configuration, drop the connection request.
17499 *
17500 * Return: 0 if check result is valid, otherwise return error code
17501 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070017502static
17503int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053017504{
17505 if (roam_profile->MFPEnabled &&
Jeff Johnson20227a92018-03-13 09:41:05 -070017506 !(roam_profile->MFPRequired || roam_profile->MFPCapable)) {
Abhishek Singhcfb44482017-03-10 12:42:37 +053017507 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
17508 roam_profile->MFPEnabled,
17509 roam_profile->MFPRequired,
17510 roam_profile->MFPCapable);
17511 return -EINVAL;
17512 }
17513 return 0;
17514}
17515#else
17516static inline
Jeff Johnson61b5e982018-03-15 11:33:31 -070017517int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053017518{
17519 return 0;
17520}
17521#endif
17522
Krunal Soni31949422016-07-29 17:17:53 -070017523/**
17524 * wlan_hdd_cfg80211_connect_start() - to start the association process
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017525 * @adapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070017526 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017527 * @ssid_len: Length of ssid
17528 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070017529 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017530 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017531 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017532 *
17533 * This function is used to start the association process
17534 *
17535 * Return: 0 for success, non-zero for failure
17536 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017537static int wlan_hdd_cfg80211_connect_start(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017538 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070017539 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017540 u8 operatingChannel,
17541 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017542{
17543 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080017544 QDF_STATUS qdf_status;
Jeff Johnsonb8944722017-09-03 09:03:19 -070017545 struct hdd_context *hdd_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070017546 struct hdd_station_ctx *hdd_sta_ctx;
Jeff Johnson29c78672019-02-26 21:05:53 -080017547 uint32_t roam_id = INVALID_ROAM_ID;
Jeff Johnson61b5e982018-03-15 11:33:31 -070017548 struct csr_roam_profile *roam_profile;
Pragaspathi Thilagaraj7a1a08e2019-05-29 01:20:29 +053017549 enum csr_akm_type rsn_auth_type;
Jeff Johnson46b4f0e2019-03-08 10:48:35 -080017550 struct sme_config_params *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053017551 uint8_t channel = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017552 mac_handle_t mac_handle;
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +053017553 uint8_t wmm_mode = 0;
17554 uint8_t value = 0;
Min Liu8c5d99e2018-09-10 17:18:44 +080017555 struct wlan_objmgr_vdev *vdev;
Wu Gaoed616a12019-01-16 15:19:21 +080017556 uint32_t channel_bonding_mode;
wadesong24c869a2019-07-19 17:38:59 +080017557 uint32_t oper_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017558
Dustin Brown491d54b2018-03-14 12:39:11 -070017559 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017560
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017561 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17562 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017563
Jeff Johnsonb8944722017-09-03 09:03:19 -070017564 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053017565 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017566 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017567
Srinivas Girigowdab8fdc642019-03-19 15:33:03 -070017568 if (WLAN_SSID_MAX_LEN < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017569 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017570 status = -EINVAL;
17571 goto ret_status;
17572 }
17573
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017574 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017575 hdd_err("Connection refused: conn in progress");
17576 status = -EINVAL;
17577 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017578 }
17579
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053017580 /* Disable roaming on all other adapters before connect start */
17581 wlan_hdd_disable_roaming(adapter);
17582
Bala Venkatesh9bb9c052019-05-27 14:16:40 +053017583 hdd_notify_teardown_tdls_links(hdd_ctx->psoc);
Nitesh Shah273e4e52017-04-03 12:53:36 +053017584
Anurag Chouhand939d3d2016-07-20 17:45:48 +053017585 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
17586 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017587
Jeff Johnson20227a92018-03-13 09:41:05 -070017588 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017589 if (roam_profile) {
Jeff Johnsond377dce2017-10-04 10:32:42 -070017590 struct hdd_station_ctx *sta_ctx;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070017591
Jeff Johnsond377dce2017-10-04 10:32:42 -070017592 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017593
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017594 /* Restart the opportunistic timer
17595 *
17596 * If hw_mode_change_in_progress is true, then wait
17597 * till firmware sends the callback for hw_mode change.
17598 *
17599 * Else set connect_in_progress as true and proceed.
17600 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017601 policy_mgr_restart_opportunistic_timer(
Dustin Brown76cd2932018-09-11 16:03:05 -070017602 hdd_ctx->psoc, false);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017603 if (policy_mgr_is_hw_mode_change_in_progress(
Dustin Brown76cd2932018-09-11 16:03:05 -070017604 hdd_ctx->psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053017605 qdf_status = policy_mgr_wait_for_connection_update(
Dustin Brown76cd2932018-09-11 16:03:05 -070017606 hdd_ctx->psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053017607 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017608 hdd_err("qdf wait for event failed!!");
17609 status = -EINVAL;
17610 goto ret_status;
17611 }
17612 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017613 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017614
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +053017615 status = ucfg_mlme_get_wmm_mode(hdd_ctx->psoc, &wmm_mode);
17616 if (!QDF_IS_STATUS_SUCCESS(status)) {
17617 hdd_err("Get wmm_mode failed");
17618 status = -EINVAL;
17619 goto ret_status;
17620 }
17621 if (HDD_WMM_USER_MODE_NO_QOS == wmm_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017622 /*QoS not enabled in cfg file */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017623 roam_profile->uapsd_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017624 } else {
17625 /*QoS enabled, update uapsd mask from cfg file */
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +053017626 status = ucfg_mlme_get_wmm_uapsd_mask(hdd_ctx->psoc,
17627 &value);
17628 if (!QDF_IS_STATUS_SUCCESS(status)) {
17629 hdd_err("Get uapsd_mask failed");
17630 status = -EINVAL;
17631 goto ret_status;
17632 }
17633 roam_profile->uapsd_mask = value;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017634 }
17635
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017636 roam_profile->SSIDs.numOfSSIDs = 1;
17637 roam_profile->SSIDs.SSIDList->SSID.length = ssid_len;
17638 qdf_mem_zero(roam_profile->SSIDs.SSIDList->SSID.ssId,
17639 sizeof(roam_profile->SSIDs.SSIDList->SSID.ssId));
17640 qdf_mem_copy((void *)(roam_profile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017641 ssid, ssid_len);
17642
Abhishek Singh3c9910e2017-01-06 17:56:47 +053017643 /* cleanup bssid hint */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017644 qdf_mem_zero(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053017645 QDF_MAC_ADDR_SIZE);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017646 qdf_mem_zero((void *)(roam_profile->BSSIDs.bssid),
Abhishek Singh3c9910e2017-01-06 17:56:47 +053017647 QDF_MAC_ADDR_SIZE);
17648
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017649 if (bssid) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017650 roam_profile->BSSIDs.numOfBSSIDs = 1;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017651 qdf_mem_copy((void *)(roam_profile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053017652 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070017653 /*
Jeff Johnsonfa7d9602018-05-06 11:25:31 -070017654 * Save BSSID in separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017655 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070017656 * association process. In case of join failure
17657 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017658 */
Jeff Johnson731bc322017-10-14 19:53:44 -070017659 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
17660 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017661 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017662 } else if (bssid_hint) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017663 qdf_mem_copy(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053017664 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070017665 /*
17666 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017667 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070017668 * association process. In case of join failure
17669 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017670 */
Jeff Johnson731bc322017-10-14 19:53:44 -070017671 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053017672 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017673 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070017674 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017675 }
17676
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017677 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017678 roam_profile->SSIDs.SSIDList->SSID.length,
17679 roam_profile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017680 operatingChannel);
17681
Jeff Johnsonce4a8342017-10-14 13:12:22 -070017682 if (hdd_sta_ctx->wpa_versions) {
Jeff Johnson784efe22019-03-09 18:31:13 -080017683 hdd_set_genie_to_csr(adapter, &rsn_auth_type);
17684 hdd_set_csr_auth_type(adapter, rsn_auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017685 }
17686#ifdef FEATURE_WLAN_WAPI
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017687 if (adapter->wapi_info.wapi_mode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017688 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017689 switch (adapter->wapi_info.wapi_auth_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017690 case WAPI_AUTH_MODE_PSK:
17691 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017692 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017693 adapter->wapi_info.wapi_auth_mode);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017694 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017695 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
17696 break;
17697 }
17698 case WAPI_AUTH_MODE_CERT:
17699 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017700 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017701 adapter->wapi_info.wapi_auth_mode);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017702 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017703 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
17704 break;
17705 }
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017706 default:
17707 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017708 } /* End of switch */
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017709 if (adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017710 WAPI_AUTH_MODE_PSK
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017711 || adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017712 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017713 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017714 roam_profile->AuthType.numEntries = 1;
17715 roam_profile->EncryptionType.numEntries = 1;
17716 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017717 eCSR_ENCRYPT_TYPE_WPI;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017718 roam_profile->mcEncryptionType.numEntries = 1;
17719 roam_profile->mcEncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017720 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
17721 }
17722 }
Krunal Soni31949422016-07-29 17:17:53 -070017723#endif
Min Liu8c5d99e2018-09-10 17:18:44 +080017724 vdev = hdd_objmgr_get_vdev(adapter);
17725 if (!vdev) {
17726 status = -EINVAL;
17727 goto conn_failure;
17728 }
17729 ucfg_pmo_flush_gtk_offload_req(vdev);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053017730 hdd_objmgr_put_vdev(vdev);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017731 roam_profile->csrPersona = adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017732
17733 if (operatingChannel) {
wadesong24c869a2019-07-19 17:38:59 +080017734 oper_freq = wlan_reg_chan_to_freq(hdd_ctx->pdev,
17735 operatingChannel);
wadesong24c869a2019-07-19 17:38:59 +080017736 roam_profile->ChannelInfo.freq_list = &oper_freq;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017737 roam_profile->ChannelInfo.numOfChannels = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017738 } else {
wadesong24c869a2019-07-19 17:38:59 +080017739 roam_profile->ChannelInfo.freq_list = NULL;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017740 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017741 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017742 if ((QDF_IBSS_MODE == adapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017743 && operatingChannel) {
17744 /*
17745 * Need to post the IBSS power save parameters
17746 * to WMA. WMA will configure this parameters
17747 * to firmware if power save is enabled by the
17748 * firmware.
17749 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017750 qdf_status = hdd_set_ibss_power_save_params(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017751
Abhishek Singh471652b2017-04-14 12:28:32 +053017752 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017753 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017754 status = -EINVAL;
17755 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017756 }
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017757 roam_profile->ch_params.ch_width =
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017758 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053017759 /*
17760 * In IBSS mode while operating in 2.4 GHz,
17761 * the device supports only 20 MHz.
17762 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017763 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017764 roam_profile->ch_params.ch_width =
Nitesh Shah87335a52016-09-05 15:47:32 +053017765 CH_WIDTH_20MHZ;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017766 hdd_select_cbmode(adapter, operatingChannel,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017767 &roam_profile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017768 }
17769
Jeff Johnson20227a92018-03-13 09:41:05 -070017770 if (wlan_hdd_cfg80211_check_pmf_valid(roam_profile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017771 status = -EINVAL;
17772 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017773 }
17774
Krunal Soni31949422016-07-29 17:17:53 -070017775 /*
17776 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017777 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070017778 * enhancements, the supplicant is not issuing the scan command
17779 * now. So the unicast frames which are sent from the host are
17780 * not having the additional IEs. If it is P2P CLIENT and there
17781 * is no additional IE present in roamProfile, then use the
17782 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017783 */
17784
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017785 if ((adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017786 (!roam_profile->pAddIEScan)) {
17787 roam_profile->pAddIEScan =
Jeff Johnson37fa0402017-10-28 12:42:29 -070017788 &adapter->scan_info.scan_add_ie.addIEdata[0];
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017789 roam_profile->nAddIEScanLength =
Jeff Johnson37fa0402017-10-28 12:42:29 -070017790 adapter->scan_info.scan_add_ie.length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017791 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017792
Dustin Brown76cd2932018-09-11 16:03:05 -070017793 if ((policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) == true)
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017794 && (false == wlan_hdd_handle_sap_sta_dfs_conc(adapter,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017795 roam_profile))) {
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017796 hdd_err("sap-sta conc will fail, can't allow sta");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017797 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017798 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017799 status = -ENOMEM;
17800 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017801 }
17802
Anurag Chouhan600c3a02016-03-01 10:33:54 +053017803 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017804 if (!sme_config) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017805 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017806 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017807 status = -ENOMEM;
17808 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017809 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017810
17811 mac_handle = hdd_ctx->mac_handle;
17812 sme_get_config_param(mac_handle, sme_config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017813 /* These values are not sessionized. So, any change in these SME
17814 * configs on an older or parallel interface will affect the
17815 * cb mode. So, restoring the default INI params before starting
17816 * interfaces such as sta, cli etc.,
17817 */
Wu Gaoed616a12019-01-16 15:19:21 +080017818 ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc,
17819 &channel_bonding_mode);
Jeff Johnsone94ccd02019-04-02 15:02:56 -070017820 sme_config->csr_config.channelBondingMode5GHz =
Wu Gaoed616a12019-01-16 15:19:21 +080017821 channel_bonding_mode;
17822 ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
17823 &channel_bonding_mode);
Jeff Johnsone94ccd02019-04-02 15:02:56 -070017824 sme_config->csr_config.channelBondingMode24GHz =
Wu Gaoed616a12019-01-16 15:19:21 +080017825 channel_bonding_mode;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017826 sme_update_config(mac_handle, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053017827 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053017828 /*
17829 * Change conn_state to connecting before sme_roam_connect(),
17830 * because sme_roam_connect() has a direct path to call
17831 * hdd_sme_roam_callback(), which will change the conn_state
17832 * If direct path, conn_state will be accordingly changed to
17833 * NotConnected or Associated by either
17834 * hdd_association_completion_handler() or
17835 * hdd_dis_connect_handler() in sme_RoamCallback()if
17836 * sme_RomConnect is to be queued,
17837 * Connecting state will remain until it is completed.
17838 *
17839 * If connection state is not changed, connection state will
17840 * remain in eConnectionState_NotConnected state.
17841 * In hdd_association_completion_handler, "hddDisconInProgress"
17842 * is set to true if conn state is
17843 * eConnectionState_NotConnected.
17844 * If "hddDisconInProgress" is set to true then cfg80211 layer
17845 * is not informed of connect result indication which
17846 * is an issue.
17847 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017848 if (QDF_STA_MODE == adapter->device_mode ||
17849 QDF_P2P_CLIENT_MODE == adapter->device_mode)
17850 hdd_conn_set_connection_state(adapter,
Agrawal Ashish6b015762016-05-05 11:22:18 +053017851 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017852
Alok Kumarb64650c2018-03-23 17:05:11 +053017853 hdd_set_disconnect_status(adapter, false);
17854
Jingxiang Geb49aa302018-01-17 20:54:15 +080017855 qdf_runtime_pm_prevent_suspend(
17856 &hdd_ctx->runtime_context.connect);
Padma, Santhosh Kumarc88de482018-04-09 16:17:04 +053017857 hdd_prevent_suspend_timeout(HDD_WAKELOCK_CONNECT_COMPLETE,
Dustin Brownceed67e2017-05-26 11:57:31 -070017858 WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017859 qdf_status = sme_roam_connect(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017860 adapter->vdev_id, roam_profile,
Jeff Johnson29c78672019-02-26 21:05:53 -080017861 &roam_id);
Abhishek Singh471652b2017-04-14 12:28:32 +053017862 if (QDF_IS_STATUS_ERROR(qdf_status))
17863 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017864
Rajeev Kumard31e1542017-01-13 14:37:42 -080017865 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017866 (QDF_STA_MODE == adapter->device_mode ||
17867 QDF_P2P_CLIENT_MODE == adapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017868 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080017869 "qdf_status %d. -> NotConnected",
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017870 adapter->vdev_id, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017871 /* change back to NotAssociated */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017872 hdd_conn_set_connection_state(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017873 eConnectionState_NotConnected);
Jingxiang Geb49aa302018-01-17 20:54:15 +080017874 qdf_runtime_pm_allow_suspend(
17875 &hdd_ctx->runtime_context.connect);
Dustin Brownceed67e2017-05-26 11:57:31 -070017876 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017877 }
17878
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017879 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017880 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017881
wadesong24c869a2019-07-19 17:38:59 +080017882 roam_profile->ChannelInfo.freq_list = NULL;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017883 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017884
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017885 if ((QDF_STA_MODE == adapter->device_mode)
Dustin Brown76cd2932018-09-11 16:03:05 -070017886 && policy_mgr_is_current_hwmode_dbs(hdd_ctx->psoc)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017887 && !policy_mgr_is_hw_dbs_2x2_capable(
Dustin Brown76cd2932018-09-11 16:03:05 -070017888 hdd_ctx->psoc)) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017889 policy_mgr_get_channel_from_scan_result(
Dustin Brown76cd2932018-09-11 16:03:05 -070017890 hdd_ctx->psoc,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017891 roam_profile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080017892 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053017893 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017894 policy_mgr_checkn_update_hw_mode_single_mac_mode(
Dustin Brown76cd2932018-09-11 16:03:05 -070017895 hdd_ctx->psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053017896 }
17897
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017898 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017899 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017900 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017901 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017902 goto ret_status;
17903
17904conn_failure:
17905 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017906 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017907
17908ret_status:
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053017909 /*
17910 * Enable roaming on other STA adapter for failure case.
17911 * For success case, it is enabled in assoc completion handler
17912 */
17913 if (status)
17914 wlan_hdd_enable_roaming(adapter);
17915
Dustin Browne74003f2018-03-14 12:51:58 -070017916 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017917 return status;
17918}
17919
17920/**
17921 * wlan_hdd_cfg80211_set_auth_type() - set auth type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017922 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017923 * @auth_type: Auth type
17924 *
17925 * This function is used to set the authentication type (OPEN/SHARED).
17926 *
17927 * Return: 0 for success, non-zero for failure
17928 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017929static int wlan_hdd_cfg80211_set_auth_type(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017930 enum nl80211_auth_type auth_type)
17931{
Jeff Johnsond377dce2017-10-04 10:32:42 -070017932 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017933 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070017934 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017935
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017936 /*set authentication type */
17937 switch (auth_type) {
17938 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017939 hdd_debug("set authentication type to AUTOSWITCH");
Jeff Johnson96e33512019-02-27 15:10:21 -080017940 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_AUTOSWITCH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017941 break;
17942
17943 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017944 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017945 hdd_debug("set authentication type to OPEN");
Jeff Johnson96e33512019-02-27 15:10:21 -080017946 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017947 break;
17948
17949 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017950 hdd_debug("set authentication type to SHARED");
Jeff Johnson96e33512019-02-27 15:10:21 -080017951 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_SHARED_KEY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017952 break;
17953#ifdef FEATURE_WLAN_ESE
17954 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017955 hdd_debug("set authentication type to CCKM WPA");
Jeff Johnson96e33512019-02-27 15:10:21 -080017956 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_CCKM_WPA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017957 break;
17958#endif
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053017959#if defined(WLAN_FEATURE_FILS_SK) && \
17960 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
17961 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053017962 case NL80211_AUTHTYPE_FILS_SK:
Dustin Brown5e89ef82018-03-14 11:50:23 -070017963 hdd_debug("set authentication type to FILS SHARED");
Jeff Johnson96e33512019-02-27 15:10:21 -080017964 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053017965 break;
17966#endif
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053017967 case NL80211_AUTHTYPE_SAE:
17968 hdd_debug("set authentication type to SAE");
Jeff Johnson96e33512019-02-27 15:10:21 -080017969 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_SAE;
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053017970 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017971 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017972 hdd_err("Unsupported authentication type: %d", auth_type);
Jeff Johnson96e33512019-02-27 15:10:21 -080017973 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_UNKNOWN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017974 return -EINVAL;
17975 }
17976
Jeff Johnson20227a92018-03-13 09:41:05 -070017977 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson96e33512019-02-27 15:10:21 -080017978 roam_profile->AuthType.authType[0] = sta_ctx->conn_info.auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017979 return 0;
17980}
17981
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053017982#if defined(WLAN_FEATURE_FILS_SK) && \
17983 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
17984 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Jeff Johnson20227a92018-03-13 09:41:05 -070017985static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053017986{
17987 struct cds_fils_connection_info *fils_con_info;
17988
Jeff Johnson20227a92018-03-13 09:41:05 -070017989 fils_con_info = roam_profile->fils_con_info;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053017990 if (!fils_con_info) {
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070017991 hdd_err("No valid Roam profile");
17992 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053017993 }
17994
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070017995 return true;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053017996}
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070017997
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070017998static enum eAniAuthType wlan_hdd_get_fils_auth_type(
17999 enum nl80211_auth_type auth)
18000{
18001 switch (auth) {
18002 case NL80211_AUTHTYPE_FILS_SK:
18003 return SIR_FILS_SK_WITHOUT_PFS;
18004 case NL80211_AUTHTYPE_FILS_SK_PFS:
18005 return SIR_FILS_SK_WITH_PFS;
18006 case NL80211_AUTHTYPE_FILS_PK:
18007 return SIR_FILS_PK_AUTH;
18008 default:
18009 return eSIR_DONOT_USE_AUTH_TYPE;
18010 }
18011}
18012
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018013static bool wlan_hdd_fils_data_in_limits(struct cfg80211_connect_params *req)
18014{
18015 hdd_debug("seq=%d auth=%d lengths: user=%zu rrk=%zu realm=%zu",
18016 req->fils_erp_next_seq_num, req->auth_type,
18017 req->fils_erp_username_len, req->fils_erp_rrk_len,
18018 req->fils_erp_realm_len);
18019 if (!req->fils_erp_rrk_len || !req->fils_erp_realm_len ||
18020 !req->fils_erp_username_len ||
18021 req->fils_erp_rrk_len > FILS_MAX_RRK_LENGTH ||
18022 req->fils_erp_realm_len > FILS_MAX_REALM_LEN ||
18023 req->fils_erp_username_len > FILS_MAX_KEYNAME_NAI_LENGTH) {
18024 hdd_err("length incorrect, user=%zu rrk=%zu realm=%zu",
18025 req->fils_erp_username_len, req->fils_erp_rrk_len,
18026 req->fils_erp_realm_len);
18027 return false;
18028 }
18029
bings77a35ac2018-06-01 15:10:44 +080018030 if (!req->fils_erp_rrk || !req->fils_erp_realm ||
18031 !req->fils_erp_username) {
18032 hdd_err("buffer incorrect, user=%pK rrk=%pK realm=%pK",
18033 req->fils_erp_username, req->fils_erp_rrk,
18034 req->fils_erp_realm);
18035 return false;
18036 }
18037
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018038 return true;
18039}
18040
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018041/**
18042 * wlan_hdd_cfg80211_set_fils_config() - set fils config params during connect
18043 * @adapter: Pointer to adapter
18044 * @req: Pointer to fils parameters
18045 *
18046 * Return: 0 for success, non-zero for failure
18047 */
18048static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
18049 struct cfg80211_connect_params *req)
18050{
Jeff Johnson61b5e982018-03-15 11:33:31 -070018051 struct csr_roam_profile *roam_profile;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018052 enum eAniAuthType auth_type;
18053 uint8_t *buf;
Karthik Kantamneni2231a232018-09-11 15:45:55 +053018054 bool value;
18055 QDF_STATUS status;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018056 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
18057
Jeff Johnson20227a92018-03-13 09:41:05 -070018058 roam_profile = hdd_roam_profile(adapter);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018059
Karthik Kantamneni2231a232018-09-11 15:45:55 +053018060 value = 0;
Dustin Brown05d81302018-09-11 16:49:22 -070018061 status = ucfg_mlme_get_fils_enabled_info(hdd_ctx->psoc, &value);
Karthik Kantamneni2231a232018-09-11 15:45:55 +053018062 if (QDF_IS_STATUS_ERROR(status) || !value) {
18063 hdd_err("get_fils_enabled status: %d fils_enabled: %d",
18064 status, value);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018065 return -EINVAL;
18066 }
Karthik Kantamneni2231a232018-09-11 15:45:55 +053018067
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018068 hdd_clear_fils_connection_info(adapter);
18069 roam_profile->fils_con_info =
18070 qdf_mem_malloc(sizeof(*roam_profile->fils_con_info));
18071
Min Liu74a1a502018-10-10 19:59:07 +080018072 if (!roam_profile->fils_con_info)
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018073 return -EINVAL;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018074 /*
18075 * The initial connection for FILS may happen with an OPEN
18076 * auth type. Hence we need to allow the connection to go
18077 * through in that case as well. Below is_fils_connection
18078 * flag is propagated down to CSR and PE sessions through
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018079 * the JOIN request. As the flag is used, do not free the
18080 * memory allocated to fils_con_info and return success.
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018081 */
18082 if (req->auth_type != NL80211_AUTHTYPE_FILS_SK) {
18083 roam_profile->fils_con_info->is_fils_connection = false;
18084 return 0;
18085 }
18086
18087 /*
18088 * Once above check is done, then we can check for valid FILS
18089 * auth types. Currently only NL80211_AUTHTYPE_FILS_SK is
18090 * supported. Once all auth types are supported, then we can
18091 * merge these 2 conditions into one.
18092 */
18093 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
18094 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
18095 hdd_err("invalid auth type for fils %d", req->auth_type);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018096 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018097 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018098 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080018099 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018100
18101 roam_profile->fils_con_info->is_fils_connection = true;
18102 roam_profile->fils_con_info->sequence_number =
Pragaspathi Thilagaraj87a60af2019-02-20 20:42:47 +053018103 (req->fils_erp_next_seq_num + 1);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018104 roam_profile->fils_con_info->auth_type = auth_type;
18105
18106 roam_profile->fils_con_info->r_rk_length =
18107 req->fils_erp_rrk_len;
18108 if (req->fils_erp_rrk_len)
18109 qdf_mem_copy(roam_profile->fils_con_info->r_rk,
18110 req->fils_erp_rrk,
18111 roam_profile->fils_con_info->r_rk_length);
18112
18113 roam_profile->fils_con_info->realm_len = req->fils_erp_realm_len;
18114 if (req->fils_erp_realm_len)
18115 qdf_mem_copy(roam_profile->fils_con_info->realm,
18116 req->fils_erp_realm,
18117 roam_profile->fils_con_info->realm_len);
18118
18119 roam_profile->fils_con_info->key_nai_length =
18120 req->fils_erp_username_len + sizeof(char) +
18121 req->fils_erp_realm_len;
18122 hdd_debug("key_nai_length = %d",
18123 roam_profile->fils_con_info->key_nai_length);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018124 if (roam_profile->fils_con_info->key_nai_length >
18125 FILS_MAX_KEYNAME_NAI_LENGTH) {
18126 hdd_err("Do not allow FILS conn due to excess NAI Length %d",
18127 roam_profile->fils_con_info->key_nai_length);
18128 goto fils_conn_fail;
18129 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018130 buf = roam_profile->fils_con_info->keyname_nai;
18131 qdf_mem_copy(buf, req->fils_erp_username, req->fils_erp_username_len);
18132 buf += req->fils_erp_username_len;
18133 *buf++ = '@';
18134 qdf_mem_copy(buf, req->fils_erp_realm, req->fils_erp_realm_len);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018135
18136 return 0;
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018137
18138fils_conn_fail:
18139 if (roam_profile->fils_con_info) {
18140 qdf_mem_free(roam_profile->fils_con_info);
18141 roam_profile->fils_con_info = NULL;
18142 }
18143 return -EINVAL;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018144}
18145
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018146static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
18147{
18148 switch (key_mgmt) {
18149 case WLAN_AKM_SUITE_FILS_SHA256:
18150 case WLAN_AKM_SUITE_FILS_SHA384:
18151 case WLAN_AKM_SUITE_FT_FILS_SHA256:
18152 case WLAN_AKM_SUITE_FT_FILS_SHA384:
18153 return true;
18154 default:
18155 return false;
18156 }
18157}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018158
18159static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
18160{
18161 enum nl80211_auth_type auth_type = req->auth_type;
18162 /*
18163 * Below n_akm_suites is defined as int in the kernel, even though it
18164 * is supposed to be unsigned.
18165 */
18166 int num_akm_suites = req->crypto.n_akm_suites;
18167 uint32_t key_mgmt = req->crypto.akm_suites[0];
18168 enum eAniAuthType fils_auth_type =
18169 wlan_hdd_get_fils_auth_type(req->auth_type);
18170
18171 hdd_debug("Num of AKM suites = %d", num_akm_suites);
18172 if (num_akm_suites <= 0)
18173 return false;
18174
18175 /*
18176 * Auth type will be either be OPEN or FILS type for a FILS connection
18177 */
18178 if ((auth_type != NL80211_AUTHTYPE_OPEN_SYSTEM) &&
18179 (fils_auth_type == eSIR_DONOT_USE_AUTH_TYPE)) {
18180 hdd_debug("Not a FILS auth type, auth = %d, fils auth = %d",
18181 auth_type, fils_auth_type);
18182 return false;
18183 }
18184
18185 if (!wlan_hdd_is_akm_suite_fils(key_mgmt)) {
18186 hdd_debug("Not a FILS AKM SUITE %d", key_mgmt);
18187 return false;
18188 }
18189
18190 return true;
18191}
18192
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018193#else
Jeff Johnson20227a92018-03-13 09:41:05 -070018194static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018195{
18196 return true;
18197}
18198
18199static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
18200 struct cfg80211_connect_params *req)
18201{
18202 return 0;
18203}
18204
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018205static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
18206{
18207 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018208}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018209
18210static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
18211{
18212 return false;
18213}
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018214#endif
18215
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018216/**
18217 * wlan_hdd_set_akm_suite() - set key management type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018218 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018219 * @key_mgmt: Key management type
18220 *
18221 * This function is used to set the key mgmt type(PSK/8021x).
18222 *
18223 * Return: 0 for success, non-zero for failure
18224 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018225static int wlan_hdd_set_akm_suite(struct hdd_adapter *adapter, u32 key_mgmt)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018226{
Jeff Johnson37ecea42018-03-18 17:54:40 -070018227 struct hdd_station_ctx *sta_ctx;
Jeff Johnson61b5e982018-03-15 11:33:31 -070018228 struct csr_roam_profile *roam_profile;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018229
Jeff Johnson20227a92018-03-13 09:41:05 -070018230 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018231
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018232 if (wlan_hdd_is_akm_suite_fils(key_mgmt) &&
Jeff Johnson20227a92018-03-13 09:41:05 -070018233 !hdd_validate_fils_info_ptr(roam_profile))
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018234 return -EINVAL;
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018235#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018236#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018237#endif
18238#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018239#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018240#endif
Jeff Johnson37ecea42018-03-18 17:54:40 -070018241
18242 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
18243
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018244 /*set key mgmt type */
18245 switch (key_mgmt) {
18246 case WLAN_AKM_SUITE_PSK:
18247 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018248 case WLAN_AKM_SUITE_FT_PSK:
Abhishek Singh02cb9e02017-08-30 17:39:50 +053018249 case WLAN_AKM_SUITE_DPP_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018250 hdd_debug("setting key mgmt type to PSK");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018251 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_PSK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018252 break;
18253
18254 case WLAN_AKM_SUITE_8021X_SHA256:
18255 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018256 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018257 hdd_debug("setting key mgmt type to 8021x");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018258 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018259 break;
18260#ifdef FEATURE_WLAN_ESE
18261#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018262 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018263 hdd_debug("setting key mgmt type to CCKM");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018264 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_CCKM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018265 break;
18266#endif
18267#ifndef WLAN_AKM_SUITE_OSEN
18268#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
18269#endif
18270 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018271 hdd_debug("setting key mgmt type to OSEN");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018272 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018273 break;
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053018274#if defined(WLAN_FEATURE_FILS_SK) && \
18275 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
18276 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053018277 case WLAN_AKM_SUITE_FILS_SHA256:
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018278 hdd_debug("setting key mgmt type to FILS SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018279 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018280 roam_profile->fils_con_info->akm_type =
18281 eCSR_AUTH_TYPE_FILS_SHA256;
18282 break;
18283
18284 case WLAN_AKM_SUITE_FILS_SHA384:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018285 hdd_debug("setting key mgmt type to FILS SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018286 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018287 roam_profile->fils_con_info->akm_type =
18288 eCSR_AUTH_TYPE_FILS_SHA384;
18289 break;
18290
18291 case WLAN_AKM_SUITE_FT_FILS_SHA256:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018292 hdd_debug("setting key mgmt type to FILS FT SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018293 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018294 roam_profile->fils_con_info->akm_type =
18295 eCSR_AUTH_TYPE_FT_FILS_SHA256;
18296 break;
18297
18298 case WLAN_AKM_SUITE_FT_FILS_SHA384:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018299 hdd_debug("setting key mgmt type to FILS FT SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018300 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018301 roam_profile->fils_con_info->akm_type =
18302 eCSR_AUTH_TYPE_FT_FILS_SHA384;
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053018303 break;
18304#endif
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053018305
18306 case WLAN_AKM_SUITE_OWE:
18307 hdd_debug("setting key mgmt type to OWE");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018308 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053018309 break;
18310
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018311 case WLAN_AKM_SUITE_EAP_SHA256:
18312 hdd_debug("setting key mgmt type to EAP_SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018313 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018314 break;
18315 case WLAN_AKM_SUITE_EAP_SHA384:
18316 hdd_debug("setting key mgmt type to EAP_SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018317 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018318 break;
18319
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018320 case WLAN_AKM_SUITE_SAE:
18321 hdd_debug("setting key mgmt type to SAE");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018322 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018323 break;
18324
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +053018325 case WLAN_AKM_SUITE_FT_SAE:
18326 hdd_debug("setting key mgmt type to FT-SAE");
18327 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
18328 break;
18329
18330 case WLAN_AKM_SUITE_FT_EAP_SHA_384:
18331 hdd_debug("setting key mgmt type to FT-EAP-SHA384");
18332 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
18333 break;
18334
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018335 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018336 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018337 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018338 }
18339 return 0;
18340}
18341
18342/**
18343 * wlan_hdd_cfg80211_set_cipher() - set encryption type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018344 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018345 * @cipher: Cipher type
18346 * @ucast: Unicast flag
18347 *
18348 * This function is used to set the encryption type
18349 * (NONE/WEP40/WEP104/TKIP/CCMP).
18350 *
18351 * Return: 0 for success, non-zero for failure
18352 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018353static int wlan_hdd_cfg80211_set_cipher(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018354 u32 cipher, bool ucast)
18355{
18356 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Jeff Johnsond377dce2017-10-04 10:32:42 -070018357 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018358 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070018359 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018360
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018361 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018362 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018363 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
18364 } else {
18365
18366 /*set encryption method */
18367 switch (cipher) {
18368 case IW_AUTH_CIPHER_NONE:
18369 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
18370 break;
18371
18372 case WLAN_CIPHER_SUITE_WEP40:
18373 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
18374 break;
18375
18376 case WLAN_CIPHER_SUITE_WEP104:
18377 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
18378 break;
18379
18380 case WLAN_CIPHER_SUITE_TKIP:
18381 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
18382 break;
18383
18384 case WLAN_CIPHER_SUITE_CCMP:
18385 encryptionType = eCSR_ENCRYPT_TYPE_AES;
18386 break;
18387#ifdef FEATURE_WLAN_WAPI
18388 case WLAN_CIPHER_SUITE_SMS4:
18389 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
18390 break;
18391#endif
18392
18393#ifdef FEATURE_WLAN_ESE
18394 case WLAN_CIPHER_SUITE_KRK:
18395 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
18396 break;
18397#ifdef WLAN_FEATURE_ROAM_OFFLOAD
18398 case WLAN_CIPHER_SUITE_BTK:
18399 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
18400 break;
18401#endif
18402#endif
Mukul Sharma05504ac2017-06-08 12:35:53 +053018403 case WLAN_CIPHER_SUITE_GCMP:
18404 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP;
18405 break;
18406 case WLAN_CIPHER_SUITE_GCMP_256:
18407 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP_256;
18408 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018409 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018410 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018411 return -EOPNOTSUPP;
18412 }
18413 }
18414
Jeff Johnson20227a92018-03-13 09:41:05 -070018415 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018416 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018417 hdd_debug("setting unicast cipher type to %d", encryptionType);
Jeff Johnsonb1959842019-02-27 13:04:04 -080018418 sta_ctx->conn_info.uc_encrypt_type = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070018419 roam_profile->EncryptionType.numEntries = 1;
18420 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018421 encryptionType;
18422 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018423 hdd_debug("setting mcast cipher type to %d", encryptionType);
Jeff Johnsonb1959842019-02-27 13:04:04 -080018424 sta_ctx->conn_info.mc_encrypt_type = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070018425 roam_profile->mcEncryptionType.numEntries = 1;
18426 roam_profile->mcEncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018427 encryptionType;
18428 }
18429
18430 return 0;
18431}
18432
18433/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018434 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
Jeff Johnson20227a92018-03-13 09:41:05 -070018435 * @adapter: Pointer to adapter
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018436 * @gen_ie: Pointer to IE data
18437 * @len: length of IE data
18438 *
18439 * Return: 0 for success, non-zero for failure
18440 */
Jeff Johnson20227a92018-03-13 09:41:05 -070018441static int wlan_hdd_add_assoc_ie(struct hdd_adapter *adapter,
18442 const uint8_t *gen_ie, uint16_t len)
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018443{
Jeff Johnson20227a92018-03-13 09:41:05 -070018444 struct csr_roam_profile *roam_profile;
18445 tSirAddie *assoc_add_ie;
18446 uint16_t cur_add_ie_len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018447
Jeff Johnson20227a92018-03-13 09:41:05 -070018448 assoc_add_ie = hdd_assoc_additional_ie(adapter);
18449 cur_add_ie_len = assoc_add_ie->length;
18450 if (SIR_MAC_MAX_ADD_IE_LENGTH < (cur_add_ie_len + len)) {
18451 hdd_err("current len %u, new ie of len %u will overflow",
18452 cur_add_ie_len, len);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018453 return -ENOMEM;
18454 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018455 memcpy(assoc_add_ie->addIEdata + cur_add_ie_len, gen_ie, len);
18456 assoc_add_ie->length += len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018457
Jeff Johnson20227a92018-03-13 09:41:05 -070018458 roam_profile = hdd_roam_profile(adapter);
18459 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
18460 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
18461
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018462 return 0;
18463}
18464
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018465#ifdef WLAN_FEATURE_FILS_SK
18466/**
18467 * wlan_hdd_save_hlp_ie - API to save HLP IE
18468 * @roam_profile: Pointer to roam profile
18469 * @gen_ie: IE buffer to store
18470 * @len: length of the IE buffer @gen_ie
18471 * @flush: Flush the older saved HLP if any
18472 *
18473 * Return: None
18474 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070018475static void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070018476 const uint8_t *gen_ie, uint16_t len,
18477 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018478{
18479 uint8_t *hlp_ie = roam_profile->hlp_ie;
18480
18481 if (flush) {
18482 roam_profile->hlp_ie_len = 0;
18483 if (hlp_ie) {
18484 qdf_mem_free(hlp_ie);
18485 roam_profile->hlp_ie = NULL;
18486 }
18487 }
18488
18489 if ((roam_profile->hlp_ie_len +
18490 len) > FILS_MAX_HLP_DATA_LEN) {
18491 hdd_err("HLP len exceeds: hlp_ie_len %d len %d",
18492 roam_profile->hlp_ie_len, len);
18493 return;
18494 }
18495
18496 if (!roam_profile->hlp_ie) {
18497 roam_profile->hlp_ie =
18498 qdf_mem_malloc(FILS_MAX_HLP_DATA_LEN);
18499 hlp_ie = roam_profile->hlp_ie;
Min Liu74a1a502018-10-10 19:59:07 +080018500 if (!hlp_ie)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018501 return;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018502 }
18503
18504 qdf_mem_copy(hlp_ie + roam_profile->hlp_ie_len, gen_ie, len);
18505 roam_profile->hlp_ie_len += len;
18506}
18507#else
Jeff Johnson61b5e982018-03-15 11:33:31 -070018508static inline void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070018509 const uint8_t *gen_ie, uint16_t len,
18510 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018511{}
18512#endif
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080018513
18514#ifdef WLAN_CONV_CRYPTO_SUPPORTED
18515/**
18516 * hdd_populate_crypto_auth_type() - populate auth type for crypto
18517 * @vdev: pointed to vdev obmgr
18518 * @auth_type: legacy auth_type
18519 *
18520 * set the crypto auth type for corresponding auth type received
18521 * from NL
18522 *
18523 * Return: None
18524 */
18525static void hdd_populate_crypto_auth_type(struct wlan_objmgr_vdev *vdev,
18526 enum nl80211_auth_type auth_type)
18527{
18528 QDF_STATUS status;
18529 uint32_t set_val = 0;
18530 wlan_crypto_auth_mode crypto_auth_type =
18531 osif_nl_to_crypto_auth_type(auth_type);
18532
18533 hdd_debug("set auth type %d to crypto component", crypto_auth_type);
18534 HDD_SET_BIT(set_val, crypto_auth_type);
18535 status = wlan_crypto_set_vdev_param(vdev,
18536 WLAN_CRYPTO_PARAM_AUTH_MODE,
18537 set_val);
18538 if (QDF_IS_STATUS_ERROR(status))
18539 hdd_err("Failed to set auth type %0X to crypto component",
18540 set_val);
18541}
18542
18543/**
18544 * hdd_populate_crypto_akm_type() - populate akm type for crypto
18545 * @vdev: pointed to vdev obmgr
18546 * @akm_type: legacy akm_type
18547 *
18548 * set the crypto akm type for corresponding akm type received
18549 * from NL
18550 *
18551 * Return: None
18552 */
18553static void hdd_populate_crypto_akm_type(struct wlan_objmgr_vdev *vdev,
18554 u32 key_mgmt)
18555{
18556 QDF_STATUS status;
18557 uint32_t set_val = 0;
18558 wlan_crypto_key_mgmt crypto_akm_type =
18559 osif_nl_to_crypto_akm_type(key_mgmt);
18560
18561 hdd_debug("set akm type %d to crypto component", crypto_akm_type);
18562 HDD_SET_BIT(set_val, crypto_akm_type);
18563
18564 status = wlan_crypto_set_vdev_param(vdev,
18565 WLAN_CRYPTO_PARAM_KEY_MGMT,
18566 set_val);
18567 if (QDF_IS_STATUS_ERROR(status))
18568 hdd_err("Failed to set akm type %0x to crypto component",
18569 set_val);
18570}
18571
18572/**
18573 * hdd_populate_crypto_cipher_type() - populate cipher type for crypto
18574 * @cipher: legacy cipher type
18575 * @vdev: pointed to vdev obmgr
18576 * @cipher_param_type: param type, UCST/MCAST
18577 *
18578 * set the crypto cipher type for corresponding cipher type received
18579 * from NL
18580 *
18581 * Return: None
18582 */
18583static void hdd_populate_crypto_cipher_type(u32 cipher,
18584 struct wlan_objmgr_vdev *vdev,
18585 wlan_crypto_param_type
18586 cipher_param_type)
18587{
18588 QDF_STATUS status;
18589 uint32_t set_val = 0;
18590 wlan_crypto_cipher_type crypto_cipher_type =
18591 osif_nl_to_crypto_cipher_type(cipher);
18592
18593 hdd_debug("set cipher params %d type %d to crypto",
18594 cipher_param_type, crypto_cipher_type);
18595 HDD_SET_BIT(set_val, crypto_cipher_type);
18596 status = wlan_crypto_set_vdev_param(vdev, cipher_param_type, set_val);
18597 if (QDF_IS_STATUS_ERROR(status))
18598 hdd_err("Failed to set cipher params %d type %0x to crypto",
18599 cipher_param_type, set_val);
18600}
18601
18602/**
18603 * hdd_populate_crypto_params() - set crypto params
18604 * @vdev: Pointer to vdev obh mgr
18605 * @req: Pointer to security parameters
18606 *
18607 * Set Auth, Akm and Cipher type for crypto
18608 *
18609 * Return: None
18610 */
18611static void hdd_populate_crypto_params(struct wlan_objmgr_vdev *vdev,
18612 struct cfg80211_connect_params *req)
18613{
18614 hdd_populate_crypto_auth_type(vdev, req->auth_type);
18615
18616 if (req->crypto.n_akm_suites)
18617 hdd_populate_crypto_akm_type(vdev, req->crypto.akm_suites[0]);
18618
18619 if (req->crypto.n_ciphers_pairwise) {
18620 hdd_populate_crypto_cipher_type(req->crypto.ciphers_pairwise[0],
18621 vdev,
18622 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
18623 } else {
18624 /* Reset previous cipher suite to none */
18625 hdd_populate_crypto_cipher_type(0, vdev,
18626 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
18627 }
18628
18629 hdd_populate_crypto_cipher_type(req->crypto.cipher_group,
18630 vdev,
18631 WLAN_CRYPTO_PARAM_MCAST_CIPHER);
18632}
18633
18634/**
18635 * hdd_set_crypto_key_mgmt_param() - Set key mgmt param.
18636 * @adapter: Pointer to adapter.
18637 *
18638 * Return: None
18639 */
18640static void hdd_set_crypto_key_mgmt_param(struct hdd_adapter *adapter)
18641{
18642 uint32_t key_mgmt = 0;
18643 struct wlan_objmgr_vdev *vdev;
18644
18645 if (!adapter) {
18646 hdd_err("adapter is null");
18647 return;
18648 }
18649
18650 vdev = hdd_objmgr_get_vdev(adapter);
18651 if (!vdev)
18652 return;
18653
18654 if (adapter->wapi_info.wapi_auth_mode == WAPI_AUTH_MODE_PSK)
18655 HDD_SET_BIT(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK);
18656 if (adapter->wapi_info.wapi_auth_mode == WAPI_AUTH_MODE_CERT)
18657 HDD_SET_BIT(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT);
18658
18659 wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT, key_mgmt);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053018660 hdd_objmgr_put_vdev(vdev);
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080018661}
18662
18663#else
18664
18665static inline
18666void hdd_populate_crypto_auth_type(struct wlan_objmgr_vdev *vdev,
18667 enum nl80211_auth_type auth_type)
18668{
18669}
18670
18671static inline
18672void hdd_populate_crypto_akm_type(struct wlan_objmgr_vdev *vdev,
18673 u32 key_mgmt)
18674{
18675}
18676
18677static inline
18678void hdd_populate_crypto_cipher_type(u32 cipher,
18679 struct wlan_objmgr_vdev *vdev,
18680 wlan_crypto_param_type
18681 cipher_param_type)
18682{
18683}
18684
18685static inline
18686void hdd_populate_crypto_params(struct wlan_objmgr_vdev *vdev,
18687 struct cfg80211_connect_params *req)
18688{
18689}
18690
18691static inline void hdd_set_crypto_key_mgmt_param(struct hdd_adapter *adapter)
18692{
18693}
18694
18695#endif
18696
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018697/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018698 * wlan_hdd_cfg80211_set_ie() - set IEs
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018699 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018700 * @ie: Pointer ot ie
18701 * @ie: IE length
18702 *
18703 * Return: 0 for success, non-zero for failure
18704 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018705static int wlan_hdd_cfg80211_set_ie(struct hdd_adapter *adapter,
Jeff Johnson2a722002017-09-30 20:02:35 -070018706 const uint8_t *ie,
18707 size_t ie_len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018708{
Jeff Johnson20227a92018-03-13 09:41:05 -070018709 struct csr_roam_profile *roam_profile;
18710 tSirAddie *assoc_add_ie;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018711 const uint8_t *genie = ie;
18712 uint16_t remLen = ie_len;
18713#ifdef FEATURE_WLAN_WAPI
18714 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
tinlin8a44b642018-04-25 13:56:06 +080018715 uint8_t *tmp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018716 uint16_t akmsuiteCount;
tinlin8a44b642018-04-25 13:56:06 +080018717 uint32_t *akmlist;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018718#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018719 int status;
Jeff Johnson20227a92018-03-13 09:41:05 -070018720 uint8_t *security_ie;
18721
18722 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018723
18724 /* clear previous assocAddIE */
Jeff Johnson20227a92018-03-13 09:41:05 -070018725 assoc_add_ie = hdd_assoc_additional_ie(adapter);
18726 assoc_add_ie->length = 0;
18727 roam_profile->bWPSAssociation = false;
18728 roam_profile->bOSENAssociation = false;
18729 security_ie = hdd_security_ie(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018730
18731 while (remLen >= 2) {
18732 uint16_t eLen = 0;
18733 uint8_t elementId;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070018734
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018735 elementId = *genie++;
18736 eLen = *genie++;
18737 remLen -= 2;
18738
Nachiket Kukade4bea8b42017-06-13 11:53:19 +053018739 /* Sanity check on eLen */
18740 if (eLen > remLen) {
18741 hdd_err("%s: Invalid IE length[%d] for IE[0x%X]",
18742 __func__, eLen, elementId);
18743 QDF_ASSERT(0);
18744 return -EINVAL;
18745 }
18746
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018747 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018748
18749 switch (elementId) {
18750 case DOT11F_EID_WPA:
18751 if (4 > eLen) { /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018752 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018753 return -EINVAL;
18754 } else if (0 ==
18755 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
Jeff Johnson20227a92018-03-13 09:41:05 -070018756 uint16_t curAddIELen = assoc_add_ie->length;
18757
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018758 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018759
18760 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018761 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018762 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018763 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018764 return -ENOMEM;
18765 }
18766 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070018767 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018768 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018769 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018770
Jeff Johnson20227a92018-03-13 09:41:05 -070018771 roam_profile->bWPSAssociation = true;
18772 roam_profile->pAddIEAssoc =
18773 assoc_add_ie->addIEdata;
18774 roam_profile->nAddIEAssocLength =
18775 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018776 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowdacf161402019-03-14 11:37:33 -070018777 if (eLen > (WLAN_MAX_IE_LEN - 2)) {
Nachiket Kukade2f6509f2017-06-13 17:45:46 +053018778 hdd_err("%s: Invalid WPA IE length[%d]",
18779 __func__, eLen);
18780 QDF_ASSERT(0);
18781 return -EINVAL;
18782 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018783 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Srinivas Girigowdacf161402019-03-14 11:37:33 -070018784 memset(security_ie, 0, WLAN_MAX_IE_LEN);
Jeff Johnson20227a92018-03-13 09:41:05 -070018785 memcpy(security_ie, genie - 2, (eLen + 2));
18786 roam_profile->pWPAReqIE = security_ie;
18787 roam_profile->nWPAReqIELength = eLen + 2; /* ie_len; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018788 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
18789 P2P_OUI_TYPE_SIZE))) {
18790 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018791 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018792 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018793
18794 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018795 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018796 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018797 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018798 return -ENOMEM;
18799 }
18800 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070018801 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018802 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018803 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018804
Jeff Johnson20227a92018-03-13 09:41:05 -070018805 roam_profile->pAddIEAssoc =
18806 assoc_add_ie->addIEdata;
18807 roam_profile->nAddIEAssocLength =
18808 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018809 }
18810#ifdef WLAN_FEATURE_WFD
18811 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
18812 WFD_OUI_TYPE_SIZE)) &&
18813 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080018814 (QDF_P2P_CLIENT_MODE ==
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018815 adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018816 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018817 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018818 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018819
18820 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018821 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018822 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018823 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018824 return -ENOMEM;
18825 }
18826 /* WFD IE is saved to Additional IE ; it should
18827 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080018828 * WFD IE
18829 */
Jeff Johnson20227a92018-03-13 09:41:05 -070018830 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018831 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018832 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018833
Jeff Johnson20227a92018-03-13 09:41:05 -070018834 roam_profile->pAddIEAssoc =
18835 assoc_add_ie->addIEdata;
18836 roam_profile->nAddIEAssocLength =
18837 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018838 }
18839#endif
18840 /* Appending HS 2.0 Indication Element in Assiciation Request */
18841 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
18842 HS20_OUI_TYPE_SIZE))) {
18843 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018844 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018845 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018846
18847 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018848 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018849 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018850 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018851 return -ENOMEM;
18852 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018853 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018854 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018855 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018856
Jeff Johnson20227a92018-03-13 09:41:05 -070018857 roam_profile->pAddIEAssoc =
18858 assoc_add_ie->addIEdata;
18859 roam_profile->nAddIEAssocLength =
18860 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018861 }
18862 /* Appending OSEN Information Element in Assiciation Request */
18863 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
18864 OSEN_OUI_TYPE_SIZE))) {
18865 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018866 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018867 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018868
18869 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018870 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018871 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018872 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018873 return -ENOMEM;
18874 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018875 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018876 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018877 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018878
Jeff Johnson20227a92018-03-13 09:41:05 -070018879 roam_profile->bOSENAssociation = true;
18880 roam_profile->pAddIEAssoc =
18881 assoc_add_ie->addIEdata;
18882 roam_profile->nAddIEAssocLength =
18883 assoc_add_ie->length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018884 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
18885 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018886 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018887 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018888 genie - 2, eLen + 2);
18889 if (status)
18890 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018891 } else {
18892 uint16_t add_ie_len =
Jeff Johnson20227a92018-03-13 09:41:05 -070018893 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018894
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018895 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018896
18897 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018898 (assoc_add_ie->length + eLen)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018899 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018900 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018901 return -ENOMEM;
18902 }
18903
Jeff Johnson20227a92018-03-13 09:41:05 -070018904 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018905 add_ie_len, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018906 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018907
Jeff Johnson20227a92018-03-13 09:41:05 -070018908 roam_profile->pAddIEAssoc =
18909 assoc_add_ie->addIEdata;
18910 roam_profile->nAddIEAssocLength =
18911 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018912 }
18913 break;
18914 case DOT11F_EID_RSN:
tinlin8a44b642018-04-25 13:56:06 +080018915 if (eLen > DOT11F_IE_RSN_MAX_LEN) {
Vignesh Viswanathan96e0e702017-12-05 19:42:46 +053018916 hdd_err("%s: Invalid WPA RSN IE length[%d]",
tinlin8a44b642018-04-25 13:56:06 +080018917 __func__, eLen);
Vignesh Viswanathan96e0e702017-12-05 19:42:46 +053018918 return -EINVAL;
18919 }
Srinivas Girigowdacf161402019-03-14 11:37:33 -070018920 memset(security_ie, 0, WLAN_MAX_IE_LEN);
Jeff Johnson20227a92018-03-13 09:41:05 -070018921 memcpy(security_ie, genie - 2, (eLen + 2));
18922 roam_profile->pRSNReqIE = security_ie;
18923 roam_profile->nRSNReqIELength = eLen + 2; /* ie_len; */
tinlin8a44b642018-04-25 13:56:06 +080018924 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018925 break;
18926 /*
18927 * Appending Extended Capabilities with Interworking bit set
18928 * in Assoc Req.
18929 *
18930 * In assoc req this EXT Cap will only be taken into account if
18931 * interworkingService bit is set to 1. Currently
18932 * driver is only interested in interworkingService capability
18933 * from supplicant. If in future any other EXT Cap info is
18934 * required from supplicat, it needs to be handled while
18935 * sending Assoc Req in LIM.
18936 */
18937 case DOT11F_EID_EXTCAP:
18938 {
18939 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018940 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018941 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018942
18943 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018944 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018945 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018946 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018947 return -ENOMEM;
18948 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018949 memcpy(assoc_add_ie->addIEdata + curAddIELen, genie - 2, eLen + 2);
18950 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018951
Jeff Johnson20227a92018-03-13 09:41:05 -070018952 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
18953 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018954 break;
18955 }
18956#ifdef FEATURE_WLAN_WAPI
Srinivas Girigowda61771262019-04-01 11:55:19 -070018957 case WLAN_ELEMID_WAPI:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018958 /* Setting WAPI Mode to ON=1 */
tinlin8a44b642018-04-25 13:56:06 +080018959 adapter->wapi_info.wapi_mode = 1;
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018960 hdd_debug("WAPI MODE IS %u", adapter->wapi_info.wapi_mode);
Abhinav Kumarf56c81f2018-06-06 16:07:01 +053018961 /* genie is pointing to data field of WAPI IE's buffer */
18962 tmp = (uint8_t *)genie;
18963 /* Validate length for Version(2 bytes) and Number
18964 * of AKM suite (2 bytes) in WAPI IE buffer, coming from
18965 * supplicant*/
18966 if (eLen < 4) {
18967 hdd_err("Invalid IE Len: %u", eLen);
18968 return -EINVAL;
18969 }
18970 tmp = tmp + 2; /* Skip Version */
tinlin8a44b642018-04-25 13:56:06 +080018971 /* Get the number of AKM suite */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018972 akmsuiteCount = WPA_GET_LE16(tmp);
tinlin8a44b642018-04-25 13:56:06 +080018973 /* Skip the number of AKM suite */
18974 tmp = tmp + 2;
Abhinav Kumarf56c81f2018-06-06 16:07:01 +053018975 /* Validate total length for WAPI IE's buffer */
18976 if (eLen < (4 + (akmsuiteCount * sizeof(uint32_t)))) {
18977 hdd_err("Invalid IE Len: %u", eLen);
18978 return -EINVAL;
18979 }
tinlin8a44b642018-04-25 13:56:06 +080018980 /* AKM suite list, each OUI contains 4 bytes */
18981 akmlist = (uint32_t *)(tmp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018982 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
Vignesh Viswanathan845bd472018-06-11 18:45:45 +053018983 qdf_mem_copy(akmsuite, akmlist,
18984 sizeof(uint32_t) * akmsuiteCount);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018985 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018986 hdd_err("Invalid akmSuite count: %u",
18987 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018988 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018989 return -EINVAL;
18990 }
18991
18992 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018993 hdd_debug("WAPI AUTH MODE SET TO PSK");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018994 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018995 WAPI_AUTH_MODE_PSK;
18996 }
18997 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018998 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018999 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019000 WAPI_AUTH_MODE_CERT;
19001 }
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080019002
19003 hdd_set_crypto_key_mgmt_param(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019004 break;
19005#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019006 case DOT11F_EID_SUPPOPERATINGCLASSES:
19007 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019008 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019009 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019010 genie - 2, eLen + 2);
19011 if (status)
19012 return status;
19013 break;
19014 }
Srinivas Girigowda61771262019-04-01 11:55:19 -070019015 case WLAN_REQUEST_IE_MAX_LEN:
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019016 {
19017 if (genie[0] == SIR_FILS_HLP_EXT_EID) {
19018 hdd_debug("Set HLP EXT IE(len %d)",
19019 eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019020 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019021 genie - 2, eLen + 2,
19022 true);
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019023 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070019024 adapter, genie - 2,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019025 eLen + 2);
19026 if (status)
19027 return status;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053019028 } else if (genie[0] ==
19029 SIR_DH_PARAMETER_ELEMENT_EXT_EID) {
19030 hdd_debug("Set DH EXT IE(len %d)",
19031 eLen + 2);
19032 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070019033 adapter, genie - 2,
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053019034 eLen + 2);
19035 if (status)
19036 return status;
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019037 } else {
19038 hdd_err("UNKNOWN EID: %X", genie[0]);
19039 }
19040 break;
19041 }
19042 case DOT11F_EID_FRAGMENT_IE:
19043 {
19044 hdd_debug("Set Fragment IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019045 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019046 genie - 2, eLen + 2,
19047 false);
Jeff Johnson20227a92018-03-13 09:41:05 -070019048 status = wlan_hdd_add_assoc_ie(adapter,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019049 genie - 2, eLen + 2);
19050 if (status)
19051 return status;
19052 break;
19053 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019054 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019055 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080019056 /* when Unknown IE is received we break
19057 * and continue to the next IE in the buffer
19058 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019059 break;
19060 }
19061 genie += eLen;
19062 remLen -= eLen;
19063 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019064 return 0;
19065}
19066
Abhishek Ambure68677462019-09-13 12:44:26 +053019067#ifdef QCA_IBSS_SUPPORT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019068/**
19069 * hdd_is_wpaie_present() - check for WPA ie
19070 * @ie: Pointer to ie
19071 * @ie_len: Ie length
19072 *
19073 * Parse the received IE to find the WPA IE
19074 *
19075 * Return: true if wpa ie is found else false
19076 */
19077static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
19078{
19079 uint8_t eLen = 0;
19080 uint16_t remLen = ie_len;
19081 uint8_t elementId = 0;
19082
19083 while (remLen >= 2) {
19084 elementId = *ie++;
19085 eLen = *ie++;
19086 remLen -= 2;
19087 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019088 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019089 return false;
19090 }
19091 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
19092 /* OUI - 0x00 0X50 0XF2
19093 * WPA Information Element - 0x01
19094 * WPA version - 0x01
19095 */
19096 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
19097 return true;
19098 }
19099 ie += eLen;
19100 remLen -= eLen;
19101 }
19102 return false;
19103}
19104
Abhishek Ambure68677462019-09-13 12:44:26 +053019105/**
19106 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
19107 * @adapter: Pointer to adapter
19108 * @param: Pointer to IBSS parameters
19109 *
19110 * This function is used to initialize the security settings in IBSS mode
19111 *
19112 * Return: 0 for success, non-zero for failure
19113 */
19114static int wlan_hdd_cfg80211_set_privacy_ibss(struct hdd_adapter *adapter,
19115 struct cfg80211_ibss_params
19116 *params)
19117{
19118 uint32_t ret;
19119 int status = 0;
19120 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
19121 struct hdd_station_ctx *sta_ctx =
19122 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19123 struct csr_roam_profile *roam_profile;
19124
19125 hdd_enter();
19126
19127 sta_ctx->wpa_versions = 0;
19128 qdf_mem_zero(&sta_ctx->ibss_enc_key, sizeof(tCsrRoamSetKey));
19129 sta_ctx->ibss_enc_key_installed = 0;
19130
19131 if (params->ie_len && (params->ie)) {
19132 if (wlan_get_ie_ptr_from_eid(WLAN_EID_RSN, params->ie,
19133 params->ie_len)) {
19134 sta_ctx->wpa_versions = NL80211_WPA_VERSION_2;
19135 encryptionType = eCSR_ENCRYPT_TYPE_AES;
19136 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
19137 tDot11fIEWPA dot11_wpa_ie;
19138 mac_handle_t mac_handle =
19139 hdd_adapter_get_mac_handle(adapter);
19140 const u8 *ie;
19141
19142 memset(&dot11_wpa_ie, 0, sizeof(dot11_wpa_ie));
19143 ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_WPA,
19144 params->ie, params->ie_len);
19145 if (ie) {
19146 sta_ctx->wpa_versions = NL80211_WPA_VERSION_1;
19147 /* Unpack the WPA IE
19148 * Skip past the EID byte and length byte
19149 * and four byte WiFi OUI
19150 */
19151 if (ie[1] < DOT11F_IE_WPA_MIN_LEN ||
19152 ie[1] > DOT11F_IE_WPA_MAX_LEN) {
19153 hdd_err("invalid ie len:%d", ie[1]);
19154 return -EINVAL;
19155 }
19156 ret = dot11f_unpack_ie_wpa(
19157 MAC_CONTEXT(mac_handle),
19158 (uint8_t *)&ie[2 + 4],
19159 ie[1] - 4, &dot11_wpa_ie, false);
19160 if (DOT11F_FAILED(ret)) {
19161 hdd_err("unpack failed ret: 0x%x", ret);
19162 return -EINVAL;
19163 }
19164 /*
19165 * Extract the multicast cipher, the
19166 * encType for unicast cipher for
19167 * wpa-none is none
19168 */
19169 encryptionType =
19170 hdd_translate_wpa_to_csr_encryption_type
19171 (dot11_wpa_ie.multicast_cipher);
19172 }
19173 }
19174
19175 status =
19176 wlan_hdd_cfg80211_set_ie(adapter, params->ie,
19177 params->ie_len);
19178
19179 if (0 > status) {
19180 hdd_err("Failed to parse WPA/RSN IE");
19181 return status;
19182 }
19183 }
19184
19185 roam_profile = hdd_roam_profile(adapter);
19186 roam_profile->AuthType.authType[0] =
19187 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM;
19188
19189 if (params->privacy) {
19190 /* Security enabled IBSS, At this time there is no information
19191 * available about the security parameters, so initialise the
19192 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
19193 * The correct security parameters will be updated later in
19194 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
19195 * set inorder enable privacy bit in beacons
19196 */
19197
19198 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
19199 }
19200 hdd_debug("encryptionType=%d", encryptionType);
19201 sta_ctx->conn_info.uc_encrypt_type = encryptionType;
19202 roam_profile->EncryptionType.numEntries = 1;
19203 roam_profile->EncryptionType.encryptionType[0] =
19204 encryptionType;
19205 return status;
19206}
19207
19208/**
19209 * __wlan_hdd_cfg80211_join_ibss() - join ibss
19210 * @wiphy: Pointer to wiphy
19211 * @dev: Pointer to network device
19212 * @param: Pointer to IBSS join parameters
19213 *
19214 * This function is used to create/join an IBSS network
19215 *
19216 * Return: 0 for success, non-zero for failure
19217 */
19218static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
19219 struct net_device *dev,
19220 struct cfg80211_ibss_params *params)
19221{
19222 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19223 struct csr_roam_profile *roam_profile;
19224 int status;
19225 struct hdd_station_ctx *sta_ctx =
19226 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19227 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
19228 struct qdf_mac_addr bssid;
19229 uint8_t channelNum = 0;
19230 mac_handle_t mac_handle;
19231 struct wlan_mlme_ibss_cfg ibss_cfg = {0};
19232 uint8_t conn_info_channel;
19233
19234 hdd_enter();
19235
19236 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19237 hdd_err("Command not allowed in FTM mode");
19238 return -EINVAL;
19239 }
19240
19241 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
19242 return -EINVAL;
19243
19244 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
19245 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
19246 adapter->vdev_id, adapter->device_mode);
19247
19248 hdd_debug("Device_mode %s(%d)",
19249 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
19250
19251 status = wlan_hdd_validate_context(hdd_ctx);
19252
19253 if (0 != status)
19254 return status;
19255
19256 if (QDF_IS_STATUS_ERROR(ucfg_mlme_get_ibss_cfg(hdd_ctx->psoc,
19257 &ibss_cfg))) {
19258 return -EINVAL;
19259 }
19260
19261 mac_handle = hdd_ctx->mac_handle;
19262 if (NULL !=
19263 params->chandef.chan) {
19264 uint32_t numChans = CFG_VALID_CHANNEL_LIST_LEN;
19265 uint32_t validChan[CFG_VALID_CHANNEL_LIST_LEN];
19266 int indx;
19267
19268 /* Get channel number */
19269 channelNum = ieee80211_frequency_to_channel(
19270 params->
19271 chandef.
19272 chan->
19273 center_freq);
19274 ucfg_mlme_get_valid_channel_freq_list(hdd_ctx->psoc, validChan,
19275 &numChans);
19276
19277 for (indx = 0; indx < numChans; indx++) {
19278 if (channelNum ==
19279 wlan_reg_freq_to_chan(hdd_ctx->pdev, validChan[indx]))
19280 break;
19281 }
19282 if (indx >= numChans) {
19283 hdd_err("Not valid Channel: %d", channelNum);
19284 return -EINVAL;
19285 }
19286 }
19287
19288 /* Disable NAN Discovery if enabled */
19289 ucfg_nan_disable_concurrency(hdd_ctx->psoc);
19290
19291 if (!policy_mgr_allow_concurrency(hdd_ctx->psoc,
19292 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
19293 hdd_err("This concurrency combination is not allowed");
19294 return -ECONNREFUSED;
19295 }
19296
19297 status = policy_mgr_reset_connection_update(hdd_ctx->psoc);
19298 if (!QDF_IS_STATUS_SUCCESS(status))
19299 hdd_err("qdf_reset_connection_update failed status: %d", status);
19300
19301 status = policy_mgr_current_connections_update(hdd_ctx->psoc,
19302 adapter->vdev_id, channelNum,
19303 POLICY_MGR_UPDATE_REASON_JOIN_IBSS);
19304 if (QDF_STATUS_E_FAILURE == status) {
19305 hdd_err("connections update failed!!");
19306 return -EINVAL;
19307 }
19308
19309 if (QDF_STATUS_SUCCESS == status) {
19310 status = policy_mgr_wait_for_connection_update(
19311 hdd_ctx->psoc);
19312 if (!QDF_IS_STATUS_SUCCESS(status)) {
19313 hdd_err("qdf wait for event failed!!");
19314 return -EINVAL;
19315 }
19316 }
19317
19318 /*Try disconnecting if already in connected state */
19319 status = wlan_hdd_try_disconnect(adapter);
19320 if (0 > status) {
19321 hdd_err("Failed to disconnect the existing IBSS connection");
19322 return -EALREADY;
19323 }
19324
19325 roam_profile = hdd_roam_profile(adapter);
19326
19327 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
19328 hdd_err("Interface type is not set to IBSS");
19329 return -EINVAL;
19330 }
19331
19332 /* enable selected protection checks in IBSS mode */
19333 roam_profile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
19334
19335 /* BSSID is provided by upper layers hence no need to AUTO generate */
19336 if (params->bssid) {
19337 if (ucfg_mlme_set_ibss_auto_bssid(hdd_ctx->psoc, 0)
19338 == QDF_STATUS_E_FAILURE) {
19339 hdd_err("Unable to update MLME IBSS Auto BSSID config");
19340 return -EIO;
19341 }
19342 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
19343 } else if (ibss_cfg.coalesing_enable == 0) {
19344 if (ucfg_mlme_set_ibss_auto_bssid(hdd_ctx->psoc, 0)
19345 == QDF_STATUS_E_FAILURE) {
19346 hdd_err("Unable to update MLME IBSS Auto BSSID config");
19347 return -EIO;
19348 }
19349 qdf_copy_macaddr(&bssid, &ibss_cfg.bssid);
19350 }
19351
19352 if (cfg_in_range(CFG_BEACON_INTERVAL, params->beacon_interval))
19353 roam_profile->beaconInterval = params->beacon_interval;
19354 else
19355 roam_profile->beaconInterval = cfg_get(hdd_ctx->psoc,
19356 CFG_BEACON_INTERVAL);
19357
19358 /* Set Channel */
19359 if (channelNum) {
19360 /* Set the Operational Channel */
19361 hdd_debug("set channel %d", channelNum);
19362 roam_profile->ChannelInfo.numOfChannels = 1;
19363 sta_ctx->conn_info.chan_freq =
19364 wlan_reg_chan_to_freq(hdd_ctx->pdev,
19365 channelNum);
19366 roam_profile->ChannelInfo.freq_list =
19367 &sta_ctx->conn_info.chan_freq;
19368 }
19369
19370 /* Initialize security parameters */
19371 status = wlan_hdd_cfg80211_set_privacy_ibss(adapter, params);
19372 if (status < 0) {
19373 hdd_err("failed to set security parameters");
19374 return status;
19375 }
19376
19377 conn_info_channel =
19378 wlan_reg_freq_to_chan(
19379 hdd_ctx->pdev,
19380 sta_ctx->conn_info.chan_freq);
19381 /* Issue connect start */
19382 status = wlan_hdd_cfg80211_connect_start(adapter, params->ssid,
19383 params->ssid_len,
19384 bssid.bytes, NULL,
19385 conn_info_channel,
19386 params->chandef.width);
19387
19388 if (0 > status) {
19389 hdd_err("connect failed");
19390 return status;
19391 }
19392 hdd_exit();
19393 return 0;
19394}
19395
19396/**
19397 * wlan_hdd_cfg80211_join_ibss() - join ibss
19398 * @wiphy: Pointer to wiphy
19399 * @dev: Pointer to network device
19400 * @param: Pointer to IBSS join parameters
19401 *
19402 * This function is used to create/join an IBSS network
19403 *
19404 * Return: 0 for success, non-zero for failure
19405 */
19406static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
19407 struct net_device *dev,
19408 struct cfg80211_ibss_params *params)
19409{
19410 int errno;
19411 struct osif_vdev_sync *vdev_sync;
19412
19413 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
19414 if (errno)
19415 return errno;
19416
19417 errno = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
19418
19419 osif_vdev_sync_op_stop(vdev_sync);
19420
19421 return errno;
19422}
19423
19424/**
19425 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
19426 * @wiphy: Pointer to wiphy
19427 * @dev: Pointer to network device
19428 *
19429 * This function is used to leave an IBSS network
19430 *
19431 * Return: 0 for success, non-zero for failure
19432 */
19433static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
19434 struct net_device *dev)
19435{
19436 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19437 struct csr_roam_profile *roam_profile;
19438 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
19439 int status;
19440 mac_handle_t mac_handle;
19441 unsigned long rc;
19442 tSirUpdateIE update_ie;
19443
19444 hdd_enter();
19445
19446 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19447 hdd_err("Command not allowed in FTM mode");
19448 return -EINVAL;
19449 }
19450
19451 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
19452 return -EINVAL;
19453
19454 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
19455 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
19456 adapter->vdev_id, eCSR_DISCONNECT_REASON_IBSS_LEAVE);
19457
19458 status = wlan_hdd_validate_context(hdd_ctx);
19459 if (0 != status)
19460 return status;
19461
19462 hdd_debug("Device_mode %s(%d)",
19463 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
19464
19465 roam_profile = hdd_roam_profile(adapter);
19466
19467 /* Issue disconnect only if interface type is set to IBSS */
19468 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
19469 hdd_err("BSS Type is not set to IBSS");
19470 return -EINVAL;
19471 }
19472 /* Clearing add IE of beacon */
19473 qdf_mem_copy(update_ie.bssid.bytes, adapter->mac_addr.bytes,
19474 sizeof(tSirMacAddr));
19475 update_ie.smeSessionId = adapter->vdev_id;
19476 update_ie.ieBufferlength = 0;
19477 update_ie.pAdditionIEBuffer = NULL;
19478 update_ie.append = true;
19479 update_ie.notify = true;
19480 mac_handle = hdd_ctx->mac_handle;
19481 if (sme_update_add_ie(mac_handle,
19482 &update_ie,
19483 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
19484 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
19485 }
19486
19487 /* Reset WNI_CFG_PROBE_RSP Flags */
19488 wlan_hdd_reset_prob_rspies(adapter);
19489
19490 /* Issue Disconnect request */
19491 INIT_COMPLETION(adapter->disconnect_comp_var);
19492 status = sme_roam_disconnect(mac_handle,
19493 adapter->vdev_id,
19494 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
19495 if (!QDF_IS_STATUS_SUCCESS(status)) {
19496 hdd_err("sme_roam_disconnect failed status: %d",
19497 status);
19498 return -EAGAIN;
19499 }
19500
19501 /* wait for mc thread to cleanup and then return to upper stack
19502 * so by the time upper layer calls the change interface, we are
19503 * all set to proceed further
19504 */
19505 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
19506 msecs_to_jiffies(SME_DISCONNECT_TIMEOUT));
19507 if (!rc) {
19508 hdd_err("Failed to disconnect, timed out");
19509 return -ETIMEDOUT;
19510 }
19511
19512 hdd_exit();
19513 return 0;
19514}
19515
19516/**
19517 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
19518 * @wiphy: Pointer to wiphy
19519 * @dev: Pointer to network device
19520 *
19521 * This function is used to leave an IBSS network
19522 *
19523 * Return: 0 for success, non-zero for failure
19524 */
19525static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
19526 struct net_device *dev)
19527{
19528 int errno;
19529 struct osif_vdev_sync *vdev_sync;
19530
19531 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
19532 if (errno)
19533 return errno;
19534
19535 errno = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
19536
19537 osif_vdev_sync_op_stop(vdev_sync);
19538
19539 return errno;
19540}
19541#else
19542/**
19543 * wlan_hdd_cfg80211_join_ibss() - join ibss
19544 * @wiphy: Pointer to wiphy
19545 * @dev: Pointer to network device
19546 * @param: Pointer to IBSS join parameters
19547 *
19548 * This function is dummy
19549 *
19550 * Return: 0
19551 */
19552static inline int
19553wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
19554 struct net_device *dev,
19555 struct cfg80211_ibss_params *params)
19556{
19557 return 0;
19558}
19559
19560/**
19561 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
19562 * @wiphy: Pointer to wiphy
19563 * @dev: Pointer to network device
19564 *
19565 * This function is dummy
19566 *
19567 * Return: 0
19568 */
19569static inline int
19570wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
19571 struct net_device *dev)
19572{
19573 return 0;
19574}
19575#endif
19576
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019577#ifdef CRYPTO_SET_KEY_CONVERGED
19578static void wlan_hdd_cfg80211_store_wep_key(struct hdd_adapter *adapter,
19579 struct wlan_objmgr_vdev *vdev,
19580 struct cfg80211_connect_params *req)
19581{
19582 struct key_params params;
19583
19584 qdf_mem_zero(&params, sizeof(params));
19585 params.cipher = req->crypto.ciphers_pairwise[0];
19586 params.key_len = req->key_len;
19587 params.key = req->key;
19588 wlan_cfg80211_store_key(vdev, req->key_idx,
19589 WLAN_CRYPTO_KEY_TYPE_UNICAST,
19590 NULL, &params);
19591}
19592#else
19593static void wlan_hdd_cfg80211_store_wep_key(struct hdd_adapter *adapter,
19594 struct wlan_objmgr_vdev *vdev,
19595 struct cfg80211_connect_params *req)
19596{
19597 struct csr_roam_profile *roam_profile;
19598
19599 roam_profile = hdd_roam_profile(adapter);
19600 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
19601 req->key_idx, req->key_len);
19602 qdf_mem_copy(&roam_profile->Keys.KeyMaterial[req->key_idx][0],
19603 req->key, req->key_len);
19604 roam_profile->Keys.KeyLength[req->key_idx] = req->key_len;
19605 roam_profile->Keys.defaultIndex = req->key_idx;
19606}
19607#endif /* !CRYPTO_SET_KEY_CONVERGED */
19608
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070019609/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019610 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019611 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019612 * @req: Pointer to security parameters
19613 *
19614 * Return: 0 for success, non-zero for failure
19615 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019616static int wlan_hdd_cfg80211_set_privacy(struct hdd_adapter *adapter,
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070019617 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019618{
19619 int status = 0;
Jeff Johnsonce4a8342017-10-14 13:12:22 -070019620 struct hdd_station_ctx *sta_ctx;
Jeff Johnson20227a92018-03-13 09:41:05 -070019621 struct csr_roam_profile *roam_profile;
Min Liu8c5d99e2018-09-10 17:18:44 +080019622 struct wlan_objmgr_vdev *vdev;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019623
Dustin Brown491d54b2018-03-14 12:39:11 -070019624 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019625
Jeff Johnsonce4a8342017-10-14 13:12:22 -070019626 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19627 sta_ctx->wpa_versions = req->crypto.wpa_versions;
19628 hdd_debug("set wpa version to %d", sta_ctx->wpa_versions);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019629
Jeff Johnson20227a92018-03-13 09:41:05 -070019630 roam_profile = hdd_roam_profile(adapter);
19631
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070019632 /* populate auth,akm and cipher params for crypto */
Min Liu8c5d99e2018-09-10 17:18:44 +080019633 vdev = hdd_objmgr_get_vdev(adapter);
19634 if (!vdev)
19635 return -EINVAL;
19636 hdd_populate_crypto_params(vdev, req);
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070019637
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019638 /*set authentication type */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019639 status = wlan_hdd_cfg80211_set_auth_type(adapter, req->auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019640
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070019641 if (wlan_hdd_is_conn_type_fils(req)) {
19642 status = wlan_hdd_cfg80211_set_fils_config(adapter, req);
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053019643
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070019644 if (0 > status) {
19645 hdd_err("Failed to set fils config");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019646 goto release_vdev_ref;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070019647 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019648 }
19649
19650 /*set key mgmt type */
19651 if (req->crypto.n_akm_suites) {
19652 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019653 wlan_hdd_set_akm_suite(adapter, req->crypto.akm_suites[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019654 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019655 hdd_err("Failed to set akm suite");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019656 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019657 }
19658 }
19659
19660 /*set pairwise cipher type */
19661 if (req->crypto.n_ciphers_pairwise) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019662 status = wlan_hdd_cfg80211_set_cipher(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019663 req->crypto.
19664 ciphers_pairwise[0],
19665 true);
19666 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019667 hdd_err("Failed to set unicast cipher type");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019668 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019669 }
19670 } else {
19671 /*Reset previous cipher suite to none */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019672 status = wlan_hdd_cfg80211_set_cipher(adapter, 0, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019673 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019674 hdd_err("Failed to set unicast cipher type");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019675 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019676 }
19677 }
19678
19679 /*set group cipher type */
19680 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019681 wlan_hdd_cfg80211_set_cipher(adapter, req->crypto.cipher_group,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019682 false);
19683
19684 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019685 hdd_err("Failed to set mcast cipher type");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019686 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019687 }
19688#ifdef WLAN_FEATURE_11W
Jeff Johnson20227a92018-03-13 09:41:05 -070019689 roam_profile->MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019690#endif
19691
19692 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
19693 if (req->ie_len) {
19694 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019695 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019696 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019697 hdd_err("Failed to parse the WPA/RSN IE");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019698 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019699 }
19700 }
19701
19702 /*incase of WEP set default key information */
19703 if (req->key && req->key_len) {
Jeff Johnson37ecea42018-03-18 17:54:40 -070019704 u32 cipher = req->crypto.ciphers_pairwise[0];
Jeff Johnson68755312017-02-10 11:46:55 -080019705
Jeff Johnson37ecea42018-03-18 17:54:40 -070019706 if ((WLAN_CIPHER_SUITE_WEP40 == cipher) ||
19707 (WLAN_CIPHER_SUITE_WEP104 == cipher)) {
19708 enum hdd_auth_key_mgmt key_mgmt =
19709 sta_ctx->auth_key_mgmt;
19710
19711 if (key_mgmt & HDD_AUTH_KEY_MGMT_802_1X) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019712 hdd_err("Dynamic WEP not supported");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019713 status = -EOPNOTSUPP;
19714 goto release_vdev_ref;
Jeff Johnson68755312017-02-10 11:46:55 -080019715 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019716
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019717 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
19718 req->key_len) && (CSR_MAX_NUM_KEY > req->key_idx))
19719 wlan_hdd_cfg80211_store_wep_key(adapter,
19720 vdev, req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019721 }
19722 }
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019723release_vdev_ref:
19724 hdd_objmgr_put_vdev(vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019725
19726 return status;
19727}
19728
wadesongcaad7c72018-08-06 13:26:27 +080019729/**
19730 * wlan_hdd_clear_wapi_privacy() - reset WAPI settings in HDD layer
19731 * @adapter: pointer to HDD adapter object
19732 *
19733 * This function resets all WAPI related parameters imposed before STA
19734 * connection starts. It's invoked when privacy checking against concurrency
19735 * fails, to make sure no improper WAPI settings are still populated before
19736 * returning an error to the upper layer requester.
19737 *
19738 * Return: none
19739 */
19740#ifdef FEATURE_WLAN_WAPI
19741static inline void wlan_hdd_clear_wapi_privacy(struct hdd_adapter *adapter)
19742{
19743 adapter->wapi_info.wapi_mode = 0;
19744 adapter->wapi_info.wapi_auth_mode = WAPI_AUTH_MODE_OPEN;
19745}
19746#else
19747static inline void wlan_hdd_clear_wapi_privacy(struct hdd_adapter *adapter)
19748{
19749}
19750#endif
19751
19752/**
19753 * wlan_hdd_cfg80211_clear_privacy() - reset STA security parameters
19754 * @adapter: pointer to HDD adapter object
19755 *
19756 * This function resets all privacy related parameters imposed
19757 * before STA connection starts. It's invoked when privacy checking
19758 * against concurrency fails, to make sure no improper settings are
19759 * still populated before returning an error to the upper layer requester.
19760 *
19761 * Return: none
19762 */
19763static void wlan_hdd_cfg80211_clear_privacy(struct hdd_adapter *adapter)
19764{
19765 struct hdd_station_ctx *hdd_sta_ctx =
19766 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19767
19768 hdd_debug("resetting all privacy configurations");
19769
19770 hdd_sta_ctx->wpa_versions = 0;
19771
Jeff Johnson96e33512019-02-27 15:10:21 -080019772 hdd_sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_NONE;
wadesongcaad7c72018-08-06 13:26:27 +080019773 hdd_sta_ctx->roam_profile.AuthType.authType[0] = eCSR_AUTH_TYPE_NONE;
19774
Jeff Johnsonb1959842019-02-27 13:04:04 -080019775 hdd_sta_ctx->conn_info.uc_encrypt_type = eCSR_ENCRYPT_TYPE_NONE;
wadesongcaad7c72018-08-06 13:26:27 +080019776 hdd_sta_ctx->roam_profile.EncryptionType.numEntries = 0;
Jeff Johnsonb1959842019-02-27 13:04:04 -080019777 hdd_sta_ctx->conn_info.mc_encrypt_type = eCSR_ENCRYPT_TYPE_NONE;
wadesongcaad7c72018-08-06 13:26:27 +080019778 hdd_sta_ctx->roam_profile.mcEncryptionType.numEntries = 0;
19779
19780 wlan_hdd_clear_wapi_privacy(adapter);
19781}
19782
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019783int wlan_hdd_try_disconnect(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019784{
19785 unsigned long rc;
Jeff Johnsond377dce2017-10-04 10:32:42 -070019786 struct hdd_station_ctx *sta_ctx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019787 int status, result = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019788 mac_handle_t mac_handle;
Abhishek Singhd1f21c72019-01-21 15:16:34 +053019789 uint32_t wait_time = SME_DISCONNECT_TIMEOUT;
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053019790 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019791
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053019792 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsond377dce2017-10-04 10:32:42 -070019793 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019794 mac_handle = hdd_adapter_get_mac_handle(adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019795 if (adapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019796 hdd_debug("Stop firmware roaming");
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019797 sme_stop_roaming(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019798 eCsrForcedDisassoc);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019799
Abhishek Singh533c9da2017-05-04 10:23:34 +053019800 /*
19801 * If firmware has already started roaming process, driver
19802 * needs to wait for processing of this disconnect request.
19803 *
19804 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019805 INIT_COMPLETION(adapter->roaming_comp_var);
nakul kachhwaha5913f352019-05-08 17:11:58 +053019806 if (hdd_is_roaming_in_progress(hdd_ctx) ||
19807 sme_neighbor_middle_of_roaming(mac_handle,
19808 adapter->vdev_id)) {
Abhishek Singh533c9da2017-05-04 10:23:34 +053019809 rc = wait_for_completion_timeout(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019810 &adapter->roaming_comp_var,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019811 msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));
19812 if (!rc) {
Jeff Johnson55d2ab42019-03-06 11:43:49 -080019813 hdd_err("roaming comp var timed out vdev id: %d",
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019814 adapter->vdev_id);
Abhishek Singh533c9da2017-05-04 10:23:34 +053019815 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019816 if (adapter->roam_ho_fail) {
19817 INIT_COMPLETION(adapter->disconnect_comp_var);
19818 hdd_conn_set_connection_state(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019819 eConnectionState_Disconnecting);
19820 }
19821 }
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019822 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019823
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019824 if ((QDF_IBSS_MODE == adapter->device_mode) ||
Jeff Johnsone7951512019-02-27 10:02:51 -080019825 (eConnectionState_Associated == sta_ctx->conn_info.conn_state) ||
19826 (eConnectionState_Connecting == sta_ctx->conn_info.conn_state) ||
19827 (eConnectionState_IbssConnected == sta_ctx->conn_info.conn_state)) {
Abhishek Singh0edeba02018-06-05 10:04:08 +053019828 eConnectionState prev_conn_state;
19829
Jeff Johnsone7951512019-02-27 10:02:51 -080019830 prev_conn_state = sta_ctx->conn_info.conn_state;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019831 hdd_conn_set_connection_state(adapter,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019832 eConnectionState_Disconnecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019833 /* Issue disconnect to CSR */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019834 INIT_COMPLETION(adapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019835
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019836 status = sme_roam_disconnect(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019837 adapter->vdev_id,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019838 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Abhishek Singh0edeba02018-06-05 10:04:08 +053019839
19840 if ((status == QDF_STATUS_CMD_NOT_QUEUED) &&
19841 prev_conn_state != eConnectionState_Connecting) {
19842 hdd_debug("Already disconnect in progress");
19843 result = 0;
19844 /*
19845 * Wait here instead of returning directly. This will
19846 * block the connect command and allow processing
19847 * of the disconnect in SME. As disconnect is already
19848 * in progress, wait here for 1 sec instead of 5 sec.
19849 */
19850 wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS;
19851 } else if (status == QDF_STATUS_CMD_NOT_QUEUED) {
19852 /*
19853 * Wait here instead of returning directly, this will
19854 * block the connect command and allow processing
19855 * of the scan for ssid and the previous connect command
19856 * in CSR.
19857 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019858 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019859 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019860 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019861 (int)status);
Jeff Johnson8380f232017-10-25 12:39:44 -070019862 sta_ctx->sta_debug_state = status;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019863 result = -EINVAL;
19864 goto disconnected;
19865 }
19866
Abhishek Singh0edeba02018-06-05 10:04:08 +053019867 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
19868 msecs_to_jiffies(wait_time));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019869 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson55d2ab42019-03-06 11:43:49 -080019870 hdd_err("Sme disconnect event timed out vdev id: %d sta_debug_state: %d",
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019871 adapter->vdev_id, sta_ctx->sta_debug_state);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019872 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019873 }
19874 } else if (eConnectionState_Disconnecting ==
Jeff Johnsone7951512019-02-27 10:02:51 -080019875 sta_ctx->conn_info.conn_state) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019876 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Abhishek Singh0edeba02018-06-05 10:04:08 +053019877 msecs_to_jiffies(wait_time));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019878 if (!rc) {
Jeff Johnson55d2ab42019-03-06 11:43:49 -080019879 hdd_err("Disconnect event timed out vdev id: %d sta_debug_state: %d",
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019880 adapter->vdev_id, sta_ctx->sta_debug_state);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019881 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019882 }
19883 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019884disconnected:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019885 hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019886 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019887}
19888
19889/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019890 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
19891 * @adapter: Pointer to the HDD adapter
19892 * @req: Pointer to the structure cfg_connect_params receieved from user space
19893 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053019894 * This function will start reassociation if prev_bssid is set and bssid/
19895 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019896 *
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019897 * Return: 0 if connect was for ReAssociation, non-zero error code otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019898 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053019899#if defined(CFG80211_CONNECT_PREV_BSSID) || \
19900 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019901static int wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
19902 struct cfg80211_connect_params *req)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019903{
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019904 int status = -EINVAL;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053019905 const uint8_t *bssid = NULL;
19906 uint16_t channel = 0;
Jeff Johnson731bc322017-10-14 19:53:44 -070019907 struct hdd_station_ctx *sta_ctx;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053019908
19909 if (req->bssid)
19910 bssid = req->bssid;
19911 else if (req->bssid_hint)
19912 bssid = req->bssid_hint;
19913
19914 if (req->channel)
19915 channel = req->channel->hw_value;
19916 else if (req->channel_hint)
19917 channel = req->channel_hint->hw_value;
19918
19919 if (bssid && channel && req->prev_bssid) {
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070019920 hdd_debug("REASSOC Attempt on channel %d to " QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070019921 channel, QDF_MAC_ADDR_ARRAY(bssid));
Arif Hussain43354e62017-05-24 11:24:25 -070019922 /*
19923 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070019924 * roam_profile's BSSID is getting zeroed out in the
Arif Hussain43354e62017-05-24 11:24:25 -070019925 * association process. In case of join failure
19926 * we should send valid BSSID to supplicant
19927 */
Jeff Johnson731bc322017-10-14 19:53:44 -070019928 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19929 qdf_mem_copy(sta_ctx->requested_bssid.bytes, bssid,
Arif Hussain43354e62017-05-24 11:24:25 -070019930 QDF_MAC_ADDR_SIZE);
19931
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019932 status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019933 CONNECT_CMD_USERSPACE);
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019934 hdd_debug("hdd_reassoc: status: %d", status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019935 }
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019936 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019937}
19938#else
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019939static int wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
19940 struct cfg80211_connect_params *req)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019941{
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019942 return -ENOTSUPP;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019943}
19944#endif
19945
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019946
19947/**
19948 * wlan_hdd_check_ht20_ht40_ind() - check if Supplicant has indicated to
19949 * connect in HT20 mode
19950 * @hdd_ctx: hdd context
19951 * @adapter: Pointer to the HDD adapter
19952 * @req: Pointer to the structure cfg_connect_params receieved from user space
19953 *
19954 * This function will check if supplicant has indicated to to connect in HT20
19955 * mode. this is currently applicable only for 2.4Ghz mode only.
19956 * if feature is enabled and supplicant indicate HT20 set
19957 * force_24ghz_in_ht20 to true to force 2.4Ghz in HT20 else set it to false.
19958 *
19959 * Return: void
19960 */
19961#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
Jeff Johnson20227a92018-03-13 09:41:05 -070019962static void
19963wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
19964 struct hdd_adapter *adapter,
19965 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019966{
Jeff Johnson61b5e982018-03-15 11:33:31 -070019967 struct csr_roam_profile *roam_profile;
Wu Gaofc81ecf2018-11-22 11:38:41 +080019968 bool is_override_ht20_40_24g;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019969
Jeff Johnson20227a92018-03-13 09:41:05 -070019970 roam_profile = hdd_roam_profile(adapter);
19971
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019972 roam_profile->force_24ghz_in_ht20 = false;
19973
Wu Gaofc81ecf2018-11-22 11:38:41 +080019974 ucfg_mlme_is_override_ht20_40_24g(hdd_ctx->psoc,
19975 &is_override_ht20_40_24g);
19976 if (is_override_ht20_40_24g &&
Jeff Johnson20227a92018-03-13 09:41:05 -070019977 !(req->ht_capa.cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019978 roam_profile->force_24ghz_in_ht20 = true;
19979
19980 hdd_debug("req->ht_capa.cap_info %x override_ht20_40_24g %d",
19981 req->ht_capa.cap_info,
Wu Gaofc81ecf2018-11-22 11:38:41 +080019982 is_override_ht20_40_24g);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019983}
19984#else
Jeff Johnson20227a92018-03-13 09:41:05 -070019985static inline void
19986wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
19987 struct hdd_adapter *adapter,
19988 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019989{
Jeff Johnson61b5e982018-03-15 11:33:31 -070019990 struct csr_roam_profile *roam_profile;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019991
Jeff Johnson20227a92018-03-13 09:41:05 -070019992 roam_profile = hdd_roam_profile(adapter);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019993
19994 roam_profile->force_24ghz_in_ht20 = false;
19995}
19996#endif
19997
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019998/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019999 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
20000 * @wiphy: Pointer to wiphy
20001 * @dev: Pointer to network device
20002 * @req: Pointer to cfg80211 connect request
20003 *
20004 * This function is used to start the association process
20005 *
20006 * Return: 0 for success, non-zero for failure
20007 */
20008static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
20009 struct net_device *ndev,
20010 struct cfg80211_connect_params *req)
20011{
20012 int status;
Manikandan Mohan956b69e2019-02-14 13:08:14 -080020013 u16 channel, sap_cnt, sta_cnt;
Arif Hussainee677012017-01-26 17:50:13 -080020014 const u8 *bssid = NULL;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053020015#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
20016 const u8 *bssid_hint = req->bssid_hint;
20017#else
20018 const u8 *bssid_hint = NULL;
20019#endif
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020020 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020021 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020022
Dustin Brown491d54b2018-03-14 12:39:11 -070020023 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020024
Anurag Chouhan6d760662016-02-20 16:05:43 +053020025 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020026 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020027 return -EINVAL;
20028 }
20029
Jeff Johnson48363022019-02-24 16:26:51 -080020030 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020031 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020032
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020033 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
20034 TRACE_CODE_HDD_CFG80211_CONNECT,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020035 adapter->vdev_id, adapter->device_mode);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020036
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020037 hdd_debug("Device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070020038 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020039
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020040 if (adapter->device_mode != QDF_STA_MODE &&
Dustin Brown458027c2018-10-19 12:26:27 -070020041 adapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020042 hdd_err("Device_mode %s(%d) is not supported",
Dustin Brown458027c2018-10-19 12:26:27 -070020043 qdf_opmode_str(adapter->device_mode),
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020044 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020045 return -EINVAL;
20046 }
20047
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020048 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020049 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020050 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020051 return -EINVAL;
20052 }
20053
Jeff Johnsonb8944722017-09-03 09:03:19 -070020054 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020055 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020056 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020057
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020058 /*
20059 * Disable NAN Discovery if incoming connection is P2P or if a STA
Manikandan Mohan956b69e2019-02-14 13:08:14 -080020060 * connection already exists and if this is a case of STA+STA
20061 * or SAP+STA concurrency
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020062 */
Manikandan Mohan956b69e2019-02-14 13:08:14 -080020063 sta_cnt = policy_mgr_mode_specific_connection_count(hdd_ctx->psoc,
20064 PM_STA_MODE, NULL);
20065 sap_cnt = policy_mgr_mode_specific_connection_count(hdd_ctx->psoc,
20066 PM_SAP_MODE, NULL);
Nachiket Kukade089b9832018-12-12 16:38:17 +053020067
Manikandan Mohan956b69e2019-02-14 13:08:14 -080020068 if (adapter->device_mode == QDF_P2P_CLIENT_MODE || sap_cnt || sta_cnt) {
20069 hdd_debug("Invalid NAN concurrency. SAP: %d STA: %d P2P: %d",
20070 sap_cnt, sta_cnt,
20071 (adapter->device_mode == QDF_P2P_CLIENT_MODE));
20072 ucfg_nan_disable_concurrency(hdd_ctx->psoc);
20073 }
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020074 /*
20075 * STA+NDI concurrency gets preference over NDI+NDI. Disable
20076 * first NDI in case an NDI+NDI concurrency exists.
20077 */
Manikandan Mohana4405672019-09-11 12:34:49 -070020078 ucfg_nan_check_and_disable_unsupported_ndi(hdd_ctx->psoc, false);
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020079
Arif Hussainee677012017-01-26 17:50:13 -080020080 if (req->bssid)
20081 bssid = req->bssid;
20082 else if (bssid_hint)
20083 bssid = bssid_hint;
20084
Jeff Johnsonb8944722017-09-03 09:03:19 -070020085 if (bssid && hdd_get_adapter_by_macaddr(hdd_ctx, (uint8_t *)bssid)) {
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070020086 hdd_err("adapter exist with same mac address " QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070020087 QDF_MAC_ADDR_ARRAY(bssid));
Arif Hussain7631afa2017-02-08 14:35:00 -080020088 return -EINVAL;
Arif Hussainee677012017-01-26 17:50:13 -080020089 }
20090
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020091 /*
20092 * Check if this is reassoc to same bssid, if reassoc is success, return
20093 */
20094 status = wlan_hdd_reassoc_bssid_hint(adapter, req);
Padma, Santhosh Kumar41552782018-06-29 15:31:25 +053020095 if (!status) {
20096 hdd_set_roaming_in_progress(true);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020097 return status;
Padma, Santhosh Kumar41552782018-06-29 15:31:25 +053020098 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020099
Agrawal Ashishf156e942016-08-04 14:54:47 +053020100 /* Try disconnecting if already in connected state */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020101 status = wlan_hdd_try_disconnect(adapter);
Agrawal Ashishf156e942016-08-04 14:54:47 +053020102 if (0 > status) {
20103 hdd_err("Failed to disconnect the existing connection");
20104 return -EALREADY;
20105 }
20106
Liangwei Dong3fa5cba2018-07-16 06:41:55 -040020107 /*initialise security parameters */
20108 status = wlan_hdd_cfg80211_set_privacy(adapter, req);
20109
20110 if (status < 0) {
20111 hdd_err("Failed to set security params");
20112 return status;
20113 }
20114
20115 /*
20116 * Check for max concurrent connections after doing disconnect if any,
20117 * must be called after the invocation of wlan_hdd_cfg80211_set_privacy
20118 * so privacy is already set for the current adapter before it's
20119 * checked against concurrency.
20120 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020121 if (req->channel) {
Min Liuab6ed4f2018-01-09 13:13:57 +080020122 bool ok = false;
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053020123
20124 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
Dustin Brown76cd2932018-09-11 16:03:05 -070020125 hdd_ctx->psoc,
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053020126 req->channel->hw_value,
20127 &ok)) {
20128 hdd_warn("Unable to get channel:%d eligibility for DNBS",
20129 req->channel->hw_value);
20130 return -EINVAL;
20131 }
20132 /**
20133 * Send connection timedout, so that Android framework does not
20134 * blacklist us.
20135 */
20136 if (!ok) {
20137 struct ieee80211_channel *chan =
Dustin Brown2eb1e452017-08-15 12:40:34 -070020138 ieee80211_get_channel(wiphy,
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053020139 wlan_chan_to_freq(req->channel->hw_value));
20140 struct cfg80211_bss *bss;
20141
20142 hdd_warn("Channel:%d not OK for DNBS",
20143 req->channel->hw_value);
20144 if (chan) {
Abhishek Singh59cdca12019-03-08 13:48:20 +053020145 bss = wlan_cfg80211_get_bss(wiphy, chan,
20146 req->bssid,
20147 req->ssid,
20148 req->ssid_len);
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053020149 if (bss) {
20150 cfg80211_assoc_timeout(ndev, bss);
20151 return -ETIMEDOUT;
20152 }
20153 }
20154 return -EINVAL;
20155 }
20156
Dustin Brown76cd2932018-09-11 16:03:05 -070020157 if (!policy_mgr_allow_concurrency(hdd_ctx->psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080020158 policy_mgr_convert_device_mode_to_qdf_type(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020159 adapter->device_mode),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020160 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020161 hdd_warn("This concurrency combination is not allowed");
wadesongcaad7c72018-08-06 13:26:27 +080020162 status = -ECONNREFUSED;
20163 goto con_chk_failed;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020164 }
20165 } else {
Dustin Brown76cd2932018-09-11 16:03:05 -070020166 if (!policy_mgr_allow_concurrency(hdd_ctx->psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080020167 policy_mgr_convert_device_mode_to_qdf_type(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020168 adapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020169 hdd_warn("This concurrency combination is not allowed");
wadesongcaad7c72018-08-06 13:26:27 +080020170 status = -ECONNREFUSED;
20171 goto con_chk_failed;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020172 }
20173 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020174
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053020175 if (req->channel)
20176 channel = req->channel->hw_value;
20177 else
20178 channel = 0;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020179
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020180 wlan_hdd_check_ht20_ht40_ind(hdd_ctx, adapter, req);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020181
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020182 status = wlan_hdd_cfg80211_connect_start(adapter, req->ssid,
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053020183 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070020184 bssid_hint, channel, 0);
Srinivas Girigowdad2412882018-09-07 15:42:04 -070020185 if (0 > status)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020186 hdd_err("connect failed");
Srinivas Girigowdad2412882018-09-07 15:42:04 -070020187
wadesongcaad7c72018-08-06 13:26:27 +080020188 return status;
20189
20190con_chk_failed:
20191 wlan_hdd_cfg80211_clear_privacy(adapter);
Dustin Browne74003f2018-03-14 12:51:58 -070020192 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020193 return status;
20194}
20195
20196/**
20197 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
20198 * @wiphy: Pointer to wiphy
20199 * @dev: Pointer to network device
20200 * @req: Pointer to cfg80211 connect request
20201 *
20202 * Return: 0 for success, non-zero for failure
20203 */
20204static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
20205 struct net_device *ndev,
20206 struct cfg80211_connect_params *req)
20207{
Dustin Brown1d31b082018-11-22 14:41:20 +053020208 int errno;
20209 struct osif_vdev_sync *vdev_sync;
20210
20211 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
20212 if (errno)
20213 return errno;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020214
Dustin Brown1d31b082018-11-22 14:41:20 +053020215 errno = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020216
Dustin Brown1d31b082018-11-22 14:41:20 +053020217 osif_vdev_sync_op_stop(vdev_sync);
20218
20219 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020220}
20221
Himanshu Agarwal6c3607a2018-01-12 12:04:19 +053020222int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020223{
Dundi Ravitejacc95c562018-07-27 12:30:24 +053020224 QDF_STATUS status;
20225 int result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020226 unsigned long rc;
Jeff Johnsond377dce2017-10-04 10:32:42 -070020227 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020228 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053020229 eConnectionState prev_conn_state;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070020230 mac_handle_t mac_handle;
Abhishek Singhd1f21c72019-01-21 15:16:34 +053020231 uint32_t wait_time = SME_DISCONNECT_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020232
Dustin Brown491d54b2018-03-14 12:39:11 -070020233 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020234
Jeff Johnson34fc63a2018-06-14 10:10:02 -070020235 mac_handle = hdd_ctx->mac_handle;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020236 if (adapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020237 hdd_debug("Stop firmware roaming");
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020238 status = sme_stop_roaming(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070020239 eCsrForcedDisassoc);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080020240 /*
Abhishek Singh533c9da2017-05-04 10:23:34 +053020241 * If firmware has already started roaming process, driver
20242 * needs to wait for processing of this disconnect request.
20243 *
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080020244 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020245 INIT_COMPLETION(adapter->roaming_comp_var);
nakul kachhwaha8dbf4b52019-06-03 13:27:49 +053020246 if (hdd_is_roaming_in_progress(hdd_ctx) ||
20247 sme_neighbor_middle_of_roaming(mac_handle,
20248 adapter->vdev_id)) {
Abhishek Singh533c9da2017-05-04 10:23:34 +053020249 rc = wait_for_completion_timeout(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020250 &adapter->roaming_comp_var,
Abhishek Singh533c9da2017-05-04 10:23:34 +053020251 msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));
20252 if (!rc) {
Jeff Johnson55d2ab42019-03-06 11:43:49 -080020253 hdd_err("roaming comp var timed out vdev id: %d",
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020254 adapter->vdev_id);
Abhishek Singh533c9da2017-05-04 10:23:34 +053020255 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020256 if (adapter->roam_ho_fail) {
20257 INIT_COMPLETION(adapter->disconnect_comp_var);
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -070020258 hdd_debug("Disabling queues");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020259 wlan_hdd_netif_queue_control(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053020260 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
20261 WLAN_CONTROL_PATH);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020262 hdd_conn_set_connection_state(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053020263 eConnectionState_Disconnecting);
20264 goto wait_for_disconnect;
20265 }
20266 }
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080020267 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020268
Jeff Johnsone7951512019-02-27 10:02:51 -080020269 prev_conn_state = sta_ctx->conn_info.conn_state;
Srinivas Girigowda6598eea2017-07-06 19:26:19 -070020270 /*stop tx queues */
20271 hdd_info("Disabling queues");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020272 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053020273 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Jeff Johnsone7951512019-02-27 10:02:51 -080020274 hdd_debug("Set HDD conn_state to eConnectionState_Disconnecting");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020275 hdd_conn_set_connection_state(adapter, eConnectionState_Disconnecting);
Varun Reddy Yeturu9e0032c2017-07-12 18:39:59 -070020276
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020277 INIT_COMPLETION(adapter->disconnect_comp_var);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020278
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080020279 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020280
Jeff Johnson34fc63a2018-06-14 10:10:02 -070020281 status = sme_roam_disconnect(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020282 adapter->vdev_id, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053020283 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
20284 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020285 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053020286 result = 0;
Abhishek Singhe9706cc2017-10-12 17:25:06 +053020287 /*
20288 * Wait here instead of returning directly. This will block the
20289 * next connect command and allow processing of the disconnect
20290 * in SME else we might hit some race conditions leading to SME
20291 * and HDD out of sync. As disconnect is already in progress,
20292 * wait here for 1 sec instead of 5 sec.
20293 */
20294 wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS;
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053020295 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
20296 /*
20297 * Wait here instead of returning directly, this will block the
20298 * next connect command and allow processing of the scan for
20299 * ssid and the previous connect command in CSR. Else we might
20300 * hit some race conditions leading to SME and HDD out of sync.
20301 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020302 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020303 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020304 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Jeff Johnson8380f232017-10-25 12:39:44 -070020305 sta_ctx->sta_debug_state = status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020306 result = -EINVAL;
20307 goto disconnected;
20308 }
Abhishek Singh533c9da2017-05-04 10:23:34 +053020309wait_for_disconnect:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020310 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Abhishek Singhe9706cc2017-10-12 17:25:06 +053020311 msecs_to_jiffies(wait_time));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020312
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020313 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020314 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020315 result = -ETIMEDOUT;
20316 }
20317disconnected:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020318 hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020319#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
20320 /* Sending disconnect event to userspace for kernel version < 3.11
20321 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
20322 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020323 hdd_debug("Send disconnected event to userspace");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020324 wlan_hdd_cfg80211_indicate_disconnect(adapter->dev, true,
Srinivas Dasarid4e87252019-07-01 15:35:52 +053020325 WLAN_REASON_UNSPECIFIED, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020326#endif
20327
20328 return result;
20329}
20330
20331/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080020332 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
20333 * @reason: ieee80211 reason code.
20334 *
20335 * This utility function helps log string conversion of reason code.
20336 *
20337 * Return: string conversion of reason code, if match found;
20338 * "Unknown" otherwise.
20339 */
20340static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
20341{
20342 switch (reason) {
20343 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
20344 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
20345 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
20346 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
20347 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
20348 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
20349 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
20350 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
20351 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
20352 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
20353 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
20354 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
20355 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
20356 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
20357 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
20358 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
20359 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
20360 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
20361 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
20362 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
20363 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
20364 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
20365 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
20366 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
20367 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
20368 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
20369 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
20370 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
20371 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
20372 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
20373 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
20374 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
20375 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
20376 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
20377 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
20378 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
20379 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
20380 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
20381 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
20382 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
20383 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
20384 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
20385 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
20386 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
20387 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
20388 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
20389 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
20390 default:
20391 return "Unknown";
20392 }
20393}
20394
20395/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020396 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
20397 * @wiphy: Pointer to wiphy
20398 * @dev: Pointer to network device
20399 * @reason: Disconnect reason code
20400 *
20401 * This function is used to issue a disconnect request to SME
20402 *
20403 * Return: 0 for success, non-zero for failure
20404 */
20405static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
20406 struct net_device *dev, u16 reason)
20407{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020408 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020409 int status;
Jeff Johnsond377dce2017-10-04 10:32:42 -070020410 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020411 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
20412 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Min Liu8c5d99e2018-09-10 17:18:44 +080020413 struct wlan_objmgr_vdev *vdev;
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053020414 bool enable_deauth_to_disassoc_map;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020415
Dustin Brown491d54b2018-03-14 12:39:11 -070020416 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020417
Anurag Chouhan6d760662016-02-20 16:05:43 +053020418 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020419 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020420 return -EINVAL;
20421 }
20422
Jeff Johnson48363022019-02-24 16:26:51 -080020423 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020424 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020425
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020426 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
20427 TRACE_CODE_HDD_CFG80211_DISCONNECT,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020428 adapter->vdev_id, reason);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020429
Srinivas Girigowda44cff5c2018-04-16 15:49:30 -070020430 hdd_print_netdev_txq_status(dev);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020431 hdd_debug("Device_mode %s(%d) reason code(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070020432 qdf_opmode_str(adapter->device_mode),
20433 adapter->device_mode, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020434
Jeff Johnsonb8944722017-09-03 09:03:19 -070020435 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020436
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020437 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020438 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020439
Alok Kumarb64650c2018-03-23 17:05:11 +053020440 qdf_mutex_acquire(&adapter->disconnection_status_lock);
20441 if (adapter->disconnection_in_progress) {
20442 qdf_mutex_release(&adapter->disconnection_status_lock);
20443 hdd_debug("Disconnect is already in progress");
20444 return 0;
20445 }
20446 adapter->disconnection_in_progress = true;
20447 qdf_mutex_release(&adapter->disconnection_status_lock);
20448
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020449 /* Issue disconnect request to SME, if station is in connected state */
Jeff Johnsone7951512019-02-27 10:02:51 -080020450 if ((sta_ctx->conn_info.conn_state == eConnectionState_Associated) ||
20451 (sta_ctx->conn_info.conn_state == eConnectionState_Connecting)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020452 eCsrRoamDisconnectReason reasonCode =
20453 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020454
20455 switch (reason) {
20456 case WLAN_REASON_MIC_FAILURE:
20457 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
20458 break;
20459
20460 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
20461 case WLAN_REASON_DISASSOC_AP_BUSY:
20462 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
20463 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
20464 break;
20465
20466 case WLAN_REASON_PREV_AUTH_NOT_VALID:
20467 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
20468 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
20469 break;
20470
20471 case WLAN_REASON_DEAUTH_LEAVING:
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053020472 status = ucfg_mlme_get_enable_deauth_to_disassoc_map(
20473 hdd_ctx->psoc,
20474 &enable_deauth_to_disassoc_map);
20475 if (QDF_IS_STATUS_ERROR(status))
20476 return -EINVAL;
20477
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020478 reasonCode =
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053020479 enable_deauth_to_disassoc_map ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020480 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
20481 eCSR_DISCONNECT_REASON_DEAUTH;
Mohit Khannaceb97782017-04-05 16:27:08 -070020482 qdf_dp_trace_dump_all(
20483 WLAN_DEAUTH_DPTRACE_DUMP_COUNT,
20484 QDF_TRACE_DEFAULT_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020485 break;
20486 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
20487 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
20488 break;
20489 default:
20490 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
20491 break;
20492 }
Min Liu8c5d99e2018-09-10 17:18:44 +080020493
20494 vdev = hdd_objmgr_get_vdev(adapter);
20495 if (!vdev)
20496 return -EINVAL;
20497 if (ucfg_scan_get_vdev_status(vdev) !=
Sandeep Puligilla5f86d992017-10-29 14:58:53 -070020498 SCAN_NOT_IN_PROGRESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020499 hdd_debug("Disconnect is in progress, Aborting Scan");
Dustin Brown07901ec2018-09-07 11:02:41 -070020500 wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020501 adapter->vdev_id, INVALID_SCAN_ID,
Dustin Brown07901ec2018-09-07 11:02:41 -070020502 false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020503 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020504 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020505 /* First clean up the tdls peers if any */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020506 hdd_notify_sta_disconnect(adapter->vdev_id,
Min Liu8c5d99e2018-09-10 17:18:44 +080020507 false, true, vdev);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053020508 hdd_objmgr_put_vdev(vdev);
Kabilan Kannanb6153b12017-07-13 17:54:02 -070020509
Dustin Browna7bb6ae2018-08-16 16:51:50 -070020510 hdd_info("Disconnect from userspace; reason:%d (%s)",
20511 reason, hdd_ieee80211_reason_code_to_str(reason));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020512 status = wlan_hdd_disconnect(adapter, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020513 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020514 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Alok Kumarb64650c2018-03-23 17:05:11 +053020515 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020516 return -EINVAL;
20517 }
20518 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020519 hdd_err("Unexpected cfg disconnect called while in state: %d",
Jeff Johnsone7951512019-02-27 10:02:51 -080020520 sta_ctx->conn_info.conn_state);
Alok Kumarb64650c2018-03-23 17:05:11 +053020521 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020522 }
20523
20524 return status;
20525}
20526
20527/**
20528 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
20529 * @wiphy: Pointer to wiphy
20530 * @dev: Pointer to network device
20531 * @reason: Disconnect reason code
20532 *
20533 * Return: 0 for success, non-zero for failure
20534 */
20535static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
20536 struct net_device *dev, u16 reason)
20537{
Dustin Brown1d31b082018-11-22 14:41:20 +053020538 int errno;
20539 struct osif_vdev_sync *vdev_sync;
20540
20541 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
20542 if (errno)
20543 return errno;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020544
Dustin Brown1d31b082018-11-22 14:41:20 +053020545 errno = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020546
Dustin Brown1d31b082018-11-22 14:41:20 +053020547 osif_vdev_sync_op_stop(vdev_sync);
20548
20549 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020550}
20551
20552/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020553 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
20554 * @wiphy: Pointer to wiphy
20555 * @changed: Parameters changed
20556 *
20557 * This function is used to set the phy parameters. RTS Threshold/FRAG
20558 * Threshold/Retry Count etc.
20559 *
20560 * Return: 0 for success, non-zero for failure
20561 */
20562static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
20563 u32 changed)
20564{
Jeff Johnsonb8944722017-09-03 09:03:19 -070020565 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020566 int status;
20567
Dustin Brown491d54b2018-03-14 12:39:11 -070020568 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020569
Anurag Chouhan6d760662016-02-20 16:05:43 +053020570 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020571 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020572 return -EINVAL;
20573 }
20574
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020575 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
20576 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
20577 NO_SESSION, wiphy->rts_threshold);
20578
Jeff Johnsonb8944722017-09-03 09:03:19 -070020579 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020580
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020581 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020582 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020583
20584 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
20585 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
Harprit Chhabadabec6de42018-09-10 10:21:15 -070020586 cfg_max(CFG_RTS_THRESHOLD) :
20587 wiphy->rts_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020588
Harprit Chhabadabec6de42018-09-10 10:21:15 -070020589 if ((cfg_min(CFG_RTS_THRESHOLD) > rts_threshold) ||
20590 (cfg_max(CFG_RTS_THRESHOLD) < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020591 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020592 rts_threshold);
20593 return -EINVAL;
20594 }
20595
Harprit Chhabadabec6de42018-09-10 10:21:15 -070020596 if (0 != ucfg_mlme_set_rts_threshold(hdd_ctx->psoc,
20597 rts_threshold)) {
20598 hdd_err("mlme_set_rts_threshold failed for val %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020599 rts_threshold);
20600 return -EIO;
20601 }
20602
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020603 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020604 }
20605
20606 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
20607 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
Harprit Chhabadabec6de42018-09-10 10:21:15 -070020608 cfg_max(CFG_FRAG_THRESHOLD) :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020609 wiphy->frag_threshold;
20610
Harprit Chhabadabec6de42018-09-10 10:21:15 -070020611 if ((cfg_min(CFG_FRAG_THRESHOLD) > frag_threshold) ||
20612 (cfg_max(CFG_FRAG_THRESHOLD) < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020613 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020614 frag_threshold);
20615 return -EINVAL;
20616 }
20617
Harprit Chhabadabec6de42018-09-10 10:21:15 -070020618 if (0 != ucfg_mlme_set_frag_threshold(hdd_ctx->psoc,
20619 frag_threshold)) {
20620 hdd_err("mlme_set_frag_threshold failed for val %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020621 frag_threshold);
20622 return -EIO;
20623 }
20624
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020625 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020626 }
20627
Dustin Browne74003f2018-03-14 12:51:58 -070020628 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020629 return 0;
20630}
20631
20632/**
20633 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
20634 * @wiphy: Pointer to wiphy
20635 * @changed: Parameters changed
20636 *
20637 * Return: 0 for success, non-zero for failure
20638 */
20639static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
20640{
Dustin Brown363b4792019-02-05 16:11:55 -080020641 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080020642 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +053020643
Dustin Brown363b4792019-02-05 16:11:55 -080020644 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080020645 if (errno)
20646 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020647
Dustin Brownf0f00612019-01-31 16:02:24 -080020648 errno = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020649
Dustin Brown363b4792019-02-05 16:11:55 -080020650 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080020651
20652 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020653}
20654
20655/**
20656 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
20657 * key
20658 * @wiphy: Pointer to wiphy
20659 * @dev: Pointer to network device
20660 * @key_index: Key index
20661 *
20662 * Return: 0
20663 */
20664static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
20665 struct net_device *netdev,
20666 u8 key_index)
20667{
Dustin Brown491d54b2018-03-14 12:39:11 -070020668 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020669 return 0;
20670}
20671
20672/**
20673 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
20674 * wlan_hdd_set_default_mgmt_key
20675 * @wiphy: pointer to wiphy
20676 * @netdev: pointer to net_device structure
20677 * @key_index: key index
20678 *
20679 * Return: 0 on success, error number on failure
20680 */
20681static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
20682 struct net_device *netdev,
20683 u8 key_index)
20684{
Dustin Brown1d31b082018-11-22 14:41:20 +053020685 int errno;
20686 struct osif_vdev_sync *vdev_sync;
20687
20688 errno = osif_vdev_sync_op_start(netdev, &vdev_sync);
20689 if (errno)
20690 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020691
Dustin Brown1d31b082018-11-22 14:41:20 +053020692 errno = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020693
Dustin Brown1d31b082018-11-22 14:41:20 +053020694 osif_vdev_sync_op_stop(vdev_sync);
20695
20696 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020697}
20698
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020699/**
20700 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
20701 * @wiphy: Pointer to wiphy
20702 * @dev: Pointer to network device
20703 * @params: Pointer to tx queue parameters
20704 *
20705 * Return: 0
20706 */
20707static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
20708 struct net_device *dev,
20709 struct ieee80211_txq_params *params)
20710{
Dustin Brown491d54b2018-03-14 12:39:11 -070020711 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020712 return 0;
20713}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020714
20715/**
20716 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
20717 * @wiphy: pointer to wiphy
20718 * @netdev: pointer to net_device structure
20719 * @params: pointer to ieee80211_txq_params
20720 *
20721 * Return: 0 on success, error number on failure
20722 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020723static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
20724 struct net_device *dev,
20725 struct ieee80211_txq_params *params)
20726{
Dustin Brown1d31b082018-11-22 14:41:20 +053020727 int errno;
20728 struct osif_vdev_sync *vdev_sync;
20729
20730 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
20731 if (errno)
20732 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020733
Dustin Brown1d31b082018-11-22 14:41:20 +053020734 errno = __wlan_hdd_set_txq_params(wiphy, dev, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020735
Dustin Brown1d31b082018-11-22 14:41:20 +053020736 osif_vdev_sync_op_stop(vdev_sync);
20737
20738 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020739}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020740
20741/**
20742 * __wlan_hdd_cfg80211_del_station() - delete station v2
20743 * @wiphy: Pointer to wiphy
Jeff Johnson50e37e92019-03-08 11:32:25 -080020744 * @dev: Underlying net device
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020745 * @param: Pointer to delete station parameter
20746 *
20747 * Return: 0 for success, non-zero for failure
20748 */
20749static
20750int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
20751 struct net_device *dev,
Jeff Johnson50e37e92019-03-08 11:32:25 -080020752 struct csr_del_sta_params *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020753{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020754 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020755 struct hdd_context *hdd_ctx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053020756 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070020757 struct hdd_hostapd_state *hapd_state;
Jeff Johnson0a082d92019-03-04 12:25:49 -080020758 uint8_t sta_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020759 uint8_t *mac;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070020760 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020761
Dustin Brown491d54b2018-03-14 12:39:11 -070020762 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020763
Anurag Chouhan6d760662016-02-20 16:05:43 +053020764 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020765 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020766 return -EINVAL;
20767 }
20768
Jeff Johnson48363022019-02-24 16:26:51 -080020769 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020770 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020771
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020772 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
20773 TRACE_CODE_HDD_CFG80211_DEL_STA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020774 adapter->vdev_id, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020775
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020776 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Abhishek Singh97e8a712019-03-29 12:14:04 +053020777 if (!hdd_ctx) {
20778 hdd_err("hdd_ctx is NULL");
20779 return -EINVAL;
20780 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020781
Jeff Johnson50e37e92019-03-08 11:32:25 -080020782 mac = (uint8_t *) param->peerMacAddr.bytes;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070020783 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020784
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020785 if ((QDF_SAP_MODE == adapter->device_mode) ||
20786 (QDF_P2P_GO_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020787
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020788 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020789 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020790 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020791 return 0;
20792 }
20793
Anurag Chouhanc5548422016-02-24 18:33:27 +053020794 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020795 uint16_t i;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020796
Harprit Chhabadae5742552019-03-21 16:28:48 -070020797 bool is_sap_bcast_deauth_enabled = false;
20798
20799 ucfg_mlme_is_sap_bcast_deauth_enabled(
20800 hdd_ctx->psoc,
20801 &is_sap_bcast_deauth_enabled);
20802 hdd_debug("is_sap_bcast_deauth_enabled %d",
20803 is_sap_bcast_deauth_enabled);
20804
20805 if (is_sap_bcast_deauth_enabled)
20806 goto fn_end;
20807
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020808 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020809 if ((adapter->sta_info[i].in_use) &&
20810 (!adapter->sta_info[i].
Jeff Johnsone4f5d932017-10-21 13:21:15 -070020811 is_deauth_in_progress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053020812 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020813 mac,
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020814 adapter->sta_info[i].
Jeff Johnsonf2356512017-10-21 16:04:12 -070020815 sta_mac.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053020816 QDF_MAC_ADDR_SIZE);
Yun Parka4bb37c2017-12-08 16:14:22 -080020817
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020818 hdd_debug("Delete STA with MAC::"
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070020819 QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070020820 QDF_MAC_ADDR_ARRAY(mac));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020821
Jeff Johnsonb8944722017-09-03 09:03:19 -070020822 if (hdd_ctx->dev_dfs_cac_status ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020823 DFS_CAC_IN_PROGRESS)
20824 goto fn_end;
20825
Wei Song2f76f642016-11-18 16:32:53 +080020826 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020827 qdf_status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020828 hdd_softap_sta_deauth(adapter,
Jeff Johnson50e37e92019-03-08 11:32:25 -080020829 param);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020830 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020831 adapter->sta_info[i].
Jeff Johnsone4f5d932017-10-21 13:21:15 -070020832 is_deauth_in_progress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053020833 qdf_status =
Nachiket Kukade0396b732017-11-14 16:35:16 +053020834 qdf_wait_for_event_completion(
Naveen Rawatb56880c2016-12-13 17:56:03 -080020835 &hapd_state->
20836 qdf_sta_disassoc_event,
Abhishek Singhd1f21c72019-01-21 15:16:34 +053020837 SME_PEER_DISCONNECT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +053020838 if (!QDF_IS_STATUS_SUCCESS(
20839 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020840 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020841 }
20842 }
20843 }
20844 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020845 qdf_status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020846 hdd_softap_get_sta_id(adapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053020847 (struct qdf_mac_addr *) mac,
Jeff Johnson0a082d92019-03-04 12:25:49 -080020848 &sta_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020849 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020850 hdd_debug("Skip DEL STA as this is not used::"
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070020851 QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070020852 QDF_MAC_ADDR_ARRAY(mac));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020853 return -ENOENT;
20854 }
20855
Jeff Johnson0a082d92019-03-04 12:25:49 -080020856 if (adapter->sta_info[sta_id].is_deauth_in_progress ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020857 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020858 hdd_debug("Skip DEL STA as deauth is in progress::"
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070020859 QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070020860 QDF_MAC_ADDR_ARRAY(mac));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020861 return -ENOENT;
20862 }
20863
Jeff Johnson0a082d92019-03-04 12:25:49 -080020864 adapter->sta_info[sta_id].is_deauth_in_progress = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020865
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070020866 hdd_debug("ucast, Delete STA with MAC:" QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070020867 QDF_MAC_ADDR_ARRAY(mac));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020868
20869 /* Case: SAP in ACS selected DFS ch and client connected
20870 * Now Radar detected. Then if random channel is another
20871 * DFS ch then new CAC is initiated and no TX allowed.
20872 * So do not send any mgmt frames as it will timeout
20873 * during CAC.
20874 */
20875
Jeff Johnsonb8944722017-09-03 09:03:19 -070020876 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020877 goto fn_end;
20878
Wei Song2f76f642016-11-18 16:32:53 +080020879 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070020880 sme_send_disassoc_req_frame(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020881 adapter->vdev_id,
Jeff Johnson50e37e92019-03-08 11:32:25 -080020882 (uint8_t *)&param->peerMacAddr,
20883 param->reason_code, 0);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020884 qdf_status = hdd_softap_sta_deauth(adapter,
Jeff Johnson50e37e92019-03-08 11:32:25 -080020885 param);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020886 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson0a082d92019-03-04 12:25:49 -080020887 adapter->sta_info[sta_id].is_deauth_in_progress =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020888 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020889 hdd_debug("STA removal failed for ::"
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070020890 QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070020891 QDF_MAC_ADDR_ARRAY(mac));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020892 return -ENOENT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020893 }
Nachiket Kukade0396b732017-11-14 16:35:16 +053020894 qdf_status = qdf_wait_for_event_completion(
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020895 &hapd_state->
20896 qdf_sta_disassoc_event,
Abhishek Singhd1f21c72019-01-21 15:16:34 +053020897 SME_PEER_DISCONNECT_TIMEOUT);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020898 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
20899 hdd_warn("Deauth wait time expired");
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +053020900
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020901 }
20902 }
20903
20904fn_end:
Dustin Browne74003f2018-03-14 12:51:58 -070020905 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020906 return 0;
20907}
20908
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020909#if defined(USE_CFG80211_DEL_STA_V2)
20910/**
20911 * wlan_hdd_del_station() - delete station wrapper
20912 * @adapter: pointer to the hdd adapter
20913 *
20914 * Return: None
20915 */
Jeff Johnsone5006672017-08-29 14:39:02 -070020916void wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020917{
20918 struct station_del_parameters del_sta;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020919
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020920 del_sta.mac = NULL;
20921 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
20922 del_sta.reason_code = eCsrForcedDeauthSta;
20923
20924 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
20925 &del_sta);
20926}
20927#else
Jeff Johnsone5006672017-08-29 14:39:02 -070020928void wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020929{
20930 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
20931}
20932#endif
20933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020934/**
Dustin Brown1d31b082018-11-22 14:41:20 +053020935 * wlan_hdd_cfg80211_del_station() - delete station entry handler
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020936 * @wiphy: Pointer to wiphy
Dustin Brown1d31b082018-11-22 14:41:20 +053020937 * @dev: net_device to operate against
20938 * @mac: binary mac address
20939 * @reason_code: reason for the deauthorization/disassociation
20940 * @subtype: management frame subtype to indicate removal
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020941 *
Dustin Brown1d31b082018-11-22 14:41:20 +053020942 * Return: Errno
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020943 */
Dustin Brown1d31b082018-11-22 14:41:20 +053020944static int _wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
20945 struct net_device *dev,
20946 const uint8_t *mac,
20947 uint16_t reason_code,
20948 uint8_t subtype)
20949{
20950 int errno;
20951 struct csr_del_sta_params delStaParams;
20952 struct osif_vdev_sync *vdev_sync;
20953
20954 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
20955 if (errno)
20956 return errno;
20957
Dustin Brown1d31b082018-11-22 14:41:20 +053020958 wlansap_populate_del_sta_params(mac, reason_code, subtype,
20959 &delStaParams);
20960 errno = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
Dustin Brown1d31b082018-11-22 14:41:20 +053020961
20962 osif_vdev_sync_op_stop(vdev_sync);
20963
20964 return errno;
20965}
20966
20967#ifdef USE_CFG80211_DEL_STA_V2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020968int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
20969 struct net_device *dev,
20970 struct station_del_parameters *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020971{
Dustin Brown1d31b082018-11-22 14:41:20 +053020972 if (!param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020973 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020974
Dustin Brown1d31b082018-11-22 14:41:20 +053020975 return _wlan_hdd_cfg80211_del_station(wiphy, dev, param->mac,
20976 param->reason_code,
20977 param->subtype);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020978}
Dustin Brown1d31b082018-11-22 14:41:20 +053020979#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
20980int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
20981 const uint8_t *mac)
20982{
20983 uint16_t reason = eSIR_MAC_DEAUTH_LEAVING_BSS_REASON;
20984 uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
20985
20986 return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
20987}
20988#else
20989int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
20990 uint8_t *mac)
20991{
20992 uint16_t reason = eSIR_MAC_DEAUTH_LEAVING_BSS_REASON;
20993 uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
20994
20995 return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
20996}
20997#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020998
20999/**
21000 * __wlan_hdd_cfg80211_add_station() - add station
21001 * @wiphy: Pointer to wiphy
21002 * @mac: Pointer to station mac address
21003 * @pmksa: Pointer to add station parameter
21004 *
21005 * Return: 0 for success, non-zero for failure
21006 */
21007static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
21008 struct net_device *dev,
21009 const uint8_t *mac,
21010 struct station_parameters *params)
21011{
21012 int status = -EPERM;
21013#ifdef FEATURE_WLAN_TDLS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021014 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021015 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021016 u32 mask, set;
21017
Dustin Brown491d54b2018-03-14 12:39:11 -070021018 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021019
Anurag Chouhan6d760662016-02-20 16:05:43 +053021020 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021021 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021022 return -EINVAL;
21023 }
21024
Jeff Johnson48363022019-02-24 16:26:51 -080021025 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021026 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021027
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021028 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21029 TRACE_CODE_HDD_CFG80211_ADD_STA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021030 adapter->vdev_id, params->listen_interval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021031
Jeff Johnsonb8944722017-09-03 09:03:19 -070021032 if (0 != wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021033 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021034
21035 mask = params->sta_flags_mask;
21036
21037 set = params->sta_flags_set;
21038
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070021039 hdd_debug("mask 0x%x set 0x%x " QDF_MAC_ADDR_STR, mask, set,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021040 QDF_MAC_ADDR_ARRAY(mac));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021041
21042 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Min Liu8c5d99e2018-09-10 17:18:44 +080021043 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
21044 struct wlan_objmgr_vdev *vdev;
21045
21046 vdev = hdd_objmgr_get_vdev(adapter);
21047 if (vdev) {
21048 status = wlan_cfg80211_tdls_add_peer(vdev,
21049 mac);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053021050 hdd_objmgr_put_vdev(vdev);
Min Liu8c5d99e2018-09-10 17:18:44 +080021051 }
21052 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021053 }
21054#endif
Dustin Browne74003f2018-03-14 12:51:58 -070021055 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021056 return status;
21057}
21058
21059/**
21060 * wlan_hdd_cfg80211_add_station() - add station
21061 * @wiphy: Pointer to wiphy
21062 * @mac: Pointer to station mac address
21063 * @pmksa: Pointer to add station parameter
21064 *
21065 * Return: 0 for success, non-zero for failure
21066 */
21067#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
21068static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
21069 struct net_device *dev,
21070 const uint8_t *mac,
21071 struct station_parameters *params)
21072#else
21073static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
21074 struct net_device *dev, uint8_t *mac,
21075 struct station_parameters *params)
21076#endif
21077{
Dustin Brown1d31b082018-11-22 14:41:20 +053021078 int errno;
21079 struct osif_vdev_sync *vdev_sync;
21080
21081 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21082 if (errno)
21083 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021084
Dustin Brown1d31b082018-11-22 14:41:20 +053021085 errno = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021086
Dustin Brown1d31b082018-11-22 14:41:20 +053021087 osif_vdev_sync_op_stop(vdev_sync);
21088
21089 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021090}
21091
Liangwei Donga44d55b2019-03-20 03:22:08 -040021092#ifdef WLAN_CONV_CRYPTO_IE_SUPPORT
21093static QDF_STATUS wlan_hdd_set_pmksa_cache(struct hdd_adapter *adapter,
21094 tPmkidCacheInfo *pmk_cache)
21095{
21096 QDF_STATUS result;
21097 struct wlan_crypto_pmksa *pmksa;
21098 struct wlan_objmgr_vdev *vdev;
21099
21100 vdev = hdd_objmgr_get_vdev(adapter);
21101 if (!vdev)
21102 return QDF_STATUS_E_FAILURE;
21103
21104 pmksa = qdf_mem_malloc(sizeof(*pmksa));
21105 if (!pmksa) {
21106 hdd_objmgr_put_vdev(vdev);
21107 return QDF_STATUS_E_NOMEM;
21108 }
21109 qdf_copy_macaddr(&pmksa->bssid, &pmk_cache->BSSID);
21110 qdf_mem_copy(pmksa->pmkid, pmk_cache->PMKID, PMKID_LEN);
21111 qdf_mem_copy(pmksa->pmk, pmk_cache->pmk, pmk_cache->pmk_len);
21112 pmksa->pmk_len = pmk_cache->pmk_len;
21113
21114 result = wlan_crypto_set_del_pmksa(vdev, pmksa, true);
21115 if (result != QDF_STATUS_SUCCESS) {
21116 qdf_mem_zero(pmksa, sizeof(*pmksa));
21117 qdf_mem_free(pmksa);
21118 }
21119 hdd_objmgr_put_vdev(vdev);
21120
21121 return result;
21122}
21123
21124static QDF_STATUS wlan_hdd_del_pmksa_cache(struct hdd_adapter *adapter,
21125 tPmkidCacheInfo *pmk_cache)
21126{
21127 QDF_STATUS result;
21128 struct wlan_crypto_pmksa pmksa;
21129 struct wlan_objmgr_vdev *vdev;
21130
21131 vdev = hdd_objmgr_get_vdev(adapter);
21132 if (!vdev)
21133 return QDF_STATUS_E_FAILURE;
21134
21135 qdf_copy_macaddr(&pmksa.bssid, &pmk_cache->BSSID);
21136 result = wlan_crypto_set_del_pmksa(adapter->vdev, &pmksa, false);
21137 hdd_objmgr_put_vdev(vdev);
21138
21139 return result;
21140}
21141
21142QDF_STATUS wlan_hdd_flush_pmksa_cache(struct hdd_adapter *adapter)
21143{
21144 QDF_STATUS result;
21145 struct wlan_objmgr_vdev *vdev;
21146
21147 vdev = hdd_objmgr_get_vdev(adapter);
21148 if (!vdev)
21149 return QDF_STATUS_E_FAILURE;
21150
21151 result = wlan_crypto_set_del_pmksa(adapter->vdev, NULL, false);
21152 hdd_objmgr_put_vdev(vdev);
21153
21154 return result;
21155}
21156#else
21157static QDF_STATUS wlan_hdd_set_pmksa_cache(struct hdd_adapter *adapter,
21158 tPmkidCacheInfo *pmk_cache)
21159{
21160 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21161
21162 return sme_roam_set_pmkid_cache(
21163 hdd_ctx->mac_handle, adapter->vdev_id, pmk_cache, 1, false);
21164}
21165
21166static QDF_STATUS wlan_hdd_del_pmksa_cache(struct hdd_adapter *adapter,
21167 tPmkidCacheInfo *pmk_cache)
21168{
21169 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21170
21171 return sme_roam_del_pmkid_from_cache(
21172 hdd_ctx->mac_handle, adapter->vdev_id, pmk_cache,
21173 false);
21174}
21175
21176QDF_STATUS wlan_hdd_flush_pmksa_cache(struct hdd_adapter *adapter)
21177{
21178 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21179
21180 return sme_roam_del_pmkid_from_cache(
21181 hdd_ctx->mac_handle, adapter->vdev_id, NULL, true);
21182}
21183#endif
21184
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053021185#if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
21186 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021187/*
21188 * wlan_hdd_is_pmksa_valid: API to validate pmksa
21189 * @pmksa: pointer to cfg80211_pmksa structure
21190 *
21191 * Return: True if valid else false
21192 */
21193static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
21194{
21195 if (!pmksa->bssid) {
Vignesh Viswanathanfa90d622017-12-22 13:13:26 +053021196 hdd_warn("bssid (%pK) is NULL",
21197 pmksa->bssid);
21198 if (!pmksa->ssid || !pmksa->cache_id) {
21199 hdd_err("either ssid (%pK) or cache_id (%pK) are NULL",
21200 pmksa->ssid, pmksa->cache_id);
21201 return false;
21202 }
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021203 }
21204 return true;
21205}
21206
21207/*
21208 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021209 * @adapter: Pointer to hdd adapter
21210 * @pmk_cache: pmk that needs to be udated
21211 * @pmksa: pmk from supplicant
21212 * @is_delete: Bool to decide set or delete PMK
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021213 * Return: None
21214 */
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021215static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
21216 tPmkidCacheInfo *pmk_cache,
21217 struct cfg80211_pmksa *pmksa, bool is_delete)
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021218{
21219 if (pmksa->bssid) {
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070021220 hdd_debug("%s PMKSA for " QDF_MAC_ADDR_STR,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021221 is_delete ? "Delete" : "Set",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021222 QDF_MAC_ADDR_ARRAY(pmksa->bssid));
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021223 qdf_mem_copy(pmk_cache->BSSID.bytes,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021224 pmksa->bssid, QDF_MAC_ADDR_SIZE);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021225 } else {
Jeff Johnson9c749db2018-05-07 12:50:46 -070021226 qdf_mem_copy(pmk_cache->ssid, pmksa->ssid, pmksa->ssid_len);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021227 qdf_mem_copy(pmk_cache->cache_id, pmksa->cache_id,
21228 CACHE_ID_LEN);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021229 pmk_cache->ssid_len = pmksa->ssid_len;
21230 hdd_debug("%s PMKSA for ssid %*.*s cache_id %x %x",
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021231 is_delete ? "Delete" : "Set",
21232 pmk_cache->ssid_len, pmk_cache->ssid_len,
21233 pmk_cache->ssid, pmk_cache->cache_id[0],
21234 pmk_cache->cache_id[1]);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021235 }
21236
21237 if (is_delete)
21238 return;
21239
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -070021240 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, PMKID_LEN);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021241 if (pmksa->pmk_len && (pmksa->pmk_len <= CSR_RSN_MAX_PMK_LEN)) {
21242 qdf_mem_copy(pmk_cache->pmk, pmksa->pmk, pmksa->pmk_len);
21243 pmk_cache->pmk_len = pmksa->pmk_len;
21244 } else
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053021245 hdd_debug("pmk len is %zu", pmksa->pmk_len);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021246}
21247#else
21248/*
21249 * wlan_hdd_is_pmksa_valid: API to validate pmksa
21250 * @pmksa: pointer to cfg80211_pmksa structure
21251 *
21252 * Return: True if valid else false
21253 */
21254static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
21255{
21256 if (!pmksa->bssid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070021257 hdd_err("both bssid is NULL %pK", pmksa->bssid);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021258 return false;
21259 }
21260 return true;
21261}
21262
21263/*
21264 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021265 * @adapter: Pointer to hdd adapter
21266 * @pmk_cache: pmk which needs to be updated
21267 * @pmksa: pmk from supplicant
21268 * @is_delete: Bool to decide whether to set or delete PMK
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021269 *
21270 * Return: None
21271 */
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021272static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
21273 tPmkidCacheInfo *pmk_cache,
21274 struct cfg80211_pmksa *pmksa, bool is_delete)
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021275{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021276 mac_handle_t mac_handle;
Srinivas Girigowda50335342018-09-07 15:21:01 -070021277
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070021278 hdd_debug("%s PMKSA for " QDF_MAC_ADDR_STR, is_delete ? "Delete" : "Set",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021279 QDF_MAC_ADDR_ARRAY(pmksa->bssid));
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021280 qdf_mem_copy(pmk_cache->BSSID.bytes,
21281 pmksa->bssid, QDF_MAC_ADDR_SIZE);
21282
21283 if (is_delete)
21284 return;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021285 mac_handle = hdd_adapter_get_mac_handle(adapter);
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021286 sme_get_pmk_info(mac_handle, adapter->vdev_id, pmk_cache);
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -070021287 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, PMKID_LEN);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021288}
21289#endif
21290
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021291/**
21292 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
21293 * @wiphy: Pointer to wiphy
21294 * @dev: Pointer to network device
21295 * @pmksa: Pointer to set pmksa parameter
21296 *
21297 * Return: 0 for success, non-zero for failure
21298 */
21299static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
21300 struct net_device *dev,
21301 struct cfg80211_pmksa *pmksa)
21302{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021303 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21304 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021305 mac_handle_t mac_handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021306 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021307 int status;
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021308 tPmkidCacheInfo pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021309
Dustin Brown491d54b2018-03-14 12:39:11 -070021310 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021311
Anurag Chouhan6d760662016-02-20 16:05:43 +053021312 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021313 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021314 return -EINVAL;
21315 }
21316
Jeff Johnson48363022019-02-24 16:26:51 -080021317 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021318 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021319
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021320 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021321 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021322 return -EINVAL;
21323 }
21324
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021325 if (!pmksa->pmkid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070021326 hdd_err("pmksa->pmkid(%pK) is NULL",
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021327 pmksa->pmkid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021328 return -EINVAL;
21329 }
21330
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021331 if (!wlan_hdd_is_pmksa_valid(pmksa))
21332 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021333
Jeff Johnsonb8944722017-09-03 09:03:19 -070021334 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021335
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021336 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021337 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021338
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021339 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021340
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021341 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021342
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021343 hdd_fill_pmksa_info(adapter, &pmk_cache, pmksa, false);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021344
21345 /*
21346 * Add to the PMKSA Cache in CSR
21347 * PMKSA cache will be having following
21348 * 1. pmkid id
21349 * 2. pmk
21350 * 3. bssid or cache identifier
21351 */
Liangwei Donga44d55b2019-03-20 03:22:08 -040021352 result = wlan_hdd_set_pmksa_cache(adapter, &pmk_cache);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021353
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021354 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21355 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021356 adapter->vdev_id, result);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021357
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021358 sme_set_del_pmkid_cache(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021359 &pmk_cache, true);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021360
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +053021361 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
Dustin Browne74003f2018-03-14 12:51:58 -070021362 hdd_exit();
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +053021363
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021364 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021365}
21366
21367/**
21368 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
21369 * @wiphy: Pointer to wiphy
21370 * @dev: Pointer to network device
21371 * @pmksa: Pointer to set pmksa parameter
21372 *
21373 * Return: 0 for success, non-zero for failure
21374 */
21375static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
21376 struct net_device *dev,
21377 struct cfg80211_pmksa *pmksa)
21378{
Dustin Brown1d31b082018-11-22 14:41:20 +053021379 int errno;
21380 struct osif_vdev_sync *vdev_sync;
21381
21382 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21383 if (errno)
21384 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021385
Dustin Brown1d31b082018-11-22 14:41:20 +053021386 errno = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021387
Dustin Brown1d31b082018-11-22 14:41:20 +053021388 osif_vdev_sync_op_stop(vdev_sync);
21389
21390 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021391}
21392
21393/**
21394 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
21395 * @wiphy: Pointer to wiphy
21396 * @dev: Pointer to network device
21397 * @pmksa: Pointer to pmksa parameter
21398 *
21399 * Return: 0 for success, non-zero for failure
21400 */
21401static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
21402 struct net_device *dev,
21403 struct cfg80211_pmksa *pmksa)
21404{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021405 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21406 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021407 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021408 int status = 0;
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021409 tPmkidCacheInfo pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021410
Dustin Brown491d54b2018-03-14 12:39:11 -070021411 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021412
Anurag Chouhan6d760662016-02-20 16:05:43 +053021413 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021414 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021415 return -EINVAL;
21416 }
21417
Jeff Johnson48363022019-02-24 16:26:51 -080021418 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021419 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021420
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021421 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021422 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021423 return -EINVAL;
21424 }
21425
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021426 if (!wlan_hdd_is_pmksa_valid(pmksa))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021427 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021428
Jeff Johnsonb8944722017-09-03 09:03:19 -070021429 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021430
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021431 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021432 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021433
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021434 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021435
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021436 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21437 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021438 adapter->vdev_id, 0);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021439
21440 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
21441
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021442 hdd_fill_pmksa_info(adapter, &pmk_cache, pmksa, true);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021443
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021444 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021445 if (QDF_STATUS_SUCCESS !=
Liangwei Donga44d55b2019-03-20 03:22:08 -040021446 wlan_hdd_del_pmksa_cache(adapter, &pmk_cache)) {
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070021447 hdd_err("Failed to delete PMKSA for " QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021448 QDF_MAC_ADDR_ARRAY(pmksa->bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021449 status = -EINVAL;
21450 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021451
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021452 sme_set_del_pmkid_cache(mac_handle, adapter->vdev_id, &pmk_cache,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021453 false);
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +053021454 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
21455
Dustin Browne74003f2018-03-14 12:51:58 -070021456 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021457 return status;
21458}
21459
21460/**
21461 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
21462 * @wiphy: Pointer to wiphy
21463 * @dev: Pointer to network device
21464 * @pmksa: Pointer to pmksa parameter
21465 *
21466 * Return: 0 for success, non-zero for failure
21467 */
21468static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
21469 struct net_device *dev,
21470 struct cfg80211_pmksa *pmksa)
21471{
Dustin Brown1d31b082018-11-22 14:41:20 +053021472 int errno;
21473 struct osif_vdev_sync *vdev_sync;
21474
21475 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21476 if (errno)
21477 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021478
Dustin Brown1d31b082018-11-22 14:41:20 +053021479 errno = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021480
Dustin Brown1d31b082018-11-22 14:41:20 +053021481 osif_vdev_sync_op_stop(vdev_sync);
21482
21483 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021484
21485}
21486
21487/**
21488 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
21489 * @wiphy: Pointer to wiphy
21490 * @dev: Pointer to network device
21491 *
21492 * Return: 0 for success, non-zero for failure
21493 */
21494static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
21495 struct net_device *dev)
21496{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021497 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21498 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021499 mac_handle_t mac_handle;
21500 int errno;
21501 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021502
Dustin Brown491d54b2018-03-14 12:39:11 -070021503 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021504
Anurag Chouhan6d760662016-02-20 16:05:43 +053021505 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021506 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021507 return -EINVAL;
21508 }
21509
Jeff Johnson48363022019-02-24 16:26:51 -080021510 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021511 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021512
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021513 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021514
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021515 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021516 errno = wlan_hdd_validate_context(hdd_ctx);
21517 if (errno)
21518 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021519
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021520 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021521
Liangwei Donga44d55b2019-03-20 03:22:08 -040021522 status = wlan_hdd_flush_pmksa_cache(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021523 if (QDF_IS_STATUS_ERROR(status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021524 hdd_err("Cannot flush PMKIDCache");
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021525 errno = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021526 }
Vignesh Viswanathane8a26b22017-10-11 20:38:47 +053021527
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021528 sme_set_del_pmkid_cache(mac_handle, adapter->vdev_id, NULL, false);
Dustin Browne74003f2018-03-14 12:51:58 -070021529 hdd_exit();
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021530 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021531}
21532
21533/**
21534 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
21535 * @wiphy: Pointer to wiphy
21536 * @dev: Pointer to network device
21537 *
21538 * Return: 0 for success, non-zero for failure
21539 */
21540static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
21541 struct net_device *dev)
21542{
Dustin Brown1d31b082018-11-22 14:41:20 +053021543 int errno;
21544 struct osif_vdev_sync *vdev_sync;
21545
21546 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21547 if (errno)
21548 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021549
Dustin Brown1d31b082018-11-22 14:41:20 +053021550 errno = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021551
Dustin Brown1d31b082018-11-22 14:41:20 +053021552 osif_vdev_sync_op_stop(vdev_sync);
21553
21554 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021555}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021556
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080021557#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021558/**
21559 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
21560 * @wiphy: Pointer to wiphy
21561 * @dev: Pointer to network device
21562 * @ftie: Pointer to fast transition ie parameter
21563 *
21564 * Return: 0 for success, non-zero for failure
21565 */
21566static int
21567__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
21568 struct net_device *dev,
21569 struct cfg80211_update_ft_ies_params *ftie)
21570{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070021571 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021572 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsond377dce2017-10-04 10:32:42 -070021573 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021574 int status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021575 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021576
Dustin Brown491d54b2018-03-14 12:39:11 -070021577 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021578
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021579 status = wlan_hdd_validate_context(hdd_ctx);
21580 if (status)
21581 return status;
21582
Anurag Chouhan6d760662016-02-20 16:05:43 +053021583 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021584 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021585 return -EINVAL;
21586 }
21587
Jeff Johnson48363022019-02-24 16:26:51 -080021588 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021589 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021590
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021591 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21592 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
Jeff Johnsone7951512019-02-27 10:02:51 -080021593 adapter->vdev_id, sta_ctx->conn_info.conn_state);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021594
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021595 /* Added for debug on reception of Re-assoc Req. */
Jeff Johnsone7951512019-02-27 10:02:51 -080021596 if (eConnectionState_Associated != sta_ctx->conn_info.conn_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021597 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021598 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021599 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021600 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021601 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021602 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021603
21604 /* Pass the received FT IEs to SME */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021605 mac_handle = hdd_ctx->mac_handle;
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021606 sme_set_ft_ies(mac_handle, adapter->vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021607 (const u8 *)ftie->ie, ftie->ie_len);
Dustin Browne74003f2018-03-14 12:51:58 -070021608 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021609 return 0;
21610}
21611
21612/**
21613 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
21614 * @wiphy: Pointer to wiphy
21615 * @dev: Pointer to network device
21616 * @ftie: Pointer to fast transition ie parameter
21617 *
21618 * Return: 0 for success, non-zero for failure
21619 */
21620static int
21621wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
21622 struct net_device *dev,
21623 struct cfg80211_update_ft_ies_params *ftie)
21624{
Dustin Brown1d31b082018-11-22 14:41:20 +053021625 int errno;
21626 struct osif_vdev_sync *vdev_sync;
21627
21628 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21629 if (errno)
21630 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021631
Dustin Brown1d31b082018-11-22 14:41:20 +053021632 errno = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021633
Dustin Brown1d31b082018-11-22 14:41:20 +053021634 osif_vdev_sync_op_stop(vdev_sync);
21635
21636 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021637}
21638#endif
21639
Min Liu0daa0982019-02-01 17:50:44 +080021640#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
21641/**
21642 * __wlan_hdd_cfg80211_update_owe_info() - update OWE info
21643 * @wiphy: Pointer to wiphy
21644 * @dev: Pointer to network device
21645 * @owe_info: Pointer to OWE info
21646 *
21647 * Return: 0 for success, non-zero for failure
21648 */
21649static int
21650__wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
21651 struct net_device *dev,
21652 struct cfg80211_update_owe_info *owe_info)
21653{
21654 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
21655 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21656 QDF_STATUS status;
Dustin Brown96b98dd2019-03-06 12:39:37 -080021657 int errno;
Min Liu0daa0982019-02-01 17:50:44 +080021658
21659 hdd_enter_dev(dev);
21660
21661 errno = wlan_hdd_validate_context(hdd_ctx);
21662 if (errno)
21663 return errno;
21664
21665 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
21666 hdd_err("Command not allowed in FTM mode");
21667 return -EINVAL;
21668 }
21669
Jeff Johnsona6b398d2019-02-24 16:26:51 -080021670 if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) {
21671 hdd_err("invalid vdev id: %d", adapter->vdev_id);
Min Liu0daa0982019-02-01 17:50:44 +080021672 return -EINVAL;
21673 }
21674
21675 hdd_debug("owe_status %d", owe_info->status);
21676
21677 status = wlansap_update_owe_info(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Min Liue2b469f2019-04-10 19:13:42 +080021678 owe_info->peer, owe_info->ie,
Min Liu0daa0982019-02-01 17:50:44 +080021679 owe_info->ie_len, owe_info->status);
21680 if (QDF_IS_STATUS_ERROR(status)) {
21681 hdd_err("Failed to update OWE info");
21682 errno = qdf_status_to_os_return(status);
21683 }
21684
21685 hdd_exit();
21686 return errno;
21687}
21688
21689/**
21690 * wlan_hdd_cfg80211_update_owe_info() - update OWE info
21691 * @wiphy: Pointer to wiphy
21692 * @dev: Pointer to network device
21693 * @owe_info: Pointer to OWE info
21694 *
21695 * Return: 0 for success, non-zero for failure
21696 */
21697static int
21698wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
Dustin Brown96b98dd2019-03-06 12:39:37 -080021699 struct net_device *net_dev,
Min Liu0daa0982019-02-01 17:50:44 +080021700 struct cfg80211_update_owe_info *owe_info)
21701{
Dustin Brown96b98dd2019-03-06 12:39:37 -080021702 struct osif_vdev_sync *vdev_sync;
21703 int errno;
Min Liu0daa0982019-02-01 17:50:44 +080021704
Dustin Brown96b98dd2019-03-06 12:39:37 -080021705 errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
21706 if (errno)
21707 return errno;
Min Liu0daa0982019-02-01 17:50:44 +080021708
Dustin Brown96b98dd2019-03-06 12:39:37 -080021709 errno = __wlan_hdd_cfg80211_update_owe_info(wiphy, net_dev, owe_info);
21710
21711 osif_vdev_sync_op_stop(vdev_sync);
21712
21713 return errno;
Min Liu0daa0982019-02-01 17:50:44 +080021714}
21715#endif
21716
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +053021717void wlan_hdd_cfg80211_update_replay_counter_cb(
Mukul Sharma3d36c392017-01-18 18:39:12 +053021718 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
21719
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021720{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021721 struct hdd_adapter *adapter = (struct hdd_adapter *)cb_ctx;
Mukul Sharma3d36c392017-01-18 18:39:12 +053021722 uint8_t temp_replay_counter[8];
21723 int i;
21724 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021725
Dustin Brown491d54b2018-03-14 12:39:11 -070021726 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021727
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021728 if (!adapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021729 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053021730 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021731 }
21732
Mukul Sharma3d36c392017-01-18 18:39:12 +053021733 if (!gtk_rsp_param) {
21734 hdd_err("gtk_rsp_param is Null");
21735 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021736 }
21737
Mukul Sharma3d36c392017-01-18 18:39:12 +053021738 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021739 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053021740 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021741 }
21742
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021743 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053021744 gtk_rsp_param->replay_counter);
21745 /* convert little to big endian since supplicant works on big endian */
21746 p = (uint8_t *)&gtk_rsp_param->replay_counter;
21747 for (i = 0; i < 8; i++)
21748 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021749
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021750 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021751 /* Update replay counter to NL */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021752 cfg80211_gtk_rekey_notify(adapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053021753 gtk_rsp_param->bssid.bytes,
21754 temp_replay_counter, GFP_KERNEL);
21755out:
Dustin Browne74003f2018-03-14 12:51:58 -070021756 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053021757
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021758}
21759
Wu Gaoa9d336b2018-05-30 14:48:04 +080021760#ifdef WLAN_FEATURE_GTK_OFFLOAD
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021761/**
21762 * wlan_hdd_copy_gtk_kek - Copy the KEK from GTK rekey data to GTK request
21763 * @gtk_req: Pointer to GTK request
21764 * @data: Pointer to rekey data
21765 *
21766 * Return: none
21767 */
21768#ifdef CFG80211_REKEY_DATA_KEK_LEN
21769static
21770void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
21771 struct cfg80211_gtk_rekey_data *data)
21772{
21773 qdf_mem_copy(gtk_req->kek, data->kek, data->kek_len);
21774 gtk_req->kek_len = data->kek_len;
21775}
21776#else
21777static
21778void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
21779 struct cfg80211_gtk_rekey_data *data)
21780{
21781 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
21782 gtk_req->kek_len = NL80211_KEK_LEN;
21783}
21784#endif
21785
21786/**
21787 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
21788 * @wiphy: Pointer to wiphy
21789 * @dev: Pointer to network device
21790 * @data: Pointer to rekey data
21791 *
21792 * This function is used to offload GTK rekeying job to the firmware.
21793 *
21794 * Return: 0 for success, non-zero for failure
21795 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070021796static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021797int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053021798 struct net_device *dev,
21799 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021800{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021801 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053021802 int result, i;
21803 struct pmo_gtk_req *gtk_req = NULL;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021804 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharma3d36c392017-01-18 18:39:12 +053021805 uint8_t *buf;
Min Liu8c5d99e2018-09-10 17:18:44 +080021806 struct wlan_objmgr_vdev *vdev;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021807 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021808
Dustin Brown491d54b2018-03-14 12:39:11 -070021809 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021810
Anurag Chouhan6d760662016-02-20 16:05:43 +053021811 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021812 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053021813 result = -EINVAL;
21814 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021815 }
21816
Jeff Johnson48363022019-02-24 16:26:51 -080021817 if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) {
Mukul Sharma3d36c392017-01-18 18:39:12 +053021818 result = -EINVAL;
21819 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021820 }
21821
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021822 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21823 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021824 adapter->vdev_id, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021825
Mukul Sharma3d36c392017-01-18 18:39:12 +053021826 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021827 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053021828 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021829
Mukul Sharma3d36c392017-01-18 18:39:12 +053021830 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
21831 if (!gtk_req) {
Mukul Sharma3d36c392017-01-18 18:39:12 +053021832 result = -ENOMEM;
21833 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021834 }
21835
Mukul Sharma3d36c392017-01-18 18:39:12 +053021836 /* convert big to little endian since driver work on little endian */
21837 buf = (uint8_t *)&gtk_req->replay_counter;
21838 for (i = 0; i < 8; i++)
21839 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021840
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021841 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053021842 gtk_req->replay_counter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021843
21844 wlan_hdd_copy_gtk_kek(gtk_req, data);
Yeshwanth Sriram Guntukae6313412019-08-06 14:18:33 +053021845 if (data->kck) {
nakul kachhwahaa580cc32019-03-15 17:45:17 +053021846 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
Yeshwanth Sriram Guntukae6313412019-08-06 14:18:33 +053021847 gtk_req->kck_len = NL80211_KCK_LEN;
21848 }
gaurank kathpalia82a1b2b2018-07-10 16:49:10 +053021849 gtk_req->is_fils_connection = hdd_is_fils_connection(adapter);
Min Liu8c5d99e2018-09-10 17:18:44 +080021850 vdev = hdd_objmgr_get_vdev(adapter);
21851 if (!vdev) {
21852 result = -EINVAL;
21853 goto out;
21854 }
21855 status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053021856 hdd_objmgr_put_vdev(vdev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053021857 if (status != QDF_STATUS_SUCCESS) {
21858 hdd_err("Failed to cache GTK Offload");
21859 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021860 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053021861out:
21862 if (gtk_req)
21863 qdf_mem_free(gtk_req);
Dustin Browne74003f2018-03-14 12:51:58 -070021864 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053021865
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021866 return result;
21867}
21868
21869/**
21870 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
21871 * @wiphy: Pointer to wiphy
21872 * @dev: Pointer to network device
21873 * @data: Pointer to rekey data
21874 *
21875 * This function is used to offload GTK rekeying job to the firmware.
21876 *
21877 * Return: 0 for success, non-zero for failure
21878 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070021879static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021880int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
21881 struct net_device *dev,
21882 struct cfg80211_gtk_rekey_data *data)
21883{
Dustin Brown1d31b082018-11-22 14:41:20 +053021884 int errno;
21885 struct osif_vdev_sync *vdev_sync;
21886
21887 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21888 if (errno)
21889 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021890
Dustin Brown1d31b082018-11-22 14:41:20 +053021891 errno = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021892
Dustin Brown1d31b082018-11-22 14:41:20 +053021893 osif_vdev_sync_op_stop(vdev_sync);
21894
21895 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021896}
Wu Gaoa9d336b2018-05-30 14:48:04 +080021897#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021898
21899/**
21900 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
21901 * @wiphy: Pointer to wiphy
21902 * @dev: Pointer to network device
21903 * @param: Pointer to access control parameter
21904 *
21905 * Return: 0 for success, non-zero for failure
21906 */
21907static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
21908 struct net_device *dev,
21909 const struct cfg80211_acl_data *params)
21910{
21911 int i;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021912 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson5c19ade2017-10-04 09:52:12 -070021913 struct hdd_hostapd_state *hostapd_state;
Jeff Johnson8f8ceb92019-03-24 08:16:55 -070021914 struct sap_config *config;
Jeff Johnsonb8944722017-09-03 09:03:19 -070021915 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021916 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021917 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021918
Dustin Brown491d54b2018-03-14 12:39:11 -070021919 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021920
Anurag Chouhan6d760662016-02-20 16:05:43 +053021921 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021922 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021923 return -EINVAL;
21924 }
21925
Jeff Johnsond36fa332019-03-18 13:42:25 -070021926 if (!params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021927 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021928 return -EINVAL;
21929 }
21930
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021931 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021932 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021933
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021934 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021935 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021936
Jeff Johnson5c19ade2017-10-04 09:52:12 -070021937 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021938
Jeff Johnsond36fa332019-03-18 13:42:25 -070021939 if (!hostapd_state) {
Jeff Johnson5c19ade2017-10-04 09:52:12 -070021940 hdd_err("hostapd_state is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021941 return -EINVAL;
21942 }
21943
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021944 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021945 params->n_acl_entries);
21946
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021947 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21948 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021949 adapter->vdev_id, adapter->device_mode);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021950
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021951 if (QDF_SAP_MODE == adapter->device_mode) {
Jeff Johnson954903d2019-03-07 20:41:27 -080021952 config = &adapter->session.ap.sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021953
21954 /* default value */
Jeff Johnson954903d2019-03-07 20:41:27 -080021955 config->num_accept_mac = 0;
21956 config->num_deny_mac = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021957
21958 /**
21959 * access control policy
21960 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
21961 * listed in hostapd.deny file.
21962 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
21963 * listed in hostapd.accept file.
21964 */
21965 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
Jeff Johnson954903d2019-03-07 20:41:27 -080021966 config->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021967 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
21968 params->acl_policy) {
Jeff Johnson954903d2019-03-07 20:41:27 -080021969 config->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021970 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021971 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021972 params->acl_policy);
21973 return -ENOTSUPP;
21974 }
21975
Jeff Johnson954903d2019-03-07 20:41:27 -080021976 if (eSAP_DENY_UNLESS_ACCEPTED == config->SapMacaddr_acl) {
21977 config->num_accept_mac = params->n_acl_entries;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021978 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021979 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070021980 QDF_MAC_ADDR_STR, i,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021981 QDF_MAC_ADDR_ARRAY(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021982 params->mac_addrs[i].addr));
21983
Jeff Johnson954903d2019-03-07 20:41:27 -080021984 qdf_mem_copy(&config->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021985 params->mac_addrs[i].addr,
Srinivas Girigowdaa47b45f2019-02-27 12:29:02 -080021986 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021987 }
Jeff Johnson954903d2019-03-07 20:41:27 -080021988 } else if (eSAP_ACCEPT_UNLESS_DENIED == config->SapMacaddr_acl) {
21989 config->num_deny_mac = params->n_acl_entries;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021990 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021991 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070021992 QDF_MAC_ADDR_STR, i,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021993 QDF_MAC_ADDR_ARRAY(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021994 params->mac_addrs[i].addr));
21995
Jeff Johnson954903d2019-03-07 20:41:27 -080021996 qdf_mem_copy(&config->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021997 params->mac_addrs[i].addr,
Srinivas Girigowdaa47b45f2019-02-27 12:29:02 -080021998 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021999 }
22000 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070022001 qdf_status = wlansap_set_mac_acl(
Jeff Johnson954903d2019-03-07 20:41:27 -080022002 WLAN_HDD_GET_SAP_CTX_PTR(adapter), config);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022003 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022004 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022005 return -EINVAL;
22006 }
22007 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022008 hdd_debug("Invalid device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070022009 qdf_opmode_str(adapter->device_mode),
22010 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022011 return -EINVAL;
22012 }
Dustin Browne74003f2018-03-14 12:51:58 -070022013 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022014 return 0;
22015}
22016
22017/**
22018 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
22019 * __wlan_hdd_cfg80211_set_mac_acl
22020 * @wiphy: pointer to wiphy structure
22021 * @dev: pointer to net_device
22022 * @params: pointer to cfg80211_acl_data
22023 *
22024 * Return; 0 on success, error number otherwise
22025 */
22026static int
22027wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
22028 struct net_device *dev,
22029 const struct cfg80211_acl_data *params)
22030{
Dustin Brown1d31b082018-11-22 14:41:20 +053022031 int errno;
22032 struct osif_vdev_sync *vdev_sync;
22033
22034 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22035 if (errno)
22036 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022037
Dustin Brown1d31b082018-11-22 14:41:20 +053022038 errno = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022039
Dustin Brown1d31b082018-11-22 14:41:20 +053022040 osif_vdev_sync_op_stop(vdev_sync);
22041
22042 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022043}
22044
22045#ifdef WLAN_NL80211_TESTMODE
22046#ifdef FEATURE_WLAN_LPHB
22047/**
22048 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
Jeff Johnsonb8944722017-09-03 09:03:19 -070022049 * @hdd_ctx: Pointer to hdd context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022050 * @lphbInd: Pointer to low power heart beat indication parameter
22051 *
22052 * Return: none
22053 */
Jeff Johnsonb8944722017-09-03 09:03:19 -070022054static void wlan_hdd_cfg80211_lphb_ind_handler(void *hdd_ctx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022055 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022056{
22057 struct sk_buff *skb;
22058
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022059 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022060
Jeff Johnsonb8944722017-09-03 09:03:19 -070022061 if (0 != wlan_hdd_validate_context((struct hdd_context *) hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022062 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022063
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022064 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022065 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022066 return;
22067 }
22068
Jeff Johnsonb8944722017-09-03 09:03:19 -070022069 skb = cfg80211_testmode_alloc_event_skb(((struct hdd_context *) hdd_ctx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022070 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022071 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022072 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022073 return;
22074 }
22075
22076 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022077 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022078 goto nla_put_failure;
22079 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022080 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022081 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022082 goto nla_put_failure;
22083 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022084 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
22085 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022086 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022087 goto nla_put_failure;
22088 }
22089 cfg80211_testmode_event(skb, GFP_ATOMIC);
22090 return;
22091
22092nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022093 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022094 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022095}
22096#endif /* FEATURE_WLAN_LPHB */
22097
22098/**
22099 * __wlan_hdd_cfg80211_testmode() - test mode
22100 * @wiphy: Pointer to wiphy
22101 * @data: Data pointer
22102 * @len: Data length
22103 *
22104 * Return: 0 for success, non-zero for failure
22105 */
22106static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
22107 void *data, int len)
22108{
22109 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
22110 int err;
Jeff Johnsonb8944722017-09-03 09:03:19 -070022111 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022112
Dustin Brown491d54b2018-03-14 12:39:11 -070022113 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022114
Jeff Johnsonb8944722017-09-03 09:03:19 -070022115 err = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022116 if (err)
22117 return err;
22118
Ryan Hsu4df41382018-06-15 15:45:22 -070022119 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
22120 hdd_err("Driver Modules are closed");
22121 return -EINVAL;
22122 }
22123
Dustin Brown4ea21db2018-01-05 14:13:17 -080022124 err = wlan_cfg80211_nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
22125 len, wlan_hdd_tm_policy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022126 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022127 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022128 return err;
22129 }
22130
22131 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022132 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022133 return -EINVAL;
22134 }
22135
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022136 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22137 TRACE_CODE_HDD_CFG80211_TESTMODE,
22138 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
22139
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022140 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
22141#ifdef FEATURE_WLAN_LPHB
22142 /* Low Power Heartbeat configuration request */
22143 case WLAN_HDD_TM_CMD_WLAN_HB:
22144 {
22145 int buf_len;
22146 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022147 struct pmo_lphb_req *hb_params = NULL;
22148 struct pmo_lphb_req *hb_params_temp = NULL;
22149 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022150
22151 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022152 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022153 return -EINVAL;
22154 }
22155
22156 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
22157 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
Rajeev Kumar Sirasanagandla012e7b72019-03-14 21:54:43 +053022158 if (buf_len < sizeof(*hb_params_temp)) {
22159 hdd_err("Invalid buffer length for TM_ATTR_DATA");
22160 return -EINVAL;
22161 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022162
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022163 hb_params_temp = (struct pmo_lphb_req *) buf;
22164 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
22165 && (hb_params_temp->params.lphb_tcp_params.
22166 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022167 return -EINVAL;
22168
Manjeet Singh00b2a562017-01-03 12:08:10 +053022169 if (buf_len > sizeof(*hb_params)) {
22170 hdd_err("buf_len=%d exceeded hb_params size limit",
22171 buf_len);
22172 return -ERANGE;
22173 }
22174
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022175 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
22176 sizeof(*hb_params));
Min Liu74a1a502018-10-10 19:59:07 +080022177 if (!hb_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022178 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022179
Ashish Kumar Dhanotiya0fa8ee02017-07-13 14:04:31 +053022180 qdf_mem_zero(hb_params, sizeof(*hb_params));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053022181 qdf_mem_copy(hb_params, buf, buf_len);
Wu Gaod7dd6e42018-10-16 17:22:56 +080022182 status = ucfg_pmo_lphb_config_req(
22183 hdd_ctx->psoc,
Jeff Johnsonb8944722017-09-03 09:03:19 -070022184 hb_params, (void *)hdd_ctx,
Wu Gaod7dd6e42018-10-16 17:22:56 +080022185 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022186 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022187 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022188
22189 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022190 return 0;
22191 }
22192#endif /* FEATURE_WLAN_LPHB */
22193
22194#if defined(QCA_WIFI_FTM)
22195 case WLAN_HDD_TM_CMD_WLAN_FTM:
22196 {
Ryan Hsu4df41382018-06-15 15:45:22 -070022197 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam()) {
22198 hdd_err("Command not allowed in FTM mode, mode %d",
22199 hdd_get_conparam());
22200 return -EINVAL;
22201 }
22202
Dustin Brown07901ec2018-09-07 11:02:41 -070022203 err = wlan_cfg80211_ftm_testmode_cmd(hdd_ctx->pdev,
Ryan Hsuc8b27a42018-01-02 13:57:56 -080022204 data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022205 break;
22206 }
22207#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022208 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022209 hdd_err("command: %d not supported",
Ryan Hsuc8b27a42018-01-02 13:57:56 -080022210 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022211 return -EOPNOTSUPP;
22212 }
Ryan Hsuc8b27a42018-01-02 13:57:56 -080022213
Dustin Browne74003f2018-03-14 12:51:58 -070022214 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022215 return err;
22216}
22217
22218/**
22219 * wlan_hdd_cfg80211_testmode() - test mode
22220 * @wiphy: Pointer to wiphy
22221 * @dev: Pointer to network device
22222 * @data: Data pointer
22223 * @len: Data length
22224 *
22225 * Return: 0 for success, non-zero for failure
22226 */
22227static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
22228#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
22229 struct wireless_dev *wdev,
22230#endif
22231 void *data, int len)
22232{
Dustin Brown363b4792019-02-05 16:11:55 -080022233 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080022234 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +053022235
Dustin Brown363b4792019-02-05 16:11:55 -080022236 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080022237 if (errno)
22238 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022239
Dustin Brownf0f00612019-01-31 16:02:24 -080022240 errno = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022241
Dustin Brown363b4792019-02-05 16:11:55 -080022242 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080022243
22244 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022245}
22246
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022247#endif /* CONFIG_NL80211_TESTMODE */
22248
22249#ifdef QCA_HT_2040_COEX
22250/**
22251 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
22252 * @wiphy: Pointer to wiphy
22253 * @dev: Pointer to network device
22254 * @chandef: Pointer to channel definition parameter
22255 *
22256 * Return: 0 for success, non-zero for failure
22257 */
22258static int
22259__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
22260 struct net_device *dev,
22261 struct cfg80211_chan_def *chandef)
22262{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022263 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070022264 struct hdd_context *hdd_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022265 QDF_STATUS status;
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053022266 int retval = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022267
Anurag Chouhan6d760662016-02-20 16:05:43 +053022268 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022269 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022270 return -EINVAL;
22271 }
22272
Jeff Johnson48363022019-02-24 16:26:51 -080022273 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022274 return -EINVAL;
Dustin Brown63500612018-08-07 11:36:09 -070022275
Abhishek Singh9d5f4582017-10-11 17:59:48 +053022276 if (!(adapter->device_mode == QDF_SAP_MODE ||
22277 adapter->device_mode == QDF_P2P_GO_MODE))
22278 return -EOPNOTSUPP;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022279
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022280 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070022281 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053022282 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022283 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022284
Abhishek Singh9d5f4582017-10-11 17:59:48 +053022285 hdd_debug("Channel width changed to %d ",
22286 cfg80211_get_chandef_type(chandef));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022287
22288 /* Change SAP ht2040 mode */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022289 status = hdd_set_sap_ht2040_mode(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022290 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022291 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022292 hdd_err("Cannot set SAP HT20/40 mode!");
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053022293 retval = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022294 }
22295
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053022296 return retval;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022297}
22298
22299/**
22300 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
22301 * @wiphy: Pointer to wiphy
22302 * @dev: Pointer to network device
22303 * @chandef: Pointer to channel definition parameter
22304 *
22305 * Return: 0 for success, non-zero for failure
22306 */
22307static int
22308wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
22309 struct net_device *dev,
22310 struct cfg80211_chan_def *chandef)
22311{
Dustin Brown1d31b082018-11-22 14:41:20 +053022312 int errno;
22313 struct osif_vdev_sync *vdev_sync;
22314
22315 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22316 if (errno)
22317 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022318
Dustin Brown1d31b082018-11-22 14:41:20 +053022319 errno = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022320
Dustin Brown1d31b082018-11-22 14:41:20 +053022321 osif_vdev_sync_op_stop(vdev_sync);
22322
22323 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022324}
22325#endif
22326
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022327#ifdef CHANNEL_SWITCH_SUPPORTED
22328/**
22329 * __wlan_hdd_cfg80211_channel_switch()- function to switch
22330 * channel in SAP/GO
22331 * @wiphy: wiphy pointer
22332 * @dev: dev pointer.
22333 * @csa_params: Change channel params
22334 *
22335 * This function is called to switch channel in SAP/GO
22336 *
22337 * Return: 0 if success else return non zero
22338 */
22339static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
22340 struct net_device *dev,
22341 struct cfg80211_csa_settings *csa_params)
22342{
Jeff Johnsone5006672017-08-29 14:39:02 -070022343 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022344 struct hdd_context *hdd_ctx;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022345 uint8_t channel;
22346 uint16_t freq;
22347 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080022348 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022349
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022350 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022351 csa_params->chandef.chan->center_freq);
22352
Jeff Johnson48363022019-02-24 16:26:51 -080022353 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022354 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022355
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022356 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22357 ret = wlan_hdd_validate_context(hdd_ctx);
22358
22359 if (0 != ret)
22360 return ret;
22361
Krunal Sonib4326f22016-03-10 13:05:51 -080022362 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
22363 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022364 return -ENOTSUPP;
Bala Venkatesh8b9bbde2019-07-03 16:25:16 +053022365 wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->vdev_id,
22366 CSA_REASON_USER_INITIATED);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022367
22368 freq = csa_params->chandef.chan->center_freq;
22369 channel = cds_freq_to_chan(freq);
22370
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053022371 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
22372
Min Liu2fef5792018-01-19 17:59:42 +080022373 ret = hdd_softap_set_channel_change(dev, channel, ch_width, false);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022374 return ret;
22375}
22376
22377/**
22378 * wlan_hdd_cfg80211_channel_switch()- function to switch
22379 * channel in SAP/GO
22380 * @wiphy: wiphy pointer
22381 * @dev: dev pointer.
22382 * @csa_params: Change channel params
22383 *
22384 * This function is called to switch channel in SAP/GO
22385 *
22386 * Return: 0 if success else return non zero
22387 */
22388static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
22389 struct net_device *dev,
22390 struct cfg80211_csa_settings *csa_params)
22391{
Dustin Brown1d31b082018-11-22 14:41:20 +053022392 int errno;
22393 struct osif_vdev_sync *vdev_sync;
22394
22395 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22396 if (errno)
22397 return errno;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022398
Dustin Brown1d31b082018-11-22 14:41:20 +053022399 errno = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
Dustin Brown1d31b082018-11-22 14:41:20 +053022400
22401 osif_vdev_sync_op_stop(vdev_sync);
22402
22403 return errno;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022404}
22405#endif
22406
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022407int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter,
22408 uint8_t channel,
22409 enum policy_mgr_conn_update_reason reason)
22410{
22411 QDF_STATUS status;
22412 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22413
Dustin Brown491d54b2018-03-14 12:39:11 -070022414 hdd_enter();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022415 if (0 != wlan_hdd_validate_context(hdd_ctx))
22416 return -EINVAL;
22417
Dustin Brown76cd2932018-09-11 16:03:05 -070022418 status = policy_mgr_reset_connection_update(hdd_ctx->psoc);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022419 if (!QDF_IS_STATUS_SUCCESS(status))
22420 hdd_err("clearing event failed");
22421
Dustin Brown76cd2932018-09-11 16:03:05 -070022422 status = policy_mgr_current_connections_update(hdd_ctx->psoc,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080022423 adapter->vdev_id, channel, reason);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022424 switch (status) {
22425 case QDF_STATUS_E_FAILURE:
22426 /*
Jeff Johnson11d7c9d2018-05-06 15:44:09 -070022427 * QDF_STATUS_E_FAILURE indicates that some error has occurred
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022428 * while changing the hw mode
22429 */
22430 hdd_err("ERROR: connections update failed!!");
22431 return -EINVAL;
22432
22433 case QDF_STATUS_SUCCESS:
22434 /*
22435 * QDF_STATUS_SUCCESS indicates that HW mode change has been
22436 * triggered and wait for it to finish.
22437 */
22438 status = policy_mgr_wait_for_connection_update(
Dustin Brown76cd2932018-09-11 16:03:05 -070022439 hdd_ctx->psoc);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022440 if (!QDF_IS_STATUS_SUCCESS(status)) {
22441 hdd_err("ERROR: qdf wait for event failed!!");
22442 return -EINVAL;
22443 }
22444 if (QDF_MONITOR_MODE == adapter->device_mode)
22445 hdd_info("Monitor mode:channel:%d (SMM->DBS)", channel);
22446 break;
22447
22448 default:
22449 /*
22450 * QDF_STATUS_E_NOSUPPORT indicates that no HW mode change is
22451 * required, so caller can proceed further.
22452 */
22453 break;
22454
22455 }
Dustin Browne74003f2018-03-14 12:51:58 -070022456 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022457
22458 return 0;
22459}
22460
Nirav Shah73713f72018-05-17 14:50:41 +053022461#ifdef FEATURE_MONITOR_MODE_SUPPORT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022462/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022463 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
22464 * @wiphy: Handle to struct wiphy to get handle to module context.
22465 * @chandef: Contains information about the capture channel to be set.
22466 *
22467 * This interface is called if and only if monitor mode interface alone is
22468 * active.
22469 *
22470 * Return: 0 success or error code on failure.
22471 */
22472static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
22473 struct cfg80211_chan_def *chandef)
22474{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022475 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsone5006672017-08-29 14:39:02 -070022476 struct hdd_adapter *adapter;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070022477 struct hdd_station_ctx *sta_ctx;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022478 struct hdd_mon_set_ch_info *ch_info;
22479 QDF_STATUS status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022480 mac_handle_t mac_handle;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022481 struct qdf_mac_addr bssid;
Jeff Johnson61b5e982018-03-15 11:33:31 -070022482 struct csr_roam_profile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080022483 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070022484 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022485 int ret;
22486 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
22487
Dustin Brown491d54b2018-03-14 12:39:11 -070022488 hdd_enter();
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022489
22490 ret = wlan_hdd_validate_context(hdd_ctx);
22491 if (ret)
22492 return ret;
22493
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022494 mac_handle = hdd_ctx->mac_handle;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022495
22496 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
22497 if (!adapter)
22498 return -EIO;
22499
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022500 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022501 adapter->dev->name, chan_num, chandef->chan->center_freq);
22502
22503 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
22504 ch_info = &sta_ctx->ch_info;
wadesong24c869a2019-07-19 17:38:59 +080022505 roam_profile.ChannelInfo.freq_list = &ch_info->freq;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022506 roam_profile.ChannelInfo.numOfChannels = 1;
22507 roam_profile.phyMode = ch_info->phy_mode;
Naveen Rawat3184dd82017-07-05 14:58:18 -070022508 roam_profile.ch_params.ch_width = hdd_map_nl_chan_width(chandef->width);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070022509 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022510
Jeff Johnson1e851a12017-10-28 14:36:12 -070022511 qdf_mem_copy(bssid.bytes, adapter->mac_addr.bytes,
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022512 QDF_MAC_ADDR_SIZE);
22513
Naveen Rawat3184dd82017-07-05 14:58:18 -070022514 ch_params.ch_width = hdd_map_nl_chan_width(chandef->width);
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070022515 /*
22516 * CDS api expects secondary channel for calculating
22517 * the channel params
22518 */
22519 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070022520 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070022521 if (chan_num >= 1 && chan_num <= 5)
22522 sec_ch = chan_num + 4;
22523 else if (chan_num >= 6 && chan_num <= 13)
22524 sec_ch = chan_num - 4;
22525 }
Dustin Brown07901ec2018-09-07 11:02:41 -070022526 wlan_reg_set_channel_params(hdd_ctx->pdev, chan_num,
22527 sec_ch, &ch_params);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022528 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, chan_num,
22529 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
22530 hdd_err("Failed to change hw mode");
22531 return -EINVAL;
22532 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022533 status = sme_roam_channel_change_req(mac_handle, bssid, &ch_params,
22534 &roam_profile);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022535 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022536 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022537 status);
22538 ret = qdf_status_to_os_return(status);
22539 return ret;
22540 }
Dustin Browne74003f2018-03-14 12:51:58 -070022541 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022542
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022543 return 0;
22544}
22545
22546/**
22547 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
22548 * @wiphy: Handle to struct wiphy to get handle to module context.
22549 * @chandef: Contains information about the capture channel to be set.
22550 *
22551 * This interface is called if and only if monitor mode interface alone is
22552 * active.
22553 *
22554 * Return: 0 success or error code on failure.
22555 */
22556static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
22557 struct cfg80211_chan_def *chandef)
22558{
Dustin Brown363b4792019-02-05 16:11:55 -080022559 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080022560 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +053022561
Dustin Brown363b4792019-02-05 16:11:55 -080022562 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080022563 if (errno)
22564 return errno;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022565
Dustin Brownf0f00612019-01-31 16:02:24 -080022566 errno = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
Arunk Khandavalli447837f2018-11-08 14:32:53 +053022567
Dustin Brown363b4792019-02-05 16:11:55 -080022568 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080022569
22570 return errno;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022571}
Nirav Shah73713f72018-05-17 14:50:41 +053022572#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022573
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022574#define CNT_DIFF(cur, prev) \
22575 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
22576#define MAX_COUNT 0xffffffff
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022577static void hdd_update_chan_info(struct hdd_context *hdd_ctx,
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022578 struct scan_chan_info *chan,
22579 struct scan_chan_info *info, uint32_t cmd_flag)
22580{
22581 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
22582 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
22583 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
22584
22585 mutex_lock(&hdd_ctx->chan_info_lock);
22586
22587 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
22588 qdf_mem_zero(chan, sizeof(*chan));
22589
22590 chan->freq = info->freq;
22591 chan->noise_floor = info->noise_floor;
22592 chan->clock_freq = info->clock_freq;
22593 chan->cmd_flag = info->cmd_flag;
22594 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
22595
22596 chan->rx_clear_count =
22597 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
22598
22599 chan->tx_frame_count =
22600 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
22601
22602 mutex_unlock(&hdd_ctx->chan_info_lock);
22603
22604}
22605#undef CNT_DIFF
22606#undef MAX_COUNT
22607
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053022608#ifndef UPDATE_ASSOC_IE
22609#define UPDATE_ASSOC_IE BIT(0)
22610#endif
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022611
22612#ifndef UPDATE_FILS_ERP_INFO
22613#define UPDATE_FILS_ERP_INFO BIT(1)
22614#endif
22615
22616#ifndef UPDATE_FILS_AUTH_TYPE
22617#define UPDATE_FILS_AUTH_TYPE BIT(2)
22618#endif
22619
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053022620#if defined(WLAN_FEATURE_FILS_SK) &&\
22621 defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) &&\
22622 (defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
22623 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
22624
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022625/**
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053022626 * hdd_update_connect_params_fils_info() - Update fils parameters based on
22627 * the update_connect_params received from userspace
22628 * @adapter: Pointer to hdd_adapter
22629 * @hdd_ctx: Pointer to hdd_context
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022630 * @req: Pointer to connect params
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053022631 * @changed: bitmap indicating which parameters have changed
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022632 *
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053022633 * Return 0 on SUCCESS or error code on FAILURE
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022634 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022635static int
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053022636hdd_update_connect_params_fils_info(struct hdd_adapter *adapter,
22637 struct hdd_context *hdd_ctx,
22638 struct cfg80211_connect_params *req,
22639 uint32_t changed)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022640{
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022641 uint8_t *buf;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022642 QDF_STATUS status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022643 mac_handle_t mac_handle;
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053022644 struct csr_roam_profile *roam_profile;
22645 struct cds_fils_connection_info *fils_info;
22646 enum eAniAuthType auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022647
Jeff Johnson20227a92018-03-13 09:41:05 -070022648 roam_profile = hdd_roam_profile(adapter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022649 fils_info = roam_profile->fils_con_info;
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053022650 mac_handle = hdd_ctx->mac_handle;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022651 if (!fils_info) {
22652 hdd_err("No valid FILS conn info");
22653 return -EINVAL;
22654 }
22655
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053022656 fils_info->is_fils_connection = true;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022657 if (changed & UPDATE_FILS_ERP_INFO) {
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080022658 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080022659 return -EINVAL;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022660 fils_info->key_nai_length = req->fils_erp_username_len +
22661 sizeof(char) +
22662 req->fils_erp_realm_len;
Dundi Raviteja170d2872018-03-23 15:49:54 +053022663 if (fils_info->key_nai_length >
22664 FILS_MAX_KEYNAME_NAI_LENGTH) {
22665 hdd_err("Key NAI Length %d",
22666 fils_info->key_nai_length);
22667 return -EINVAL;
22668 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022669 if (req->fils_erp_username_len && req->fils_erp_username) {
22670 buf = fils_info->keyname_nai;
22671 qdf_mem_copy(buf, req->fils_erp_username,
22672 req->fils_erp_username_len);
22673 buf += req->fils_erp_username_len;
22674 *buf++ = '@';
22675 qdf_mem_copy(buf, req->fils_erp_realm,
22676 req->fils_erp_realm_len);
22677 }
22678
Pragaspathi Thilagaraj87a60af2019-02-20 20:42:47 +053022679 fils_info->sequence_number = req->fils_erp_next_seq_num + 1;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022680 fils_info->r_rk_length = req->fils_erp_rrk_len;
22681
22682 if (req->fils_erp_rrk_len && req->fils_erp_rrk)
22683 qdf_mem_copy(fils_info->r_rk, req->fils_erp_rrk,
22684 fils_info->r_rk_length);
22685
22686 fils_info->realm_len = req->fils_erp_realm_len;
22687 if (req->fils_erp_realm_len && req->fils_erp_realm)
22688 qdf_mem_copy(fils_info->realm, req->fils_erp_realm,
22689 fils_info->realm_len);
22690 }
22691
22692 if (changed & UPDATE_FILS_AUTH_TYPE) {
22693 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070022694 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022695 hdd_err("invalid auth type for fils %d",
22696 req->auth_type);
22697 return -EINVAL;
22698 }
22699
22700 roam_profile->fils_con_info->auth_type = auth_type;
22701 }
22702
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080022703 hdd_debug("fils conn update: changed %x is_fils %d keyname nai len %d",
22704 changed, roam_profile->fils_con_info->is_fils_connection,
22705 roam_profile->fils_con_info->key_nai_length);
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053022706 /*
22707 * Update the FILS config from adapter->roam_profile to
22708 * csr_session
22709 */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080022710 status = sme_update_fils_config(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022711 roam_profile);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022712 if (QDF_IS_STATUS_ERROR(status))
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053022713 hdd_err("Update FILS connect params to csr failed %d", status);
22714
22715 return 0;
22716}
22717#else
22718
Lin Bai9dc616c2019-04-10 10:08:49 +080022719static inline int
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053022720hdd_update_connect_params_fils_info(struct hdd_adapter *adapter,
22721 struct hdd_context *hdd_ctx,
22722 struct cfg80211_connect_params *req,
22723 uint32_t changed)
22724{
22725 return -EINVAL;
22726}
22727
22728#endif
22729
22730#if defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
22731 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
22732
22733/**
22734 * __wlan_hdd_cfg80211_update_connect_params - update connect params
22735 * @wiphy: Handle to struct wiphy to get handle to module context.
22736 * @dev: Pointer to network device
22737 * @req: Pointer to connect params
22738 * @changed: Bitmap used to indicate the changed params
22739 *
22740 * Update the connect parameters while connected to a BSS. The updated
22741 * parameters can be used by driver/firmware for subsequent BSS selection
22742 * (roaming) decisions and to form the Authentication/(Re)Association
22743 * Request frames. This call does not request an immediate disassociation
22744 * or reassociation with the current BSS, i.e., this impacts only
22745 * subsequent (re)associations. The bits in changed are defined in enum
22746 * cfg80211_connect_params_changed
22747 *
22748 * Return: zero for success, non-zero for failure
22749 */
22750static int
22751__wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
22752 struct net_device *dev,
22753 struct cfg80211_connect_params *req,
22754 uint32_t changed)
22755{
22756 struct csr_roam_profile *roam_profile;
22757 int ret;
22758 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
22759 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
22760 QDF_STATUS status;
22761 mac_handle_t mac_handle;
22762
22763 hdd_enter_dev(dev);
22764
22765 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
22766 return -EINVAL;
22767
22768 ret = wlan_hdd_validate_context(hdd_ctx);
22769 if (ret)
22770 return -EINVAL;
22771
22772 mac_handle = hdd_ctx->mac_handle;
22773 roam_profile = hdd_roam_profile(adapter);
22774
22775 if (changed & UPDATE_ASSOC_IE) {
22776 /*
22777 * Validate the elements of the IE and copy it to
22778 * roam_profile in adapter
22779 */
22780 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
22781
22782 /*
22783 * Update this assoc IE received from user space to
22784 * csr_session. RSO command will pick up the assoc
22785 * IEs to be sent to firmware from the csr_session.
22786 */
22787 sme_update_session_assoc_ie(mac_handle, adapter->vdev_id,
22788 roam_profile);
22789 }
22790
22791 if ((changed & UPDATE_FILS_ERP_INFO) ||
22792 (changed & UPDATE_FILS_AUTH_TYPE)) {
22793 ret = hdd_update_connect_params_fils_info(adapter, hdd_ctx,
22794 req, changed);
22795 if (ret)
22796 return -EINVAL;
22797
22798 if (!hdd_ctx->is_fils_roaming_supported) {
22799 hdd_debug("FILS roaming support %d",
22800 hdd_ctx->is_fils_roaming_supported);
22801 return 0;
22802 }
22803 }
22804
22805 if (changed) {
22806 status = sme_send_rso_connect_params(mac_handle,
22807 adapter->vdev_id,
22808 roam_profile);
22809 if (QDF_IS_STATUS_ERROR(status))
22810 hdd_err("Update connect params to fw failed %d",
22811 status);
22812 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022813
22814 return 0;
22815}
22816
22817/**
22818 * wlan_hdd_cfg80211_update_connect_params - SSR wrapper for
22819 * __wlan_hdd_cfg80211_update_connect_params
22820 * @wiphy: Pointer to wiphy structure
22821 * @dev: Pointer to net_device
22822 * @req: Pointer to connect params
22823 * @changed: flags used to indicate the changed params
22824 *
22825 * Return: zero for success, non-zero for failure
22826 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022827static int
22828wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
22829 struct net_device *dev,
22830 struct cfg80211_connect_params *req,
22831 uint32_t changed)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022832{
Dustin Brown1d31b082018-11-22 14:41:20 +053022833 int errno;
22834 struct osif_vdev_sync *vdev_sync;
22835
22836 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22837 if (errno)
22838 return errno;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022839
Dustin Brown1d31b082018-11-22 14:41:20 +053022840 errno = __wlan_hdd_cfg80211_update_connect_params(wiphy, dev,
22841 req, changed);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022842
Dustin Brown1d31b082018-11-22 14:41:20 +053022843 osif_vdev_sync_op_stop(vdev_sync);
22844
22845 return errno;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022846}
22847#endif
22848
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022849#if defined(WLAN_FEATURE_SAE) && \
22850 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
Srinivas Dasari29186ca2019-02-11 18:45:48 +053022851#if defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT)
22852/**
22853 * wlan_hdd_extauth_cache_pmkid() - Extract and cache pmkid
22854 * @adapter: hdd vdev/net_device context
22855 * @mac_handle: Handle to the MAC
22856 * @params: Pointer to external auth params.
22857 *
22858 * Extract the PMKID and BSS from external auth params and add to the
22859 * PMKSA Cache in CSR.
22860 */
22861static void
22862wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
22863 mac_handle_t mac_handle,
22864 struct cfg80211_external_auth_params *params)
22865{
22866 tPmkidCacheInfo pmk_cache;
22867 QDF_STATUS result;
22868 if (params->pmkid) {
22869 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
22870 qdf_mem_copy(pmk_cache.BSSID.bytes, params->bssid,
22871 QDF_MAC_ADDR_SIZE);
22872 qdf_mem_copy(pmk_cache.PMKID, params->pmkid,
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -070022873 PMKID_LEN);
Liangwei Donga44d55b2019-03-20 03:22:08 -040022874 result = wlan_hdd_set_pmksa_cache(adapter, &pmk_cache);
Srinivas Dasari29186ca2019-02-11 18:45:48 +053022875 if (!QDF_IS_STATUS_SUCCESS(result))
22876 hdd_debug("external_auth: Failed to cache PMKID");
22877 }
22878}
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053022879
22880/**
22881 * wlan_hdd_extauth_copy_pmkid() - Copy the pmkid received from the
22882 * external authentication command received from the userspace.
22883 * @params: pointer to auth params
22884 * @pmkid: Pointer to destination pmkid buffer to be filled
22885 *
22886 * The caller should ensure that destination pmkid buffer is not NULL.
22887 *
22888 * Return: None
22889 */
22890static void
22891wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params *params,
22892 uint8_t *pmkid)
22893{
Pragaspathi Thilagarajaf840592019-08-14 11:45:32 +053022894 if (params->pmkid)
22895 qdf_mem_copy(pmkid, params->pmkid, PMKID_LEN);
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053022896}
22897
Srinivas Dasari29186ca2019-02-11 18:45:48 +053022898#else
22899static void
22900wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
22901 mac_handle_t mac_handle,
22902 struct cfg80211_external_auth_params *params)
22903{}
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053022904
22905static void
22906wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params *params,
22907 uint8_t *pmkid)
22908{}
Srinivas Dasari29186ca2019-02-11 18:45:48 +053022909#endif
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022910/**
22911 * __wlan_hdd_cfg80211_external_auth() - Handle external auth
Srinivas Dasari29186ca2019-02-11 18:45:48 +053022912 *
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022913 * @wiphy: Pointer to wireless phy
22914 * @dev: net device
Srinivas Dasari29186ca2019-02-11 18:45:48 +053022915 * @params: Pointer to external auth params.
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022916 * Return: 0 on success, negative errno on failure
Srinivas Dasari29186ca2019-02-11 18:45:48 +053022917 *
22918 * Userspace sends status of the external authentication(e.g., SAE) with a peer.
22919 * The message carries BSSID of the peer and auth status (WLAN_STATUS_SUCCESS/
22920 * WLAN_STATUS_UNSPECIFIED_FAILURE) in params.
22921 * Userspace may send PMKID in params, which can be used for
22922 * further connections.
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022923 */
22924static int
22925__wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
22926 struct net_device *dev,
22927 struct cfg80211_external_auth_params *params)
22928{
22929 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
22930 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
22931 int ret;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022932 mac_handle_t mac_handle;
Srinivas Dasarie854ff02019-02-11 17:24:48 +053022933 struct qdf_mac_addr peer_mac_addr;
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053022934 uint8_t pmkid[PMKID_LEN] = {0};
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022935
22936 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
22937 hdd_err("Command not allowed in FTM mode");
22938 return -EPERM;
22939 }
22940
Jeff Johnson48363022019-02-24 16:26:51 -080022941 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022942 return -EINVAL;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022943
22944 ret = wlan_hdd_validate_context(hdd_ctx);
22945 if (ret)
22946 return ret;
22947
Srinivas Dasarie854ff02019-02-11 17:24:48 +053022948 hdd_debug("external_auth status: %d peer mac: " QDF_MAC_ADDR_STR,
22949 params->status, QDF_MAC_ADDR_ARRAY(params->bssid));
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022950 mac_handle = hdd_ctx->mac_handle;
Srinivas Dasarie854ff02019-02-11 17:24:48 +053022951 qdf_mem_copy(peer_mac_addr.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Srinivas Dasari29186ca2019-02-11 18:45:48 +053022952
22953 wlan_hdd_extauth_cache_pmkid(adapter, mac_handle, params);
22954
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053022955 wlan_hdd_extauth_copy_pmkid(params, pmkid);
Srinivas Dasarie854ff02019-02-11 17:24:48 +053022956 sme_handle_sae_msg(mac_handle, adapter->vdev_id, params->status,
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053022957 peer_mac_addr, pmkid);
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022958
22959 return ret;
22960}
22961
22962/**
22963 * wlan_hdd_cfg80211_external_auth() - Handle external auth
22964 * @wiphy: Pointer to wireless phy
22965 * @dev: net device
22966 * @params: Pointer to external auth params
22967 *
22968 * Return: 0 on success, negative errno on failure
22969 */
22970static int
22971wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
22972 struct net_device *dev,
22973 struct cfg80211_external_auth_params *params)
22974{
Dustin Brown1d31b082018-11-22 14:41:20 +053022975 int errno;
22976 struct osif_vdev_sync *vdev_sync;
22977
22978 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22979 if (errno)
22980 return errno;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022981
Dustin Brown1d31b082018-11-22 14:41:20 +053022982 errno = __wlan_hdd_cfg80211_external_auth(wiphy, dev, params);
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022983
Dustin Brown1d31b082018-11-22 14:41:20 +053022984 osif_vdev_sync_op_stop(vdev_sync);
22985
22986 return errno;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022987}
22988#endif
22989
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022990/**
22991 * wlan_hdd_chan_info_cb() - channel info callback
22992 * @chan_info: struct scan_chan_info
22993 *
22994 * Store channel info into HDD context
22995 *
22996 * Return: None.
22997 */
22998static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
22999{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070023000 struct hdd_context *hdd_ctx;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023001 struct scan_chan_info *chan;
23002 uint8_t idx;
23003
Dustin Brown491d54b2018-03-14 12:39:11 -070023004 hdd_enter();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023005
23006 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
23007 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
23008 hdd_err("hdd_ctx is invalid");
23009 return;
23010 }
23011
23012 if (!hdd_ctx->chan_info) {
23013 hdd_err("chan_info is NULL");
23014 return;
23015 }
23016
23017 chan = hdd_ctx->chan_info;
23018 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
23019 if (chan[idx].freq == info->freq) {
23020 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
23021 info->cmd_flag);
Rajeev Kumareb6ec172018-09-26 20:45:36 -070023022 hdd_debug("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
23023 chan[idx].cmd_flag, chan[idx].freq,
23024 chan[idx].noise_floor,
23025 chan[idx].cycle_count,
23026 chan[idx].rx_clear_count,
23027 chan[idx].clock_freq, chan[idx].cmd_flag,
23028 chan[idx].tx_frame_count, idx);
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023029 if (chan[idx].freq == 0)
23030 break;
23031
23032 }
23033 }
23034
Dustin Browne74003f2018-03-14 12:51:58 -070023035 hdd_exit();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023036}
23037
23038/**
23039 * wlan_hdd_init_chan_info() - init chan info in hdd context
23040 * @hdd_ctx: HDD context pointer
23041 *
23042 * Return: none
23043 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070023044void wlan_hdd_init_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023045{
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053023046 uint32_t num_2g, num_5g, index = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023047 mac_handle_t mac_handle;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023048
Kapil Gupta63e75282017-05-18 20:55:10 +053023049 hdd_ctx->chan_info = NULL;
Jeff Johnsona8fef4e2019-03-11 14:38:49 -070023050 if (!hdd_ctx->config->enable_snr_monitoring) {
Dustin Brown31116772018-08-15 14:59:21 -070023051 hdd_debug("SNR monitoring is disabled");
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023052 return;
23053 }
23054
23055 hdd_ctx->chan_info =
23056 qdf_mem_malloc(sizeof(struct scan_chan_info)
23057 * QDF_MAX_NUM_CHAN);
Min Liu74a1a502018-10-10 19:59:07 +080023058 if (!hdd_ctx->chan_info)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023059 return;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023060 mutex_init(&hdd_ctx->chan_info_lock);
23061
23062 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
23063 for (; index < num_2g; index++) {
23064 hdd_ctx->chan_info[index].freq =
23065 hdd_channels_2_4_ghz[index].center_freq;
23066 }
23067
23068 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
23069 for (; (index - num_2g) < num_5g; index++) {
Dustin Brown07901ec2018-09-07 11:02:41 -070023070 if (wlan_reg_is_dsrc_chan(hdd_ctx->pdev,
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070023071 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023072 continue;
23073 hdd_ctx->chan_info[index].freq =
23074 hdd_channels_5_ghz[index - num_2g].center_freq;
23075 }
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053023076
23077 index = num_2g + num_5g;
23078 index = wlan_hdd_populate_srd_chan_info(hdd_ctx, index);
23079
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023080 mac_handle = hdd_ctx->mac_handle;
23081 sme_set_chan_info_callback(mac_handle,
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023082 &wlan_hdd_chan_info_cb);
23083}
23084
23085/**
23086 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
23087 * @hdd_ctx: hdd context pointer
23088 *
23089 * Return: none
23090 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070023091void wlan_hdd_deinit_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023092{
23093 struct scan_chan_info *chan;
23094
23095 chan = hdd_ctx->chan_info;
23096 hdd_ctx->chan_info = NULL;
23097 if (chan)
23098 qdf_mem_free(chan);
23099}
23100
Dustin Brown32cb4792017-06-15 15:33:42 -070023101#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
23102static enum rate_info_bw hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
23103{
23104 switch (hdd_bw) {
23105 case HDD_RATE_BW_5:
23106 return RATE_INFO_BW_5;
23107 case HDD_RATE_BW_10:
23108 return RATE_INFO_BW_10;
23109 case HDD_RATE_BW_20:
23110 return RATE_INFO_BW_20;
23111 case HDD_RATE_BW_40:
23112 return RATE_INFO_BW_40;
23113 case HDD_RATE_BW_80:
23114 return RATE_INFO_BW_80;
23115 case HDD_RATE_BW_160:
23116 return RATE_INFO_BW_160;
23117 }
23118
23119 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
23120
23121 return RATE_INFO_BW_20;
23122}
23123
23124void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
23125{
23126 info->bw = hdd_map_hdd_bw_to_os(hdd_bw);
23127}
23128#else
23129static enum rate_info_flags hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
23130{
23131 switch (hdd_bw) {
23132 case HDD_RATE_BW_5:
23133 case HDD_RATE_BW_10:
23134 case HDD_RATE_BW_20:
23135 return (enum rate_info_flags)0;
23136 case HDD_RATE_BW_40:
23137 return RATE_INFO_FLAGS_40_MHZ_WIDTH;
23138 case HDD_RATE_BW_80:
23139 return RATE_INFO_FLAGS_80_MHZ_WIDTH;
23140 case HDD_RATE_BW_160:
23141 return RATE_INFO_FLAGS_160_MHZ_WIDTH;
23142 }
23143
23144 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
23145
23146 return (enum rate_info_flags)0;
23147}
23148
23149void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
23150{
23151 const enum rate_info_flags all_bws =
23152 RATE_INFO_FLAGS_40_MHZ_WIDTH |
23153 RATE_INFO_FLAGS_80_MHZ_WIDTH |
23154 RATE_INFO_FLAGS_80P80_MHZ_WIDTH |
23155 RATE_INFO_FLAGS_160_MHZ_WIDTH;
23156
23157 info->flags &= ~all_bws;
23158 info->flags |= hdd_map_hdd_bw_to_os(hdd_bw);
23159}
23160#endif
23161
Min Liue34708a2019-02-01 15:00:34 +080023162#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
23163void hdd_send_update_owe_info_event(struct hdd_adapter *adapter,
23164 uint8_t sta_addr[],
23165 uint8_t *owe_ie,
23166 uint32_t owe_ie_len)
23167{
23168 struct cfg80211_update_owe_info owe_info;
23169 struct net_device *dev = adapter->dev;
23170
23171 hdd_enter_dev(dev);
23172
Min Liue2b469f2019-04-10 19:13:42 +080023173 qdf_mem_copy(owe_info.peer, sta_addr, ETH_ALEN);
Min Liue34708a2019-02-01 15:00:34 +080023174 owe_info.ie = owe_ie;
23175 owe_info.ie_len = owe_ie_len;
23176
23177 cfg80211_update_owe_info_event(dev, &owe_info, GFP_KERNEL);
23178
23179 hdd_exit();
23180}
23181#endif
23182
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053023183/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023184 * struct cfg80211_ops - cfg80211_ops
23185 *
23186 * @add_virtual_intf: Add virtual interface
23187 * @del_virtual_intf: Delete virtual interface
23188 * @change_virtual_intf: Change virtual interface
23189 * @change_station: Change station
23190 * @add_beacon: Add beacon in sap mode
23191 * @del_beacon: Delete beacon in sap mode
23192 * @set_beacon: Set beacon in sap mode
23193 * @start_ap: Start ap
23194 * @change_beacon: Change beacon
23195 * @stop_ap: Stop ap
23196 * @change_bss: Change bss
23197 * @add_key: Add key
23198 * @get_key: Get key
23199 * @del_key: Delete key
23200 * @set_default_key: Set default key
23201 * @set_channel: Set channel
23202 * @scan: Scan
23203 * @connect: Connect
23204 * @disconnect: Disconnect
23205 * @join_ibss = Join ibss
23206 * @leave_ibss = Leave ibss
23207 * @set_wiphy_params = Set wiphy params
23208 * @set_tx_power = Set tx power
23209 * @get_tx_power = get tx power
23210 * @remain_on_channel = Remain on channel
23211 * @cancel_remain_on_channel = Cancel remain on channel
23212 * @mgmt_tx = Tx management frame
23213 * @mgmt_tx_cancel_wait = Cancel management tx wait
23214 * @set_default_mgmt_key = Set default management key
23215 * @set_txq_params = Set tx queue parameters
23216 * @get_station = Get station
23217 * @set_power_mgmt = Set power management
23218 * @del_station = Delete station
23219 * @add_station = Add station
23220 * @set_pmksa = Set pmksa
23221 * @del_pmksa = Delete pmksa
23222 * @flush_pmksa = Flush pmksa
23223 * @update_ft_ies = Update FT IEs
23224 * @tdls_mgmt = Tdls management
23225 * @tdls_oper = Tdls operation
23226 * @set_rekey_data = Set rekey data
23227 * @sched_scan_start = Scheduled scan start
23228 * @sched_scan_stop = Scheduled scan stop
23229 * @resume = Resume wlan
23230 * @suspend = Suspend wlan
23231 * @set_mac_acl = Set mac acl
23232 * @testmode_cmd = Test mode command
23233 * @set_ap_chanwidth = Set AP channel bandwidth
23234 * @dump_survey = Dump survey
23235 * @key_mgmt_set_pmk = Set pmk key management
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023236 * @update_connect_params = Update connect params
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023237 */
23238static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
23239 .add_virtual_intf = wlan_hdd_add_virtual_intf,
23240 .del_virtual_intf = wlan_hdd_del_virtual_intf,
23241 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
23242 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023243 .start_ap = wlan_hdd_cfg80211_start_ap,
23244 .change_beacon = wlan_hdd_cfg80211_change_beacon,
23245 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023246 .change_bss = wlan_hdd_cfg80211_change_bss,
23247 .add_key = wlan_hdd_cfg80211_add_key,
23248 .get_key = wlan_hdd_cfg80211_get_key,
23249 .del_key = wlan_hdd_cfg80211_del_key,
23250 .set_default_key = wlan_hdd_cfg80211_set_default_key,
23251 .scan = wlan_hdd_cfg80211_scan,
23252 .connect = wlan_hdd_cfg80211_connect,
23253 .disconnect = wlan_hdd_cfg80211_disconnect,
23254 .join_ibss = wlan_hdd_cfg80211_join_ibss,
23255 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
23256 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
23257 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
23258 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
23259 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
23260 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
23261 .mgmt_tx = wlan_hdd_mgmt_tx,
23262 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
23263 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
23264 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053023265 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023266 .get_station = wlan_hdd_cfg80211_get_station,
23267 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
23268 .del_station = wlan_hdd_cfg80211_del_station,
23269 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023270 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
23271 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
23272 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080023273#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023274 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
23275#endif
Min Liu0daa0982019-02-01 17:50:44 +080023276#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
23277 .update_owe_info = wlan_hdd_cfg80211_update_owe_info,
23278#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023279#ifdef FEATURE_WLAN_TDLS
23280 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
23281 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
23282#endif
23283#ifdef WLAN_FEATURE_GTK_OFFLOAD
23284 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
23285#endif /* WLAN_FEATURE_GTK_OFFLOAD */
23286#ifdef FEATURE_WLAN_SCAN_PNO
23287 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
23288 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
23289#endif /*FEATURE_WLAN_SCAN_PNO */
23290 .resume = wlan_hdd_cfg80211_resume_wlan,
23291 .suspend = wlan_hdd_cfg80211_suspend_wlan,
23292 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
23293#ifdef WLAN_NL80211_TESTMODE
23294 .testmode_cmd = wlan_hdd_cfg80211_testmode,
23295#endif
23296#ifdef QCA_HT_2040_COEX
23297 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
23298#endif
23299 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053023300#ifdef CHANNEL_SWITCH_SUPPORTED
23301 .channel_switch = wlan_hdd_cfg80211_channel_switch,
23302#endif
Nirav Shah73713f72018-05-17 14:50:41 +053023303#ifdef FEATURE_MONITOR_MODE_SUPPORT
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023304 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Nirav Shah73713f72018-05-17 14:50:41 +053023305#endif
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053023306#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
Srinivas Girigowda576b2352017-08-25 14:44:26 -070023307 defined(CFG80211_ABORT_SCAN)
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053023308 .abort_scan = wlan_hdd_cfg80211_abort_scan,
23309#endif
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023310#if defined(CFG80211_UPDATE_CONNECT_PARAMS) || \
23311 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023312 .update_connect_params = wlan_hdd_cfg80211_update_connect_params,
23313#endif
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023314#if defined(WLAN_FEATURE_SAE) && \
23315 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
23316 .external_auth = wlan_hdd_cfg80211_external_auth,
23317#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023318};