blob: 6064cd7b05e380a7722e76b9f8c093c99a66c14f [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Srinivas Dasarid2ba2612019-12-11 17:27:52 +05302 * Copyright (c) 2012-2020 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>
Subrat Dashe1f1da82019-10-21 15:54:15 +053036#include <net/mac80211.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080037#include <wlan_hdd_wowl.h>
38#include <ani_global.h>
39#include "sir_params.h"
40#include "dot11f.h"
41#include "wlan_hdd_assoc.h"
42#include "wlan_hdd_wext.h"
43#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070044#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include "wlan_hdd_p2p.h"
46#include "wlan_hdd_cfg80211.h"
47#include "wlan_hdd_hostapd.h"
48#include "wlan_hdd_softap_tx_rx.h"
49#include "wlan_hdd_main.h"
50#include "wlan_hdd_power.h"
51#include "wlan_hdd_trace.h"
Rakesh Pillai6c48d132020-06-30 15:22:01 +053052#include "wlan_hdd_tx_rx.h"
Dustin Brownd4241942018-02-26 12:51:37 -080053#include "qdf_str.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053054#include "qdf_trace.h"
Dustin Brownd4241942018-02-26 12:51:37 -080055#include "qdf_types.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080056#include "cds_utils.h"
57#include "cds_sched.h"
58#include "wlan_hdd_scan.h"
59#include <qc_sap_ioctl.h>
60#include "wlan_hdd_tdls.h"
61#include "wlan_hdd_wmm.h"
62#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053063#include "wma.h"
Arif Hussain1f58cbb2019-03-14 17:06:56 -070064#include "wma_twt.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080065#include "wlan_hdd_misc.h"
66#include "wlan_hdd_nan.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080067#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053068#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053069#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053070#include "pld_common.h"
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070071#include "wmi_unified_param.h"
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070072
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080073#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080074#include <wlan_cfg80211_scan.h>
Ryan Hsuc8b27a42018-01-02 13:57:56 -080075#include <wlan_cfg80211_ftm.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080076
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077#include "wlan_hdd_ext_scan.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080078
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080079#include "wlan_hdd_stats.h"
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080080#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080081#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080082#include "qwlan_version.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083
84#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070085#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080086
Ravi Joshideb5a8d2015-11-09 19:11:43 -080087#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053088#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070089#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070090#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053091#include "wlan_hdd_disa.h"
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070092#include "wlan_osif_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080093#include "wlan_hdd_he.h"
Nachiket Kukade177b5b02018-05-22 20:52:17 +053094#ifdef FEATURE_WLAN_APF
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053095#include "wlan_hdd_apf.h"
Nachiket Kukade177b5b02018-05-22 20:52:17 +053096#endif
Qun Zhangef655622019-02-25 10:48:10 +080097#include "wlan_hdd_fw_state.h"
stonez2d686482019-03-12 14:54:26 +080098#include "wlan_hdd_mpta_helper.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -080099
Leo Changfdb45c32016-10-28 11:09:23 -0700100#include <cdp_txrx_cmn.h>
101#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800102#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530103#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800104#include "os_if_wifi_pos.h"
Ajit Pal Singh90a45a42017-04-18 18:53:46 +0530105#include "wlan_utility.h"
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -0700106#include "wlan_reg_ucfg_api.h"
Naveen Rawatd2657be2017-10-10 14:31:23 -0700107#include "wifi_pos_api.h"
Sandeep Puligilla063a4342018-01-10 02:50:14 -0800108#include "wlan_hdd_spectralscan.h"
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +0530109#include "wlan_ipa_ucfg_api.h"
Naveen Rawate8b1b822018-01-30 09:46:16 -0800110#include <wlan_cfg80211_mc_cp_stats.h>
Yu Wang157d1472018-03-09 16:05:01 +0800111#include <wlan_cp_stats_mc_ucfg_api.h>
Wu Gaobdb7f272018-07-05 19:33:26 +0800112#include "wlan_tdls_cfg_api.h"
Qiwei Caie689a262018-07-26 15:50:22 +0800113#include <wlan_hdd_bss_transition.h>
114#include <wlan_hdd_concurrency_matrix.h>
115#include <wlan_hdd_p2p_listen_offload.h>
116#include <wlan_hdd_rssi_monitor.h>
117#include <wlan_hdd_sap_cond_chan_switch.h>
118#include <wlan_hdd_station_info.h>
119#include <wlan_hdd_tx_power.h>
120#include <wlan_hdd_active_tos.h>
121#include <wlan_hdd_sar_limits.h>
122#include <wlan_hdd_ota_test.h>
Krunal Soni5e3f9622018-09-26 16:35:50 -0700123#include "wlan_policy_mgr_ucfg.h"
Arunk Khandavalli99716d12018-11-14 15:02:02 +0530124#include "wlan_mlme_ucfg_api.h"
125#include "wlan_mlme_public_struct.h"
Harprit Chhabadae8155d32018-08-22 16:19:34 -0700126#include "wlan_extscan_ucfg_api.h"
Wu Gao93816212018-08-31 16:49:54 +0800127#include "wlan_mlme_ucfg_api.h"
Wu Gao66454f12018-09-26 19:55:41 +0800128#include "wlan_pmo_cfg.h"
129#include "cfg_ucfg_api.h"
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +0530130
Harprit Chhabada6c641ba2018-06-28 14:45:10 -0700131#include "wlan_crypto_global_api.h"
132#include "wlan_nl_to_crypto_params.h"
133#include "wlan_crypto_global_def.h"
jitiphil377bcc12018-10-05 19:46:08 +0530134#include "cdp_txrx_cfg.h"
Min Liu8c5d99e2018-09-10 17:18:44 +0800135#include "wlan_hdd_object_manager.h"
Nachiket Kukade089b9832018-12-12 16:38:17 +0530136#include "nan_ucfg_api.h"
Manikandan Mohand350c192018-11-29 14:01:12 -0800137#include "wlan_fwol_ucfg_api.h"
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -0700138#include "wlan_cfg80211_crypto.h"
Paul Zhang37185672019-05-14 11:20:14 +0800139#include "wlan_cfg80211_interop_issues_ap.h"
gaurank kathpalia97c070b2019-01-07 17:23:06 +0530140#include "wlan_scan_ucfg_api.h"
Jiani Liua5f17222019-03-04 16:22:33 +0800141#include "wlan_hdd_coex_config.h"
Abhinav Kumardbbfd2c2019-05-07 12:22:06 +0530142#include "wlan_hdd_bcn_recv.h"
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +0530143#include "wlan_blm_ucfg_api.h"
guangde4853c402019-05-06 15:54:04 +0800144#include "wlan_hdd_hw_capability.h"
Paul Zhangda2970b2019-06-23 18:16:38 +0800145#include "wlan_hdd_oemdata.h"
Paul Zhangc9dbaee2019-06-23 22:07:31 +0800146#include "os_if_fwol.h"
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +0530147#include "wlan_hdd_sta_info.h"
Pankaj Singh50e40422020-01-09 15:29:35 +0530148#include "sme_api.h"
149#include "wlan_hdd_thermal.h"
Rakesh Pillai6a36b0a2019-09-06 16:30:05 +0530150#include <ol_defines.h>
Wu Gao29012452020-03-07 17:06:34 +0800151#include "wlan_hdd_cfr.h"
Harprit Chhabada6c641ba2018-06-28 14:45:10 -0700152
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800153#define g_mode_rates_size (12)
154#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800155
Sourav Mohapatrafab026a2019-11-20 14:22:28 +0530156/**
157 * rtt_is_initiator - Macro to check if the bitmap has any RTT roles set
158 * @bitmap: The bitmap to be checked
159 */
160#define rtt_is_enabled(bitmap) \
161 ((bitmap) & (WMI_FW_STA_RTT_INITR | \
162 WMI_FW_STA_RTT_RESPR | \
163 WMI_FW_AP_RTT_INITR | \
164 WMI_FW_AP_RTT_RESPR))
165
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800166/*
167 * Android CTS verifier needs atleast this much wait time (in msec)
168 */
169#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
170
171/*
172 * Refer @tCfgProtection structure for definition of the bit map.
173 * below value is obtained by setting the following bit-fields.
174 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
175 */
176#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
177
178#define HDD2GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700179 .band = HDD_NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 .center_freq = (freq), \
181 .hw_value = (chan), \
182 .flags = (flag), \
183 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800184 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800185}
186
187#define HDD5GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700188 .band = HDD_NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800189 .center_freq = (freq), \
190 .hw_value = (chan), \
191 .flags = (flag), \
192 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800193 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800194}
195
196#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
197 { \
198 .bitrate = rate, \
199 .hw_value = rate_id, \
200 .flags = flag, \
201 }
202
Agrawal Ashish65634612016-08-18 13:24:32 +0530203#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
204 mode <= DFS_MODE_DEPRIORITIZE))
Mohit Khannaceb97782017-04-05 16:27:08 -0700205/*
206 * Number of DPTRACE records to dump when a cfg80211 disconnect with reason
207 * WLAN_REASON_DEAUTH_LEAVING DEAUTH is received from user-space.
208 */
209#define WLAN_DEAUTH_DPTRACE_DUMP_COUNT 100
Mukul Sharma05504ac2017-06-08 12:35:53 +0530210#ifndef WLAN_CIPHER_SUITE_GCMP
211#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
212#endif
213#ifndef WLAN_CIPHER_SUITE_GCMP_256
214#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09
215#endif
Mohit Khannaceb97782017-04-05 16:27:08 -0700216
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +0530217static const u32 hdd_gcmp_cipher_suits[] = {
218 WLAN_CIPHER_SUITE_GCMP,
219 WLAN_CIPHER_SUITE_GCMP_256,
220};
221
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222static const u32 hdd_cipher_suites[] = {
223 WLAN_CIPHER_SUITE_WEP40,
224 WLAN_CIPHER_SUITE_WEP104,
225 WLAN_CIPHER_SUITE_TKIP,
226#ifdef FEATURE_WLAN_ESE
227#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
228#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
229 WLAN_CIPHER_SUITE_BTK,
230 WLAN_CIPHER_SUITE_KRK,
231 WLAN_CIPHER_SUITE_CCMP,
232#else
233 WLAN_CIPHER_SUITE_CCMP,
234#endif
235#ifdef FEATURE_WLAN_WAPI
236 WLAN_CIPHER_SUITE_SMS4,
237#endif
238#ifdef WLAN_FEATURE_11W
239 WLAN_CIPHER_SUITE_AES_CMAC,
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +0530240#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
241 WLAN_CIPHER_SUITE_BIP_GMAC_128,
242 WLAN_CIPHER_SUITE_BIP_GMAC_256,
243#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800244#endif
245};
246
Abhishek Singhf512bf32016-05-04 16:47:46 +0530247static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800248 HDD2GHZCHAN(2412, 1, 0),
249 HDD2GHZCHAN(2417, 2, 0),
250 HDD2GHZCHAN(2422, 3, 0),
251 HDD2GHZCHAN(2427, 4, 0),
252 HDD2GHZCHAN(2432, 5, 0),
253 HDD2GHZCHAN(2437, 6, 0),
254 HDD2GHZCHAN(2442, 7, 0),
255 HDD2GHZCHAN(2447, 8, 0),
256 HDD2GHZCHAN(2452, 9, 0),
257 HDD2GHZCHAN(2457, 10, 0),
258 HDD2GHZCHAN(2462, 11, 0),
259 HDD2GHZCHAN(2467, 12, 0),
260 HDD2GHZCHAN(2472, 13, 0),
261 HDD2GHZCHAN(2484, 14, 0),
262};
263
Abhishek Singhf512bf32016-05-04 16:47:46 +0530264static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800265 HDD5GHZCHAN(5180, 36, 0),
266 HDD5GHZCHAN(5200, 40, 0),
267 HDD5GHZCHAN(5220, 44, 0),
268 HDD5GHZCHAN(5240, 48, 0),
269 HDD5GHZCHAN(5260, 52, 0),
270 HDD5GHZCHAN(5280, 56, 0),
271 HDD5GHZCHAN(5300, 60, 0),
272 HDD5GHZCHAN(5320, 64, 0),
273 HDD5GHZCHAN(5500, 100, 0),
274 HDD5GHZCHAN(5520, 104, 0),
275 HDD5GHZCHAN(5540, 108, 0),
276 HDD5GHZCHAN(5560, 112, 0),
277 HDD5GHZCHAN(5580, 116, 0),
278 HDD5GHZCHAN(5600, 120, 0),
279 HDD5GHZCHAN(5620, 124, 0),
280 HDD5GHZCHAN(5640, 128, 0),
281 HDD5GHZCHAN(5660, 132, 0),
282 HDD5GHZCHAN(5680, 136, 0),
283 HDD5GHZCHAN(5700, 140, 0),
284 HDD5GHZCHAN(5720, 144, 0),
285 HDD5GHZCHAN(5745, 149, 0),
286 HDD5GHZCHAN(5765, 153, 0),
287 HDD5GHZCHAN(5785, 157, 0),
288 HDD5GHZCHAN(5805, 161, 0),
289 HDD5GHZCHAN(5825, 165, 0),
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +0530290};
291
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -0700292#ifdef WLAN_FEATURE_DSRC
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +0530293static const struct ieee80211_channel hdd_channels_dot11p[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800294 HDD5GHZCHAN(5852, 170, 0),
295 HDD5GHZCHAN(5855, 171, 0),
296 HDD5GHZCHAN(5860, 172, 0),
297 HDD5GHZCHAN(5865, 173, 0),
298 HDD5GHZCHAN(5870, 174, 0),
299 HDD5GHZCHAN(5875, 175, 0),
300 HDD5GHZCHAN(5880, 176, 0),
301 HDD5GHZCHAN(5885, 177, 0),
302 HDD5GHZCHAN(5890, 178, 0),
303 HDD5GHZCHAN(5895, 179, 0),
304 HDD5GHZCHAN(5900, 180, 0),
305 HDD5GHZCHAN(5905, 181, 0),
306 HDD5GHZCHAN(5910, 182, 0),
307 HDD5GHZCHAN(5915, 183, 0),
308 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800309};
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -0700310#else
311static const struct ieee80211_channel hdd_etsi13_srd_ch[] = {
312 HDD5GHZCHAN(5845, 169, 0),
313 HDD5GHZCHAN(5865, 173, 0),
314};
315#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800316
Qun Zhang043635a2019-02-27 15:19:29 +0800317#define band_2_ghz_channels_size sizeof(hdd_channels_2_4_ghz)
318
319#ifdef WLAN_FEATURE_DSRC
320#define band_5_ghz_chanenls_size (sizeof(hdd_channels_5_ghz) + \
321 sizeof(hdd_channels_dot11p))
322#else
323#define band_5_ghz_chanenls_size (sizeof(hdd_channels_5_ghz) + \
324 sizeof(hdd_etsi13_srd_ch))
325#endif
326
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800327static struct ieee80211_rate g_mode_rates[] = {
328 HDD_G_MODE_RATETAB(10, 0x1, 0),
329 HDD_G_MODE_RATETAB(20, 0x2, 0),
330 HDD_G_MODE_RATETAB(55, 0x4, 0),
331 HDD_G_MODE_RATETAB(110, 0x8, 0),
332 HDD_G_MODE_RATETAB(60, 0x10, 0),
333 HDD_G_MODE_RATETAB(90, 0x20, 0),
334 HDD_G_MODE_RATETAB(120, 0x40, 0),
335 HDD_G_MODE_RATETAB(180, 0x80, 0),
336 HDD_G_MODE_RATETAB(240, 0x100, 0),
337 HDD_G_MODE_RATETAB(360, 0x200, 0),
338 HDD_G_MODE_RATETAB(480, 0x400, 0),
339 HDD_G_MODE_RATETAB(540, 0x800, 0),
340};
341
342static struct ieee80211_rate a_mode_rates[] = {
343 HDD_G_MODE_RATETAB(60, 0x10, 0),
344 HDD_G_MODE_RATETAB(90, 0x20, 0),
345 HDD_G_MODE_RATETAB(120, 0x40, 0),
346 HDD_G_MODE_RATETAB(180, 0x80, 0),
347 HDD_G_MODE_RATETAB(240, 0x100, 0),
348 HDD_G_MODE_RATETAB(360, 0x200, 0),
349 HDD_G_MODE_RATETAB(480, 0x400, 0),
350 HDD_G_MODE_RATETAB(540, 0x800, 0),
351};
352
353static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530354 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800355 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700356 .band = HDD_NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800357 .bitrates = g_mode_rates,
358 .n_bitrates = g_mode_rates_size,
359 .ht_cap.ht_supported = 1,
360 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
361 | IEEE80211_HT_CAP_GRN_FLD
362 | IEEE80211_HT_CAP_DSSSCCK40
363 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
364 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
365 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
366 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
367 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
368 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
369 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
370};
371
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800372static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530373 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800374 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700375 .band = HDD_NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800376 .bitrates = a_mode_rates,
377 .n_bitrates = a_mode_rates_size,
378 .ht_cap.ht_supported = 1,
379 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
380 | IEEE80211_HT_CAP_GRN_FLD
381 | IEEE80211_HT_CAP_DSSSCCK40
382 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
383 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
384 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
385 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
386 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
387 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
388 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
389 .vht_cap.vht_supported = 1,
390};
391
Liangwei Dong692455f2019-08-09 17:59:46 +0800392#if defined(CONFIG_BAND_6GHZ) && (defined(CFG80211_6GHZ_BAND_SUPPORTED) || \
393 (KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE))
394
395static struct ieee80211_channel hdd_channels_6_ghz[NUM_6GHZ_CHANNELS];
396
397static struct ieee80211_supported_band wlan_hdd_band_6_ghz = {
398 .channels = NULL,
399 .n_channels = 0,
400 .band = HDD_NL80211_BAND_6GHZ,
401 .bitrates = a_mode_rates,
402 .n_bitrates = a_mode_rates_size,
Liangwei Dong692455f2019-08-09 17:59:46 +0800403};
404
405#define HDD_SET_6GHZCHAN(ch, freq, chan, flag) { \
406 (ch).band = HDD_NL80211_BAND_6GHZ; \
407 (ch).center_freq = (freq); \
408 (ch).hw_value = (chan); \
409 (ch).flags = (flag); \
410 (ch).max_antenna_gain = 0; \
411 (ch).max_power = 0; \
412}
413
414static void hdd_init_6ghz(struct hdd_context *hdd_ctx)
415{
416 uint32_t i;
417 struct wiphy *wiphy = hdd_ctx->wiphy;
418 struct ieee80211_channel *chlist = hdd_channels_6_ghz;
419 uint32_t num = ARRAY_SIZE(hdd_channels_6_ghz);
420
421 qdf_mem_zero(chlist, sizeof(*chlist) * num);
422 for (i = 0; i < num; i++)
423 HDD_SET_6GHZCHAN(chlist[i], 5945 + i * 20, 1 + i * 4, \
424 IEEE80211_CHAN_DISABLED);
425 wiphy->bands[HDD_NL80211_BAND_6GHZ] = &wlan_hdd_band_6_ghz;
426 wiphy->bands[HDD_NL80211_BAND_6GHZ]->channels = chlist;
427 wiphy->bands[HDD_NL80211_BAND_6GHZ]->n_channels = num;
428}
429#else
430static void hdd_init_6ghz(struct hdd_context *hdd_ctx)
431{
432}
433#endif
434
sheenam mongacaeb3c22020-03-23 17:03:07 +0530435#if defined(CFG80211_IFTYPE_AKM_SUITES_SUPPORT)
436/*akm suits supported by sta*/
437static const u32 hdd_sta_akm_suites[] = {
438 WLAN_AKM_SUITE_8021X,
439 WLAN_AKM_SUITE_PSK,
440 WLAN_AKM_SUITE_FT_8021X,
441 WLAN_AKM_SUITE_FT_PSK,
442 WLAN_AKM_SUITE_8021X_SHA256,
443 WLAN_AKM_SUITE_PSK_SHA256,
444 WLAN_AKM_SUITE_TDLS,
445 WLAN_AKM_SUITE_SAE,
446 WLAN_AKM_SUITE_FT_OVER_SAE,
sheenam mongad9d430f2020-04-20 12:53:21 +0530447#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
sheenam mongacaeb3c22020-03-23 17:03:07 +0530448 WLAN_AKM_SUITE_8021X_SUITE_B,
449 WLAN_AKM_SUITE_8021X_SUITE_B_192,
sheenam mongad9d430f2020-04-20 12:53:21 +0530450#endif
sheenam mongacaeb3c22020-03-23 17:03:07 +0530451 WLAN_AKM_SUITE_FILS_SHA256,
452 WLAN_AKM_SUITE_FILS_SHA384,
453 WLAN_AKM_SUITE_FT_FILS_SHA256,
454 WLAN_AKM_SUITE_FT_FILS_SHA384,
455 WLAN_AKM_SUITE_OWE,
456};
457
458/*akm suits supported by AP*/
459static const u32 hdd_ap_akm_suites[] = {
460 WLAN_AKM_SUITE_PSK,
461 WLAN_AKM_SUITE_SAE,
462 WLAN_AKM_SUITE_OWE,
463};
464
465/* This structure contain information what akm suits are
466 * supported for each mode
467 */
468static const struct wiphy_iftype_akm_suites
469 wlan_hdd_akm_suites[] = {
470 {
471 .iftypes_mask = BIT(NL80211_IFTYPE_STATION) |
472 BIT(NL80211_IFTYPE_P2P_CLIENT),
473 .akm_suites = hdd_sta_akm_suites,
474 .n_akm_suites = (sizeof(hdd_sta_akm_suites) / sizeof(u32)),
475 },
476 {
477 .iftypes_mask = BIT(NL80211_IFTYPE_AP) |
478 BIT(NL80211_IFTYPE_P2P_GO),
479 .akm_suites = hdd_ap_akm_suites,
480 .n_akm_suites = (sizeof(hdd_ap_akm_suites) / sizeof(u32)),
481 },
482};
483#endif
484
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800485/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800486 * TX/RX direction for each kind of interface
487 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800488static const struct ieee80211_txrx_stypes
489 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
490 [NL80211_IFTYPE_STATION] = {
491 .tx = 0xffff,
492 .rx = BIT(SIR_MAC_MGMT_ACTION) |
Padma, Santhosh Kumar1ccc1332017-09-13 17:39:01 +0530493 BIT(SIR_MAC_MGMT_PROBE_REQ) |
494 BIT(SIR_MAC_MGMT_AUTH),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800495 },
496 [NL80211_IFTYPE_AP] = {
497 .tx = 0xffff,
498 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
499 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
500 BIT(SIR_MAC_MGMT_PROBE_REQ) |
501 BIT(SIR_MAC_MGMT_DISASSOC) |
502 BIT(SIR_MAC_MGMT_AUTH) |
503 BIT(SIR_MAC_MGMT_DEAUTH) |
504 BIT(SIR_MAC_MGMT_ACTION),
505 },
506 [NL80211_IFTYPE_ADHOC] = {
507 .tx = 0xffff,
508 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
509 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
510 BIT(SIR_MAC_MGMT_PROBE_REQ) |
511 BIT(SIR_MAC_MGMT_DISASSOC) |
512 BIT(SIR_MAC_MGMT_AUTH) |
513 BIT(SIR_MAC_MGMT_DEAUTH) |
514 BIT(SIR_MAC_MGMT_ACTION),
515 },
516 [NL80211_IFTYPE_P2P_CLIENT] = {
517 .tx = 0xffff,
518 .rx = BIT(SIR_MAC_MGMT_ACTION) |
519 BIT(SIR_MAC_MGMT_PROBE_REQ),
520 },
521 [NL80211_IFTYPE_P2P_GO] = {
522 /* This is also same as for SoftAP */
523 .tx = 0xffff,
524 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
525 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
526 BIT(SIR_MAC_MGMT_PROBE_REQ) |
527 BIT(SIR_MAC_MGMT_DISASSOC) |
528 BIT(SIR_MAC_MGMT_AUTH) |
529 BIT(SIR_MAC_MGMT_DEAUTH) |
530 BIT(SIR_MAC_MGMT_ACTION),
531 },
532};
533
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800534/* Interface limits and combinations registered by the driver */
535
536/* STA ( + STA ) combination */
537static const struct ieee80211_iface_limit
538 wlan_hdd_sta_iface_limit[] = {
539 {
540 .max = 3, /* p2p0 is a STA as well */
541 .types = BIT(NL80211_IFTYPE_STATION),
542 },
543};
544
545/* ADHOC (IBSS) limit */
546static const struct ieee80211_iface_limit
547 wlan_hdd_adhoc_iface_limit[] = {
548 {
549 .max = 1,
550 .types = BIT(NL80211_IFTYPE_STATION),
551 },
552 {
553 .max = 1,
554 .types = BIT(NL80211_IFTYPE_ADHOC),
555 },
556};
557
558/* AP ( + AP ) combination */
559static const struct ieee80211_iface_limit
560 wlan_hdd_ap_iface_limit[] = {
561 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530562 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800563 .types = BIT(NL80211_IFTYPE_AP),
564 },
565};
566
567/* P2P limit */
568static const struct ieee80211_iface_limit
569 wlan_hdd_p2p_iface_limit[] = {
570 {
571 .max = 1,
572 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
573 },
574 {
575 .max = 1,
576 .types = BIT(NL80211_IFTYPE_P2P_GO),
577 },
578};
579
580static const struct ieee80211_iface_limit
581 wlan_hdd_sta_ap_iface_limit[] = {
582 {
583 /* We need 1 extra STA interface for OBSS scan when SAP starts
584 * with HT40 in STA+SAP concurrency mode
585 */
586 .max = (1 + SAP_MAX_OBSS_STA_CNT),
587 .types = BIT(NL80211_IFTYPE_STATION),
588 },
589 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530590 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591 .types = BIT(NL80211_IFTYPE_AP),
592 },
593};
594
595/* STA + P2P combination */
596static const struct ieee80211_iface_limit
597 wlan_hdd_sta_p2p_iface_limit[] = {
598 {
599 /* One reserved for dedicated P2PDEV usage */
600 .max = 2,
601 .types = BIT(NL80211_IFTYPE_STATION)
602 },
603 {
604 /* Support for two identical (GO + GO or CLI + CLI)
605 * or dissimilar (GO + CLI) P2P interfaces
606 */
607 .max = 2,
608 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
609 },
610};
611
612/* STA + AP + P2PGO combination */
613static const struct ieee80211_iface_limit
614wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
615 /* Support for AP+P2PGO interfaces */
616 {
617 .max = 2,
618 .types = BIT(NL80211_IFTYPE_STATION)
619 },
620 {
621 .max = 1,
622 .types = BIT(NL80211_IFTYPE_P2P_GO)
623 },
624 {
625 .max = 1,
626 .types = BIT(NL80211_IFTYPE_AP)
627 }
628};
629
630/* SAP + P2P combination */
631static const struct ieee80211_iface_limit
632wlan_hdd_sap_p2p_iface_limit[] = {
633 {
634 /* 1 dedicated for p2p0 which is a STA type */
635 .max = 1,
636 .types = BIT(NL80211_IFTYPE_STATION)
637 },
638 {
639 /* The p2p interface in SAP+P2P can be GO/CLI.
640 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
641 */
642 .max = 1,
643 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
644 },
645 {
646 /* SAP+GO to support only one SAP interface */
647 .max = 1,
648 .types = BIT(NL80211_IFTYPE_AP)
649 }
650};
651
652/* P2P + P2P combination */
653static const struct ieee80211_iface_limit
654wlan_hdd_p2p_p2p_iface_limit[] = {
655 {
656 /* 1 dedicated for p2p0 which is a STA type */
657 .max = 1,
658 .types = BIT(NL80211_IFTYPE_STATION)
659 },
660 {
661 /* The p2p interface in P2P+P2P can be GO/CLI.
662 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
663 */
664 .max = 2,
665 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
666 },
667};
668
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700669static const struct ieee80211_iface_limit
670 wlan_hdd_mon_iface_limit[] = {
671 {
672 .max = 3, /* Monitor interface */
673 .types = BIT(NL80211_IFTYPE_MONITOR),
674 },
675};
676
677static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800678 wlan_hdd_iface_combination[] = {
679 /* STA */
680 {
681 .limits = wlan_hdd_sta_iface_limit,
682 .num_different_channels = 2,
683 .max_interfaces = 3,
684 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
685 },
686 /* ADHOC */
687 {
688 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700689 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800690 .max_interfaces = 2,
691 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
692 },
693 /* AP */
694 {
695 .limits = wlan_hdd_ap_iface_limit,
696 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530697 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
hqu3c4ed3d2017-09-19 11:42:35 +0800699#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
700 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
701 .beacon_int_min_gcd = 1,
702#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800703 },
704 /* P2P */
705 {
706 .limits = wlan_hdd_p2p_iface_limit,
707 .num_different_channels = 2,
708 .max_interfaces = 2,
709 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
710 },
711 /* STA + AP */
712 {
713 .limits = wlan_hdd_sta_ap_iface_limit,
714 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530715 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
717 .beacon_int_infra_match = true,
hqu3c4ed3d2017-09-19 11:42:35 +0800718#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
719 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
720 .beacon_int_min_gcd = 1,
721#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 },
723 /* STA + P2P */
724 {
725 .limits = wlan_hdd_sta_p2p_iface_limit,
726 .num_different_channels = 2,
727 /* one interface reserved for P2PDEV dedicated usage */
728 .max_interfaces = 4,
729 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
730 .beacon_int_infra_match = true,
731 },
732 /* STA + P2P GO + SAP */
733 {
734 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
735 /* we can allow 3 channels for three different persona
736 * but due to firmware limitation, allow max 2 concrnt channels.
737 */
738 .num_different_channels = 2,
739 /* one interface reserved for P2PDEV dedicated usage */
740 .max_interfaces = 4,
741 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
742 .beacon_int_infra_match = true,
743 },
744 /* SAP + P2P */
745 {
746 .limits = wlan_hdd_sap_p2p_iface_limit,
747 .num_different_channels = 2,
748 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
749 .max_interfaces = 3,
750 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
751 .beacon_int_infra_match = true,
752 },
753 /* P2P + P2P */
754 {
755 .limits = wlan_hdd_p2p_p2p_iface_limit,
756 .num_different_channels = 2,
757 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
758 .max_interfaces = 3,
759 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
760 .beacon_int_infra_match = true,
761 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530762 /* Monitor */
763 {
764 .limits = wlan_hdd_mon_iface_limit,
765 .max_interfaces = 3,
766 .num_different_channels = 2,
767 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
768 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800770
771static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772
773#ifdef WLAN_NL80211_TESTMODE
774enum wlan_hdd_tm_attr {
775 WLAN_HDD_TM_ATTR_INVALID = 0,
776 WLAN_HDD_TM_ATTR_CMD = 1,
777 WLAN_HDD_TM_ATTR_DATA = 2,
778 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
779 WLAN_HDD_TM_ATTR_TYPE = 4,
780 /* keep last */
781 WLAN_HDD_TM_ATTR_AFTER_LAST,
782 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
783};
784
785enum wlan_hdd_tm_cmd {
786 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
787 WLAN_HDD_TM_CMD_WLAN_HB = 1,
788};
789
790#define WLAN_HDD_TM_DATA_MAX_LEN 5000
791
792static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
793 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
794 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
795 .len = WLAN_HDD_TM_DATA_MAX_LEN},
796};
797#endif /* WLAN_NL80211_TESTMODE */
798
Lin Baia016e9a2017-08-29 19:10:42 +0800799enum wlan_hdd_vendor_ie_access_policy {
800 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
801 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
802};
803
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
805static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
806 .flags = WIPHY_WOWLAN_MAGIC_PKT,
807 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
808 .pattern_min_len = 1,
809 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
810};
811#endif
812
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530814 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
815 * @flags: Pointer to the flags to Add channel switch flag.
816 *
817 * This Function adds Channel Switch support flag, if channel switch is
818 * supported by kernel.
819 * Return: void.
820 */
821#ifdef CHANNEL_SWITCH_SUPPORTED
822static inline void hdd_add_channel_switch_support(uint32_t *flags)
823{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800824 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530825}
826#else
827static inline void hdd_add_channel_switch_support(uint32_t *flags)
828{
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530829}
830#endif
831
Manikandan Mohan22b83722015-12-15 15:03:23 -0800832#ifdef FEATURE_WLAN_TDLS
833
834/* TDLS capabilities params */
835#define PARAM_MAX_TDLS_SESSION \
836 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
837#define PARAM_TDLS_FEATURE_SUPPORT \
838 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
839
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530840/**
Jeff Johnson118a4a02018-05-06 00:14:15 -0700841 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800842 * @wiphy: WIPHY structure pointer
843 * @wdev: Wireless device structure pointer
844 * @data: Pointer to the data received
845 * @data_len: Length of the data received
846 *
847 * This function provides TDLS capabilities
848 *
849 * Return: 0 on success and errno on failure
850 */
851static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
852 struct wireless_dev *wdev,
853 const void *data,
854 int data_len)
855{
856 int status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -0700857 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800858 struct sk_buff *skb;
859 uint32_t set = 0;
Frank Liu5c63dc82017-09-07 14:49:05 +0800860 uint32_t max_num_tdls_sta = 0;
Wu Gaobdb7f272018-07-05 19:33:26 +0800861 bool tdls_support;
862 bool tdls_external_control;
863 bool tdls_sleep_sta_enable;
864 bool tdls_buffer_sta;
865 bool tdls_off_channel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800866
Dustin Brownfdf17c12018-03-14 12:55:34 -0700867 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -0800868
Anurag Chouhan6d760662016-02-20 16:05:43 +0530869 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800870 hdd_err("Command not allowed in FTM mode");
871 return -EPERM;
872 }
873
874 status = wlan_hdd_validate_context(hdd_ctx);
875 if (status)
876 return status;
877
878 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
879 NLMSG_HDRLEN);
880 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700881 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800882 goto fail;
883 }
884
Dustin Brown76cd2932018-09-11 16:03:05 -0700885 if ((cfg_tdls_get_support_enable(hdd_ctx->psoc, &tdls_support) ==
Bala Venkateshdcbad342019-03-18 13:57:24 +0530886 QDF_STATUS_SUCCESS) && !tdls_support) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800887 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800888 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
889 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700890 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800891 goto fail;
892 }
893 } else {
Dustin Brown76cd2932018-09-11 16:03:05 -0700894 cfg_tdls_get_external_control(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800895 &tdls_external_control);
Dustin Brown76cd2932018-09-11 16:03:05 -0700896 cfg_tdls_get_sleep_sta_enable(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800897 &tdls_sleep_sta_enable);
Dustin Brown76cd2932018-09-11 16:03:05 -0700898 cfg_tdls_get_buffer_sta_enable(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800899 &tdls_buffer_sta);
Dustin Brown76cd2932018-09-11 16:03:05 -0700900 cfg_tdls_get_off_channel_enable(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800901 &tdls_off_channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800902 set = set | WIFI_TDLS_SUPPORT;
Wu Gaobdb7f272018-07-05 19:33:26 +0800903 set = set | (tdls_external_control ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800904 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
Wu Gaobdb7f272018-07-05 19:33:26 +0800905 set = set | (tdls_off_channel ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800906 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Wu Gaoe5568fe2020-06-25 22:50:47 +0800907 max_num_tdls_sta = cfg_tdls_get_max_peer_count(hdd_ctx->psoc);
Frank Liu5c63dc82017-09-07 14:49:05 +0800908
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800909 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800910 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
Frank Liu5c63dc82017-09-07 14:49:05 +0800911 max_num_tdls_sta) ||
912 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700913 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914 goto fail;
915 }
916 }
917 return cfg80211_vendor_cmd_reply(skb);
918fail:
919 if (skb)
920 kfree_skb(skb);
921 return -EINVAL;
922}
923
924/**
Jeff Johnson118a4a02018-05-06 00:14:15 -0700925 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800926 * @wiphy: WIPHY structure pointer
927 * @wdev: Wireless device structure pointer
928 * @data: Pointer to the data received
929 * @data_len: Length of the data received
930 *
931 * This function provides TDLS capabilities
932 *
933 * Return: 0 on success and errno on failure
934 */
935static int
936wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
937 struct wireless_dev *wdev,
938 const void *data,
939 int data_len)
940{
Dustin Brown363b4792019-02-05 16:11:55 -0800941 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -0800942 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +0530943
Dustin Brown363b4792019-02-05 16:11:55 -0800944 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -0800945 if (errno)
946 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800947
Dustin Brownf0f00612019-01-31 16:02:24 -0800948 errno = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
949 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800950
Dustin Brown363b4792019-02-05 16:11:55 -0800951 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -0800952
953 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800954}
jiad7b8a5e02018-11-26 16:37:57 +0800955
956static uint8_t hdd_get_bw_offset(uint32_t ch_width)
957{
958 uint8_t bw_offset = 0;
959
960 if (ch_width == CH_WIDTH_40MHZ)
961 bw_offset = 1 << BW_40_OFFSET_BIT;
962 else if (ch_width == CH_WIDTH_20MHZ)
963 bw_offset = 1 << BW_20_OFFSET_BIT;
964
965 return bw_offset;
966}
967
968#else /* !FEATURE_WLAN_TDLS */
969
970static inline uint8_t hdd_get_bw_offset(uint32_t ch_width)
971{
972 return 0;
973}
974
975#endif /* FEATURE_WLAN_TDLS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800976
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700977int wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type *destFreqList,
978 struct ch_avoid_ind_type *srcFreqList)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530979{
980 int i;
Jeff Johnson62f28992019-03-05 14:48:42 -0800981 uint32_t room;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700982 struct ch_avoid_freq_type *avoid_range =
983 &destFreqList->avoid_freq_range[destFreqList->ch_avoid_range_cnt];
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530984
Jeff Johnson62f28992019-03-05 14:48:42 -0800985 room = CH_AVOID_MAX_RANGE - destFreqList->ch_avoid_range_cnt;
986 if (srcFreqList->ch_avoid_range_cnt > room) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530987 hdd_err("avoid freq overflow");
988 return -EINVAL;
989 }
Jeff Johnson62f28992019-03-05 14:48:42 -0800990 destFreqList->ch_avoid_range_cnt += srcFreqList->ch_avoid_range_cnt;
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530991
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700992 for (i = 0; i < srcFreqList->ch_avoid_range_cnt; i++) {
993 avoid_range->start_freq =
994 srcFreqList->avoid_freq_range[i].start_freq;
995 avoid_range->end_freq =
996 srcFreqList->avoid_freq_range[i].end_freq;
997 avoid_range++;
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530998 }
999 return 0;
1000}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001001/*
1002 * FUNCTION: wlan_hdd_send_avoid_freq_event
1003 * This is called when wlan driver needs to send vendor specific
1004 * avoid frequency range event to userspace
1005 */
Jeff Johnsonb8944722017-09-03 09:03:19 -07001006int wlan_hdd_send_avoid_freq_event(struct hdd_context *hdd_ctx,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001007 struct ch_avoid_ind_type *avoid_freq_list)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001008{
1009 struct sk_buff *vendor_event;
1010
Dustin Brown491d54b2018-03-14 12:39:11 -07001011 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001012
Jeff Johnsonb8944722017-09-03 09:03:19 -07001013 if (!hdd_ctx) {
Jeff Johnson020db452016-06-29 14:37:26 -07001014 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001015 return -EINVAL;
1016 }
1017
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001018 if (!avoid_freq_list) {
1019 hdd_err("avoid_freq_list is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001020 return -EINVAL;
1021 }
1022
Jeff Johnsonb8944722017-09-03 09:03:19 -07001023 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001024 NULL, sizeof(struct ch_avoid_ind_type),
1025 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
1026 GFP_KERNEL);
1027
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001028 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -07001029 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001030 return -EINVAL;
1031 }
1032
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001033 memcpy(skb_put(vendor_event, sizeof(struct ch_avoid_ind_type)),
1034 (void *)avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001035
1036 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1037
Dustin Browne74003f2018-03-14 12:51:58 -07001038 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001039 return 0;
1040}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001041
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301042/*
1043 * define short names for the global vendor params
1044 * used by QCA_NL80211_VENDOR_SUBCMD_HANG
1045 */
1046#define HANG_REASON_INDEX QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX
1047
1048/**
1049 * hdd_convert_hang_reason() - Convert cds recovery reason to vendor specific
1050 * hang reason
1051 * @reason: cds recovery reason
1052 *
1053 * Return: Vendor specific reason code
1054 */
1055static enum qca_wlan_vendor_hang_reason
1056hdd_convert_hang_reason(enum qdf_hang_reason reason)
1057{
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -07001058 u32 ret_val;
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301059
1060 switch (reason) {
1061 case QDF_RX_HASH_NO_ENTRY_FOUND:
1062 ret_val = QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND;
1063 break;
1064 case QDF_PEER_DELETION_TIMEDOUT:
1065 ret_val = QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT;
1066 break;
1067 case QDF_PEER_UNMAP_TIMEDOUT:
1068 ret_val = QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT;
1069 break;
1070 case QDF_SCAN_REQ_EXPIRED:
1071 ret_val = QCA_WLAN_HANG_SCAN_REQ_EXPIRED;
1072 break;
1073 case QDF_SCAN_ATTEMPT_FAILURES:
1074 ret_val = QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES;
1075 break;
1076 case QDF_GET_MSG_BUFF_FAILURE:
1077 ret_val = QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE;
1078 break;
1079 case QDF_ACTIVE_LIST_TIMEOUT:
1080 ret_val = QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT;
1081 break;
1082 case QDF_SUSPEND_TIMEOUT:
1083 ret_val = QCA_WLAN_HANG_SUSPEND_TIMEOUT;
1084 break;
1085 case QDF_RESUME_TIMEOUT:
1086 ret_val = QCA_WLAN_HANG_RESUME_TIMEOUT;
1087 break;
Jingxiang Ge2a67be52019-04-10 14:47:51 +08001088 case QDF_WMI_EXCEED_MAX_PENDING_CMDS:
1089 ret_val = QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS;
1090 break;
Sourav Mohapatraec6eabb2020-03-26 19:48:09 +05301091 case QDF_AP_STA_CONNECT_REQ_TIMEOUT:
1092 ret_val = QCA_WLAN_HANG_AP_STA_CONNECT_REQ_TIMEOUT;
1093 break;
1094 case QDF_STA_AP_CONNECT_REQ_TIMEOUT:
1095 ret_val = QCA_WLAN_HANG_STA_AP_CONNECT_REQ_TIMEOUT;
1096 break;
1097 case QDF_MAC_HW_MODE_CHANGE_TIMEOUT:
1098 ret_val = QCA_WLAN_HANG_MAC_HW_MODE_CHANGE_TIMEOUT;
1099 break;
1100 case QDF_MAC_HW_MODE_CONFIG_TIMEOUT:
1101 ret_val = QCA_WLAN_HANG_MAC_HW_MODE_CONFIG_TIMEOUT;
1102 break;
1103 case QDF_VDEV_START_RESPONSE_TIMED_OUT:
1104 ret_val = QCA_WLAN_HANG_VDEV_START_RESPONSE_TIMED_OUT;
1105 break;
1106 case QDF_VDEV_RESTART_RESPONSE_TIMED_OUT:
1107 ret_val = QCA_WLAN_HANG_VDEV_RESTART_RESPONSE_TIMED_OUT;
1108 break;
1109 case QDF_VDEV_STOP_RESPONSE_TIMED_OUT:
1110 ret_val = QCA_WLAN_HANG_VDEV_STOP_RESPONSE_TIMED_OUT;
1111 break;
1112 case QDF_VDEV_DELETE_RESPONSE_TIMED_OUT:
1113 ret_val = QCA_WLAN_HANG_VDEV_DELETE_RESPONSE_TIMED_OUT;
1114 break;
1115 case QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT:
1116 ret_val = QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT;
1117 break;
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301118 case QDF_REASON_UNSPECIFIED:
1119 default:
1120 ret_val = QCA_WLAN_HANG_REASON_UNSPECIFIED;
1121 }
1122 return ret_val;
1123}
1124
1125/**
1126 * wlan_hdd_send_hang_reason_event() - Send hang reason to the userspace
1127 * @hdd_ctx: Pointer to hdd context
1128 * @reason: cds recovery reason
Arun Kumar Khandavalliedaeb662020-04-19 21:51:50 +05301129 * @data: Hang Data
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301130 *
1131 * Return: 0 on success or failure reason
1132 */
1133int wlan_hdd_send_hang_reason_event(struct hdd_context *hdd_ctx,
Arun Kumar Khandavalliedaeb662020-04-19 21:51:50 +05301134 enum qdf_hang_reason reason, void *data,
1135 size_t data_len)
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301136{
1137 struct sk_buff *vendor_event;
1138 enum qca_wlan_vendor_hang_reason hang_reason;
Abhinav Kumarcab72532019-11-22 12:19:22 +05301139 struct hdd_adapter *sta_adapter;
1140 struct wireless_dev *wdev = NULL;
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301141
Dustin Brown491d54b2018-03-14 12:39:11 -07001142 hdd_enter();
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301143
1144 if (!hdd_ctx) {
1145 hdd_err("HDD context is null");
1146 return -EINVAL;
1147 }
1148
Abhinav Kumarcab72532019-11-22 12:19:22 +05301149 sta_adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
1150 if (sta_adapter)
1151 wdev = &(sta_adapter->wdev);
1152
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301153 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Abhinav Kumarcab72532019-11-22 12:19:22 +05301154 wdev,
Arun Kumar Khandavalliedaeb662020-04-19 21:51:50 +05301155 sizeof(uint32_t) + data_len,
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301156 HANG_REASON_INDEX,
1157 GFP_KERNEL);
1158 if (!vendor_event) {
1159 hdd_err("cfg80211_vendor_event_alloc failed");
1160 return -ENOMEM;
1161 }
1162
1163 hang_reason = hdd_convert_hang_reason(reason);
1164
1165 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON,
Arun Kumar Khandavalliedaeb662020-04-19 21:51:50 +05301166 (uint32_t)hang_reason) ||
1167 nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON_DATA,
1168 data_len, data)) {
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301169 hdd_err("QCA_WLAN_VENDOR_ATTR_HANG_REASON put fail");
1170 kfree_skb(vendor_event);
1171 return -EINVAL;
1172 }
1173
1174 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1175
Dustin Browne74003f2018-03-14 12:51:58 -07001176 hdd_exit();
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301177 return 0;
1178}
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -07001179
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301180#undef HANG_REASON_INDEX
1181
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301182/**
1183 * wlan_hdd_get_adjacent_chan(): Gets next/previous channel
1184 * with respect to the channel passed.
1185 * @chan: Channel
1186 * @upper: If "true" then next channel is returned or else
1187 * previous channel is returned.
1188 *
1189 * This function returns the next/previous adjacent-channel to
1190 * the channel passed. If "upper = true" then next channel is
1191 * returned else previous is returned.
1192 */
1193int wlan_hdd_get_adjacent_chan(uint8_t chan, bool upper)
1194{
Ashish Kumar Dhanotiyaaa9fdbb2018-12-14 15:29:14 +05301195 enum channel_enum ch_idx = wlan_reg_get_chan_enum(chan);
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301196
1197 if (ch_idx == INVALID_CHANNEL)
1198 return -EINVAL;
1199
1200 if (upper && (ch_idx < (NUM_CHANNELS - 1)))
1201 ch_idx++;
Amar Singhal2e4cccc2019-08-06 12:47:18 -07001202 else if (!upper && (ch_idx > CHAN_ENUM_2412))
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301203 ch_idx--;
1204 else
1205 return -EINVAL;
1206
1207 return WLAN_REG_CH_NUM(ch_idx);
1208}
1209
1210/**
1211 * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
1212 * avoided when Do_Not_Break_Stream is active.
Jeff Johnsonb8944722017-09-03 09:03:19 -07001213 * @hdd_ctx: HDD Context
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301214 * @op_chan: AP/P2P-GO operating channel
1215 *
1216 * This function sends list of frequencies to be avoided when
1217 * Do_Not_Break_Stream is active.
1218 * To clear the avoid_frequency_list in the application,
1219 * op_chan = 0 can be passed.
1220 *
1221 * Return: 0 on success and errno on failure
1222 */
Jeff Johnsonb8944722017-09-03 09:03:19 -07001223int wlan_hdd_send_avoid_freq_for_dnbs(struct hdd_context *hdd_ctx, uint8_t op_chan)
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301224{
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001225 struct ch_avoid_ind_type p2p_avoid_freq_list;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301226 uint8_t min_chan, max_chan;
1227 int ret;
1228 int chan;
1229
Dustin Brown491d54b2018-03-14 12:39:11 -07001230 hdd_enter();
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301231
Jeff Johnsonb8944722017-09-03 09:03:19 -07001232 if (!hdd_ctx) {
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301233 hdd_err("invalid param");
1234 return -EINVAL;
1235 }
1236
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001237 qdf_mem_zero(&p2p_avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301238 /*
1239 * If channel passed is zero, clear the avoid_freq list in application.
1240 */
1241 if (!op_chan) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301242#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001243 mutex_lock(&hdd_ctx->avoid_freq_lock);
1244 qdf_mem_zero(&hdd_ctx->dnbs_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001245 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001246 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301247 memcpy(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001248 &hdd_ctx->coex_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001249 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001250 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301251#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001252 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx,
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301253 &p2p_avoid_freq_list);
1254 if (ret)
1255 hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
1256 ret);
1257
1258 return ret;
1259 }
1260
1261 if (WLAN_REG_IS_24GHZ_CH(op_chan)) {
Ashish Kumar Dhanotiyaaa9fdbb2018-12-14 15:29:14 +05301262 min_chan = WLAN_REG_MIN_24GHZ_CH_NUM;
1263 max_chan = WLAN_REG_MAX_24GHZ_CH_NUM;
1264 } else if (WLAN_REG_IS_5GHZ_CH(op_chan)) {
1265 min_chan = WLAN_REG_MIN_5GHZ_CH_NUM;
1266 max_chan = WLAN_REG_MAX_5GHZ_CH_NUM;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301267 } else {
1268 hdd_err("invalid channel:%d", op_chan);
1269 return -EINVAL;
1270 }
1271
1272 if ((op_chan > min_chan) && (op_chan < max_chan)) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001273 p2p_avoid_freq_list.ch_avoid_range_cnt = 2;
1274 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301275 wlan_chan_to_freq(min_chan);
1276
1277 /* Get channel before the op_chan */
1278 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1279 if (chan < 0)
1280 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001281 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301282 wlan_chan_to_freq(chan);
1283
1284 /* Get channel next to the op_chan */
1285 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1286 if (chan < 0)
1287 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001288 p2p_avoid_freq_list.avoid_freq_range[1].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301289 wlan_chan_to_freq(chan);
1290
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001291 p2p_avoid_freq_list.avoid_freq_range[1].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301292 wlan_chan_to_freq(max_chan);
1293 } else if (op_chan == min_chan) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001294 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301295
1296 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1297 if (chan < 0)
1298 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001299 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301300 wlan_chan_to_freq(chan);
1301
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001302 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301303 wlan_chan_to_freq(max_chan);
1304 } else {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001305 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
1306 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301307 wlan_chan_to_freq(min_chan);
1308
1309 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1310 if (chan < 0)
1311 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001312 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301313 wlan_chan_to_freq(chan);
1314 }
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301315#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001316 mutex_lock(&hdd_ctx->avoid_freq_lock);
1317 hdd_ctx->dnbs_avoid_freq_list = p2p_avoid_freq_list;
1318 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301319 ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001320 &hdd_ctx->coex_avoid_freq_list);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301321 if (ret) {
Jeff Johnsonb8944722017-09-03 09:03:19 -07001322 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301323 hdd_err("avoid freq merge failed");
1324 return ret;
1325 }
1326 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07001327 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301328#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001329 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx, &p2p_avoid_freq_list);
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301330 if (ret)
1331 hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
1332
1333 return ret;
1334}
1335
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001336/* vendor specific events */
1337static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001338 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
1339 .vendor_id =
1340 QCA_NL80211_VENDOR_ID,
1341 .subcmd =
1342 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
1343 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001344
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001345 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
1346 .vendor_id =
1347 QCA_NL80211_VENDOR_ID,
1348 .subcmd =
1349 QCA_NL80211_VENDOR_SUBCMD_NAN
1350 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001351
1352#ifdef WLAN_FEATURE_STATS_EXT
1353 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
1354 .vendor_id =
1355 QCA_NL80211_VENDOR_ID,
1356 .subcmd =
1357 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
1358 },
1359#endif /* WLAN_FEATURE_STATS_EXT */
1360#ifdef FEATURE_WLAN_EXTSCAN
1361 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
1362 .vendor_id =
1363 QCA_NL80211_VENDOR_ID,
1364 .subcmd =
1365 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
1366 },
1367 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
1368 .vendor_id =
1369 QCA_NL80211_VENDOR_ID,
1370 .subcmd =
1371 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
1372 },
1373 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
1374 .
1375 vendor_id
1376 =
1377 QCA_NL80211_VENDOR_ID,
1378 .subcmd =
1379 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
1380 },
1381 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
1382 .
1383 vendor_id
1384 =
1385 QCA_NL80211_VENDOR_ID,
1386 .
1387 subcmd =
1388 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
1389 },
1390 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
1391 .
1392 vendor_id
1393 =
1394 QCA_NL80211_VENDOR_ID,
1395 .
1396 subcmd
1397 =
1398 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1399 },
1400 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1401 .
1402 vendor_id
1403 =
1404 QCA_NL80211_VENDOR_ID,
1405 .subcmd =
1406 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1407 },
1408 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1409 .vendor_id =
1410 QCA_NL80211_VENDOR_ID,
1411 .subcmd =
1412 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1413 },
1414 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1415 .
1416 vendor_id
1417 =
1418 QCA_NL80211_VENDOR_ID,
1419 .subcmd =
1420 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1421 },
1422 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1423 .
1424 vendor_id
1425 =
1426 QCA_NL80211_VENDOR_ID,
1427 .subcmd =
1428 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1429 },
1430 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1431 .
1432 vendor_id
1433 =
1434 QCA_NL80211_VENDOR_ID,
1435 .
1436 subcmd
1437 =
1438 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1439 },
1440 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1441 .
1442 vendor_id
1443 =
1444 QCA_NL80211_VENDOR_ID,
1445 .
1446 subcmd =
1447 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1448 },
1449 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1450 .
1451 vendor_id
1452 =
1453 QCA_NL80211_VENDOR_ID,
1454 .
1455 subcmd
1456 =
1457 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
1458 },
1459 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
1460 .
1461 vendor_id
1462 =
1463 QCA_NL80211_VENDOR_ID,
1464 .
1465 subcmd
1466 =
1467 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
1468 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001469#endif /* FEATURE_WLAN_EXTSCAN */
1470
1471#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1472 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
1473 .vendor_id =
1474 QCA_NL80211_VENDOR_ID,
1475 .subcmd =
1476 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
1477 },
1478 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
1479 .vendor_id =
1480 QCA_NL80211_VENDOR_ID,
1481 .subcmd =
1482 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
1483 },
1484 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
1485 .vendor_id =
1486 QCA_NL80211_VENDOR_ID,
1487 .subcmd =
1488 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
1489 },
1490 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
1491 .vendor_id =
1492 QCA_NL80211_VENDOR_ID,
1493 .subcmd =
1494 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
1495 },
1496 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
1497 .vendor_id =
1498 QCA_NL80211_VENDOR_ID,
1499 .subcmd =
1500 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
1501 },
1502 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
1503 .vendor_id =
1504 QCA_NL80211_VENDOR_ID,
1505 .subcmd =
1506 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
1507 },
Zhang Qianca38fb12016-12-23 11:10:48 +08001508 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
1509 .vendor_id =
1510 QCA_NL80211_VENDOR_ID,
1511 .subcmd =
1512 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
1513 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001514#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1515 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1516 .vendor_id =
1517 QCA_NL80211_VENDOR_ID,
1518 .subcmd =
1519 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1520 },
1521 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1522 .vendor_id = QCA_NL80211_VENDOR_ID,
1523 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1524 },
1525#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1526 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1527 .vendor_id =
1528 QCA_NL80211_VENDOR_ID,
1529 .subcmd =
1530 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1531 },
1532#endif
1533 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1534 .vendor_id =
1535 QCA_NL80211_VENDOR_ID,
1536 .subcmd =
1537 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1538 },
1539 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1540 .vendor_id =
1541 QCA_NL80211_VENDOR_ID,
1542 .subcmd =
1543 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1544 },
1545 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1546 .vendor_id =
1547 QCA_NL80211_VENDOR_ID,
1548 .subcmd =
1549 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1550 },
1551 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1552 .vendor_id =
1553 QCA_NL80211_VENDOR_ID,
1554 .subcmd =
1555 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1556 },
1557 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1558 .vendor_id =
1559 QCA_NL80211_VENDOR_ID,
1560 .subcmd =
1561 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1562 },
1563#ifdef FEATURE_WLAN_EXTSCAN
1564 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1565 .vendor_id = QCA_NL80211_VENDOR_ID,
1566 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1567 },
1568 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1569 .vendor_id = QCA_NL80211_VENDOR_ID,
1570 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1571 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001572 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1573 .vendor_id = QCA_NL80211_VENDOR_ID,
1574 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1575 },
1576#endif /* FEATURE_WLAN_EXTSCAN */
Qiwei Caie689a262018-07-26 15:50:22 +08001577
1578 FEATURE_RSSI_MONITOR_VENDOR_EVENTS
1579
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001580#ifdef WLAN_FEATURE_TSF
1581 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1582 .vendor_id = QCA_NL80211_VENDOR_ID,
1583 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1584 },
1585#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001586 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1587 .vendor_id = QCA_NL80211_VENDOR_ID,
1588 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1589 },
1590 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1591 .vendor_id = QCA_NL80211_VENDOR_ID,
1592 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1593 },
1594 /* OCB events */
1595 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1596 .vendor_id = QCA_NL80211_VENDOR_ID,
1597 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1598 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001599#ifdef FEATURE_LFR_SUBNET_DETECTION
1600 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1601 .vendor_id = QCA_NL80211_VENDOR_ID,
1602 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1603 },
1604#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001605
Paul Zhang37185672019-05-14 11:20:14 +08001606 FEATURE_INTEROP_ISSUES_AP_VENDOR_COMMANDS_INDEX
1607
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001608 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1609 .vendor_id = QCA_NL80211_VENDOR_ID,
1610 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1611 },
Peng Xu8fdaa492016-06-22 10:20:47 -07001612
1613 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1614 .vendor_id = QCA_NL80211_VENDOR_ID,
1615 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1616 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301617 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1618 .vendor_id = QCA_NL80211_VENDOR_ID,
1619 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1620 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301621 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1622 .vendor_id = QCA_NL80211_VENDOR_ID,
1623 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1624 },
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05301625 [QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX] = {
1626 .vendor_id = QCA_NL80211_VENDOR_ID,
1627 .subcmd = QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE
Anurag Chouhan3920c0f2017-09-11 17:10:56 +05301628 },
1629 [QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX] = {
1630 .vendor_id = QCA_NL80211_VENDOR_ID,
1631 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
1632 },
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301633 [QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX] = {
1634 .vendor_id = QCA_NL80211_VENDOR_ID,
1635 .subcmd = QCA_NL80211_VENDOR_SUBCMD_HANG,
1636 },
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +05301637 [QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX] = {
1638 .vendor_id = QCA_NL80211_VENDOR_ID,
1639 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO,
1640 },
Alok Kumar2fad6442018-11-08 19:19:28 +05301641 [QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT_INDEX] = {
1642 .vendor_id = QCA_NL80211_VENDOR_ID,
1643 .subcmd = QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT,
1644 },
Nachiket Kukadea6a70a92018-10-09 20:07:21 +05301645 [QCA_NL80211_VENDOR_SUBCMD_NAN_EXT_INDEX] = {
1646 .vendor_id = QCA_NL80211_VENDOR_ID,
1647 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN_EXT
1648 },
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +05301649 [QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX] = {
1650 .vendor_id = QCA_NL80211_VENDOR_ID,
1651 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
1652 },
Abhinav Kumar4d1f9f42019-05-07 13:14:49 +05301653
1654 BCN_RECV_FEATURE_VENDOR_EVENTS
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05301655 [QCA_NL80211_VENDOR_SUBCMD_ROAM_INDEX] = {
1656 .vendor_id = QCA_NL80211_VENDOR_ID,
1657 .subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
1658 },
Ashish Kumar Dhanotiyad8d7dea2019-10-24 14:34:56 +05301659 [QCA_NL80211_VENDOR_SUBCMD_OEM_DATA_INDEX] = {
1660 .vendor_id = QCA_NL80211_VENDOR_ID,
1661 .subcmd = QCA_NL80211_VENDOR_SUBCMD_OEM_DATA,
1662 },
Ashish Kumar Dhanotiya3d5a7422020-01-20 14:42:02 +05301663 [QCA_NL80211_VENDOR_SUBCMD_REQUEST_SAR_LIMITS_INDEX] = {
1664 .vendor_id = QCA_NL80211_VENDOR_ID,
1665 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS_EVENT,
1666 },
Abhishek Ambure5e9b6a42020-02-12 21:32:35 +05301667 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO_INDEX] = {
1668 .vendor_id = QCA_NL80211_VENDOR_ID,
1669 .subcmd = QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO,
1670 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001671};
1672
1673/**
1674 * __is_driver_dfs_capable() - get driver DFS capability
1675 * @wiphy: pointer to wireless wiphy structure.
1676 * @wdev: pointer to wireless_dev structure.
1677 * @data: Pointer to the data to be passed via vendor interface
1678 * @data_len:Length of the data to be passed
1679 *
1680 * This function is called by userspace to indicate whether or not
1681 * the driver supports DFS offload.
1682 *
1683 * Return: 0 on success, negative errno on failure
1684 */
1685static int __is_driver_dfs_capable(struct wiphy *wiphy,
1686 struct wireless_dev *wdev,
1687 const void *data,
1688 int data_len)
1689{
1690 u32 dfs_capability = 0;
1691 struct sk_buff *temp_skbuff;
1692 int ret_val;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001693 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001694
Dustin Brownfdf17c12018-03-14 12:55:34 -07001695 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001696
1697 ret_val = wlan_hdd_validate_context(hdd_ctx);
1698 if (ret_val)
1699 return ret_val;
1700
Anurag Chouhan6d760662016-02-20 16:05:43 +05301701 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001702 hdd_err("Command not allowed in FTM mode");
1703 return -EPERM;
1704 }
1705
Peng Xu8e8b0392018-04-30 11:32:34 -07001706#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
1707 defined(CFG80211_DFS_OFFLOAD_BACKPORT)
1708 dfs_capability =
1709 wiphy_ext_feature_isset(wiphy,
1710 NL80211_EXT_FEATURE_DFS_OFFLOAD);
1711#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001712 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Peng Xu8e8b0392018-04-30 11:32:34 -07001713#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001714
1715 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1716 NLMSG_HDRLEN);
1717
Jeff Johnsond36fa332019-03-18 13:42:25 -07001718 if (temp_skbuff) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001719 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1720 dfs_capability);
1721 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001722 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001723 kfree_skb(temp_skbuff);
1724
1725 return ret_val;
1726 }
1727
1728 return cfg80211_vendor_cmd_reply(temp_skbuff);
1729 }
1730
Jeff Johnson020db452016-06-29 14:37:26 -07001731 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001732 return -ENOMEM;
1733}
1734
1735/**
1736 * is_driver_dfs_capable() - get driver DFS capability
1737 * @wiphy: pointer to wireless wiphy structure.
1738 * @wdev: pointer to wireless_dev structure.
1739 * @data: Pointer to the data to be passed via vendor interface
1740 * @data_len:Length of the data to be passed
1741 *
1742 * This function is called by userspace to indicate whether or not
1743 * the driver supports DFS offload. This is an SSR-protected
1744 * wrapper function.
1745 *
1746 * Return: 0 on success, negative errno on failure
1747 */
1748static int is_driver_dfs_capable(struct wiphy *wiphy,
1749 struct wireless_dev *wdev,
1750 const void *data,
1751 int data_len)
1752{
Dustin Brown363b4792019-02-05 16:11:55 -08001753 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08001754 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05301755
Dustin Brown363b4792019-02-05 16:11:55 -08001756 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001757 if (errno)
1758 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001759
Dustin Brownf0f00612019-01-31 16:02:24 -08001760 errno = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001761
Dustin Brown363b4792019-02-05 16:11:55 -08001762 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001763
1764 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001765}
1766
1767/**
1768 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1769 *
1770 * @adapter: SAP adapter pointer
1771 *
1772 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1773 * radio. So in case of DFS MCC scenario override current SAP given config
1774 * to follow concurrent SAP DFS config
1775 *
1776 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1777 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001778int wlan_hdd_sap_cfg_dfs_override(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001779{
Jeff Johnsone5006672017-08-29 14:39:02 -07001780 struct hdd_adapter *con_sap_adapter;
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001781 struct sap_config *sap_config, *con_sap_config;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001782 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001783 uint32_t con_ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001784
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001785 if (!hdd_ctx) {
1786 hdd_err("hdd context is NULL");
1787 return 0;
1788 }
1789
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001790 /*
1791 * Check if AP+AP case, once primary AP chooses a DFS
1792 * channel secondary AP should always follow primary APs channel
1793 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001794 if (!policy_mgr_concurrent_beaconing_sessions_running(
Dustin Brown76cd2932018-09-11 16:03:05 -07001795 hdd_ctx->psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001796 return 0;
1797
1798 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1799 if (!con_sap_adapter)
1800 return 0;
1801
Jeff Johnsonb9424862017-10-30 08:49:35 -07001802 sap_config = &adapter->session.ap.sap_config;
1803 con_sap_config = &con_sap_adapter->session.ap.sap_config;
Will Huang4b097f52019-08-29 10:51:56 -07001804 con_ch_freq = con_sap_adapter->session.ap.operating_chan_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001805
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001806 if (!wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, con_ch_freq))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001807 return 0;
1808
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001809 hdd_debug("Only SCC AP-AP DFS Permitted (ch_freq=%d, con_ch_freq=%d)",
1810 sap_config->chan_freq, con_ch_freq);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001811 hdd_debug("Overriding guest AP's channel");
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001812 sap_config->chan_freq = con_ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001813
1814 if (con_sap_config->acs_cfg.acs_mode == true) {
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05301815 if (con_ch_freq != con_sap_config->acs_cfg.pri_ch_freq &&
1816 con_ch_freq != con_sap_config->acs_cfg.ht_sec_ch_freq) {
Jeff Johnson020db452016-06-29 14:37:26 -07001817 hdd_err("Primary AP channel config error");
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05301818 hdd_err("Operating ch: %d ACS ch freq: %d Sec Freq %d",
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001819 con_ch_freq,
1820 con_sap_config->acs_cfg.pri_ch_freq,
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05301821 con_sap_config->acs_cfg.ht_sec_ch_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001822 return -EINVAL;
1823 }
1824 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1825 * MCC restriction. So free ch list allocated in do_acs
1826 * func for Sec AP and realloc for Pri AP ch list size
1827 */
hque6ea8ee2020-02-19 14:46:49 +08001828 if (sap_config->acs_cfg.freq_list) {
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301829 qdf_mem_free(sap_config->acs_cfg.freq_list);
hque6ea8ee2020-02-19 14:46:49 +08001830 sap_config->acs_cfg.freq_list = NULL;
1831 }
1832 if (sap_config->acs_cfg.master_freq_list) {
1833 qdf_mem_free(sap_config->acs_cfg.master_freq_list);
1834 sap_config->acs_cfg.master_freq_list = NULL;
1835 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001836
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301837 qdf_mem_copy(&sap_config->acs_cfg,
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301838 &con_sap_config->acs_cfg,
1839 sizeof(struct sap_acs_cfg));
hque6ea8ee2020-02-19 14:46:49 +08001840
1841 sap_config->acs_cfg.freq_list =
1842 qdf_mem_malloc(sizeof(uint32_t) *
1843 con_sap_config->acs_cfg.ch_list_count);
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301844 if (!sap_config->acs_cfg.freq_list) {
gaurank kathpalia6701aef2019-06-27 11:53:08 +05301845 sap_config->acs_cfg.ch_list_count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001846 return -ENOMEM;
gaurank kathpalia6701aef2019-06-27 11:53:08 +05301847 }
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301848 qdf_mem_copy(sap_config->acs_cfg.freq_list,
1849 con_sap_config->acs_cfg.freq_list,
1850 con_sap_config->acs_cfg.ch_list_count *
hque6ea8ee2020-02-19 14:46:49 +08001851 sizeof(uint32_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001852
hque6ea8ee2020-02-19 14:46:49 +08001853 sap_config->acs_cfg.master_freq_list =
1854 qdf_mem_malloc(sizeof(uint32_t) *
1855 con_sap_config->acs_cfg.master_ch_list_count);
1856 if (!sap_config->acs_cfg.master_freq_list) {
1857 sap_config->acs_cfg.master_ch_list_count = 0;
1858 qdf_mem_free(sap_config->acs_cfg.freq_list);
1859 sap_config->acs_cfg.freq_list = NULL;
1860 return -ENOMEM;
1861 }
1862 qdf_mem_copy(sap_config->acs_cfg.master_freq_list,
1863 con_sap_config->acs_cfg.master_freq_list,
1864 con_sap_config->acs_cfg.master_ch_list_count *
1865 sizeof(uint32_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001866 } else {
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05301867 sap_config->acs_cfg.pri_ch_freq = con_ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001868 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05301869 sap_config->acs_cfg.ht_sec_ch_freq =
1870 con_sap_config->sec_ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001871 }
1872
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001873 return con_ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001874}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001875
1876/**
wadesong1795e142018-01-05 11:13:07 +08001877 * wlan_hdd_set_acs_ch_range : Populate ACS hw mode and channel range values
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001878 * @sap_cfg: pointer to SAP config struct
wadesong1795e142018-01-05 11:13:07 +08001879 * @hw_mode: hw mode retrieved from vendor command buffer
1880 * @ht_enabled: whether HT phy mode is enabled
1881 * @vht_enabled: whether VHT phy mode is enabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001882 *
wadesong1795e142018-01-05 11:13:07 +08001883 * This function populates the ACS hw mode based on the configuration retrieved
1884 * from the vendor command buffer; and sets ACS start and end channel for the
1885 * given band.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886 *
wadesong1795e142018-01-05 11:13:07 +08001887 * Return: 0 if success; -EINVAL if ACS channel list is NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888 */
wadesong1795e142018-01-05 11:13:07 +08001889static int wlan_hdd_set_acs_ch_range(
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001890 struct sap_config *sap_cfg, enum qca_wlan_vendor_acs_hw_mode hw_mode,
wadesong1795e142018-01-05 11:13:07 +08001891 bool ht_enabled, bool vht_enabled)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001892{
1893 int i;
Srinivas Girigowda576b2352017-08-25 14:44:26 -07001894
wadesong1795e142018-01-05 11:13:07 +08001895 if (hw_mode == QCA_ACS_MODE_IEEE80211B) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001896 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001897 sap_cfg->acs_cfg.start_ch_freq =
1898 wlan_reg_ch_to_freq(CHAN_ENUM_2412);
1899 sap_cfg->acs_cfg.end_ch_freq =
1900 wlan_reg_ch_to_freq(CHAN_ENUM_2484);
wadesong1795e142018-01-05 11:13:07 +08001901 } else if (hw_mode == QCA_ACS_MODE_IEEE80211G) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001902 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001903 sap_cfg->acs_cfg.start_ch_freq =
1904 wlan_reg_ch_to_freq(CHAN_ENUM_2412);
1905 sap_cfg->acs_cfg.end_ch_freq =
1906 wlan_reg_ch_to_freq(CHAN_ENUM_2472);
wadesong1795e142018-01-05 11:13:07 +08001907 } else if (hw_mode == QCA_ACS_MODE_IEEE80211A) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001909 sap_cfg->acs_cfg.start_ch_freq =
1910 wlan_reg_ch_to_freq(CHAN_ENUM_5180);
1911 sap_cfg->acs_cfg.end_ch_freq =
1912 wlan_reg_ch_to_freq(CHAN_ENUM_5865);
wadesong1795e142018-01-05 11:13:07 +08001913 } else if (hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001914 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001915 sap_cfg->acs_cfg.start_ch_freq =
1916 wlan_reg_ch_to_freq(CHAN_ENUM_2412);
1917 sap_cfg->acs_cfg.end_ch_freq =
1918 wlan_reg_ch_to_freq(CHAN_ENUM_5865);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919 }
1920
1921 if (ht_enabled)
1922 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1923
1924 if (vht_enabled)
1925 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1926
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927 /* Parse ACS Chan list from hostapd */
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301928 if (!sap_cfg->acs_cfg.freq_list)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301929 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001931 sap_cfg->acs_cfg.start_ch_freq = sap_cfg->acs_cfg.freq_list[0];
1932 sap_cfg->acs_cfg.end_ch_freq =
1933 sap_cfg->acs_cfg.freq_list[sap_cfg->acs_cfg.ch_list_count - 1];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001934 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301935 /* avoid channel as start channel */
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001936 if (sap_cfg->acs_cfg.start_ch_freq >
1937 sap_cfg->acs_cfg.freq_list[i] &&
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301938 sap_cfg->acs_cfg.freq_list[i] != 0)
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001939 sap_cfg->acs_cfg.start_ch_freq =
1940 sap_cfg->acs_cfg.freq_list[i];
1941 if (sap_cfg->acs_cfg.end_ch_freq <
1942 sap_cfg->acs_cfg.freq_list[i])
1943 sap_cfg->acs_cfg.end_ch_freq =
1944 sap_cfg->acs_cfg.freq_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001945 }
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301946
1947 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001948}
1949
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001950static void hdd_update_acs_channel_list(struct sap_config *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001951 enum band_info band)
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301952{
1953 int i, temp_count = 0;
1954 int acs_list_count = sap_config->acs_cfg.ch_list_count;
1955
1956 for (i = 0; i < acs_list_count; i++) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001957 if (BAND_2G == band) {
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301958 if (WLAN_REG_IS_24GHZ_CH_FREQ(
1959 sap_config->acs_cfg.freq_list[i])) {
1960 sap_config->acs_cfg.freq_list[temp_count] =
1961 sap_config->acs_cfg.freq_list[i];
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301962 temp_count++;
1963 }
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001964 } else if (BAND_5G == band) {
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301965 if (WLAN_REG_IS_5GHZ_CH_FREQ(
1966 sap_config->acs_cfg.freq_list[i]) ||
1967 WLAN_REG_IS_6GHZ_CHAN_FREQ(
1968 sap_config->acs_cfg.freq_list[i])) {
1969 sap_config->acs_cfg.freq_list[temp_count] =
1970 sap_config->acs_cfg.freq_list[i];
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301971 temp_count++;
1972 }
1973 }
1974 }
1975 sap_config->acs_cfg.ch_list_count = temp_count;
1976}
1977
1978
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979/**
1980 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1981 * @adapter: pointer to SAP adapter struct
1982 *
1983 * This function starts the ACS procedure if there are no
1984 * constraints like MBSSID DFS restrictions.
1985 *
1986 * Return: Status of ACS Start procedure
1987 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001988int wlan_hdd_cfg80211_start_acs(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989{
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001990 struct hdd_context *hdd_ctx;
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001991 struct sap_config *sap_config;
Jeff Johnson7dcac7e2019-03-23 15:10:06 -07001992 sap_event_cb acs_event_callback;
Krunal Soni5e3f9622018-09-26 16:35:50 -07001993 uint8_t mcc_to_scc_switch = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001994 int status;
gaurank kathpaliafa8b2e12019-11-20 12:30:38 +05301995 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001996
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001997 if (!adapter) {
Jeff Johnsondd2f1fc2018-05-06 11:22:52 -07001998 hdd_err("adapter is NULL");
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001999 return -EINVAL;
2000 }
2001 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Ashish Kumar Dhanotiyadc3900f2019-01-11 20:42:04 +05302002 status = wlan_hdd_validate_context(hdd_ctx);
2003 if (0 != status)
2004 return status;
2005
Jeff Johnsonb9424862017-10-30 08:49:35 -07002006 sap_config = &adapter->session.ap.sap_config;
Ashish Kumar Dhanotiyab0629622018-09-21 18:58:59 +05302007 if (!sap_config) {
2008 hdd_err("SAP config is NULL");
2009 return -EINVAL;
2010 }
Rajeev Kumar Sirasanagandlae83ac292019-09-19 16:35:26 +05302011 if (hdd_ctx->acs_policy.acs_chan_freq)
2012 sap_config->chan_freq = hdd_ctx->acs_policy.acs_chan_freq;
Agrawal Ashish65634612016-08-18 13:24:32 +05302013 else
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07002014 sap_config->chan_freq = AUTO_CHANNEL_SELECT;
Krunal Soni5e3f9622018-09-26 16:35:50 -07002015 ucfg_policy_mgr_get_mcc_scc_switch(hdd_ctx->psoc,
2016 &mcc_to_scc_switch);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302017 /*
2018 * No DFS SCC is allowed in Auto use case. Hence not
2019 * calling DFS override
2020 */
2021 if (QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION !=
Jianmin Zhu7f212f72019-06-18 15:41:10 +08002022 mcc_to_scc_switch &&
2023 !(policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) &&
Liangwei Dong50d12dc2019-11-06 14:19:46 +08002024 WLAN_REG_IS_24GHZ_CH_FREQ(sap_config->acs_cfg.end_ch_freq))) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302025 status = wlan_hdd_sap_cfg_dfs_override(adapter);
2026 if (status < 0)
2027 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302029 if (status > 0) {
2030 /*notify hostapd about channel override */
2031 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302032 return 0;
2033 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002034 }
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302035 /* When first 2 connections are on the same frequency band,
2036 * then PCL would include only channels from the other
2037 * frequency band on which no connections are active
2038 */
Dustin Brown76cd2932018-09-11 16:03:05 -07002039 if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302040 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
2041 struct policy_mgr_conc_connection_info *conc_connection_info;
2042 uint32_t i;
Jeff Johnson68755312017-02-10 11:46:55 -08002043
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302044 conc_connection_info = policy_mgr_get_conn_info(&i);
2045 if (conc_connection_info[0].mac ==
2046 conc_connection_info[1].mac) {
wadesong88378bd2020-03-24 13:25:21 +08002047 if (!WLAN_REG_IS_24GHZ_CH_FREQ(
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302048 sap_config->acs_cfg.pcl_chan_freq[0])) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302049 sap_config->acs_cfg.band =
2050 QCA_ACS_MODE_IEEE80211A;
2051 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002052 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302053 } else {
2054 sap_config->acs_cfg.band =
2055 QCA_ACS_MODE_IEEE80211G;
2056 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002057 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302058 }
2059 }
2060 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002061 status = wlan_hdd_config_acs(hdd_ctx, adapter);
2062 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07002063 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002064 return -EINVAL;
2065 }
2066
2067 acs_event_callback = hdd_hostapd_sap_event_cb;
2068
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302069 qdf_mem_copy(sap_config->self_macaddr.bytes,
Jeff Johnson1e851a12017-10-28 14:36:12 -07002070 adapter->mac_addr.bytes, sizeof(struct qdf_mac_addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071
gaurank kathpaliafa8b2e12019-11-20 12:30:38 +05302072 qdf_status = wlansap_acs_chselect(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2073 acs_event_callback,
2074 sap_config, adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002075
gaurank kathpaliafa8b2e12019-11-20 12:30:38 +05302076 if (QDF_IS_STATUS_ERROR(qdf_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002077 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002078 return -EINVAL;
2079 }
bings394afdd2017-01-09 11:22:38 +08002080 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
2081 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082
2083 return 0;
2084}
2085
2086/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05302087 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
2088 * @hdd_ctx: hdd context
2089 * @acs_chan_params: external acs channel params
2090 * @sap_config: SAP config
2091 *
2092 * This API provides unsorted pcl list.
2093 * this list is a subset of the valid channel list given by hostapd.
2094 * if channel is not present in pcl, weightage will be given as zero
2095 *
2096 * Return: Zero on success, non-zero on failure
2097 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002098static void hdd_update_vendor_pcl_list(struct hdd_context *hdd_ctx,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302099 struct hdd_vendor_acs_chan_params *acs_chan_params,
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002100 struct sap_config *sap_config)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302101{
2102 int i, j;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05302103 /*
2104 * PCL shall contain only the preferred channels from the
2105 * application. If those channels are not present in the
2106 * driver PCL, then set the weight to zero
2107 */
2108 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
2109 acs_chan_params->vendor_pcl_list[i] =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302110 sap_config->acs_cfg.freq_list[i];
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05302111 acs_chan_params->vendor_weight_list[i] = 0;
2112 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302113 if (sap_config->acs_cfg.freq_list[i] ==
2114 sap_config->acs_cfg.pcl_chan_freq[j]) {
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05302115 acs_chan_params->vendor_weight_list[i] =
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302116 sap_config->acs_cfg.pcl_channels_weight_list[j];
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05302117 break;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302118 }
2119 }
2120 }
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05302121 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302122}
2123
2124/**
Kapil Gupta086c6202016-12-11 18:17:06 +05302125 * hdd_update_reg_chan_info : This API contructs channel info
2126 * for all the given channel
2127 * @adapter: pointer to SAP adapter struct
2128 * @channel_count: channel count
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302129 * @freq_list: channel frequency (MHz) list
Kapil Gupta086c6202016-12-11 18:17:06 +05302130 *
2131 * Return: Status of of channel information updation
2132 */
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302133static int
2134hdd_update_reg_chan_info(struct hdd_adapter *adapter,
2135 uint32_t channel_count, uint32_t *freq_list)
Kapil Gupta086c6202016-12-11 18:17:06 +05302136{
2137 int i;
2138 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08002139 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05302140 uint8_t bw_offset = 0, chan = 0;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002141 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002142 struct sap_config *sap_config = &adapter->session.ap.sap_config;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07002143 mac_handle_t mac_handle;
Vignesh Viswanathana1f3a1a2018-10-04 13:10:46 +05302144 uint8_t sub_20_chan_width = 0;
2145 QDF_STATUS status;
Kapil Gupta086c6202016-12-11 18:17:06 +05302146
Jeff Johnson34fc63a2018-06-14 10:10:02 -07002147 mac_handle = hdd_ctx->mac_handle;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302148 sap_config->channel_info_count = channel_count;
Vignesh Viswanathana1f3a1a2018-10-04 13:10:46 +05302149
2150 status = ucfg_mlme_get_sub_20_chan_width(hdd_ctx->psoc,
2151 &sub_20_chan_width);
2152 if (QDF_IS_STATUS_ERROR(status))
2153 hdd_err("Failed to get sub_20_chan_width config");
2154
Kapil Gupta086c6202016-12-11 18:17:06 +05302155 for (i = 0; i < channel_count; i++) {
2156 icv = &sap_config->channel_info[i];
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302157 chan = wlan_reg_freq_to_chan(hdd_ctx->pdev,
2158 freq_list[i]);
Kapil Gupta086c6202016-12-11 18:17:06 +05302159 if (chan == 0)
2160 continue;
2161
Dustin Brown07901ec2018-09-07 11:02:41 -07002162 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05302163 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002164 icv->max_reg_power = wlan_reg_get_channel_reg_power(
Dustin Brown07901ec2018-09-07 11:02:41 -07002165 hdd_ctx->pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05302166
2167 /* filling demo values */
2168 icv->max_radio_power = HDD_MAX_TX_POWER;
2169 icv->min_radio_power = HDD_MIN_TX_POWER;
2170 /* not supported in current driver */
2171 icv->max_antenna_gain = 0;
2172
jiad7b8a5e02018-11-26 16:37:57 +08002173 bw_offset = hdd_get_bw_offset(sap_config->acs_cfg.ch_width);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07002174 icv->reg_class_id =
2175 wlan_hdd_find_opclass(mac_handle, chan, bw_offset);
Kapil Gupta086c6202016-12-11 18:17:06 +05302176
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002177 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05302178 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Dustin Brown07901ec2018-09-07 11:02:41 -07002179 wlan_reg_set_channel_params(hdd_ctx->pdev, chan,
2180 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05302181 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
2182 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
2183 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002184
Kapil Gupta086c6202016-12-11 18:17:06 +05302185 icv->flags = 0;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302186 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->pdev,
2187 icv->ieee_chan_number,
Kapil Gupta086c6202016-12-11 18:17:06 +05302188 sap_config->acs_cfg.ch_width,
2189 sap_config->acs_cfg.is_ht_enabled,
2190 sap_config->acs_cfg.is_vht_enabled,
Vignesh Viswanathana1f3a1a2018-10-04 13:10:46 +05302191 sub_20_chan_width);
Kapil Guptac1224bf2017-06-22 21:22:40 +05302192 if (icv->flags & IEEE80211_CHAN_PASSIVE)
2193 icv->flagext |= IEEE80211_CHAN_DFS;
Kapil Gupta086c6202016-12-11 18:17:06 +05302194
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +05302195 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 +05302196 icv->freq, icv->flags,
2197 icv->flagext, icv->ieee_chan_number,
2198 icv->max_reg_power, icv->max_radio_power,
2199 icv->min_radio_power, icv->reg_class_id,
2200 icv->max_antenna_gain, icv->vht_center_freq_seg0,
2201 icv->vht_center_freq_seg1);
2202 }
2203 return 0;
2204}
2205
2206/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
2207#define CHAN_INFO_ATTR_FLAGS \
2208 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
2209#define CHAN_INFO_ATTR_FLAG_EXT \
2210 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
2211#define CHAN_INFO_ATTR_FREQ \
2212 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
2213#define CHAN_INFO_ATTR_MAX_REG_POWER \
2214 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
2215#define CHAN_INFO_ATTR_MAX_POWER \
2216 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
2217#define CHAN_INFO_ATTR_MIN_POWER \
2218 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
2219#define CHAN_INFO_ATTR_REG_CLASS_ID \
2220 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
2221#define CHAN_INFO_ATTR_ANTENNA_GAIN \
2222 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
2223#define CHAN_INFO_ATTR_VHT_SEG_0 \
2224 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
2225#define CHAN_INFO_ATTR_VHT_SEG_1 \
2226 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
2227
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302228#define CHAN_INFO_ATTR_FREQ_VHT_SEG_0 \
2229 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0
2230#define CHAN_INFO_ATTR_FREQ_VHT_SEG_1 \
2231 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1
2232
Kapil Gupta086c6202016-12-11 18:17:06 +05302233/**
2234 * hdd_cfg80211_update_channel_info() - add channel info attributes
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302235 * @hdd_ctx: pointer to hdd context
Kapil Gupta086c6202016-12-11 18:17:06 +05302236 * @skb: pointer to sk buff
2237 * @hdd_ctx: pointer to hdd station context
2238 * @idx: attribute index
2239 *
2240 * Return: Success(0) or reason code for failure
2241 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05302242static int32_t
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302243hdd_cfg80211_update_channel_info(struct hdd_context *hdd_ctx,
2244 struct sk_buff *skb,
2245 struct sap_config *sap_config, int idx)
Kapil Gupta086c6202016-12-11 18:17:06 +05302246{
2247 struct nlattr *nla_attr, *channel;
2248 struct hdd_channel_info *icv;
2249 int i;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302250 uint32_t freq_seg_0, freq_seg_1;
Kapil Gupta086c6202016-12-11 18:17:06 +05302251
2252 nla_attr = nla_nest_start(skb, idx);
2253 if (!nla_attr)
2254 goto fail;
2255
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302256 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05302257 channel = nla_nest_start(skb, i);
2258 if (!channel)
2259 goto fail;
2260
2261 icv = &sap_config->channel_info[i];
2262 if (!icv) {
2263 hdd_err("channel info not found");
2264 goto fail;
2265 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302266
2267 freq_seg_0 = wlan_reg_legacy_chan_to_freq(
2268 hdd_ctx->pdev,
2269 icv->vht_center_freq_seg0);
2270 freq_seg_1 = wlan_reg_legacy_chan_to_freq(
2271 hdd_ctx->pdev,
2272 icv->vht_center_freq_seg1);
2273
Kapil Gupta086c6202016-12-11 18:17:06 +05302274 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
2275 icv->freq) ||
2276 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
2277 icv->flags) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302278 nla_put_u32(skb, CHAN_INFO_ATTR_FLAG_EXT,
Kapil Gupta086c6202016-12-11 18:17:06 +05302279 icv->flagext) ||
2280 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
2281 icv->max_reg_power) ||
2282 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
2283 icv->max_radio_power) ||
2284 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
2285 icv->min_radio_power) ||
2286 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
2287 icv->reg_class_id) ||
2288 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
2289 icv->max_antenna_gain) ||
2290 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
2291 icv->vht_center_freq_seg0) ||
2292 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302293 icv->vht_center_freq_seg1) ||
2294 nla_put_u32(skb, CHAN_INFO_ATTR_FREQ_VHT_SEG_0,
2295 freq_seg_0) ||
2296 nla_put_u32(skb, CHAN_INFO_ATTR_FREQ_VHT_SEG_1,
2297 freq_seg_1)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05302298 hdd_err("put fail");
2299 goto fail;
2300 }
2301 nla_nest_end(skb, channel);
2302 }
2303 nla_nest_end(skb, nla_attr);
2304 return 0;
2305fail:
2306 hdd_err("nl channel update failed");
2307 return -EINVAL;
2308}
2309#undef CHAN_INFO_ATTR_FLAGS
2310#undef CHAN_INFO_ATTR_FLAG_EXT
2311#undef CHAN_INFO_ATTR_FREQ
2312#undef CHAN_INFO_ATTR_MAX_REG_POWER
2313#undef CHAN_INFO_ATTR_MAX_POWER
2314#undef CHAN_INFO_ATTR_MIN_POWER
2315#undef CHAN_INFO_ATTR_REG_CLASS_ID
2316#undef CHAN_INFO_ATTR_ANTENNA_GAIN
2317#undef CHAN_INFO_ATTR_VHT_SEG_0
2318#undef CHAN_INFO_ATTR_VHT_SEG_1
2319
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302320#undef CHAN_INFO_ATTR_FREQ_VHT_SEG_0
2321#undef CHAN_INFO_ATTR_FREQ_VHT_SEG_1
2322
Kapil Gupta086c6202016-12-11 18:17:06 +05302323/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05302324 * hdd_cfg80211_update_pcl() - add pcl info attributes
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302325 * @hdd_ctx: pointer to hdd context
Kapil Gupta8878ad92017-02-13 11:56:04 +05302326 * @skb: pointer to sk buff
2327 * @hdd_ctx: pointer to hdd station context
2328 * @idx: attribute index
2329 * @vendor_pcl_list: PCL list
2330 * @vendor_weight_list: PCL weights
2331 *
2332 * Return: Success(0) or reason code for failure
2333 */
2334static int32_t
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302335hdd_cfg80211_update_pcl(struct hdd_context *hdd_ctx,
2336 struct sk_buff *skb,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302337 uint8_t ch_list_count, int idx,
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302338 uint32_t *vendor_pcl_list, uint8_t *vendor_weight_list)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302339{
2340 struct nlattr *nla_attr, *channel;
2341 int i;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302342 uint8_t chan;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302343
2344 nla_attr = nla_nest_start(skb, idx);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302345 if (!nla_attr)
2346 goto fail;
2347
2348 for (i = 0; i < ch_list_count; i++) {
2349 channel = nla_nest_start(skb, i);
2350 if (!channel)
2351 goto fail;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302352
2353 chan = (uint8_t)wlan_reg_freq_to_chan(hdd_ctx->pdev,
2354 vendor_pcl_list[i]);
2355
2356 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL, chan) ||
2357 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_PCL_FREQ,
2358 vendor_pcl_list[i]) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302359 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302360 vendor_weight_list[i])) {
2361 hdd_err("put fail");
2362 goto fail;
2363 }
2364 nla_nest_end(skb, channel);
2365 }
2366 nla_nest_end(skb, nla_attr);
2367
2368 return 0;
2369fail:
2370 hdd_err("updating pcl list failed");
2371 return -EINVAL;
2372}
2373
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002374static void hdd_get_scan_band(struct hdd_context *hdd_ctx,
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002375 struct sap_config *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002376 enum band_info *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302377{
2378 /* Get scan band */
Kapil Guptac1224bf2017-06-22 21:22:40 +05302379 if ((sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211B) ||
2380 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211G)) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002381 *band = BAND_2G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302382 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002383 *band = BAND_5G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302384 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002385 *band = BAND_ALL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302386 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302387}
2388
Qiwei Caie689a262018-07-26 15:50:22 +08002389/**
2390 * wlan_hdd_sap_get_valid_channellist() - Get SAPs valid channel list
2391 * @ap_adapter: adapter
2392 * @channel_count: valid channel count
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302393 * @freq_list: valid channel frequency (MHz) list
Qiwei Caie689a262018-07-26 15:50:22 +08002394 * @band: frequency band
2395 *
2396 * This API returns valid channel list for SAP after removing nol and
2397 * channel which lies outside of configuration.
2398 *
2399 * Return: Zero on success, non-zero on failure
2400 */
2401static int wlan_hdd_sap_get_valid_channellist(struct hdd_adapter *adapter,
2402 uint32_t *channel_count,
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302403 uint32_t *freq_list,
Qiwei Caie689a262018-07-26 15:50:22 +08002404 enum band_info band)
2405{
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002406 struct sap_config *sap_config;
Qiwei Caie689a262018-07-26 15:50:22 +08002407 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Qun Zhang3a5bd1a2020-03-20 12:05:25 +08002408 uint32_t pcl_freqs[NUM_CHANNELS] = {0};
Qiwei Caie689a262018-07-26 15:50:22 +08002409 uint32_t chan_count;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302410 uint32_t i;
Qiwei Caie689a262018-07-26 15:50:22 +08002411 QDF_STATUS status;
Dustin Brown07901ec2018-09-07 11:02:41 -07002412 struct wlan_objmgr_pdev *pdev = hdd_ctx->pdev;
Qiwei Caie689a262018-07-26 15:50:22 +08002413
2414 sap_config = &adapter->session.ap.sap_config;
2415
Manikandan Mohan19f36092019-08-15 15:54:02 -07002416 status = policy_mgr_get_valid_chans(hdd_ctx->psoc,
2417 pcl_freqs,
2418 &chan_count);
Qiwei Caie689a262018-07-26 15:50:22 +08002419 if (QDF_IS_STATUS_ERROR(status)) {
2420 hdd_err("Failed to get channel list");
2421 return -EINVAL;
2422 }
2423
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302424 *channel_count = 0;
Qiwei Caie689a262018-07-26 15:50:22 +08002425 for (i = 0; i < chan_count; i++) {
Qun Zhang3a5bd1a2020-03-20 12:05:25 +08002426 if (*channel_count >= NUM_CHANNELS)
Qiwei Caie689a262018-07-26 15:50:22 +08002427 break;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302428
2429 if (band == BAND_2G &&
2430 WLAN_REG_IS_24GHZ_CH_FREQ(pcl_freqs[i]) &&
2431 !wlan_reg_is_disable_for_freq(pdev, pcl_freqs[i])) {
2432 freq_list[*channel_count] = pcl_freqs[i];
2433 *channel_count += 1;
2434 } else if (band == BAND_5G &&
2435 (WLAN_REG_IS_5GHZ_CH_FREQ(pcl_freqs[i]) ||
2436 WLAN_REG_IS_6GHZ_CHAN_FREQ(pcl_freqs[i])) &&
2437 !wlan_reg_is_disable_for_freq(pdev, pcl_freqs[i])) {
2438 freq_list[*channel_count] = pcl_freqs[i];
2439 *channel_count += 1;
Qiwei Caie689a262018-07-26 15:50:22 +08002440 }
2441 }
2442
2443 if (*channel_count == 0) {
2444 hdd_err("no valid channel found");
2445 return -EINVAL;
2446 }
2447
2448 return 0;
2449}
2450
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302451/**
2452 * hdd_get_external_acs_event_len() - Get event buffer length for external ACS
2453 * @channel_count: number of channels for ACS operation
2454 *
2455 * Return: External ACS event (SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG) buffer length.
2456 */
2457static int hdd_get_external_acs_event_len(uint32_t channel_count)
2458{
2459 uint32_t len = NLMSG_HDRLEN;
2460 uint32_t i;
2461
2462 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON */
2463 len += nla_total_size(sizeof(u8));
2464
2465 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED */
2466 len += nla_total_size(sizeof(u32));
2467
2468 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT */
2469 len += nla_total_size(sizeof(u32));
2470
2471 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH */
2472 len += nla_total_size(sizeof(u8));
2473
2474 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND */
2475 len += nla_total_size(sizeof(u8));
2476
2477 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE */
2478 len += nla_total_size(sizeof(u32));
2479
2480 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST */
2481 len += nla_total_size(channel_count * sizeof(u32));
2482
2483 for (i = 0; i < channel_count; i++) {
2484 /* QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL */
2485 len += nla_total_size(sizeof(u8));
2486
2487 /* QCA_WLAN_VENDOR_ATTR_PCL_FREQ */
2488 len += nla_total_size(sizeof(u32));
2489
2490 /* QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT */
2491 len += nla_total_size(sizeof(u8));
2492 }
2493
2494 for (i = 0; i < channel_count; i++) {
2495 /* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ */
2496 len += nla_total_size(sizeof(u16));
2497
2498 /* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS */
2499 len += nla_total_size(sizeof(u32));
2500
2501 /* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT */
2502 len += nla_total_size(sizeof(u32));
2503
2504 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER */
2505 len += nla_total_size(sizeof(u8));
2506
2507 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER */
2508 len += nla_total_size(sizeof(u8));
2509
2510 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER */
2511 len += nla_total_size(sizeof(u8));
2512
2513 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID */
2514 len += nla_total_size(sizeof(u8));
2515
2516 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN */
2517 len += nla_total_size(sizeof(u8));
2518
2519 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0 */
2520 len += nla_total_size(sizeof(u8));
2521
2522 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1 */
2523 len += nla_total_size(sizeof(u8));
2524
2525 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 */
2526 len += nla_total_size(sizeof(u32));
2527
2528 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 */
2529 len += nla_total_size(sizeof(u32));
2530 }
2531
2532 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY */
2533 len += nla_total_size(sizeof(u32));
2534
2535 return len;
2536}
2537
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302538int hdd_cfg80211_update_acs_config(struct hdd_adapter *adapter,
2539 uint8_t reason)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302540{
Qun Zhang63db9552020-03-27 11:57:53 +08002541 struct sk_buff *skb = NULL;
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002542 struct sap_config *sap_config;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302543 uint32_t channel_count = 0, status = -EINVAL;
Qun Zhang63db9552020-03-27 11:57:53 +08002544 uint32_t *freq_list;
Qun Zhang3a5bd1a2020-03-20 12:05:25 +08002545 uint32_t vendor_pcl_list[NUM_CHANNELS] = {0};
2546 uint8_t vendor_weight_list[NUM_CHANNELS] = {0};
Kapil Gupta8878ad92017-02-13 11:56:04 +05302547 struct hdd_vendor_acs_chan_params acs_chan_params;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002548 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002549 enum band_info band = BAND_2G;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302550 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302551 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302552 uint32_t i, id;
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002553 QDF_STATUS qdf_status;
2554 bool is_external_acs_policy = cfg_default(CFG_EXTERNAL_ACS_POLICY);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302555 uint32_t len;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302556
Kapil Gupta8878ad92017-02-13 11:56:04 +05302557 if (!hdd_ctx) {
2558 hdd_err("HDD context is NULL");
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302559 return -EINVAL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302560 }
2561
Dustin Brown491d54b2018-03-14 12:39:11 -07002562 hdd_enter();
Jeff Johnsonb9424862017-10-30 08:49:35 -07002563 sap_config = &adapter->session.ap.sap_config;
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302564 /* When first 2 connections are on the same frequency band,
2565 * then PCL would include only channels from the other
2566 * frequency band on which no connections are active
2567 */
Dustin Brown76cd2932018-09-11 16:03:05 -07002568 if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302569 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
2570 struct policy_mgr_conc_connection_info *conc_connection_info;
2571
2572 conc_connection_info = policy_mgr_get_conn_info(&i);
2573 if (conc_connection_info[0].mac ==
2574 conc_connection_info[1].mac) {
2575
wadesong88378bd2020-03-24 13:25:21 +08002576 if (!WLAN_REG_IS_24GHZ_CH_FREQ(
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302577 sap_config->acs_cfg.pcl_chan_freq[0])) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302578 sap_config->acs_cfg.band =
2579 QCA_ACS_MODE_IEEE80211A;
2580 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002581 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302582 } else {
2583 sap_config->acs_cfg.band =
2584 QCA_ACS_MODE_IEEE80211G;
2585 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002586 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302587 }
2588 }
2589 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302590
Jeff Johnsonb9424862017-10-30 08:49:35 -07002591 hdd_get_scan_band(hdd_ctx, &adapter->session.ap.sap_config, &band);
Nachiket Kukade3208c162017-08-29 17:40:59 +05302592
Qun Zhang63db9552020-03-27 11:57:53 +08002593 freq_list = qdf_mem_malloc(sizeof(uint32_t) * NUM_CHANNELS);
2594 if (!freq_list)
2595 return -ENOMEM;
2596
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302597 if (sap_config->acs_cfg.freq_list) {
Nachiket Kukade3208c162017-08-29 17:40:59 +05302598 /* Copy INI or hostapd provided ACS channel range*/
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302599 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302600 freq_list[i] = sap_config->acs_cfg.freq_list[i];
Nachiket Kukade3208c162017-08-29 17:40:59 +05302601 channel_count = sap_config->acs_cfg.ch_list_count;
2602 } else {
2603 /* No channel list provided, copy all valid channels */
2604 wlan_hdd_sap_get_valid_channellist(adapter,
2605 &channel_count,
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302606 freq_list,
Nachiket Kukade3208c162017-08-29 17:40:59 +05302607 band);
2608 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302609
Lin Baifac77972018-07-05 19:51:49 +08002610 sap_config->channel_info = qdf_mem_malloc(
2611 sizeof(struct hdd_channel_info) *
2612 channel_count);
Qun Zhang63db9552020-03-27 11:57:53 +08002613 if (!sap_config->channel_info) {
2614 status = -ENOMEM;
2615 goto fail;
2616 }
Lin Baifac77972018-07-05 19:51:49 +08002617
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302618 hdd_update_reg_chan_info(adapter, channel_count, freq_list);
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302619
Kapil Gupta8878ad92017-02-13 11:56:04 +05302620 /* Get phymode */
Jeff Johnsonb9424862017-10-30 08:49:35 -07002621 phy_mode = adapter->session.ap.sap_config.acs_cfg.hw_mode;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302622
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302623 len = hdd_get_external_acs_event_len(channel_count);
2624 id = QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG;
2625 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, &adapter->wdev,
2626 len, id, GFP_KERNEL);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302627 if (!skb) {
2628 hdd_err("cfg80211_vendor_event_alloc failed");
Qun Zhang63db9552020-03-27 11:57:53 +08002629 status = -ENOMEM;
2630 goto fail;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302631 }
2632 /*
2633 * Application expects pcl to be a subset of channel list
2634 * Remove all channels which are not in channel list from pcl
2635 * and add weight as zero
2636 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05302637 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
2638 acs_chan_params.vendor_weight_list = vendor_weight_list;
2639
2640 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
2641 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302642
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302643 if (acs_chan_params.pcl_count) {
2644 hdd_debug("ACS PCL list: len: %d",
2645 acs_chan_params.pcl_count);
2646 for (i = 0; i < acs_chan_params.pcl_count; i++)
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302647 hdd_debug("channel_frequency: %u, weight: %u",
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302648 acs_chan_params.
2649 vendor_pcl_list[i],
2650 acs_chan_params.
2651 vendor_weight_list[i]);
2652 }
2653
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002654 qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
2655 &is_external_acs_policy);
2656 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2657 hdd_err("get_external_acs_policy failed, set default");
2658
2659 if (is_external_acs_policy) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302660 acs_policy =
2661 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
2662 } else {
2663 acs_policy =
2664 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
2665 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302666 /* Update values in NL buffer */
2667 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
2668 reason) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302669 nla_put_flag(skb,
2670 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED) ||
2671 nla_put_flag(skb,
2672 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT)
2673 ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302674 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
2675 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302676 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
2677 band) ||
2678 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
2679 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05302680 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta63e75282017-05-18 20:55:10 +05302681 channel_count * sizeof(uint32_t), freq_list)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302682 hdd_err("nla put fail");
2683 goto fail;
2684 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302685 status =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302686 hdd_cfg80211_update_pcl(hdd_ctx, skb,
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302687 acs_chan_params.pcl_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302688 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
2689 vendor_pcl_list,
2690 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302691
2692 if (status != 0)
2693 goto fail;
2694
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302695 id = QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302696
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302697 status = hdd_cfg80211_update_channel_info(hdd_ctx, skb, sap_config, id);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302698 if (status != 0)
2699 goto fail;
2700
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302701 status = nla_put_u32(skb,
2702 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
2703 acs_policy);
2704
2705 if (status != 0)
2706 goto fail;
2707
Kapil Gupta8878ad92017-02-13 11:56:04 +05302708 cfg80211_vendor_event(skb, GFP_KERNEL);
Qun Zhang63db9552020-03-27 11:57:53 +08002709 qdf_mem_free(freq_list);
Lin Baifac77972018-07-05 19:51:49 +08002710 qdf_mem_free(sap_config->channel_info);
2711
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302712 return 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302713fail:
Qun Zhang63db9552020-03-27 11:57:53 +08002714 qdf_mem_free(freq_list);
2715 if (sap_config->channel_info)
2716 qdf_mem_free(sap_config->channel_info);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302717 if (skb)
2718 kfree_skb(skb);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302719 return status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302720}
2721
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302722/**
2723 * hdd_create_acs_timer(): Initialize vendor ACS timer
2724 * @adapter: pointer to SAP adapter struct
2725 *
2726 * This function initializes the vendor ACS timer.
2727 *
2728 * Return: Status of create vendor ACS timer
2729 */
Jeff Johnsone5006672017-08-29 14:39:02 -07002730static int hdd_create_acs_timer(struct hdd_adapter *adapter)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302731{
2732 struct hdd_external_acs_timer_context *timer_context;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302733 QDF_STATUS status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302734
Jeff Johnsonb9424862017-10-30 08:49:35 -07002735 if (adapter->session.ap.vendor_acs_timer_initialized)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302736 return 0;
2737
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302738 hdd_debug("Starting vendor app based ACS");
Kapil Gupta8878ad92017-02-13 11:56:04 +05302739 timer_context = qdf_mem_malloc(sizeof(*timer_context));
Min Liu74a1a502018-10-10 19:59:07 +08002740 if (!timer_context)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302741 return -ENOMEM;
Min Liu74a1a502018-10-10 19:59:07 +08002742
Kapil Gupta8878ad92017-02-13 11:56:04 +05302743 timer_context->adapter = adapter;
2744
2745 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
Jeff Johnsonb9424862017-10-30 08:49:35 -07002746 status = qdf_mc_timer_init(&adapter->session.ap.vendor_acs_timer,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302747 QDF_TIMER_TYPE_SW,
2748 hdd_acs_response_timeout_handler, timer_context);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302749 if (status != QDF_STATUS_SUCCESS) {
2750 hdd_err("Failed to initialize acs response timeout timer");
2751 return -EFAULT;
2752 }
Jeff Johnsonb9424862017-10-30 08:49:35 -07002753 adapter->session.ap.vendor_acs_timer_initialized = true;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302754 return 0;
2755}
2756
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302757static const struct nla_policy
2758wlan_hdd_cfg80211_do_acs_policy[QCA_WLAN_VENDOR_ATTR_ACS_MAX+1] = {
2759 [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
2760 [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
2761 [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
2762 [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
2763 [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
2764 [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_UNSPEC },
2765 [QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_UNSPEC },
2766};
2767
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302768int hdd_start_vendor_acs(struct hdd_adapter *adapter)
2769{
2770 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2771 int status;
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002772 QDF_STATUS qdf_status;
2773 bool is_acs_support_for_dfs_ltecoex = cfg_default(CFG_USER_ACS_DFS_LTE);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302774
2775 status = hdd_create_acs_timer(adapter);
2776 if (status != 0) {
2777 hdd_err("failed to create acs timer");
2778 return status;
2779 }
2780 status = hdd_update_acs_timer_reason(adapter,
2781 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2782 if (status != 0) {
2783 hdd_err("failed to update acs timer reason");
2784 return status;
2785 }
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002786 qdf_status = ucfg_mlme_get_acs_support_for_dfs_ltecoex(
2787 hdd_ctx->psoc,
2788 &is_acs_support_for_dfs_ltecoex);
2789 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2790 hdd_err("get_acs_support_for_dfs_ltecoex failed, set def");
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302791
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002792 if (is_acs_support_for_dfs_ltecoex)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302793 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2794 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2795 true));
2796 else
2797 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2798 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2799 false));
2800
2801 return status;
2802}
2803
Kapil Gupta8878ad92017-02-13 11:56:04 +05302804/**
Ashish Kumar Dhanotiya2168aad2019-06-12 20:51:36 +05302805 * hdd_avoid_acs_channels() - Avoid acs channels
2806 * @hdd_ctx: Pointer to the hdd context
2807 * @sap_config: Sap config structure pointer
2808 *
2809 * This function avoids channels from the acs corresponding to
2810 * the frequencies configured in the ini sap_avoid_acs_freq_list
2811 *
2812 * Return: None
2813 */
2814
2815#ifdef SAP_AVOID_ACS_FREQ_LIST
2816static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
2817 struct sap_config *sap_config)
2818{
2819 int i, j, ch_cnt = 0;
2820 uint16_t avoid_acs_freq_list[CFG_VALID_CHANNEL_LIST_LEN];
2821 uint8_t avoid_acs_freq_list_num;
2822
Ashish Kumar Dhanotiya2168aad2019-06-12 20:51:36 +05302823 ucfg_mlme_get_acs_avoid_freq_list(hdd_ctx->psoc,
2824 avoid_acs_freq_list,
2825 &avoid_acs_freq_list_num);
2826
2827 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
2828 for (j = 0; j < avoid_acs_freq_list_num; j++) {
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302829 if (sap_config->acs_cfg.freq_list[i] ==
2830 avoid_acs_freq_list[j]) {
2831 hdd_debug("skip freq %d",
2832 sap_config->acs_cfg.freq_list[i]);
Ashish Kumar Dhanotiya2168aad2019-06-12 20:51:36 +05302833 break;
2834 }
2835 }
2836 if (j == avoid_acs_freq_list_num)
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302837 sap_config->acs_cfg.freq_list[ch_cnt++] =
2838 sap_config->acs_cfg.freq_list[i];
Ashish Kumar Dhanotiya2168aad2019-06-12 20:51:36 +05302839 }
2840 sap_config->acs_cfg.ch_list_count = ch_cnt;
2841}
2842#else
2843static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
2844 struct sap_config *sap_config)
2845{
2846}
2847#endif
2848
2849/**
Manikandan Mohan932c11e2019-08-14 14:09:08 -07002850 * wlan_hdd_trim_acs_channel_list() - Trims ACS channel list with
2851 * intersection of PCL
2852 * @pcl: preferred channel list
2853 * @pcl_count: Preferred channel list count
2854 * @org_ch_list: ACS channel list from user space
2855 * @org_ch_list_count: ACS channel count from user space
2856 *
2857 * Return: None
2858 */
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302859static void wlan_hdd_trim_acs_channel_list(uint32_t *pcl, uint8_t pcl_count,
2860 uint32_t *org_freq_list,
Manikandan Mohan932c11e2019-08-14 14:09:08 -07002861 uint8_t *org_ch_list_count)
2862{
2863 uint16_t i, j, ch_list_count = 0;
2864
Qun Zhang3a5bd1a2020-03-20 12:05:25 +08002865 if (*org_ch_list_count >= NUM_CHANNELS) {
Manikandan Mohan932c11e2019-08-14 14:09:08 -07002866 hdd_err("org_ch_list_count too big %d",
2867 *org_ch_list_count);
2868 return;
2869 }
2870
Qun Zhang3a5bd1a2020-03-20 12:05:25 +08002871 if (pcl_count >= NUM_CHANNELS) {
Manikandan Mohan932c11e2019-08-14 14:09:08 -07002872 hdd_err("pcl_count is too big %d", pcl_count);
2873 return;
2874 }
2875
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302876 hdd_debug("Update ACS chan freq with PCL");
Manikandan Mohan932c11e2019-08-14 14:09:08 -07002877 for (j = 0; j < *org_ch_list_count; j++)
2878 for (i = 0; i < pcl_count; i++)
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302879 if (pcl[i] == org_freq_list[j]) {
2880 org_freq_list[ch_list_count++] = pcl[i];
Manikandan Mohan932c11e2019-08-14 14:09:08 -07002881 break;
2882 }
2883
2884 *org_ch_list_count = ch_list_count;
2885}
2886
2887/**
Liangwei Donge0279e32020-01-15 16:05:32 +08002888 * wlan_hdd_handle_zero_acs_list() - Handle worst case of acs channel
2889 * trimmed to zero
2890 * @hdd_ctx: struct hdd_context
2891 * @org_ch_list: ACS channel list from user space
2892 * @org_ch_list_count: ACS channel count from user space
2893 *
2894 * When all chan in ACS freq list is filtered out
2895 * by wlan_hdd_trim_acs_channel_list, the hostapd start will fail.
2896 * This happens when PCL is PM_24G_SCC_CH_SBS_CH, and SAP acs range includes
2897 * 5G channel list. One example is STA active on 6Ghz chan. Hostapd
2898 * start SAP on 5G ACS range. The intersection of PCL and ACS range is zero.
2899 * Instead of ACS failure, this API selects one channel from ACS range
2900 * and report to Hostapd. When hostapd do start_ap, the driver will
2901 * force SCC to 6G or move SAP to 2G based on SAP's configuration.
2902 *
2903 * Return: None
2904 */
2905static void wlan_hdd_handle_zero_acs_list(struct hdd_context *hdd_ctx,
2906 uint32_t *acs_freq_list,
2907 uint8_t *acs_ch_list_count,
2908 uint32_t *org_freq_list,
2909 uint8_t org_ch_list_count)
2910{
2911 uint16_t i, sta_count;
2912 uint32_t acs_chan_default = 0;
2913
2914 if (!acs_ch_list_count || *acs_ch_list_count > 0 ||
2915 !acs_freq_list) {
2916 return;
2917 }
2918 if (!org_ch_list_count || !org_freq_list)
2919 return;
2920
2921 if (!policy_mgr_is_force_scc(hdd_ctx->psoc))
2922 return;
2923 sta_count = policy_mgr_mode_specific_connection_count
2924 (hdd_ctx->psoc, PM_STA_MODE, NULL);
2925 sta_count += policy_mgr_mode_specific_connection_count
2926 (hdd_ctx->psoc, PM_P2P_CLIENT_MODE, NULL);
2927 if (!sta_count)
2928 return;
2929
2930 for (i = 0; i < org_ch_list_count; i++) {
2931 if (!wlan_reg_is_dfs_for_freq(hdd_ctx->pdev,
2932 org_freq_list[i])) {
2933 acs_chan_default = org_freq_list[i];
2934 break;
2935 }
2936 }
2937 if (!acs_chan_default)
2938 acs_chan_default = org_freq_list[0];
2939
2940 acs_freq_list[0] = acs_chan_default;
2941 *acs_ch_list_count = 1;
2942 hdd_debug("retore acs chan list to single freq %d", acs_chan_default);
2943}
2944
2945/**
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302946 * __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 * @wiphy: Linux wiphy struct pointer
2948 * @wdev: Linux wireless device struct pointer
2949 * @data: ACS information from hostapd
2950 * @data_len: ACS information length
2951 *
2952 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2953 * and starts ACS procedure.
2954 *
2955 * Return: ACS procedure start status
2956 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2958 struct wireless_dev *wdev,
2959 const void *data, int data_len)
2960{
2961 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07002962 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002963 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002964 struct sap_config *sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002965 struct sk_buff *temp_skbuff;
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302966 int ret, i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
2968 bool ht_enabled, ht40_enabled, vht_enabled;
wadesong1795e142018-01-05 11:13:07 +08002969 uint8_t ch_width;
2970 enum qca_wlan_vendor_acs_hw_mode hw_mode;
Rachit Kankanedef2b172019-03-07 11:34:44 +05302971 enum policy_mgr_con_mode pm_mode;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302972 QDF_STATUS qdf_status;
gaurank kathpaliafa8b2e12019-11-20 12:30:38 +05302973 bool is_vendor_acs_support = false;
2974 bool is_external_acs_policy = false;
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302975 bool sap_force_11n_for_11ac = 0;
2976 bool go_force_11n_for_11ac = 0;
Sandeep Puligilla34618782019-01-04 17:42:42 -08002977 bool go_11ac_override = 0;
2978 bool sap_11ac_override = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002979
2980 /* ***Note*** Donot set SME config related to ACS operation here because
2981 * ACS operation is not synchronouse and ACS for Second AP may come when
2982 * ACS operation for first AP is going on. So only do_acs is split to
Jeff Johnsonfa7d9602018-05-06 11:25:31 -07002983 * separate start_acs routine. Also SME-PMAC struct that is used to
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002984 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
2985 * config shall be set only from start_acs.
2986 */
2987
Anurag Chouhan6d760662016-02-20 16:05:43 +05302988 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002989 hdd_err("Command not allowed in FTM mode");
2990 return -EPERM;
2991 }
2992
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302993 ret = wlan_hdd_validate_context(hdd_ctx);
2994 if (ret)
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302995 return ret;
2996
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302997 ucfg_mlme_get_sap_force_11n_for_11ac(hdd_ctx->psoc,
2998 &sap_force_11n_for_11ac);
2999 ucfg_mlme_get_go_force_11n_for_11ac(hdd_ctx->psoc,
3000 &go_force_11n_for_11ac);
3001
Hanumanth Reddy Pothula89b0dce2018-05-18 12:49:43 +05303002 if (!((adapter->device_mode == QDF_SAP_MODE) ||
3003 (adapter->device_mode == QDF_P2P_GO_MODE))) {
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05303004 hdd_err("Invalid device mode %d", adapter->device_mode);
3005 return -EINVAL;
3006 }
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303007
Naveen Rawat64e477e2016-05-20 10:34:56 -07003008 if (cds_is_sub_20_mhz_enabled()) {
3009 hdd_err("ACS not supported in sub 20 MHz ch wd.");
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05303010 return -EINVAL;
Naveen Rawat64e477e2016-05-20 10:34:56 -07003011 }
3012
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05303013 if (qdf_atomic_read(&adapter->session.ap.acs_in_progress) > 0) {
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05303014 hdd_err("ACS rejected as previous req already in progress");
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05303015 return -EINVAL;
3016 } else {
3017 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 1);
gaurank kathpalia7aed85e2019-10-10 15:12:54 +05303018 qdf_event_reset(&adapter->acs_complete_event);
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05303019 }
3020
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303021 ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
Dustin Brown4ea21db2018-01-05 14:13:17 -08003022 data_len,
3023 wlan_hdd_cfg80211_do_acs_policy);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303024 if (ret) {
Jeff Johnson020db452016-06-29 14:37:26 -07003025 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003026 goto out;
3027 }
3028
3029 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003030 hdd_err("Attr hw_mode failed");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303031 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003032 goto out;
3033 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05303034 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003035
Arun Kumar Khandavalliafcb0552020-01-20 11:46:36 +05303036 hdd_nofl_info("ACS request vid %d hw mode %d", adapter->vdev_id,
3037 hw_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
3039 ht_enabled =
3040 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
3041 else
3042 ht_enabled = 0;
3043
3044 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
3045 ht40_enabled =
3046 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
3047 else
3048 ht40_enabled = 0;
3049
3050 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
3051 vht_enabled =
3052 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
3053 else
3054 vht_enabled = 0;
3055
Bala Venkateshb9cf3362017-11-09 15:48:46 +05303056 if (((adapter->device_mode == QDF_SAP_MODE) &&
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05303057 sap_force_11n_for_11ac) ||
3058 ((adapter->device_mode == QDF_P2P_GO_MODE) &&
3059 go_force_11n_for_11ac)) {
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05303060 vht_enabled = 0;
Dustin Brownbacc48f2018-03-14 14:48:44 -07003061 hdd_info("VHT is Disabled in ACS");
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05303062 }
3063
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003064 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
3065 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
3066 } else {
3067 if (ht_enabled && ht40_enabled)
3068 ch_width = 40;
3069 else
3070 ch_width = 20;
3071 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05303072
Bala Venkateshb9cf3362017-11-09 15:48:46 +05303073 /* this may be possible, when sap_force_11n_for_11ac or
3074 * go_force_11n_for_11ac is set
3075 */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05303076 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
3077 if (ht_enabled && ht40_enabled)
3078 ch_width = 40;
3079 else
3080 ch_width = 20;
3081 }
3082
Hanumanth Reddy Pothula560d5712018-03-15 18:11:27 +05303083 sap_config = &adapter->session.ap.sap_config;
3084
3085 /* Check and free if memory is already allocated for acs channel list */
3086 wlan_hdd_undo_acs(adapter);
3087
3088 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
3089
Himanshu Agarwal75e74412018-02-01 20:51:47 +05303090 if (ch_width == 160)
3091 sap_config->acs_cfg.ch_width = CH_WIDTH_160MHZ;
3092 else if (ch_width == 80)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003093 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
3094 else if (ch_width == 40)
3095 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
3096 else
3097 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
3098
Rajeev Kumar Sirasanagandlaa57c6702019-11-01 18:41:41 +05303099 /* Firstly try to get channel frequencies */
3100 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003101 uint32_t *freq =
3102 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
3103 sap_config->acs_cfg.ch_list_count = nla_len(
3104 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
3105 sizeof(uint32_t);
3106 if (sap_config->acs_cfg.ch_list_count) {
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303107 sap_config->acs_cfg.freq_list = qdf_mem_malloc(
3108 sap_config->acs_cfg.ch_list_count *
3109 sizeof(uint32_t));
gaurank kathpaliaaa252b52019-10-30 15:29:04 +05303110 sap_config->acs_cfg.master_freq_list = qdf_mem_malloc(
3111 sap_config->acs_cfg.ch_list_count *
3112 sizeof(uint32_t));
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303113 if (!sap_config->acs_cfg.freq_list ||
gaurank kathpaliaaa252b52019-10-30 15:29:04 +05303114 !sap_config->acs_cfg.master_freq_list) {
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303115 ret = -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003116 goto out;
3117 }
3118
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303119 for (i = 0; i < sap_config->acs_cfg.ch_list_count;
3120 i++) {
gaurank kathpaliaaa252b52019-10-30 15:29:04 +05303121 sap_config->acs_cfg.master_freq_list[i] =
3122 freq[i];
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303123 sap_config->acs_cfg.freq_list[i] = freq[i];
3124 }
gaurank kathpalia7ca94ae2019-08-14 11:33:52 +05303125 sap_config->acs_cfg.master_ch_list_count =
3126 sap_config->acs_cfg.ch_list_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003127 }
Rajeev Kumar Sirasanagandlaa57c6702019-11-01 18:41:41 +05303128 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
3129 uint8_t *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
3130
3131 sap_config->acs_cfg.ch_list_count = nla_len(
3132 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
3133 if (sap_config->acs_cfg.ch_list_count) {
3134 sap_config->acs_cfg.freq_list = qdf_mem_malloc(
3135 sap_config->acs_cfg.ch_list_count *
3136 sizeof(uint32_t));
3137 sap_config->acs_cfg.master_freq_list = qdf_mem_malloc(
3138 sap_config->acs_cfg.ch_list_count *
3139 sizeof(uint32_t));
3140 if (!sap_config->acs_cfg.freq_list ||
3141 !sap_config->acs_cfg.master_freq_list) {
3142 ret = -ENOMEM;
3143 goto out;
3144 }
3145
3146 /* convert channel to frequency */
3147 for (i = 0; i < sap_config->acs_cfg.ch_list_count;
3148 i++) {
3149 sap_config->acs_cfg.freq_list[i] =
3150 wlan_reg_legacy_chan_to_freq(
3151 hdd_ctx->pdev,
3152 tmp[i]);
3153 sap_config->acs_cfg.master_freq_list[i] =
3154 sap_config->acs_cfg.freq_list[i];
3155 }
3156 sap_config->acs_cfg.master_ch_list_count =
3157 sap_config->acs_cfg.ch_list_count;
3158 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003159 }
3160
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303161 if (!sap_config->acs_cfg.ch_list_count) {
Amar Singhal5f783132018-03-29 13:58:50 -07003162 hdd_err("acs config chan count 0");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303163 ret = -EINVAL;
3164 goto out;
3165 }
3166
Ashish Kumar Dhanotiya2168aad2019-06-12 20:51:36 +05303167 hdd_avoid_acs_channels(hdd_ctx, sap_config);
3168
Rachit Kankanedef2b172019-03-07 11:34:44 +05303169 pm_mode =
3170 policy_mgr_convert_device_mode_to_qdf_type(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003171 /* consult policy manager to get PCL */
Rachit Kankanedef2b172019-03-07 11:34:44 +05303172 qdf_status = policy_mgr_get_pcl(hdd_ctx->psoc, pm_mode,
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303173 sap_config->acs_cfg.pcl_chan_freq,
Rachit Kankanedef2b172019-03-07 11:34:44 +05303174 &sap_config->acs_cfg.pcl_ch_count,
3175 sap_config->acs_cfg.
3176 pcl_channels_weight_list,
Qun Zhang3a5bd1a2020-03-20 12:05:25 +08003177 NUM_CHANNELS);
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303178
Kapil Guptac1224bf2017-06-22 21:22:40 +05303179 sap_config->acs_cfg.band = hw_mode;
Rachit Kankanedef2b172019-03-07 11:34:44 +05303180
3181 qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
3182 &is_external_acs_policy);
3183 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
3184 hdd_err("get_external_acs_policy failed");
3185
gaurank kathpaliaaf483f52019-07-19 09:04:07 +05303186 sap_config->acs_cfg.acs_mode = true;
3187
Rachit Kankanedef2b172019-03-07 11:34:44 +05303188 if (is_external_acs_policy &&
3189 policy_mgr_is_force_scc(hdd_ctx->psoc) &&
3190 policy_mgr_get_connection_count(hdd_ctx->psoc)) {
Manikandan Mohan932c11e2019-08-14 14:09:08 -07003191 wlan_hdd_trim_acs_channel_list(
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303192 sap_config->acs_cfg.pcl_chan_freq,
Rachit Kankanedef2b172019-03-07 11:34:44 +05303193 sap_config->acs_cfg.pcl_ch_count,
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303194 sap_config->acs_cfg.freq_list,
Rachit Kankanedef2b172019-03-07 11:34:44 +05303195 &sap_config->acs_cfg.ch_list_count);
Liangwei Donge0279e32020-01-15 16:05:32 +08003196 if (!sap_config->acs_cfg.ch_list_count &&
3197 sap_config->acs_cfg.master_ch_list_count)
3198 wlan_hdd_handle_zero_acs_list(
3199 hdd_ctx,
3200 sap_config->acs_cfg.freq_list,
3201 &sap_config->acs_cfg.ch_list_count,
3202 sap_config->acs_cfg.master_freq_list,
3203 sap_config->acs_cfg.master_ch_list_count);
Rachit Kankanedef2b172019-03-07 11:34:44 +05303204 /* if it is only one channel, send ACS event to upper layer */
3205 if (sap_config->acs_cfg.ch_list_count == 1) {
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303206 sap_config->acs_cfg.pri_ch_freq =
3207 sap_config->acs_cfg.freq_list[0];
Rachit Kankanedef2b172019-03-07 11:34:44 +05303208 wlan_sap_set_sap_ctx_acs_cfg(
3209 WLAN_HDD_GET_SAP_CTX_PTR(adapter), sap_config);
3210 sap_config_acs_result(hdd_ctx->mac_handle,
3211 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303212 sap_config->acs_cfg.ht_sec_ch_freq);
Rachit Kankanedef2b172019-03-07 11:34:44 +05303213 sap_config->ch_params.ch_width =
3214 sap_config->acs_cfg.ch_width;
3215 sap_config->ch_params.sec_ch_offset =
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303216 wlan_reg_freq_to_chan(hdd_ctx->pdev,
3217 sap_config->acs_cfg.ht_sec_ch_freq);
Rachit Kankanedef2b172019-03-07 11:34:44 +05303218 sap_config->ch_params.center_freq_seg0 =
Liangwei Dong0e18c472019-11-08 17:59:09 +08003219 wlan_reg_freq_to_chan(
3220 hdd_ctx->pdev,
3221 sap_config->acs_cfg.vht_seg0_center_ch_freq);
Rachit Kankanedef2b172019-03-07 11:34:44 +05303222 sap_config->ch_params.center_freq_seg1 =
Liangwei Dong0e18c472019-11-08 17:59:09 +08003223 wlan_reg_freq_to_chan(
3224 hdd_ctx->pdev,
3225 sap_config->acs_cfg.vht_seg1_center_ch_freq);
3226 sap_config->ch_params.mhz_freq_seg0 =
3227 sap_config->acs_cfg.vht_seg0_center_ch_freq;
3228 sap_config->ch_params.mhz_freq_seg1 =
3229 sap_config->acs_cfg.vht_seg1_center_ch_freq;
Rachit Kankanedef2b172019-03-07 11:34:44 +05303230 /*notify hostapd about channel override */
3231 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
3232 ret = 0;
3233 goto out;
3234 }
3235 }
3236
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303237 ret = wlan_hdd_set_acs_ch_range(sap_config, hw_mode,
gaurank kathpaliaaa252b52019-10-30 15:29:04 +05303238 ht_enabled, vht_enabled);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303239 if (ret) {
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05303240 hdd_err("set acs channel range failed");
3241 goto out;
3242 }
3243
Sandeep Puligilla34618782019-01-04 17:42:42 -08003244 ucfg_mlme_is_go_11ac_override(hdd_ctx->psoc, &go_11ac_override);
3245 ucfg_mlme_is_sap_11ac_override(hdd_ctx->psoc, &sap_11ac_override);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05303246 /* ACS override for android */
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05303247 if (ht_enabled &&
Liangwei Dong50d12dc2019-11-06 14:19:46 +08003248 sap_config->acs_cfg.end_ch_freq >=
3249 WLAN_REG_CH_TO_FREQ(CHAN_ENUM_5180) &&
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05303250 ((adapter->device_mode == QDF_SAP_MODE &&
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05303251 !sap_force_11n_for_11ac &&
Sandeep Puligilla34618782019-01-04 17:42:42 -08003252 sap_11ac_override) ||
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05303253 (adapter->device_mode == QDF_P2P_GO_MODE &&
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05303254 !go_force_11n_for_11ac &&
Sandeep Puligilla34618782019-01-04 17:42:42 -08003255 go_11ac_override))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003256 vht_enabled = 1;
3257 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05303258 qdf_status =
3259 ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
3260 &ch_width);
3261 sap_config->acs_cfg.ch_width = ch_width;
Himanshu Agarwal29a9a3e2018-02-21 17:44:37 +05303262 }
3263
3264 /* No VHT80 in 2.4G so perform ACS accordingly */
Liangwei Dong50d12dc2019-11-06 14:19:46 +08003265 if (sap_config->acs_cfg.end_ch_freq <=
3266 WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484) &&
Himanshu Agarwal29a9a3e2018-02-21 17:44:37 +05303267 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
3268 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
3269 hdd_debug("resetting to 40Mhz in 2.4Ghz");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003270 }
3271
gaurank kathpaliaac1feea2020-02-03 16:37:23 +05303272 hdd_nofl_debug("ACS Config country %s ch_width %d hw_mode %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d band %d",
3273 hdd_ctx->reg.alpha2, ch_width,
3274 sap_config->acs_cfg.hw_mode, sap_config->acs_cfg.ch_width,
3275 ht_enabled, vht_enabled, sap_config->acs_cfg.start_ch_freq,
3276 sap_config->acs_cfg.end_ch_freq,
3277 sap_config->acs_cfg.band);
wadesongcb0ded22018-02-02 17:57:20 +08003278 host_log_acs_req_event(adapter->dev->name,
3279 csr_phy_mode_str(sap_config->acs_cfg.hw_mode),
3280 ch_width, ht_enabled, vht_enabled,
Liangwei Dong50d12dc2019-11-06 14:19:46 +08003281 sap_config->acs_cfg.start_ch_freq,
3282 sap_config->acs_cfg.end_ch_freq);
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07003283
Kapil Gupta8878ad92017-02-13 11:56:04 +05303284 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
3285 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
3286
gaurank kathpalia00d7c342020-02-18 11:40:51 +05303287 sap_dump_acs_channel(&sap_config->acs_cfg);
Himanshu Agarwal33163982018-05-17 18:11:10 +05303288
gaurank kathpaliafa8b2e12019-11-20 12:30:38 +05303289 qdf_status = ucfg_mlme_get_vendor_acs_support(hdd_ctx->psoc,
3290 &is_vendor_acs_support);
3291 if (QDF_IS_STATUS_ERROR(qdf_status))
3292 hdd_err("get_vendor_acs_support failed, set default");
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07003293
gaurank kathpaliafa8b2e12019-11-20 12:30:38 +05303294 /* Check if vendor specific acs is enabled */
3295 if (is_vendor_acs_support)
3296 ret = hdd_start_vendor_acs(adapter);
3297 else
3298 ret = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299
3300out:
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303301 if (ret == 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003302 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3303 NLMSG_HDRLEN);
Jeff Johnsond36fa332019-03-18 13:42:25 -07003304 if (temp_skbuff)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003305 return cfg80211_vendor_cmd_reply(temp_skbuff);
3306 }
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05303307 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003308
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303309 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003310}
3311
Jeff Johnsonf3826e12017-01-12 09:49:40 -08003312/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003313 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
3314 * @wiphy: Linux wiphy struct pointer
3315 * @wdev: Linux wireless device struct pointer
3316 * @data: ACS information from hostapd
3317 * @data_len: ACS information len
3318 *
3319 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
3320 * and starts ACS procedure.
3321 *
3322 * Return: ACS procedure start status
3323 */
3324
3325static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
3326 struct wireless_dev *wdev,
3327 const void *data, int data_len)
3328{
Dustin Browna09acf42018-11-08 12:32:26 +05303329 int errno;
3330 struct osif_vdev_sync *vdev_sync;
3331
3332 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
3333 if (errno)
3334 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003335
Dustin Browna09acf42018-11-08 12:32:26 +05303336 errno = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003337
Dustin Browna09acf42018-11-08 12:32:26 +05303338 osif_vdev_sync_op_stop(vdev_sync);
3339
3340 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003341}
3342
3343/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003344 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
3345 * @adapter: Pointer to adapter struct
3346 *
3347 * This function handle cleanup of what was done in DO_ACS, including free
3348 * memory.
3349 *
3350 * Return: void
3351 */
Jeff Johnsone5006672017-08-29 14:39:02 -07003352void wlan_hdd_undo_acs(struct hdd_adapter *adapter)
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003353{
gaurank kathpalia081c66c2019-09-19 14:44:35 +05303354 sap_undo_acs(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
3355 &adapter->session.ap.sap_config);
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003356}
3357
3358/**
Rajeev Kumar Sirasanagandlaa57c6702019-11-01 18:41:41 +05303359 * hdd_fill_acs_chan_freq() - Populate channel frequencies (MHz) selected in ACS
3360 * @hdd_ctx: pointer to hdd context
3361 * @sap_cfg: sap acs configuration
3362 * @vendor_event: output pointer to populate channel frequencies (MHz)
3363 *
3364 * Return: If populated successfully return 0 else negative value.
3365 */
3366static int hdd_fill_acs_chan_freq(struct hdd_context *hdd_ctx,
3367 struct sap_config *sap_cfg,
3368 struct sk_buff *vendor_event)
3369{
3370 uint32_t id;
3371 int errno;
3372
3373 id = QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY;
3374 errno = nla_put_u32(vendor_event, id, sap_cfg->acs_cfg.pri_ch_freq);
3375 if (errno) {
3376 hdd_err("VENDOR_ATTR_ACS_PRIMARY_FREQUENCY put fail");
3377 return errno;
3378 }
3379
3380 id = QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY;
3381 errno = nla_put_u32(vendor_event, id, sap_cfg->acs_cfg.ht_sec_ch_freq);
3382 if (errno) {
3383 hdd_err("VENDOR_ATTR_ACS_SECONDARY_FREQUENCY put fail");
3384 return errno;
3385 }
3386
3387 id = QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY;
3388 errno = nla_put_u32(vendor_event, id,
3389 sap_cfg->acs_cfg.vht_seg0_center_ch_freq);
3390 if (errno) {
3391 hdd_err("VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY put fail");
3392 return errno;
3393 }
3394
3395 id = QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY;
3396 errno = nla_put_u32(vendor_event, id,
3397 sap_cfg->acs_cfg.vht_seg1_center_ch_freq);
3398 if (errno) {
3399 hdd_err("VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY put fail");
3400 return errno;
3401 }
3402
3403 return 0;
3404}
3405
3406static int hdd_get_acs_evt_data_len(void)
3407{
3408 uint32_t len = NLMSG_HDRLEN;
3409
3410 /* QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL */
3411 len += nla_total_size(sizeof(u8));
3412
3413 /* QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL */
3414 len += nla_total_size(sizeof(u8));
3415
3416 /* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL */
3417 len += nla_total_size(sizeof(u8));
3418
3419 /* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL */
3420 len += nla_total_size(sizeof(u8));
3421
3422 /* QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY */
3423 len += nla_total_size(sizeof(u32));
3424
3425 /* QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY */
3426 len += nla_total_size(sizeof(u32));
3427
3428 /* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY */
3429 len += nla_total_size(sizeof(u32));
3430
3431 /* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY */
3432 len += nla_total_size(sizeof(u32));
3433
3434 /* QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH */
3435 len += nla_total_size(sizeof(u16));
3436
3437 /* QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE */
3438 len += nla_total_size(sizeof(u8));
3439
3440 return len;
3441}
3442
3443/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003444 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
3445 * @adapter: Pointer to SAP adapter struct
3446 * @pri_channel: SAP ACS procedure selected Primary channel
3447 * @sec_channel: SAP ACS procedure selected secondary channel
3448 *
3449 * This is a callback function from SAP module on ACS procedure is completed.
3450 * This function send the ACS selected channel information to hostapd
3451 *
3452 * Return: None
3453 */
Jeff Johnsone5006672017-08-29 14:39:02 -07003454void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003455{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003456 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07003457 struct sap_config *sap_cfg =
3458 &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003459 struct sk_buff *vendor_event;
3460 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003461 uint16_t ch_width;
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303462 uint8_t pri_channel;
3463 uint8_t ht_sec_channel;
Liangwei Dong0e18c472019-11-08 17:59:09 +08003464 uint8_t vht_seg0_center_ch, vht_seg1_center_ch;
Rajeev Kumar Sirasanagandlaa57c6702019-11-01 18:41:41 +05303465 uint32_t id = QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX;
3466 uint32_t len = hdd_get_acs_evt_data_len();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003467
gaurank kathpalia11aa98c2019-12-09 17:56:08 +05303468 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 0);
3469 qdf_event_set(&adapter->acs_complete_event);
3470
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003471 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Rajeev Kumar Sirasanagandlaa57c6702019-11-01 18:41:41 +05303472 &adapter->wdev, len, id,
3473 GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003474
3475 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003476 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003477 return;
3478 }
3479
Rajeev Kumar Sirasanagandlaa57c6702019-11-01 18:41:41 +05303480 ret_val = hdd_fill_acs_chan_freq(hdd_ctx, sap_cfg, vendor_event);
3481 if (ret_val) {
3482 hdd_err("failed to put frequencies");
3483 kfree_skb(vendor_event);
3484 return;
3485 }
3486
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303487 pri_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev,
3488 sap_cfg->acs_cfg.pri_ch_freq);
3489
3490 ht_sec_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev,
3491 sap_cfg->acs_cfg.ht_sec_ch_freq);
3492
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003493 ret_val = nla_put_u8(vendor_event,
3494 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303495 pri_channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003496 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003497 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003498 kfree_skb(vendor_event);
3499 return;
3500 }
3501
3502 ret_val = nla_put_u8(vendor_event,
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303503 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
3504 ht_sec_channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003505 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003506 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003507 kfree_skb(vendor_event);
3508 return;
3509 }
Liangwei Dong0e18c472019-11-08 17:59:09 +08003510 vht_seg0_center_ch = wlan_reg_freq_to_chan(
3511 hdd_ctx->pdev,
3512 sap_cfg->acs_cfg.vht_seg0_center_ch_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003513 ret_val = nla_put_u8(vendor_event,
3514 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
Liangwei Dong0e18c472019-11-08 17:59:09 +08003515 vht_seg0_center_ch);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003516 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003517 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003518 kfree_skb(vendor_event);
3519 return;
3520 }
Liangwei Dong0e18c472019-11-08 17:59:09 +08003521 vht_seg1_center_ch = wlan_reg_freq_to_chan(
3522 hdd_ctx->pdev,
3523 sap_cfg->acs_cfg.vht_seg1_center_ch_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003524 ret_val = nla_put_u8(vendor_event,
3525 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
Liangwei Dong0e18c472019-11-08 17:59:09 +08003526 vht_seg1_center_ch);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003527 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003528 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003529 kfree_skb(vendor_event);
3530 return;
3531 }
3532
Himanshu Agarwal75e74412018-02-01 20:51:47 +05303533 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_160MHZ)
3534 ch_width = 160;
3535 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003536 ch_width = 80;
3537 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
3538 ch_width = 40;
3539 else
3540 ch_width = 20;
3541
3542 ret_val = nla_put_u16(vendor_event,
3543 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
3544 ch_width);
3545 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003546 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003547 kfree_skb(vendor_event);
3548 return;
3549 }
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303550 if (WLAN_REG_IS_24GHZ_CH_FREQ(sap_cfg->acs_cfg.pri_ch_freq))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551 ret_val = nla_put_u8(vendor_event,
3552 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
3553 QCA_ACS_MODE_IEEE80211G);
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303554 else
3555 ret_val = nla_put_u8(vendor_event,
3556 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
3557 QCA_ACS_MODE_IEEE80211A);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003558
3559 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003560 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561 kfree_skb(vendor_event);
3562 return;
3563 }
3564
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303565 hdd_debug("ACS result for %s: PRI_CH_FREQ: %d SEC_CH_FREQ: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
3566 adapter->dev->name, sap_cfg->acs_cfg.pri_ch_freq,
3567 sap_cfg->acs_cfg.ht_sec_ch_freq,
Liangwei Dong0e18c472019-11-08 17:59:09 +08003568 sap_cfg->acs_cfg.vht_seg0_center_ch_freq,
3569 sap_cfg->acs_cfg.vht_seg1_center_ch_freq, ch_width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003570
3571 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003572}
3573
Sourav Mohapatrac457ae62018-12-06 15:19:41 +05303574/**
3575 * hdd_is_wlm_latency_manager_supported - Checks if WLM Latency manager is
3576 * supported
3577 * @hdd_ctx: The HDD context
3578 *
3579 * Return: True if supported, false otherwise
3580 */
3581static inline
3582bool hdd_is_wlm_latency_manager_supported(struct hdd_context *hdd_ctx)
3583{
3584 bool latency_enable;
3585
3586 if (QDF_IS_STATUS_ERROR(ucfg_mlme_get_latency_enable
3587 (hdd_ctx->psoc, &latency_enable)))
3588 return false;
3589
3590 if (latency_enable &&
3591 sme_is_feature_supported_by_fw(VDEV_LATENCY_CONFIG))
3592 return true;
3593 else
3594 return false;
3595}
3596
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003597static int
3598__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
3599 struct wireless_dev *wdev,
3600 const void *data,
3601 int data_len)
3602{
Jeff Johnsonb8944722017-09-03 09:03:19 -07003603 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003604 struct sk_buff *skb = NULL;
3605 uint32_t fset = 0;
3606 int ret;
Wu Gaobdb7f272018-07-05 19:33:26 +08003607#ifdef FEATURE_WLAN_TDLS
3608 bool bvalue;
3609#endif
Sourav Mohapatrafab026a2019-11-20 14:22:28 +05303610 uint32_t fine_time_meas_cap;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003611
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07003612 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303613
Anurag Chouhan6d760662016-02-20 16:05:43 +05303614 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003615 hdd_err("Command not allowed in FTM mode");
3616 return -EPERM;
3617 }
3618
Jeff Johnsonb8944722017-09-03 09:03:19 -07003619 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303620 if (ret)
3621 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003622
3623 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003624 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003625 fset |= WIFI_FEATURE_INFRA;
3626 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07003627 if (true == hdd_is_5g_supported(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003628 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003629 fset |= WIFI_FEATURE_INFRA_5G;
3630 }
3631#ifdef WLAN_FEATURE_P2P
3632 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
3633 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003634 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003635 fset |= WIFI_FEATURE_P2P;
3636 }
3637#endif
3638 fset |= WIFI_FEATURE_SOFT_AP;
3639
3640 /* HOTSPOT is a supplicant feature, enable it by default */
3641 fset |= WIFI_FEATURE_HOTSPOT;
3642
Dustin Brown76cd2932018-09-11 16:03:05 -07003643 if (ucfg_extscan_get_enable(hdd_ctx->psoc) &&
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303644 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003645 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003646 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
3647 }
Nachiket Kukade989bb352018-07-31 18:01:17 +05303648 if (wlan_hdd_nan_is_supported(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003649 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003650 fset |= WIFI_FEATURE_NAN;
3651 }
Sourav Mohapatrafab026a2019-11-20 14:22:28 +05303652
3653 ucfg_mlme_get_fine_time_meas_cap(hdd_ctx->psoc, &fine_time_meas_cap);
3654
Sourav Mohapatra9e014cf2018-12-11 09:39:33 +05303655 if (sme_is_feature_supported_by_fw(RTT) &&
Sourav Mohapatrafab026a2019-11-20 14:22:28 +05303656 rtt_is_enabled(fine_time_meas_cap)) {
3657 hdd_debug("RTT is supported by firmware and driver: %x",
3658 fine_time_meas_cap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003659 fset |= WIFI_FEATURE_D2D_RTT;
3660 fset |= WIFI_FEATURE_D2AP_RTT;
3661 }
3662#ifdef FEATURE_WLAN_SCAN_PNO
Pragaspathi Thilagaraj24789d32018-12-10 22:28:03 +05303663 if (ucfg_scan_get_pno_scan_support(hdd_ctx->psoc) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003664 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003665 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003666 fset |= WIFI_FEATURE_PNO;
3667 }
3668#endif
3669 fset |= WIFI_FEATURE_ADDITIONAL_STA;
3670#ifdef FEATURE_WLAN_TDLS
Dustin Brown76cd2932018-09-11 16:03:05 -07003671 cfg_tdls_get_support_enable(hdd_ctx->psoc, &bvalue);
Wu Gaobdb7f272018-07-05 19:33:26 +08003672 if ((bvalue) && sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003673 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003674 fset |= WIFI_FEATURE_TDLS;
3675 }
Wu Gaobdb7f272018-07-05 19:33:26 +08003676
Dustin Brown76cd2932018-09-11 16:03:05 -07003677 cfg_tdls_get_off_channel_enable(hdd_ctx->psoc, &bvalue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003678 if (sme_is_feature_supported_by_fw(TDLS) &&
Wu Gaobdb7f272018-07-05 19:33:26 +08003679 bvalue && sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003680 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003681 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
3682 }
3683#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003684 fset |= WIFI_FEATURE_AP_STA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003685 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07003686 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Srinivas Girigowda5a1da622017-07-12 17:07:44 -07003687 fset |= WIFI_FEATURE_SET_TX_POWER_LIMIT;
Sourav Mohapatra804359e2017-12-07 13:52:05 +05303688 fset |= WIFI_FEATURE_CONFIG_NDO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003689
3690 if (hdd_link_layer_stats_supported())
3691 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
3692
Jeff Johnsonb8944722017-09-03 09:03:19 -07003693 if (hdd_roaming_supported(hdd_ctx))
Srinivas Girigowda8df27ea2017-01-06 12:42:16 -08003694 fset |= WIFI_FEATURE_CONTROL_ROAMING;
3695
3696 if (hdd_scan_random_mac_addr_supported())
3697 fset |= WIFI_FEATURE_SCAN_RAND;
3698
Sourav Mohapatrac457ae62018-12-06 15:19:41 +05303699 if (hdd_is_wlm_latency_manager_supported(hdd_ctx))
3700 fset |= WIFI_FEATURE_SET_LATENCY_MODE;
3701
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003702 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
3703 NLMSG_HDRLEN);
3704 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003705 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003706 return -EINVAL;
3707 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003708 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003709 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003710 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003711 goto nla_put_failure;
3712 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303713 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303714 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003715nla_put_failure:
3716 kfree_skb(skb);
3717 return -EINVAL;
3718}
3719
3720/**
3721 * wlan_hdd_cfg80211_get_supported_features() - get supported features
3722 * @wiphy: pointer to wireless wiphy structure.
3723 * @wdev: pointer to wireless_dev structure.
3724 * @data: Pointer to the data to be passed via vendor interface
3725 * @data_len:Length of the data to be passed
3726 *
3727 * Return: Return the Success or Failure code.
3728 */
3729static int
3730wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
3731 struct wireless_dev *wdev,
3732 const void *data, int data_len)
3733{
Dustin Brown363b4792019-02-05 16:11:55 -08003734 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08003735 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303736
Dustin Brown363b4792019-02-05 16:11:55 -08003737 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08003738 if (errno)
3739 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003740
Dustin Brownf0f00612019-01-31 16:02:24 -08003741 errno = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
3742 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003743
Dustin Brown363b4792019-02-05 16:11:55 -08003744 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303745
Dustin Brownf0f00612019-01-31 16:02:24 -08003746 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003747}
3748
3749/**
3750 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3751 * @wiphy: pointer to wireless wiphy structure.
3752 * @wdev: pointer to wireless_dev structure.
3753 * @data: Pointer to the data to be passed via vendor interface
3754 * @data_len:Length of the data to be passed
3755 *
3756 * Set the MAC address that is to be used for scanning.
3757 *
3758 * Return: Return the Success or Failure code.
3759 */
3760static int
3761__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3762 struct wireless_dev *wdev,
3763 const void *data,
3764 int data_len)
3765{
Jeff Johnson9d45f332019-01-29 08:42:00 -08003766 struct scan_mac_oui scan_mac_oui = { {0} };
Jeff Johnsonb8944722017-09-03 09:03:19 -07003767 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003768 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303769 QDF_STATUS status;
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +05303770 int ret, len;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303771 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07003772 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003773 mac_handle_t mac_handle;
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +05303774 bool mac_spoofing_enabled;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003775
Dustin Brownfdf17c12018-03-14 12:55:34 -07003776 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003777
Anurag Chouhan6d760662016-02-20 16:05:43 +05303778 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003779 hdd_err("Command not allowed in FTM mode");
3780 return -EPERM;
3781 }
3782
Jeff Johnsonb8944722017-09-03 09:03:19 -07003783 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303784 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003785 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003786
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +05303787 mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
3788 if (!mac_spoofing_enabled) {
Dustin Browna7bb6ae2018-08-16 16:51:50 -07003789 hdd_debug("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003790 return -ENOTSUPP;
3791 }
3792
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003793 /*
3794 * audit note: it is ok to pass a NULL policy here since only
3795 * one attribute is parsed and it is explicitly validated
3796 */
Dustin Brown4ea21db2018-01-05 14:13:17 -08003797 if (wlan_cfg80211_nla_parse(tb,
3798 QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
3799 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003800 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003801 return -EINVAL;
3802 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003803
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003804 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003805 hdd_err("attr mac oui failed");
Jeff Johnson9d45f332019-01-29 08:42:00 -08003806 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003807 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003808
3809 len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]);
Jeff Johnson9d45f332019-01-29 08:42:00 -08003810 if (len != sizeof(scan_mac_oui.oui)) {
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003811 hdd_err("attr mac oui invalid size %d expected %zu",
Jeff Johnson9d45f332019-01-29 08:42:00 -08003812 len, sizeof(scan_mac_oui.oui));
3813 return -EINVAL;
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003814 }
3815
Jeff Johnson9d45f332019-01-29 08:42:00 -08003816 nla_memcpy(scan_mac_oui.oui,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003817 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
Jeff Johnson9d45f332019-01-29 08:42:00 -08003818 sizeof(scan_mac_oui.oui));
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303819
Jeff Johnson9d45f332019-01-29 08:42:00 -08003820 /* populate rest of scan_mac_oui for mac addr randomization */
Jeff Johnsoncf07c312019-02-04 13:53:29 -08003821 scan_mac_oui.vdev_id = adapter->vdev_id;
Jeff Johnson9d45f332019-01-29 08:42:00 -08003822 scan_mac_oui.enb_probe_req_sno_randomization = true;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303823
Jeff Johnson9d45f332019-01-29 08:42:00 -08003824 hdd_debug("Oui (%02x:%02x:%02x), vdev_id = %d",
3825 scan_mac_oui.oui[0], scan_mac_oui.oui[1],
3826 scan_mac_oui.oui[2], scan_mac_oui.vdev_id);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303827
Jeff Johnson9d45f332019-01-29 08:42:00 -08003828 hdd_update_ie_whitelist_attr(&scan_mac_oui.ie_whitelist, hdd_ctx);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303829
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003830 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson9d45f332019-01-29 08:42:00 -08003831 status = sme_set_scanning_mac_oui(mac_handle, &scan_mac_oui);
3832 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson020db452016-06-29 14:37:26 -07003833 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Jeff Johnson9d45f332019-01-29 08:42:00 -08003834
3835 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003836}
3837
3838/**
3839 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3840 * @wiphy: pointer to wireless wiphy structure.
3841 * @wdev: pointer to wireless_dev structure.
3842 * @data: Pointer to the data to be passed via vendor interface
3843 * @data_len:Length of the data to be passed
3844 *
3845 * Set the MAC address that is to be used for scanning. This is an
3846 * SSR-protecting wrapper function.
3847 *
3848 * Return: Return the Success or Failure code.
3849 */
3850static int
3851wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3852 struct wireless_dev *wdev,
3853 const void *data,
3854 int data_len)
3855{
Dustin Browna09acf42018-11-08 12:32:26 +05303856 int errno;
3857 struct osif_vdev_sync *vdev_sync;
3858
3859 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
3860 if (errno)
3861 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003862
Dustin Browna09acf42018-11-08 12:32:26 +05303863 errno = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
3864 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003865
Dustin Browna09acf42018-11-08 12:32:26 +05303866 osif_vdev_sync_op_stop(vdev_sync);
3867
3868 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003869}
3870
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303871/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003872 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
3873 * @feature_flags: pointer to the byte array of features.
3874 * @feature: Feature to be turned ON in the byte array.
3875 *
3876 * Return: None
3877 *
3878 * This is called to turn ON or SET the feature flag for the requested feature.
3879 **/
3880#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07003881static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
3882 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003883{
3884 uint32_t index;
3885 uint8_t bit_mask;
3886
3887 index = feature / NUM_BITS_IN_BYTE;
3888 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
3889 feature_flags[index] |= bit_mask;
3890}
3891
3892/**
3893 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
3894 * @wiphy: pointer to wireless wiphy structure.
3895 * @wdev: pointer to wireless_dev structure.
3896 * @data: Pointer to the data to be passed via vendor interface
3897 * @data_len:Length of the data to be passed
3898 *
3899 * This is called when wlan driver needs to send supported feature set to
3900 * supplicant upon a request/query from the supplicant.
3901 *
3902 * Return: Return the Success or Failure code.
3903 **/
3904#define MAX_CONCURRENT_CHAN_ON_24G 2
3905#define MAX_CONCURRENT_CHAN_ON_5G 2
3906static int
3907__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3908 struct wireless_dev *wdev,
3909 const void *data, int data_len)
3910{
3911 struct sk_buff *skb = NULL;
3912 uint32_t dbs_capability = 0;
3913 bool one_by_one_dbs, two_by_two_dbs;
Ashish Kumar Dhanotiya12de5332019-03-27 14:45:27 +05303914 bool value, twt_req, twt_res;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303915 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303916 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003917 int ret_val;
3918
3919 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003920 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003921
Dustin Brownfdf17c12018-03-14 12:55:34 -07003922 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08003923
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003924 ret_val = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003925 if (ret_val)
3926 return ret_val;
3927
Anurag Chouhan6d760662016-02-20 16:05:43 +05303928 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003929 hdd_err("Command not allowed in FTM mode");
3930 return -EPERM;
3931 }
3932
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003933 if (roaming_offload_enabled(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003934 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003935 wlan_hdd_cfg80211_set_feature(feature_flags,
3936 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
3937 }
3938
3939 wlan_hdd_cfg80211_set_feature(feature_flags,
3940 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Dustin Brown76cd2932018-09-11 16:03:05 -07003941 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx->psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003942 wlan_hdd_cfg80211_set_feature(feature_flags,
3943 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07003944
3945 if (wma_is_p2p_lo_capable())
3946 wlan_hdd_cfg80211_set_feature(feature_flags,
3947 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
3948
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303949 value = 0;
Dustin Brown05d81302018-09-11 16:49:22 -07003950 status = ucfg_mlme_get_oce_sta_enabled_info(hdd_ctx->psoc, &value);
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303951 if (QDF_IS_STATUS_ERROR(status))
3952 hdd_err("could not get OCE STA enable info");
3953 if (value)
yeshwanth sriram guntuka1413dfb2017-06-23 14:09:48 +05303954 wlan_hdd_cfg80211_set_feature(feature_flags,
3955 QCA_WLAN_VENDOR_FEATURE_OCE_STA);
3956
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303957 value = 0;
Dustin Brown05d81302018-09-11 16:49:22 -07003958 status = ucfg_mlme_get_oce_sap_enabled_info(hdd_ctx->psoc, &value);
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303959 if (QDF_IS_STATUS_ERROR(status))
3960 hdd_err("could not get OCE SAP enable info");
3961 if (value)
yeshwanth sriram guntuka1413dfb2017-06-23 14:09:48 +05303962 wlan_hdd_cfg80211_set_feature(feature_flags,
3963 QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON);
3964
Ashish Kumar Dhanotiya12de5332019-03-27 14:45:27 +05303965 ucfg_mlme_get_twt_requestor(hdd_ctx->psoc, &twt_req);
3966 ucfg_mlme_get_twt_responder(hdd_ctx->psoc, &twt_res);
3967
3968 if (twt_req || twt_res)
3969 wlan_hdd_cfg80211_set_feature(feature_flags,
3970 QCA_WLAN_VENDOR_FEATURE_TWT);
3971
Kiran Kumar Lokere0508af92018-04-23 18:38:32 -07003972 /* Check the kernel version for upstream commit aced43ce780dc5 that
3973 * has support for processing user cell_base hints when wiphy is
3974 * self managed or check the backport flag for the same.
3975 */
3976#if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
3977 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
3978 wlan_hdd_cfg80211_set_feature(feature_flags,
3979 QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY);
3980#endif
Pankaj Singh50e40422020-01-09 15:29:35 +05303981
3982 if (wlan_hdd_thermal_config_support())
3983 wlan_hdd_cfg80211_set_feature(feature_flags,
3984 QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG);
3985
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003986 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
3987 NLMSG_HDRLEN);
3988
3989 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003990 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003991 return -ENOMEM;
3992 }
3993
3994 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
3995 sizeof(feature_flags), feature_flags))
3996 goto nla_put_failure;
3997
Dustin Brown76cd2932018-09-11 16:03:05 -07003998 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx->psoc,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003999 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304000 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004001 if (one_by_one_dbs)
4002 dbs_capability = DRV_DBS_CAPABILITY_1X1;
4003
4004 if (two_by_two_dbs)
4005 dbs_capability = DRV_DBS_CAPABILITY_2X2;
4006
4007 if (!one_by_one_dbs && !two_by_two_dbs)
4008 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
4009 } else {
4010 hdd_err("wma_get_dbs_hw_mode failed");
4011 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
4012 }
4013
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004014 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004015
4016 if (nla_put_u32(skb,
Ganesh Kondabattinid921ed92017-06-20 16:40:48 +05304017 QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA,
4018 dbs_capability))
4019 goto nla_put_failure;
4020
4021
4022 if (nla_put_u32(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004023 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
4024 MAX_CONCURRENT_CHAN_ON_24G))
4025 goto nla_put_failure;
4026
4027 if (nla_put_u32(skb,
4028 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
4029 MAX_CONCURRENT_CHAN_ON_5G))
4030 goto nla_put_failure;
4031
4032 return cfg80211_vendor_cmd_reply(skb);
4033
4034nla_put_failure:
4035 kfree_skb(skb);
4036 return -EINVAL;
4037}
4038
4039/**
4040 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
4041 * @wiphy: pointer to wireless wiphy structure.
4042 * @wdev: pointer to wireless_dev structure.
4043 * @data: Pointer to the data to be passed via vendor interface
4044 * @data_len:Length of the data to be passed
4045 *
4046 * This is called when wlan driver needs to send supported feature set to
4047 * supplicant upon a request/query from the supplicant.
4048 *
4049 * Return: Return the Success or Failure code.
4050 */
4051static int
4052wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
4053 struct wireless_dev *wdev,
4054 const void *data, int data_len)
4055{
Dustin Brown363b4792019-02-05 16:11:55 -08004056 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08004057 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05304058
Dustin Brown363b4792019-02-05 16:11:55 -08004059 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08004060 if (errno)
4061 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004062
Dustin Brownf0f00612019-01-31 16:02:24 -08004063 errno = __wlan_hdd_cfg80211_get_features(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004064
Dustin Brown363b4792019-02-05 16:11:55 -08004065 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05304066
Dustin Brownf0f00612019-01-31 16:02:24 -08004067 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004068}
4069
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304070#define PARAM_NUM_NW \
4071 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
4072#define PARAM_SET_BSSID \
4073 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304074#define PARAM_SET_BSSID_HINT \
4075 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004076#define PARAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304077#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05304078#define MAX_ROAMING_PARAM \
4079 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004080#define PARAM_NUM_BSSID \
4081 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID
4082#define PARAM_BSSID_PREFS \
4083 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS
4084#define PARAM_ROAM_BSSID \
4085 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID
4086#define PARAM_RSSI_MODIFIER \
4087 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER
4088#define PARAMS_NUM_BSSID \
4089 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID
4090#define PARAM_BSSID_PARAMS \
4091 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS
4092#define PARAM_A_BAND_BOOST_THLD \
4093 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD
4094#define PARAM_A_BAND_PELT_THLD \
4095 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD
4096#define PARAM_A_BAND_BOOST_FACTOR \
4097 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR
4098#define PARAM_A_BAND_PELT_FACTOR \
4099 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR
4100#define PARAM_A_BAND_MAX_BOOST \
4101 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST
4102#define PARAM_ROAM_HISTERESYS \
4103 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS
4104#define PARAM_RSSI_TRIGGER \
4105 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER
4106#define PARAM_ROAM_ENABLE \
4107 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304108#define PARAM_ROAM_CONTROL_CONFIG \
4109 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL
4110#define PARAM_FREQ_LIST_SCHEME \
4111 QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME
4112#define PARAM_FREQ_LIST_SCHEME_MAX \
4113 QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_MAX
4114#define PARAM_SCAN_FREQ_LIST \
4115 QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST
4116#define PARAM_SCAN_FREQ_LIST_TYPE \
4117 QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_TYPE
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304118#define PARAM_CAND_SEL_CRITERIA_MAX \
4119 QCA_ATTR_ROAM_CAND_SEL_CRITERIA_RATE_MAX
4120#define PARAM_CAND_SEL_SCORE_RSSI \
4121 QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_RSSI
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004122
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05304123
4124static const struct nla_policy
4125wlan_hdd_set_roam_param_policy[MAX_ROAMING_PARAM + 1] = {
4126 [QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD] = {.type = NLA_U32},
4127 [QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID] = {.type = NLA_U32},
4128 [PARAM_NUM_NW] = {.type = NLA_U32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004129 [PARAM_A_BAND_BOOST_FACTOR] = {.type = NLA_U32},
4130 [PARAM_A_BAND_PELT_FACTOR] = {.type = NLA_U32},
4131 [PARAM_A_BAND_MAX_BOOST] = {.type = NLA_U32},
4132 [PARAM_ROAM_HISTERESYS] = {.type = NLA_S32},
4133 [PARAM_A_BAND_BOOST_THLD] = {.type = NLA_S32},
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07004134 [PARAM_A_BAND_PELT_THLD] = {.type = NLA_S32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004135 [PARAM_RSSI_TRIGGER] = {.type = NLA_U32},
4136 [PARAM_ROAM_ENABLE] = { .type = NLA_S32},
4137 [PARAM_NUM_BSSID] = {.type = NLA_U32},
4138 [PARAM_RSSI_MODIFIER] = {.type = NLA_U32},
4139 [PARAMS_NUM_BSSID] = {.type = NLA_U32},
4140 [PARAM_ROAM_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
4141 [PARAM_SET_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304142 [PARAM_SET_BSSID_HINT] = {.type = NLA_FLAG},
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304143 [PARAM_ROAM_CONTROL_CONFIG] = {.type = NLA_NESTED},
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05304144};
4145
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004146/**
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004147 * hdd_set_white_list() - parse white list
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004148 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004149 * @roam_params: roam params
4150 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004151 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004152 *
4153 * Return: 0 on success; error number on failure
4154 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004155static int hdd_set_white_list(struct hdd_context *hdd_ctx,
4156 struct roam_ext_params *roam_params,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004157 struct nlattr **tb, uint8_t vdev_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004158{
4159 int rem, i;
4160 uint32_t buf_len = 0, count;
4161 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
4162 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004163 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004164
4165 i = 0;
4166 if (tb[PARAM_NUM_NW]) {
4167 count = nla_get_u32(tb[PARAM_NUM_NW]);
4168 } else {
4169 hdd_err("Number of networks is not provided");
4170 goto fail;
4171 }
4172
4173 if (count && tb[PARAM_SSID_LIST]) {
4174 nla_for_each_nested(curr_attr,
Min Liudd308892019-05-16 18:48:41 +08004175 tb[PARAM_SSID_LIST], rem) {
4176 if (i == MAX_SSID_ALLOWED_LIST) {
4177 hdd_err("Excess MAX_SSID_ALLOWED_LIST");
4178 goto fail;
4179 }
Dustin Brown4ea21db2018-01-05 14:13:17 -08004180 if (wlan_cfg80211_nla_parse(tb2,
Srinivas Dasari0cc64372019-08-13 12:04:20 +05304181 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
4182 nla_data(curr_attr),
4183 nla_len(curr_attr),
4184 wlan_hdd_set_roam_param_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08004185 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004186 goto fail;
4187 }
4188 /* Parse and Fetch allowed SSID list*/
4189 if (!tb2[PARAM_LIST_SSID]) {
4190 hdd_err("attr allowed ssid failed");
4191 goto fail;
4192 }
4193 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
4194 /*
4195 * Upper Layers include a null termination
4196 * character. Check for the actual permissible
4197 * length of SSID and also ensure not to copy
4198 * the NULL termination character to the driver
4199 * buffer.
4200 */
Min Liudd308892019-05-16 18:48:41 +08004201 if (buf_len > 1 &&
Srinivas Girigowdab8fdc642019-03-19 15:33:03 -07004202 ((buf_len - 1) <= WLAN_SSID_MAX_LEN)) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004203 nla_memcpy(roam_params->ssid_allowed_list[i].ssId,
4204 tb2[PARAM_LIST_SSID], buf_len - 1);
4205 roam_params->ssid_allowed_list[i].length = buf_len - 1;
4206 hdd_debug("SSID[%d]: %.*s,length = %d",
4207 i,
4208 roam_params->ssid_allowed_list[i].length,
4209 roam_params->ssid_allowed_list[i].ssId,
4210 roam_params->ssid_allowed_list[i].length);
4211 i++;
4212 } else {
4213 hdd_err("Invalid buffer length");
4214 }
4215 }
4216 }
4217
4218 if (i != count) {
4219 hdd_err("Invalid number of SSIDs i = %d, count = %d", i, count);
4220 goto fail;
4221 }
4222
4223 roam_params->num_ssid_allowed_list = i;
4224 hdd_debug("Num of Allowed SSID %d", roam_params->num_ssid_allowed_list);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004225 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004226 sme_update_roam_params(mac_handle, vdev_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004227 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
4228 return 0;
4229
4230fail:
4231 return -EINVAL;
4232}
4233
4234/**
4235 * hdd_set_bssid_prefs() - parse set bssid prefs
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004236 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004237 * @roam_params: roam params
4238 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004239 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004240 *
4241 * Return: 0 on success; error number on failure
4242 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004243static int hdd_set_bssid_prefs(struct hdd_context *hdd_ctx,
4244 struct roam_ext_params *roam_params,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004245 struct nlattr **tb, uint8_t vdev_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004246{
4247 int rem, i;
4248 uint32_t count;
4249 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
4250 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004251 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004252
4253 /* Parse and fetch number of preferred BSSID */
4254 if (!tb[PARAM_NUM_BSSID]) {
4255 hdd_err("attr num of preferred bssid failed");
4256 goto fail;
4257 }
4258 count = nla_get_u32(tb[PARAM_NUM_BSSID]);
4259 if (count > MAX_BSSID_FAVORED) {
4260 hdd_err("Preferred BSSID count %u exceeds max %u",
4261 count, MAX_BSSID_FAVORED);
4262 goto fail;
4263 }
4264 hdd_debug("Num of Preferred BSSID (%d)", count);
4265 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS]) {
4266 hdd_err("attr Preferred BSSID failed");
4267 goto fail;
4268 }
4269
4270 i = 0;
4271 nla_for_each_nested(curr_attr,
4272 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
4273 rem) {
4274 if (i == count) {
4275 hdd_warn("Ignoring excess Preferred BSSID");
4276 break;
4277 }
4278
Dustin Brown4ea21db2018-01-05 14:13:17 -08004279 if (wlan_cfg80211_nla_parse(tb2,
4280 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
4281 nla_data(curr_attr),
4282 nla_len(curr_attr),
4283 wlan_hdd_set_roam_param_policy)) {
4284 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004285 goto fail;
4286 }
4287 /* Parse and fetch MAC address */
4288 if (!tb2[PARAM_ROAM_BSSID]) {
4289 hdd_err("attr mac address failed");
4290 goto fail;
4291 }
4292 nla_memcpy(roam_params->bssid_favored[i].bytes,
4293 tb2[PARAM_ROAM_BSSID],
4294 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07004295 hdd_debug(QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07004296 QDF_MAC_ADDR_ARRAY(roam_params->bssid_favored[i].bytes));
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004297 /* Parse and fetch preference factor*/
4298 if (!tb2[PARAM_RSSI_MODIFIER]) {
4299 hdd_err("BSSID Preference score failed");
4300 goto fail;
4301 }
4302 roam_params->bssid_favored_factor[i] = nla_get_u32(
4303 tb2[PARAM_RSSI_MODIFIER]);
4304 hdd_debug("BSSID Preference score (%d)",
4305 roam_params->bssid_favored_factor[i]);
4306 i++;
4307 }
4308 if (i < count)
4309 hdd_warn("Num Preferred BSSID %u less than expected %u",
4310 i, count);
4311
4312 roam_params->num_bssid_favored = i;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004313 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004314 sme_update_roam_params(mac_handle, vdev_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004315 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
4316
4317 return 0;
4318
4319fail:
4320 return -EINVAL;
4321}
4322
4323/**
4324 * hdd_set_blacklist_bssid() - parse set blacklist bssid
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004325 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004326 * @roam_params: roam params
4327 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004328 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004329 *
4330 * Return: 0 on success; error number on failure
4331 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004332static int hdd_set_blacklist_bssid(struct hdd_context *hdd_ctx,
4333 struct roam_ext_params *roam_params,
4334 struct nlattr **tb,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004335 uint8_t vdev_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004336{
4337 int rem, i;
4338 uint32_t count;
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304339 uint8_t j = 0;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004340 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
4341 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004342 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004343
4344 /* Parse and fetch number of blacklist BSSID */
4345 if (!tb[PARAMS_NUM_BSSID]) {
4346 hdd_err("attr num of blacklist bssid failed");
4347 goto fail;
4348 }
4349 count = nla_get_u32(tb[PARAMS_NUM_BSSID]);
4350 if (count > MAX_BSSID_AVOID_LIST) {
4351 hdd_err("Blacklist BSSID count %u exceeds max %u",
4352 count, MAX_BSSID_AVOID_LIST);
4353 goto fail;
4354 }
4355 hdd_debug("Num of blacklist BSSID (%d)", count);
4356
4357 i = 0;
4358 if (count && tb[PARAM_BSSID_PARAMS]) {
4359 nla_for_each_nested(curr_attr,
4360 tb[PARAM_BSSID_PARAMS],
4361 rem) {
4362 if (i == count) {
4363 hdd_warn("Ignoring excess Blacklist BSSID");
4364 break;
4365 }
4366
Dustin Brown4ea21db2018-01-05 14:13:17 -08004367 if (wlan_cfg80211_nla_parse(tb2,
Dustin Brown3fb15042017-08-15 15:54:49 -07004368 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
4369 nla_data(curr_attr),
4370 nla_len(curr_attr),
4371 wlan_hdd_set_roam_param_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08004372 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004373 goto fail;
4374 }
4375 /* Parse and fetch MAC address */
4376 if (!tb2[PARAM_SET_BSSID]) {
4377 hdd_err("attr blacklist addr failed");
4378 goto fail;
4379 }
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304380 if (tb2[PARAM_SET_BSSID_HINT]) {
4381 struct reject_ap_info ap_info;
4382
4383 nla_memcpy(ap_info.bssid.bytes,
4384 tb2[PARAM_SET_BSSID],
4385 QDF_MAC_ADDR_SIZE);
4386 ap_info.reject_ap_type = USERSPACE_AVOID_TYPE;
4387 /* This BSSID is avoided and not blacklisted */
4388 ucfg_blm_add_bssid_to_reject_list(hdd_ctx->pdev,
4389 &ap_info);
4390 i++;
4391 continue;
4392 }
4393 nla_memcpy(roam_params->bssid_avoid_list[j].bytes,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004394 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07004395 hdd_debug(QDF_MAC_ADDR_STR,
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304396 QDF_MAC_ADDR_ARRAY(roam_params->
4397 bssid_avoid_list[j].bytes));
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004398 i++;
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304399 j++;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004400 }
4401 }
4402
4403 if (i < count)
4404 hdd_warn("Num Blacklist BSSID %u less than expected %u",
4405 i, count);
4406
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304407 roam_params->num_bssid_avoid_list = j;
4408 /* Send the blacklist to the blacklist mgr component */
4409 ucfg_blm_add_userspace_black_list(hdd_ctx->pdev,
4410 roam_params->bssid_avoid_list,
4411 roam_params->num_bssid_avoid_list);
4412
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004413 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004414 sme_update_roam_params(mac_handle, vdev_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004415 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
4416
4417 return 0;
4418fail:
4419 return -EINVAL;
4420}
4421
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304422static const struct nla_policy
4423roam_scan_freq_list_scheme_policy[PARAM_FREQ_LIST_SCHEME_MAX + 1] = {
4424 [PARAM_SCAN_FREQ_LIST_TYPE] = {.type = NLA_U32},
4425 [PARAM_SCAN_FREQ_LIST] = {.type = NLA_NESTED},
4426};
4427
4428/**
4429 * hdd_send_roam_scan_channel_freq_list_to_sme() - Send control roam scan freqs
4430 * @hdd_ctx: HDD context
4431 * @vdev_id: vdev id
4432 * @tb: Nested attribute carrying frequency list scheme
4433 *
4434 * Extracts the frequency list and frequency list type from the frequency
4435 * list scheme and send the frequencies to SME.
4436 *
4437 * Return: QDF_STATUS
4438 */
4439static QDF_STATUS
4440hdd_send_roam_scan_channel_freq_list_to_sme(struct hdd_context *hdd_ctx,
4441 uint8_t vdev_id, struct nlattr *tb)
4442{
4443 QDF_STATUS status;
4444 struct nlattr *tb2[PARAM_FREQ_LIST_SCHEME_MAX + 1], *curr_attr;
4445 uint8_t num_chan = 0;
4446 uint32_t freq_list[SIR_MAX_SUPPORTED_CHANNEL_LIST] = {0};
4447 uint32_t list_type;
4448 mac_handle_t mac_handle = hdd_ctx->mac_handle;
4449 int rem;
4450
4451 if (wlan_cfg80211_nla_parse_nested(tb2, PARAM_FREQ_LIST_SCHEME_MAX,
4452 tb,
4453 roam_scan_freq_list_scheme_policy)) {
4454 hdd_err("nla_parse failed");
4455 return QDF_STATUS_E_INVAL;
4456 }
4457
4458 if (!tb2[PARAM_SCAN_FREQ_LIST] || !tb2[PARAM_SCAN_FREQ_LIST_TYPE]) {
4459 hdd_err("ROAM_CONTROL_SCAN_FREQ_LIST or type are not present");
4460 return QDF_STATUS_E_INVAL;
4461 }
4462
4463 list_type = nla_get_u32(tb2[PARAM_SCAN_FREQ_LIST_TYPE]);
4464 if (list_type != QCA_PREFERRED_SCAN_FREQ_LIST &&
4465 list_type != QCA_SPECIFIC_SCAN_FREQ_LIST) {
4466 hdd_err("Invalid freq list type received: %u", list_type);
4467 return QDF_STATUS_E_INVAL;
4468 }
4469
4470 nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem)
4471 num_chan++;
4472 if (num_chan > SIR_MAX_SUPPORTED_CHANNEL_LIST) {
4473 hdd_err("number of channels (%d) supported exceeded max (%d)",
4474 num_chan, SIR_MAX_SUPPORTED_CHANNEL_LIST);
4475 return QDF_STATUS_E_INVAL;
4476 }
4477 num_chan = 0;
4478
Srinivas Dasariac5312a2019-08-23 07:21:46 +05304479 nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem) {
4480 if (nla_len(curr_attr) != sizeof(uint32_t)) {
4481 hdd_err("len is not correct for frequency %d",
4482 num_chan);
4483 return QDF_STATUS_E_INVAL;
4484 }
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304485 freq_list[num_chan++] = nla_get_u32(curr_attr);
Srinivas Dasariac5312a2019-08-23 07:21:46 +05304486 }
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304487
4488 status = sme_update_roam_scan_freq_list(mac_handle, vdev_id, freq_list,
4489 num_chan, list_type);
4490 if (QDF_IS_STATUS_ERROR(status))
4491 hdd_err("Failed to update channel list information");
4492
4493 return status;
4494}
4495
4496static const struct nla_policy
4497roam_control_policy[QCA_ATTR_ROAM_CONTROL_MAX + 1] = {
Srinivas Dasari391692d2019-08-21 08:40:53 +05304498 [QCA_ATTR_ROAM_CONTROL_ENABLE] = {.type = NLA_U8},
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304499 [QCA_ATTR_ROAM_CONTROL_STATUS] = {.type = NLA_U8},
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304500 [PARAM_FREQ_LIST_SCHEME] = {.type = NLA_NESTED},
Srinivas Dasari0628e842019-08-22 01:17:38 +05304501 [QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD] = {.type = NLA_U32},
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05304502 [QCA_ATTR_ROAM_CONTROL_CLEAR_ALL] = {.type = NLA_FLAG},
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304503 [QCA_ATTR_ROAM_CONTROL_TRIGGERS] = {.type = NLA_U32},
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304504 [QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA] = {.type = NLA_NESTED},
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304505 [QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD] = {.type = NLA_U32},
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304506};
4507
4508/**
Srinivas Dasari0628e842019-08-22 01:17:38 +05304509 * hdd_send_roam_full_scan_period_to_sme() - Send full roam scan period to SME
4510 * @hdd_ctx: HDD context
4511 * @vdev_id: vdev id
4512 * @full_roam_scan_period: Idle period in seconds between two successive
Srinivas Dasari240d3272019-09-20 12:00:57 +05304513 * full channel roam scans
4514 * @check_and_update: If this is true/set, update the value only if the current
4515 * configured value is not same as global value read from
4516 * ini param. This is to give priority to the user configured
4517 * values and retain the value, if updated already.
4518 * If this is not set, update the value without any check.
Srinivas Dasari0628e842019-08-22 01:17:38 +05304519 *
4520 * Validate the full roam scan period and send it to firmware
4521 *
4522 * Return: QDF_STATUS
4523 */
4524static QDF_STATUS
4525hdd_send_roam_full_scan_period_to_sme(struct hdd_context *hdd_ctx,
4526 uint8_t vdev_id,
Srinivas Dasari240d3272019-09-20 12:00:57 +05304527 uint32_t full_roam_scan_period,
4528 bool check_and_update)
Srinivas Dasari0628e842019-08-22 01:17:38 +05304529{
4530 QDF_STATUS status;
Srinivas Dasari240d3272019-09-20 12:00:57 +05304531 uint32_t full_roam_scan_period_current, full_roam_scan_period_global;
Srinivas Dasari0628e842019-08-22 01:17:38 +05304532
4533 if (!ucfg_mlme_validate_full_roam_scan_period(full_roam_scan_period))
4534 return QDF_STATUS_E_INVAL;
4535
4536 hdd_debug("Received Command to Set full roam scan period = %u",
4537 full_roam_scan_period);
4538
Srinivas Dasari240d3272019-09-20 12:00:57 +05304539 status = sme_get_full_roam_scan_period(hdd_ctx->mac_handle, vdev_id,
4540 &full_roam_scan_period_current);
4541 if (QDF_IS_STATUS_ERROR(status))
4542 return status;
4543
4544 full_roam_scan_period_global =
4545 sme_get_full_roam_scan_period_global(hdd_ctx->mac_handle);
4546 if (check_and_update &&
4547 full_roam_scan_period_current != full_roam_scan_period_global) {
4548 hdd_debug("Full roam scan period is already updated, value: %u",
4549 full_roam_scan_period_current);
4550 return QDF_STATUS_SUCCESS;
4551 }
Srinivas Dasari0628e842019-08-22 01:17:38 +05304552 status = sme_update_full_roam_scan_period(hdd_ctx->mac_handle, vdev_id,
4553 full_roam_scan_period);
4554 if (QDF_IS_STATUS_ERROR(status))
4555 hdd_err("Failed to set full scan period");
4556
4557 return status;
4558}
4559
4560/**
Pragaspathi Thilagaraj47385952020-02-28 14:41:42 +05304561 * wlan_hdd_convert_control_roam_trigger_reason_bitmap - Convert the
4562 * vendor specific reason code to internal reason code.
4563 * @trigger_reason_bitmap: Vendor specific roam trigger bitmap
4564 *
4565 * Return: Internal roam trigger bitmap
4566 */
4567static uint32_t
4568wlan_hdd_convert_control_roam_trigger_bitmap(uint32_t trigger_reason_bitmap)
4569{
4570 uint32_t drv_trigger_bitmap = 0, all_bitmap;
4571
4572 /* Enable the complete trigger bitmap when all bits are set in
4573 * the control config bitmap
4574 */
4575 all_bitmap = (QCA_ROAM_TRIGGER_REASON_BSS_LOAD << 1) - 1;
4576 if (trigger_reason_bitmap == all_bitmap)
4577 return BIT(ROAM_TRIGGER_REASON_MAX) - 1;
4578
4579 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_PER)
4580 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_PER);
4581
4582 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BEACON_MISS)
4583 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BMISS);
4584
4585 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_POOR_RSSI)
4586 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_LOW_RSSI);
4587
4588 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BETTER_RSSI)
4589 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_HIGH_RSSI);
4590
4591 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_PERIODIC)
4592 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_PERIODIC);
4593
4594 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_DENSE)
4595 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_DENSE);
4596
4597 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BTM)
4598 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BTM);
4599
4600 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BSS_LOAD)
4601 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BSS_LOAD);
4602
4603 return drv_trigger_bitmap;
4604}
4605
4606/**
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304607 * hdd_send_roam_triggers_to_sme() - Send roam trigger bitmap to SME
4608 * @hdd_ctx: HDD context
4609 * @vdev_id: vdev id
4610 * @roam_trigger_bitmap: Vendor configured roam trigger bitmap to be configured
4611 * to firmware
4612 *
4613 * Send the roam trigger bitmap received to SME
4614 *
4615 * Return: QDF_STATUS
4616 */
4617static QDF_STATUS
4618hdd_send_roam_triggers_to_sme(struct hdd_context *hdd_ctx,
4619 uint8_t vdev_id,
4620 uint32_t roam_trigger_bitmap)
4621{
4622 QDF_STATUS status;
4623 struct roam_triggers triggers;
Abhinav Kumar523ca372019-08-30 16:28:19 +05304624 struct hdd_adapter *adapter;
4625
4626 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
4627 if (!adapter) {
4628 hdd_err("adapter NULL");
4629 return QDF_STATUS_E_FAILURE;
4630 }
4631
4632 if (adapter->device_mode != QDF_STA_MODE) {
4633 hdd_err("Roam trigger bitmap supported only in STA mode");
4634 return QDF_STATUS_E_FAILURE;
4635 }
4636
4637 /*
4638 * In standalone STA, if this vendor command is received between
4639 * ROAM_START and roam synch indication, it is better to reject
4640 * roam disable since driver would send vdev_params command to
4641 * de-initialize roaming structures in fw.
4642 * In STA+STA mode, if this vendor command to enable roaming is
4643 * received for one STA vdev and ROAM_START was received for other
4644 * STA vdev, then also driver would be send vdev_params command to
4645 * de-initialize roaming structures in fw on the roaming enabled
4646 * vdev.
4647 */
4648 if (hdd_ctx->roaming_in_progress) {
4649 hdd_err("Reject set roam trigger as roaming is in progress");
4650 return QDF_STATUS_E_FAILURE;
4651 }
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304652
4653 triggers.vdev_id = vdev_id;
Pragaspathi Thilagaraj47385952020-02-28 14:41:42 +05304654 triggers.trigger_bitmap =
4655 wlan_hdd_convert_control_roam_trigger_bitmap(roam_trigger_bitmap);
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304656
4657 status = sme_set_roam_triggers(hdd_ctx->mac_handle, &triggers);
4658 if (QDF_IS_STATUS_ERROR(status))
4659 hdd_err("Failed to set roam control trigger bitmap");
4660
4661 return status;
4662}
4663
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304664/*
4665 * Disable default scoring algorithm. This is intended to set all bits of the
4666 * disable_bitmap in struct scoring_param.
4667 */
4668#define DISABLE_SCORING 0
4669
4670/*
4671 * Enable scoring algorithm. This is intended to clear all bits of the
4672 * disable_bitmap in struct scoring_param.
4673 */
4674#define ENABLE_SCORING 1
4675
4676/*
4677 * Controlled roam candidate selection is enabled from userspace.
4678 * Driver/firmware should honor the selection criteria
4679 */
4680#define CONTROL_ROAM_CAND_SEL_ENABLE 1
4681
4682/*
4683 * Controlled roam candidate selection is disabled from userspace.
4684 * Driver/firmware can use its internal candidate selection criteria
4685 */
4686#define CONTROL_ROAM_CAND_SEL_DISABLE 0
4687
4688static const struct nla_policy
4689roam_scan_cand_sel_policy[PARAM_CAND_SEL_CRITERIA_MAX + 1] = {
4690 [PARAM_CAND_SEL_SCORE_RSSI] = {.type = NLA_U8},
4691};
4692
4693/**
4694 * hdd_send_roam_cand_sel_criteria_to_sme() - Send candidate sel criteria to SME
4695 * @hdd_ctx: HDD context
4696 * @vdev_id: vdev id
4697 * @attr: Nested attribute carrying candidate selection criteria
4698 *
4699 * Extract different candidate sel criteria mentioned and convert it to
4700 * driver/firmware understable format.
4701 *
4702 * Return: QDF_STATUS
4703 */
4704static QDF_STATUS
4705hdd_send_roam_cand_sel_criteria_to_sme(struct hdd_context *hdd_ctx,
4706 uint8_t vdev_id,
4707 struct nlattr *attr)
4708{
4709 QDF_STATUS status;
4710 struct nlattr *tb2[PARAM_CAND_SEL_CRITERIA_MAX + 1];
4711 struct nlattr *curr_attr;
4712 uint8_t sel_criteria = 0, rssi_score = 0, scoring;
4713 int rem;
4714
4715 hdd_debug("Received Command to Set candidate selection criteria ");
4716 nla_for_each_nested(curr_attr, attr, rem) {
4717 sel_criteria++;
4718 break;
4719 }
4720
4721 if (sel_criteria &&
4722 wlan_cfg80211_nla_parse_nested(tb2, PARAM_CAND_SEL_CRITERIA_MAX,
4723 attr, roam_scan_cand_sel_policy)) {
4724 hdd_err("nla_parse failed");
4725 return QDF_STATUS_E_INVAL;
4726 }
4727
4728 /*
4729 * Firmware supports the below configurations currently,
4730 * 1. Default selection criteria where all scoring params
4731 * are enabled and different weightages/scores are given to
4732 * different parameters.
4733 * When userspace doesn't specify any candidate selection criteria,
4734 * this will be enabled.
4735 * 2. Legacy candidate selection criteria where scoring
4736 * algorithm is disabled and only RSSI is considered for
4737 * roam candidate selection.
4738 * When userspace specify 100% weightage for RSSI, this will
4739 * be enabled.
4740 * Rest of the combinations are not supported for now.
4741 */
4742 if (sel_criteria == CONTROL_ROAM_CAND_SEL_ENABLE) {
4743 /* Legacy selection criteria: 100% weightage to RSSI */
4744 if (tb2[PARAM_CAND_SEL_SCORE_RSSI])
4745 rssi_score = nla_get_u8(tb2[PARAM_CAND_SEL_SCORE_RSSI]);
4746
4747 if (rssi_score != 100) {
4748 hdd_debug("Ignore the candidate selection criteria");
4749 return QDF_STATUS_E_INVAL;
4750 }
4751 scoring = DISABLE_SCORING;
4752 } else {
4753 /* Default selection criteria */
4754 scoring = ENABLE_SCORING;
4755 }
4756
4757 status = sme_modify_roam_cand_sel_criteria(hdd_ctx->mac_handle, vdev_id,
4758 !!scoring);
4759 if (QDF_IS_STATUS_ERROR(status))
4760 hdd_err("Failed to disable scoring");
4761
4762 return status;
4763}
4764
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304765/**
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304766 * hdd_send_roam_scan_period_to_sme() - Send roam scan period to SME
4767 * @hdd_ctx: HDD context
4768 * @vdev_id: vdev id
4769 * @roam_scan_period: Roam scan period in seconds
Srinivas Dasari240d3272019-09-20 12:00:57 +05304770 * @check_and_update: If this is true/set, update the value only if the current
4771 * configured value is not same as global value read from
4772 * ini param. This is to give priority to the user configured
4773 * values and retain the value, if updated already.
4774 * If this is not set, update the value without any check.
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304775 *
4776 * Validate the roam scan period and send it to firmware if valid.
4777 *
4778 * Return: QDF_STATUS
4779 */
4780static QDF_STATUS
4781hdd_send_roam_scan_period_to_sme(struct hdd_context *hdd_ctx,
4782 uint8_t vdev_id,
Srinivas Dasari240d3272019-09-20 12:00:57 +05304783 uint32_t roam_scan_period,
4784 bool check_and_update)
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304785{
4786 QDF_STATUS status;
Srinivas Dasari240d3272019-09-20 12:00:57 +05304787 uint16_t roam_scan_period_current, roam_scan_period_global;
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304788
4789 if (!ucfg_mlme_validate_scan_period(roam_scan_period * 1000))
4790 return QDF_STATUS_E_INVAL;
4791
4792 hdd_debug("Received Command to Set roam scan period (Empty Scan refresh period) = %d",
4793 roam_scan_period);
4794
Srinivas Dasari240d3272019-09-20 12:00:57 +05304795 status = sme_get_empty_scan_refresh_period(hdd_ctx->mac_handle, vdev_id,
4796 &roam_scan_period_current);
4797 if (QDF_IS_STATUS_ERROR(status))
4798 return status;
4799
4800 roam_scan_period_global =
4801 sme_get_empty_scan_refresh_period_global(hdd_ctx->mac_handle);
4802 if (check_and_update &&
4803 roam_scan_period_current != roam_scan_period_global) {
4804 hdd_debug("roam scan period is already updated, value: %u",
4805 roam_scan_period_current / 1000);
4806 return QDF_STATUS_SUCCESS;
4807 }
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304808 status = sme_update_empty_scan_refresh_period(hdd_ctx->mac_handle,
4809 vdev_id,
4810 roam_scan_period * 1000);
4811 if (QDF_IS_STATUS_ERROR(status))
4812 hdd_err("Failed to set scan period");
4813
4814 return status;
4815}
4816
4817/**
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304818 * hdd_set_roam_with_control_config() - Set roam control configuration
4819 * @hdd_ctx: HDD context
4820 * @tb: List of attributes carrying roam subcmd data
4821 * @vdev_id: vdev id
4822 *
4823 * Extracts the attribute PARAM_ROAM_CONTROL_CONFIG from the attributes list tb
4824 * and sends the corresponding roam control configuration to driver/firmware.
4825 *
4826 * Return: 0 on success; error number on failure
4827 */
4828static int
4829hdd_set_roam_with_control_config(struct hdd_context *hdd_ctx,
4830 struct nlattr **tb,
4831 uint8_t vdev_id)
4832{
4833 QDF_STATUS status = QDF_STATUS_SUCCESS;
4834 struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1], *attr;
Srinivas Dasari0628e842019-08-22 01:17:38 +05304835 uint32_t value;
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304836
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304837 hdd_enter();
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304838 /* The command must carry PARAM_ROAM_CONTROL_CONFIG */
4839 if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
4840 hdd_err("Attribute CONTROL_CONFIG is not present");
4841 return -EINVAL;
4842 }
4843
4844 if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
4845 tb[PARAM_ROAM_CONTROL_CONFIG],
4846 roam_control_policy)) {
4847 hdd_err("nla_parse failed");
4848 return -EINVAL;
4849 }
4850
4851 attr = tb2[PARAM_FREQ_LIST_SCHEME];
4852 if (attr) {
4853 status = hdd_send_roam_scan_channel_freq_list_to_sme(hdd_ctx,
4854 vdev_id,
4855 attr);
4856 if (QDF_IS_STATUS_ERROR(status))
4857 hdd_err("failed to config roam control");
4858 }
4859
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304860 if (tb2[QCA_ATTR_ROAM_CONTROL_TRIGGERS]) {
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304861 value = nla_get_u32(tb2[QCA_ATTR_ROAM_CONTROL_TRIGGERS]);
4862 hdd_debug("Received roam trigger bitmap: 0x%x", value);
4863 status = hdd_send_roam_triggers_to_sme(hdd_ctx,
4864 vdev_id,
4865 value);
4866 if (status)
4867 hdd_err("failed to config roam triggers");
4868 }
4869
Srinivas Dasari391692d2019-08-21 08:40:53 +05304870 attr = tb2[QCA_ATTR_ROAM_CONTROL_ENABLE];
4871 if (attr) {
Srinivas Dasari391692d2019-08-21 08:40:53 +05304872 status = sme_set_roam_config_enable(hdd_ctx->mac_handle,
4873 vdev_id,
4874 nla_get_u8(attr));
4875 if (QDF_IS_STATUS_ERROR(status))
4876 hdd_err("failed to enable/disable roam control config");
Srinivas Dasari240d3272019-09-20 12:00:57 +05304877
sheenam monga65415d12020-02-07 14:39:15 +05304878 hdd_debug("Parse and send roam control %s:",
4879 nla_get_u8(attr) ? "Enable" : "Disable");
4880
Srinivas Dasari240d3272019-09-20 12:00:57 +05304881 attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD];
4882 if (attr) {
Srinivas Dasari240d3272019-09-20 12:00:57 +05304883 /* Default value received as part of Roam control enable
4884 * Set this only if user hasn't configured any value so
4885 * far.
4886 */
4887 value = nla_get_u32(attr);
4888 status = hdd_send_roam_scan_period_to_sme(hdd_ctx,
4889 vdev_id,
4890 value, true);
4891 if (QDF_IS_STATUS_ERROR(status))
4892 hdd_err("failed to send scan period to firmware");
4893 }
4894
4895 attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD];
4896 if (attr) {
Srinivas Dasari240d3272019-09-20 12:00:57 +05304897 value = nla_get_u32(attr);
4898 /* Default value received as part of Roam control enable
4899 * Set this only if user hasn't configured any value so
4900 * far.
4901 */
4902 status = hdd_send_roam_full_scan_period_to_sme(hdd_ctx,
4903 vdev_id,
4904 value,
4905 true);
4906 if (status)
4907 hdd_err("failed to config full scan period");
4908 }
4909 } else {
4910 attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD];
4911 if (attr) {
Srinivas Dasari240d3272019-09-20 12:00:57 +05304912 /* User configured value, cache the value directly */
4913 value = nla_get_u32(attr);
4914 status = hdd_send_roam_scan_period_to_sme(hdd_ctx,
4915 vdev_id,
4916 value, false);
4917 if (QDF_IS_STATUS_ERROR(status))
4918 hdd_err("failed to send scan period to firmware");
4919 }
4920
4921 attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD];
4922 if (attr) {
Srinivas Dasari240d3272019-09-20 12:00:57 +05304923 value = nla_get_u32(attr);
4924 /* User configured value, cache the value directly */
4925 status = hdd_send_roam_full_scan_period_to_sme(hdd_ctx,
4926 vdev_id,
4927 value,
4928 false);
4929 if (status)
4930 hdd_err("failed to config full scan period");
4931 }
Srinivas Dasari391692d2019-08-21 08:40:53 +05304932 }
4933
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304934 /* Scoring and roam candidate selection criteria */
4935 attr = tb2[QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA];
4936 if (attr) {
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304937 status = hdd_send_roam_cand_sel_criteria_to_sme(hdd_ctx,
4938 vdev_id, attr);
4939 if (QDF_IS_STATUS_ERROR(status))
4940 hdd_err("failed to set candidate selection criteria");
4941 }
4942
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304943 return qdf_status_to_os_return(status);
4944}
4945
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05304946#define ENABLE_ROAM_TRIGGERS_ALL (QCA_ROAM_TRIGGER_REASON_PER | \
4947 QCA_ROAM_TRIGGER_REASON_BEACON_MISS | \
4948 QCA_ROAM_TRIGGER_REASON_POOR_RSSI | \
4949 QCA_ROAM_TRIGGER_REASON_BETTER_RSSI | \
4950 QCA_ROAM_TRIGGER_REASON_PERIODIC | \
4951 QCA_ROAM_TRIGGER_REASON_DENSE | \
4952 QCA_ROAM_TRIGGER_REASON_BTM | \
4953 QCA_ROAM_TRIGGER_REASON_BSS_LOAD)
4954
4955static int
4956hdd_clear_roam_control_config(struct hdd_context *hdd_ctx,
4957 struct nlattr **tb,
4958 uint8_t vdev_id)
4959{
4960 QDF_STATUS status;
4961 struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1];
4962 mac_handle_t mac_handle = hdd_ctx->mac_handle;
Srinivas Dasari05bc2c22019-08-23 17:54:53 +05304963 uint32_t value;
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05304964
4965 /* The command must carry PARAM_ROAM_CONTROL_CONFIG */
4966 if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
4967 hdd_err("Attribute CONTROL_CONFIG is not present");
4968 return -EINVAL;
4969 }
4970
4971 if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
4972 tb[PARAM_ROAM_CONTROL_CONFIG],
4973 roam_control_policy)) {
4974 hdd_err("nla_parse failed");
4975 return -EINVAL;
4976 }
4977
4978 hdd_debug("Clear the control config done through SET");
4979 if (tb2[QCA_ATTR_ROAM_CONTROL_CLEAR_ALL]) {
4980 hdd_debug("Disable roam control config done through SET");
4981 status = sme_set_roam_config_enable(hdd_ctx->mac_handle,
4982 vdev_id, 0);
4983 if (QDF_IS_STATUS_ERROR(status)) {
4984 hdd_err("failed to enable/disable roam control config");
4985 return qdf_status_to_os_return(status);
4986 }
4987
Srinivas Dasari05bc2c22019-08-23 17:54:53 +05304988 value = ENABLE_ROAM_TRIGGERS_ALL;
4989 hdd_debug("Reset roam trigger bitmap to 0x%x", value);
4990 status = hdd_send_roam_triggers_to_sme(hdd_ctx, vdev_id, value);
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05304991 if (QDF_IS_STATUS_ERROR(status)) {
4992 hdd_err("failed to restore roam trigger bitmap");
4993 return qdf_status_to_os_return(status);
4994 }
4995
4996 status = sme_roam_control_restore_default_config(mac_handle,
4997 vdev_id);
4998 if (QDF_IS_STATUS_ERROR(status)) {
4999 hdd_err("failed to config roam control");
5000 return qdf_status_to_os_return(status);
5001 }
5002 }
5003
5004 return 0;
5005}
5006
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305007/**
5008 * hdd_roam_control_config_buf_size() - Calculate the skb size to be allocated
5009 * @hdd_ctx: HDD context
5010 * @tb: List of attributes to be populated
5011 *
5012 * Calculate the buffer size to be allocated based on the attributes
5013 * mentioned in tb.
5014 *
5015 * Return: buffer size to be allocated
5016 */
5017static uint16_t
5018hdd_roam_control_config_buf_size(struct hdd_context *hdd_ctx,
5019 struct nlattr **tb)
5020{
5021 uint16_t skb_len = 0;
5022
5023 if (tb[QCA_ATTR_ROAM_CONTROL_STATUS])
5024 skb_len += NLA_HDRLEN + sizeof(uint8_t);
5025
Srinivas Dasaria33fdd82019-08-21 16:15:22 +05305026 if (tb[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD])
5027 skb_len += NLA_HDRLEN + sizeof(uint32_t);
5028
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305029 return skb_len;
5030}
5031
5032/**
5033 * hdd_roam_control_config_fill_data() - Fill the data requested by userspace
5034 * @hdd_ctx: HDD context
5035 * @vdev_id: vdev id
5036 * @skb: SK buffer
5037 * @tb: List of attributes
5038 *
5039 * Get the data corresponding to the attribute list specified in tb and
5040 * update the same to skb by populating the same attributes.
5041 *
5042 * Return: 0 on success; error number on failure
5043 */
5044static int
5045hdd_roam_control_config_fill_data(struct hdd_context *hdd_ctx, uint8_t vdev_id,
5046 struct sk_buff *skb, struct nlattr **tb)
5047{
5048 QDF_STATUS status = QDF_STATUS_SUCCESS;
5049 uint8_t roam_control;
5050 struct nlattr *config;
Srinivas Dasaria33fdd82019-08-21 16:15:22 +05305051 uint32_t full_roam_scan_period;
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305052
5053 config = nla_nest_start(skb, PARAM_ROAM_CONTROL_CONFIG);
sheenam monga65415d12020-02-07 14:39:15 +05305054 if (!config) {
5055 hdd_err("nla nest start failure");
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305056 return -EINVAL;
sheenam monga65415d12020-02-07 14:39:15 +05305057 }
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305058
5059 if (tb[QCA_ATTR_ROAM_CONTROL_STATUS]) {
5060 status = sme_get_roam_config_status(hdd_ctx->mac_handle,
5061 vdev_id,
5062 &roam_control);
5063 if (QDF_IS_STATUS_ERROR(status))
5064 goto out;
5065 hdd_debug("Roam control: %s",
5066 roam_control ? "Enabled" : "Disabled");
5067 if (nla_put_u8(skb, QCA_ATTR_ROAM_CONTROL_STATUS,
5068 roam_control)) {
5069 hdd_info("failed to put vendor_roam_control");
5070 return -ENOMEM;
5071 }
5072 }
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305073
Srinivas Dasaria33fdd82019-08-21 16:15:22 +05305074 if (tb[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD]) {
5075 status = sme_get_full_roam_scan_period(hdd_ctx->mac_handle,
5076 vdev_id,
5077 &full_roam_scan_period);
5078 if (QDF_IS_STATUS_ERROR(status))
5079 goto out;
5080 hdd_debug("full_roam_scan_period: %u", full_roam_scan_period);
5081
5082 if (nla_put_u32(skb, QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD,
5083 full_roam_scan_period)) {
5084 hdd_info("failed to put full_roam_scan_period");
5085 return -EINVAL;
5086 }
5087 }
5088
5089 nla_nest_end(skb, config);
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305090out:
5091 return qdf_status_to_os_return(status);
5092}
5093
5094/**
5095 * hdd_send_roam_control_config() - Send the roam config as vendor cmd reply
5096 * @mac_handle: Opaque handle to the MAC context
5097 * @vdev_id: vdev id
5098 * @tb: List of attributes
5099 *
5100 * Parse the attributes list tb and get the data corresponding to the
5101 * attributes specified in tb. Send them as a vendor response.
5102 *
5103 * Return: 0 on success; error number on failure
5104 */
5105static int
5106hdd_send_roam_control_config(struct hdd_context *hdd_ctx,
5107 uint8_t vdev_id,
5108 struct nlattr **tb)
5109{
5110 struct sk_buff *skb;
5111 uint16_t skb_len;
5112 int status;
5113
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305114 skb_len = hdd_roam_control_config_buf_size(hdd_ctx, tb);
5115 if (!skb_len) {
5116 hdd_err("No data requested");
5117 return -EINVAL;
5118 }
5119
5120 skb_len += NLMSG_HDRLEN;
5121 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, skb_len);
5122 if (!skb) {
5123 hdd_info("cfg80211_vendor_cmd_alloc_reply_skb failed");
5124 return -ENOMEM;
5125 }
5126
5127 status = hdd_roam_control_config_fill_data(hdd_ctx, vdev_id, skb, tb);
5128 if (status)
5129 goto fail;
5130
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305131 return cfg80211_vendor_cmd_reply(skb);
5132
5133fail:
5134 hdd_err("nla put fail");
5135 kfree_skb(skb);
5136 return status;
5137}
5138
5139/**
5140 * hdd_get_roam_control_config() - Send requested roam config to userspace
5141 * @hdd_ctx: HDD context
5142 * @tb: list of attributes
5143 * @vdev_id: vdev id
5144 *
5145 * Return: 0 on success; error number on failure
5146 */
5147static int hdd_get_roam_control_config(struct hdd_context *hdd_ctx,
5148 struct nlattr **tb,
5149 uint8_t vdev_id)
5150{
5151 QDF_STATUS status;
5152 struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1];
5153
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305154 /* The command must carry PARAM_ROAM_CONTROL_CONFIG */
5155 if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
5156 hdd_err("Attribute CONTROL_CONFIG is not present");
5157 return -EINVAL;
5158 }
5159
5160 if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
5161 tb[PARAM_ROAM_CONTROL_CONFIG],
5162 roam_control_policy)) {
5163 hdd_err("nla_parse failed");
5164 return -EINVAL;
5165 }
5166
5167 status = hdd_send_roam_control_config(hdd_ctx, vdev_id, tb2);
5168 if (status) {
5169 hdd_err("failed to enable/disable roam control");
5170 return status;
5171 }
5172
5173 return qdf_status_to_os_return(status);
5174}
5175
Srinivas Dasari25d77b22019-08-07 16:21:48 +05305176#undef PARAM_ROAM_CONTROL_CONFIG
5177#undef PARAM_FREQ_LIST_SCHEME_MAX
5178#undef PARAM_FREQ_LIST_SCHEME
5179#undef PARAM_SCAN_FREQ_LIST
5180#undef PARAM_SCAN_FREQ_LIST_TYPE
Srinivas Dasari5fb81902019-08-22 01:39:42 +05305181#undef PARAM_CAND_SEL_CRITERIA_MAX
5182#undef PARAM_CAND_SEL_SCORE_RSSI
Srinivas Dasari25d77b22019-08-07 16:21:48 +05305183
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005184/**
5185 * hdd_set_ext_roam_params() - parse ext roam params
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005186 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005187 * @roam_params: roam params
5188 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005189 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005190 *
5191 * Return: 0 on success; error number on failure
5192 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005193static int hdd_set_ext_roam_params(struct hdd_context *hdd_ctx,
5194 const void *data, int data_len,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005195 uint8_t vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005196 struct roam_ext_params *roam_params)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005197{
5198 uint32_t cmd_type, req_id;
5199 struct nlattr *tb[MAX_ROAMING_PARAM + 1];
5200 int ret;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005201 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005202
Dustin Brown4ea21db2018-01-05 14:13:17 -08005203 if (wlan_cfg80211_nla_parse(tb, MAX_ROAMING_PARAM, data, data_len,
5204 wlan_hdd_set_roam_param_policy)) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005205 hdd_err("Invalid ATTR");
5206 return -EINVAL;
5207 }
5208 /* Parse and fetch Command Type */
5209 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
5210 hdd_err("roam cmd type failed");
5211 goto fail;
5212 }
5213
5214 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
5215 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
5216 hdd_err("attr request id failed");
5217 goto fail;
5218 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005219 mac_handle = hdd_ctx->mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005220 req_id = nla_get_u32(
5221 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
5222 hdd_debug("Req Id: %u Cmd Type: %u", req_id, cmd_type);
5223 switch (cmd_type) {
Srinivas Dasari0cc64372019-08-13 12:04:20 +05305224 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST:
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005225 ret = hdd_set_white_list(hdd_ctx, roam_params, tb, vdev_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005226 if (ret)
5227 goto fail;
5228 break;
5229
Srinivas Dasari0cc64372019-08-13 12:04:20 +05305230 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005231 /* Parse and fetch 5G Boost Threshold */
5232 if (!tb[PARAM_A_BAND_BOOST_THLD]) {
5233 hdd_err("5G boost threshold failed");
5234 goto fail;
5235 }
5236 roam_params->raise_rssi_thresh_5g = nla_get_s32(
5237 tb[PARAM_A_BAND_BOOST_THLD]);
5238 hdd_debug("5G Boost Threshold (%d)",
5239 roam_params->raise_rssi_thresh_5g);
5240 /* Parse and fetch 5G Penalty Threshold */
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07005241 if (!tb[PARAM_A_BAND_PELT_THLD]) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005242 hdd_err("5G penalty threshold failed");
5243 goto fail;
5244 }
5245 roam_params->drop_rssi_thresh_5g = nla_get_s32(
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07005246 tb[PARAM_A_BAND_PELT_THLD]);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005247 hdd_debug("5G Penalty Threshold (%d)",
5248 roam_params->drop_rssi_thresh_5g);
5249 /* Parse and fetch 5G Boost Factor */
5250 if (!tb[PARAM_A_BAND_BOOST_FACTOR]) {
5251 hdd_err("5G boost Factor failed");
5252 goto fail;
5253 }
5254 roam_params->raise_factor_5g = nla_get_u32(
5255 tb[PARAM_A_BAND_BOOST_FACTOR]);
5256 hdd_debug("5G Boost Factor (%d)",
5257 roam_params->raise_factor_5g);
5258 /* Parse and fetch 5G Penalty factor */
5259 if (!tb[PARAM_A_BAND_PELT_FACTOR]) {
5260 hdd_err("5G Penalty Factor failed");
5261 goto fail;
5262 }
5263 roam_params->drop_factor_5g = nla_get_u32(
5264 tb[PARAM_A_BAND_PELT_FACTOR]);
5265 hdd_debug("5G Penalty factor (%d)",
5266 roam_params->drop_factor_5g);
5267 /* Parse and fetch 5G Max Boost */
5268 if (!tb[PARAM_A_BAND_MAX_BOOST]) {
5269 hdd_err("5G Max Boost failed");
5270 goto fail;
5271 }
5272 roam_params->max_raise_rssi_5g = nla_get_u32(
5273 tb[PARAM_A_BAND_MAX_BOOST]);
5274 hdd_debug("5G Max Boost (%d)",
5275 roam_params->max_raise_rssi_5g);
5276 /* Parse and fetch Rssi Diff */
5277 if (!tb[PARAM_ROAM_HISTERESYS]) {
5278 hdd_err("Rssi Diff failed");
5279 goto fail;
5280 }
5281 roam_params->rssi_diff = nla_get_s32(
5282 tb[PARAM_ROAM_HISTERESYS]);
5283 hdd_debug("RSSI Diff (%d)",
5284 roam_params->rssi_diff);
5285 /* Parse and fetch Alert Rssi Threshold */
5286 if (!tb[PARAM_RSSI_TRIGGER]) {
5287 hdd_err("Alert Rssi Threshold failed");
5288 goto fail;
5289 }
5290 roam_params->alert_rssi_threshold = nla_get_u32(
5291 tb[PARAM_RSSI_TRIGGER]);
5292 hdd_debug("Alert RSSI Threshold (%d)",
5293 roam_params->alert_rssi_threshold);
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005294 sme_update_roam_params(mac_handle, vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005295 roam_params,
5296 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005297 break;
Srinivas Dasari0cc64372019-08-13 12:04:20 +05305298 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_LAZY_ROAM:
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005299 /* Parse and fetch Activate Good Rssi Roam */
5300 if (!tb[PARAM_ROAM_ENABLE]) {
5301 hdd_err("Activate Good Rssi Roam failed");
5302 goto fail;
5303 }
5304 roam_params->good_rssi_roam = nla_get_s32(
5305 tb[PARAM_ROAM_ENABLE]);
5306 hdd_debug("Activate Good Rssi Roam (%d)",
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005307 roam_params->good_rssi_roam);
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005308 sme_update_roam_params(mac_handle, vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005309 roam_params,
5310 REASON_ROAM_GOOD_RSSI_CHANGED);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005311 break;
Srinivas Dasari0cc64372019-08-13 12:04:20 +05305312 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PREFS:
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005313 ret = hdd_set_bssid_prefs(hdd_ctx, roam_params, tb, vdev_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005314 if (ret)
5315 goto fail;
5316 break;
Srinivas Dasari0cc64372019-08-13 12:04:20 +05305317 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID:
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005318 ret = hdd_set_blacklist_bssid(hdd_ctx, roam_params,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005319 tb, vdev_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005320 if (ret)
5321 goto fail;
5322 break;
Srinivas Dasari25d77b22019-08-07 16:21:48 +05305323 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET:
5324 ret = hdd_set_roam_with_control_config(hdd_ctx, tb, vdev_id);
5325 if (ret)
5326 goto fail;
5327 break;
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05305328 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR:
5329 ret = hdd_clear_roam_control_config(hdd_ctx, tb, vdev_id);
5330 if (ret)
5331 goto fail;
5332 break;
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305333 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET:
5334 ret = hdd_get_roam_control_config(hdd_ctx, tb, vdev_id);
5335 if (ret)
5336 goto fail;
5337 break;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005338 }
5339
5340 return 0;
5341
5342fail:
5343 return -EINVAL;
5344}
5345
5346/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005347 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
5348 * @wiphy: The wiphy structure
5349 * @wdev: The wireless device
5350 * @data: Data passed by framework
5351 * @data_len: Parameters to be configured passed as data
5352 *
5353 * The roaming related parameters are configured by the framework
5354 * using this interface.
5355 *
5356 * Return: Return either success or failure code.
5357 */
5358static int
5359__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
5360 struct wireless_dev *wdev, const void *data, int data_len)
5361{
5362 struct net_device *dev = wdev->netdev;
Jeff Johnsonce2ba702017-10-02 13:30:24 -07005363 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -07005364 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005365 struct roam_ext_params *roam_params = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005366 int ret;
5367
Anurag Chouhan6d760662016-02-20 16:05:43 +05305368 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005369 hdd_err("Command not allowed in FTM mode");
5370 return -EPERM;
5371 }
5372
Jeff Johnsonb8944722017-09-03 09:03:19 -07005373 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305374 if (ret)
5375 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376
Jeff Johnsonb8944722017-09-03 09:03:19 -07005377 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05305378 hdd_err("Driver Modules are closed");
5379 return -EINVAL;
5380 }
5381
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005382 roam_params = qdf_mem_malloc(sizeof(*roam_params));
Min Liu74a1a502018-10-10 19:59:07 +08005383 if (!roam_params)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005384 return -ENOMEM;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005385
Jeff Johnsonb8944722017-09-03 09:03:19 -07005386 ret = hdd_set_ext_roam_params(hdd_ctx, data, data_len,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005387 adapter->vdev_id, roam_params);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005388 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005389 goto fail;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05305390
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005391 if (roam_params)
5392 qdf_mem_free(roam_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005393 return 0;
5394fail:
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005395 if (roam_params)
5396 qdf_mem_free(roam_params);
5397
5398 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005399}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05305400#undef PARAM_NUM_NW
5401#undef PARAM_SET_BSSID
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05305402#undef PARAM_SET_BSSID_HINT
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005403#undef PARAM_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05305404#undef PARAM_LIST_SSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005405#undef MAX_ROAMING_PARAM
5406#undef PARAM_NUM_BSSID
5407#undef PARAM_BSSID_PREFS
5408#undef PARAM_ROAM_BSSID
5409#undef PARAM_RSSI_MODIFIER
5410#undef PARAMS_NUM_BSSID
5411#undef PARAM_BSSID_PARAMS
5412#undef PARAM_A_BAND_BOOST_THLD
5413#undef PARAM_A_BAND_PELT_THLD
5414#undef PARAM_A_BAND_BOOST_FACTOR
5415#undef PARAM_A_BAND_PELT_FACTOR
5416#undef PARAM_A_BAND_MAX_BOOST
5417#undef PARAM_ROAM_HISTERESYS
5418#undef PARAM_RSSI_TRIGGER
5419#undef PARAM_ROAM_ENABLE
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05305420
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421
5422/**
5423 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
5424 * @wiphy: pointer to wireless wiphy structure.
5425 * @wdev: pointer to wireless_dev structure.
5426 * @data: Pointer to the data to be passed via vendor interface
5427 * @data_len:Length of the data to be passed
5428 *
5429 * Return: Return the Success or Failure code.
5430 */
5431static int
5432wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
5433 struct wireless_dev *wdev,
5434 const void *data,
5435 int data_len)
5436{
Dustin Browna09acf42018-11-08 12:32:26 +05305437 int errno;
5438 struct osif_vdev_sync *vdev_sync;
5439
5440 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
5441 if (errno)
5442 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443
Dustin Browna09acf42018-11-08 12:32:26 +05305444 errno = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005445 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446
Dustin Browna09acf42018-11-08 12:32:26 +05305447 osif_vdev_sync_op_stop(vdev_sync);
5448
5449 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005450}
5451
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305452#define PWR_SAVE_FAIL_CMD_INDEX \
5453 QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX
Jeff Johnsonb7fa2562018-07-02 08:36:17 -07005454
5455void hdd_chip_pwr_save_fail_detected_cb(hdd_handle_t hdd_handle,
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305456 struct chip_pwr_save_fail_detected_params
5457 *data)
5458{
Jeff Johnsonb7fa2562018-07-02 08:36:17 -07005459 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305460 struct sk_buff *skb;
5461 int flags = cds_get_gfp_flags();
5462
Dustin Brown491d54b2018-03-14 12:39:11 -07005463 hdd_enter();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305464
5465 if (wlan_hdd_validate_context(hdd_ctx))
5466 return;
5467
5468 if (!data) {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07005469 hdd_debug("data is null");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305470 return;
5471 }
5472
5473 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5474 NULL, NLMSG_HDRLEN +
5475 sizeof(data->failure_reason_code) +
5476 NLMSG_HDRLEN, PWR_SAVE_FAIL_CMD_INDEX,
5477 flags);
5478
5479 if (!skb) {
Dustin Brown5e89ef82018-03-14 11:50:23 -07005480 hdd_info("cfg80211_vendor_event_alloc failed");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305481 return;
5482 }
5483
Dustin Brownbacc48f2018-03-14 14:48:44 -07005484 hdd_debug("failure reason code: %u", data->failure_reason_code);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305485
5486 if (nla_put_u32(skb,
5487 QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON,
5488 data->failure_reason_code))
5489 goto fail;
5490
5491 cfg80211_vendor_event(skb, flags);
Dustin Browne74003f2018-03-14 12:51:58 -07005492 hdd_exit();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305493 return;
5494
5495fail:
5496 kfree_skb(skb);
5497}
5498#undef PWR_SAVE_FAIL_CMD_INDEX
5499
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005500static const struct nla_policy
5501wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
5502 +1] = {
5503 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
5504};
5505
5506/**
5507 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
5508 * @hdd_ctx: HDD context
5509 * @device_mode: device mode
5510 * Return: bool
5511 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005512static bool wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context *hdd_ctx,
Jeff Johnsonc1e62782017-11-09 09:50:17 -08005513 enum QDF_OPMODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005514{
Jeff Johnsone5006672017-08-29 14:39:02 -07005515 struct hdd_adapter *adapter;
Jeff Johnson87251032017-08-29 13:31:11 -07005516 struct hdd_ap_ctx *ap_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07005517 struct hdd_station_ctx *sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005518
Dustin Brown920397d2017-12-13 16:27:50 -08005519 hdd_for_each_adapter(hdd_ctx, adapter) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005520 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08005521 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005522 ap_ctx =
5523 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005524 /*
5525 * if there is SAP already running on DFS channel,
5526 * do not disable scan on dfs channels. Note that
5527 * with SAP on DFS, there cannot be conurrency on
5528 * single radio. But then we can have multiple
5529 * radios !!
5530 */
Will Huang4b097f52019-08-29 10:51:56 -07005531 if (CHANNEL_STATE_DFS ==
5532 wlan_reg_get_channel_state_for_freq(
5533 hdd_ctx->pdev,
5534 ap_ctx->operating_chan_freq)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005535 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005536 return true;
5537 }
5538 }
5539
5540 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08005541 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005542 sta_ctx =
5543 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005544 /*
5545 * if STA is already connected on DFS channel,
5546 * do not disable scan on dfs channels
5547 */
5548 if (hdd_conn_is_connected(sta_ctx) &&
Will Huang4b097f52019-08-29 10:51:56 -07005549 (CHANNEL_STATE_DFS ==
5550 wlan_reg_get_channel_state_for_freq(
5551 hdd_ctx->pdev,
5552 sta_ctx->conn_info.chan_freq))) {
Jeff Johnson020db452016-06-29 14:37:26 -07005553 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005554 return true;
5555 }
5556 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005557 }
5558
5559 return false;
5560}
5561
5562/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005563 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005564 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005565 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005566 *
5567 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005568 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005569 * Fails the disable request if any device is active on a DFS channel.
5570 *
5571 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005572 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005573
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005574int wlan_hdd_enable_dfs_chan_scan(struct hdd_context *hdd_ctx,
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005575 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005576{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305577 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005578 bool err;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005579 mac_handle_t mac_handle;
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305580 bool enable_dfs_scan = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005581
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305582 ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
5583 &enable_dfs_scan);
5584
5585 if (enable_dfs_channels == enable_dfs_scan) {
Dustin Brown6a8d39b2018-08-14 15:27:26 -07005586 hdd_debug("DFS channels are already %s",
5587 enable_dfs_channels ? "enabled" : "disabled");
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005588 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005589 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005590
5591 if (!enable_dfs_channels) {
5592 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
5593 QDF_STA_MODE);
5594 if (err)
5595 return -EOPNOTSUPP;
5596
5597 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
5598 QDF_SAP_MODE);
5599 if (err)
5600 return -EOPNOTSUPP;
5601 }
5602
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305603 ucfg_scan_cfg_set_dfs_chan_scan_allowed(hdd_ctx->psoc,
5604 enable_dfs_channels);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005605
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005606 mac_handle = hdd_ctx->mac_handle;
5607 status = sme_enable_dfs_chan_scan(mac_handle, enable_dfs_channels);
Min Liu5eaf7242018-03-13 17:32:15 +08005608 if (QDF_IS_STATUS_ERROR(status)) {
5609 hdd_err("Failed to set DFS channel scan flag to %d",
5610 enable_dfs_channels);
5611 return qdf_status_to_os_return(status);
5612 }
5613
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005614 hdd_abort_mac_scan_all_adapters(hdd_ctx);
5615
5616 /* pass dfs channel status to regulatory component */
Dustin Brown07901ec2018-09-07 11:02:41 -07005617 status = ucfg_reg_enable_dfs_channels(hdd_ctx->pdev,
5618 enable_dfs_channels);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005619
5620 if (QDF_IS_STATUS_ERROR(status))
5621 hdd_err("Failed to %s DFS channels",
5622 enable_dfs_channels ? "enable" : "disable");
5623
5624 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005625}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005626
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005627/**
5628 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
5629 * @wiphy: corestack handler
5630 * @wdev: wireless device
5631 * @data: data
5632 * @data_len: data length
5633 * Return: success(0) or reason code for failure
5634 */
5635static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
5636 struct wireless_dev *wdev,
5637 const void *data,
5638 int data_len)
5639{
5640 struct net_device *dev = wdev->netdev;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005641 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005642 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
5643 int ret_val;
5644 uint32_t no_dfs_flag = 0;
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305645 bool enable_dfs_scan = true;
Dustin Brownfdf17c12018-03-14 12:55:34 -07005646 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005647
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005648 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305649 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005650 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005651
Dustin Brown4ea21db2018-01-05 14:13:17 -08005652 if (wlan_cfg80211_nla_parse(tb,
5653 QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
5654 data, data_len,
5655 wlan_hdd_set_no_dfs_flag_config_policy)) {
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005656 hdd_err("invalid attr");
5657 return -EINVAL;
5658 }
5659
5660 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
5661 hdd_err("attr dfs flag failed");
5662 return -EINVAL;
5663 }
5664
5665 no_dfs_flag = nla_get_u32(
5666 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
5667
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005668 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005669
5670 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07005671 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005672 return -EINVAL;
5673 }
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305674 ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
5675 &enable_dfs_scan);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005676
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305677 if (enable_dfs_scan) {
bings50112bb2018-12-21 15:51:51 +08005678 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
5679 } else {
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305680 if ((!no_dfs_flag) != enable_dfs_scan) {
bings50112bb2018-12-21 15:51:51 +08005681 hdd_err("DFS chan ini configured %d, no dfs flag: %d",
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305682 enable_dfs_scan,
bings50112bb2018-12-21 15:51:51 +08005683 no_dfs_flag);
5684 return -EINVAL;
5685 }
5686 }
5687
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005688 return ret_val;
5689}
5690
5691/**
5692 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
5693 *
5694 * @wiphy: wiphy device pointer
5695 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07005696 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005697 * @data_len: Buffer length
5698 *
5699 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
5700 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
5701 *
5702 * Return: EOK or other error codes.
5703 */
5704
5705static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
5706 struct wireless_dev *wdev,
5707 const void *data,
5708 int data_len)
5709{
Dustin Brown363b4792019-02-05 16:11:55 -08005710 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08005711 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05305712
Dustin Brown363b4792019-02-05 16:11:55 -08005713 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08005714 if (errno)
5715 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005716
Dustin Brownf0f00612019-01-31 16:02:24 -08005717 errno = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
5718 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005719
Dustin Brown363b4792019-02-05 16:11:55 -08005720 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05305721
Dustin Brownf0f00612019-01-31 16:02:24 -08005722 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005723}
5724
Manikandan Mohan80dea792016-04-28 16:36:48 -07005725static const struct nla_policy
5726wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
5727 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
5728};
5729
5730/**
5731 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
5732 * @wiphy: wiphy device pointer
5733 * @wdev: wireless device pointer
5734 * @data: Vendor command data buffer
5735 * @data_len: Buffer length
5736 *
5737 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
5738 * setup WISA Mode features.
5739 *
5740 * Return: Success(0) or reason code for failure
5741 */
5742static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
5743 struct wireless_dev *wdev, const void *data, int data_len)
5744{
5745 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07005746 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005747 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005748 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
5749 struct sir_wisa_params wisa;
5750 int ret_val;
5751 QDF_STATUS status;
5752 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07005753 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005754 mac_handle_t mac_handle;
Manikandan Mohan80dea792016-04-28 16:36:48 -07005755
Dustin Brownfdf17c12018-03-14 12:55:34 -07005756 hdd_enter_dev(dev);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005757 ret_val = wlan_hdd_validate_context(hdd_ctx);
5758 if (ret_val)
5759 goto err;
5760
5761 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5762 hdd_err("Command not allowed in FTM mode");
5763 return -EPERM;
5764 }
5765
Dustin Brown4ea21db2018-01-05 14:13:17 -08005766 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data,
5767 data_len, wlan_hdd_wisa_cmd_policy)) {
Manikandan Mohan80dea792016-04-28 16:36:48 -07005768 hdd_err("Invalid WISA cmd attributes");
5769 ret_val = -EINVAL;
5770 goto err;
5771 }
5772 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
5773 hdd_err("Invalid WISA mode");
5774 ret_val = -EINVAL;
5775 goto err;
5776 }
5777
5778 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005779 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005780 wisa.mode = wisa_mode;
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005781 wisa.vdev_id = adapter->vdev_id;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005782 mac_handle = hdd_ctx->mac_handle;
5783 status = sme_set_wisa_params(mac_handle, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07005784 if (!QDF_IS_STATUS_SUCCESS(status)) {
5785 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005786 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07005787 }
Rakesh Pillai6a36b0a2019-09-06 16:30:05 +05305788 if (QDF_IS_STATUS_SUCCESS(status) || !wisa_mode)
5789 cdp_set_wisa_mode(soc, adapter->vdev_id, wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005790err:
Dustin Browne74003f2018-03-14 12:51:58 -07005791 hdd_exit();
Manikandan Mohan80dea792016-04-28 16:36:48 -07005792 return ret_val;
5793}
5794
5795/**
5796 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
5797 * @wiphy: corestack handler
5798 * @wdev: wireless device
5799 * @data: data
5800 * @data_len: data length
5801 *
5802 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
5803 * setup WISA mode features.
5804 *
5805 * Return: Success(0) or reason code for failure
5806 */
5807static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
5808 struct wireless_dev *wdev,
5809 const void *data,
5810 int data_len)
5811{
Dustin Browna09acf42018-11-08 12:32:26 +05305812 int errno;
5813 struct osif_vdev_sync *vdev_sync;
5814
5815 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
5816 if (errno)
5817 return errno;
Manikandan Mohan80dea792016-04-28 16:36:48 -07005818
Dustin Browna09acf42018-11-08 12:32:26 +05305819 errno = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev,
5820 data, data_len);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005821
Dustin Browna09acf42018-11-08 12:32:26 +05305822 osif_vdev_sync_op_stop(vdev_sync);
5823
5824 return errno;
Manikandan Mohan80dea792016-04-28 16:36:48 -07005825}
5826
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05305827struct hdd_station_info *hdd_get_stainfo(struct hdd_station_info *astainfo,
5828 struct qdf_mac_addr mac_addr)
Will Huang496b36c2017-07-11 16:38:50 +08005829{
Jeff Johnson82155922017-09-30 16:54:14 -07005830 struct hdd_station_info *stainfo = NULL;
Will Huang496b36c2017-07-11 16:38:50 +08005831 int i;
5832
5833 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05305834 if (!qdf_mem_cmp(&astainfo[i].sta_mac,
Will Huang496b36c2017-07-11 16:38:50 +08005835 &mac_addr,
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05305836 QDF_MAC_ADDR_SIZE)) {
5837 stainfo = &astainfo[i];
5838 break;
5839 }
Will Huang496b36c2017-07-11 16:38:50 +08005840 }
5841
5842 return stainfo;
5843}
5844
Anurag Chouhan96919482016-07-13 16:36:57 +05305845/*
5846 * undef short names defined for get station command
5847 * used by __wlan_hdd_cfg80211_get_station_cmd()
5848 */
5849#undef STATION_INVALID
5850#undef STATION_INFO
5851#undef STATION_ASSOC_FAIL_REASON
Will Huang496b36c2017-07-11 16:38:50 +08005852#undef STATION_REMOTE
Anurag Chouhan96919482016-07-13 16:36:57 +05305853#undef STATION_MAX
Will Huang496b36c2017-07-11 16:38:50 +08005854#undef LINK_INFO_STANDARD_NL80211_ATTR
5855#undef AP_INFO_STANDARD_NL80211_ATTR
5856#undef INFO_ROAM_COUNT
5857#undef INFO_AKM
5858#undef WLAN802_11_MODE
5859#undef AP_INFO_HS20_INDICATION
5860#undef HT_OPERATION
5861#undef VHT_OPERATION
5862#undef INFO_ASSOC_FAIL_REASON
5863#undef REMOTE_MAX_PHY_RATE
5864#undef REMOTE_TX_PACKETS
5865#undef REMOTE_TX_BYTES
5866#undef REMOTE_RX_PACKETS
5867#undef REMOTE_RX_BYTES
5868#undef REMOTE_LAST_TX_RATE
5869#undef REMOTE_LAST_RX_RATE
5870#undef REMOTE_WMM
5871#undef REMOTE_SUPPORTED_MODE
5872#undef REMOTE_AMPDU
5873#undef REMOTE_TX_STBC
5874#undef REMOTE_RX_STBC
5875#undef REMOTE_CH_WIDTH
5876#undef REMOTE_SGI_ENABLE
5877#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
5878#undef REMOTE_PAD
5879#endif
Anurag Chouhan96919482016-07-13 16:36:57 +05305880
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005881#ifdef WLAN_FEATURE_ROAM_OFFLOAD
sheenam monga6e49e5c2019-04-04 12:49:04 +05305882
5883/**
5884 * hdd_get_roam_reason() - convert wmi roam reason to
5885 * enum qca_roam_reason
5886 * @roam_scan_trigger: wmi roam scan trigger ID
5887 *
5888 * Return: Meaningful qca_roam_reason from enum WMI_ROAM_TRIGGER_REASON_ID
5889 */
5890static enum qca_roam_reason hdd_get_roam_reason(uint16_t roam_scan_trigger)
5891{
5892 switch (roam_scan_trigger) {
5893 case WMI_ROAM_TRIGGER_REASON_PER:
5894 return QCA_ROAM_REASON_PER;
5895 case WMI_ROAM_TRIGGER_REASON_BMISS:
5896 return QCA_ROAM_REASON_BEACON_MISS;
5897 case WMI_ROAM_TRIGGER_REASON_LOW_RSSI:
5898 case WMI_ROAM_TRIGGER_REASON_BACKGROUND:
5899 return QCA_ROAM_REASON_POOR_RSSI;
5900 case WMI_ROAM_TRIGGER_REASON_HIGH_RSSI:
5901 return QCA_ROAM_REASON_BETTER_RSSI;
5902 case WMI_ROAM_TRIGGER_REASON_DENSE:
5903 return QCA_ROAM_REASON_CONGESTION;
5904 case WMI_ROAM_TRIGGER_REASON_FORCED:
5905 return QCA_ROAM_REASON_USER_TRIGGER;
5906 case WMI_ROAM_TRIGGER_REASON_BTM:
5907 return QCA_ROAM_REASON_BTM;
5908 case WMI_ROAM_TRIGGER_REASON_BSS_LOAD:
5909 return QCA_ROAM_REASON_BSS_LOAD;
5910 default:
5911 return QCA_ROAM_REASON_UNKNOWN;
5912 }
5913
5914 return QCA_ROAM_REASON_UNKNOWN;
5915}
5916
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005917/**
5918 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
5919 * @wiphy: pointer to wireless wiphy structure.
5920 * @wdev: pointer to wireless_dev structure.
5921 * @data: Pointer to the Key data
5922 * @data_len:Length of the data passed
5923 *
5924 * This is called when wlan driver needs to save the keys received via
5925 * vendor specific command.
5926 *
5927 * Return: Return the Success or Failure code.
5928 */
5929static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
5930 struct wireless_dev *wdev,
5931 const void *data, int data_len)
5932{
5933 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
5934 struct net_device *dev = wdev->netdev;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005935 struct hdd_adapter *hdd_adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5936 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005937 int status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005938 struct pmkid_mode_bits pmkid_modes;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005939 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005940
Dustin Brownfdf17c12018-03-14 12:55:34 -07005941 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005942
Anurag Chouhan6d760662016-02-20 16:05:43 +05305943 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005944 hdd_err("Command not allowed in FTM mode");
5945 return -EPERM;
5946 }
5947
Jeff Johnsond36fa332019-03-18 13:42:25 -07005948 if ((!data) || (data_len <= 0) ||
Hanumanth Reddy Pothula53874852018-03-08 19:57:49 +05305949 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005950 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005951 return -EINVAL;
5952 }
5953
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005954 hdd_ctx = WLAN_HDD_GET_CTX(hdd_adapter);
5955 if (!hdd_ctx) {
Jeff Johnson020db452016-06-29 14:37:26 -07005956 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005957 return -EINVAL;
5958 }
5959
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005960 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305961 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005962 return status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005963
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005964 hdd_get_pmkid_modes(hdd_ctx, &pmkid_modes);
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005965
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005966 mac_handle = hdd_ctx->mac_handle;
5967 sme_update_roam_key_mgmt_offload_enabled(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005968 hdd_adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005969 true, &pmkid_modes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305970 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
5971 qdf_mem_copy(local_pmk, data, data_len);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005972 sme_roam_set_psk_pmk(mac_handle, hdd_adapter->vdev_id,
Pragaspathi Thilagaraj400a7832020-04-09 01:05:32 +05305973 local_pmk, data_len, true);
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +05305974 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005975 return 0;
5976}
5977
5978/**
5979 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
5980 * @wiphy: pointer to wireless wiphy structure.
5981 * @wdev: pointer to wireless_dev structure.
5982 * @data: Pointer to the Key data
5983 * @data_len:Length of the data passed
5984 *
5985 * This is called when wlan driver needs to save the keys received via
5986 * vendor specific command.
5987 *
5988 * Return: Return the Success or Failure code.
5989 */
5990static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
5991 struct wireless_dev *wdev,
5992 const void *data, int data_len)
5993{
Dustin Browna09acf42018-11-08 12:32:26 +05305994 int errno;
5995 struct osif_vdev_sync *vdev_sync;
5996
5997 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
5998 if (errno)
5999 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006000
Dustin Browna09acf42018-11-08 12:32:26 +05306001 errno = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev,
6002 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006003
Dustin Browna09acf42018-11-08 12:32:26 +05306004 osif_vdev_sync_op_stop(vdev_sync);
6005
6006 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006007}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08006008#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006009
6010static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
6011 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
6012 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
6013 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07006014 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006015};
6016
6017/**
6018 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
6019 * @wiphy: pointer to wireless wiphy structure.
6020 * @wdev: pointer to wireless_dev structure.
6021 * @data: Pointer to the data to be passed via vendor interface
6022 * @data_len:Length of the data to be passed
6023 *
6024 * This is called when wlan driver needs to send wifi driver related info
6025 * (driver/fw version) to the user space application upon request.
6026 *
6027 * Return: Return the Success or Failure code.
6028 */
6029static int
6030__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
6031 struct wireless_dev *wdev,
6032 const void *data, int data_len)
6033{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006034 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006035 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07006036 tSirVersionString driver_version;
6037 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006038 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07006039 struct sk_buff *reply_skb;
6040 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006041
Dustin Brownfdf17c12018-03-14 12:55:34 -07006042 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08006043
Anurag Chouhan6d760662016-02-20 16:05:43 +05306044 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006045 hdd_err("Command not allowed in FTM mode");
6046 return -EPERM;
6047 }
6048
6049 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05306050 if (status)
6051 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006052
Dustin Brown4ea21db2018-01-05 14:13:17 -08006053 if (wlan_cfg80211_nla_parse(tb_vendor,
6054 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
6055 data, data_len,
6056 qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07006057 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006058 return -EINVAL;
6059 }
6060
6061 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08006062 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07006063 strlcpy(driver_version, QWLAN_VERSIONSTR,
6064 sizeof(driver_version));
6065 skb_len += strlen(driver_version) + 1;
6066 count++;
6067 }
6068
6069 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006070 hdd_debug("Rcvd req for FW version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07006071 snprintf(firmware_version, sizeof(firmware_version),
Ashish Kumar Dhanotiyaeadb28b2019-06-28 14:34:19 +05306072 "FW:%d.%d.%d.%d.%d.%d HW:%s",
6073 hdd_ctx->fw_version_info.major_spid,
6074 hdd_ctx->fw_version_info.minor_spid,
6075 hdd_ctx->fw_version_info.siid,
6076 hdd_ctx->fw_version_info.rel_id,
6077 hdd_ctx->fw_version_info.crmid,
6078 hdd_ctx->fw_version_info.sub_id,
6079 hdd_ctx->target_hw_name);
Ryan Hsu7ac88852016-04-28 10:20:34 -07006080 skb_len += strlen(firmware_version) + 1;
6081 count++;
6082 }
6083
Rajeev Kumar Sirasanagandla551613d2018-05-16 17:21:01 +05306084 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
6085 hdd_debug("Rcvd req for Radio index");
6086 skb_len += sizeof(uint32_t);
6087 count++;
6088 }
6089
Ryan Hsu7ac88852016-04-28 10:20:34 -07006090 if (count == 0) {
6091 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006092 return -EINVAL;
6093 }
6094
Ryan Hsu7ac88852016-04-28 10:20:34 -07006095 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
6096 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
6097
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006098 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07006099 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006100 return -ENOMEM;
6101 }
6102
Ryan Hsu7ac88852016-04-28 10:20:34 -07006103 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
6104 if (nla_put_string(reply_skb,
6105 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
6106 driver_version))
6107 goto error_nla_fail;
6108 }
6109
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05306110 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07006111 if (nla_put_string(reply_skb,
6112 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
6113 firmware_version))
6114 goto error_nla_fail;
6115 }
6116
6117 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
6118 if (nla_put_u32(reply_skb,
6119 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
6120 hdd_ctx->radio_index))
6121 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006122 }
6123
6124 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07006125
6126error_nla_fail:
6127 hdd_err("nla put fail");
6128 kfree_skb(reply_skb);
6129 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006130}
6131
6132/**
6133 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
6134 * @wiphy: pointer to wireless wiphy structure.
6135 * @wdev: pointer to wireless_dev structure.
6136 * @data: Pointer to the data to be passed via vendor interface
6137 * @data_len:Length of the data to be passed
6138 *
6139 * This is called when wlan driver needs to send wifi driver related info
6140 * (driver/fw version) to the user space application upon request.
6141 *
6142 * Return: Return the Success or Failure code.
6143 */
6144static int
6145wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
6146 struct wireless_dev *wdev,
6147 const void *data, int data_len)
6148{
Dustin Brown363b4792019-02-05 16:11:55 -08006149 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08006150 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006151
Dustin Brown363b4792019-02-05 16:11:55 -08006152 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08006153 if (errno)
6154 return errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05306155
Dustin Brownf0f00612019-01-31 16:02:24 -08006156 errno = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006157
Dustin Brown363b4792019-02-05 16:11:55 -08006158 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08006159
6160 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006161}
6162
6163/**
6164 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
6165 * @wiphy: pointer to wireless wiphy structure.
6166 * @wdev: pointer to wireless_dev structure.
6167 * @data: Pointer to the data to be passed via vendor interface
6168 * @data_len:Length of the data to be passed
6169 *
6170 * This is called by userspace to know the supported logger features
6171 *
6172 * Return: Return the Success or Failure code.
6173 */
6174static int
6175__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
6176 struct wireless_dev *wdev,
6177 const void *data, int data_len)
6178{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006179 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006180 int status;
6181 uint32_t features;
6182 struct sk_buff *reply_skb = NULL;
sheenam monga63736f62019-12-23 18:44:31 +05306183 bool enable_ring_buffer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006184
Dustin Brownfdf17c12018-03-14 12:55:34 -07006185 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08006186
Anurag Chouhan6d760662016-02-20 16:05:43 +05306187 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006188 hdd_err("Command not allowed in FTM mode");
6189 return -EPERM;
6190 }
6191
6192 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05306193 if (status)
6194 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006195
6196 features = 0;
sheenam monga63736f62019-12-23 18:44:31 +05306197 wlan_mlme_get_status_ring_buffer(hdd_ctx->psoc, &enable_ring_buffer);
6198 if (enable_ring_buffer) {
6199 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
6200 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
6201 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
6202 features |= WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
6203 features |= WIFI_LOGGER_PACKET_FATE_SUPPORTED;
6204 hdd_debug("Supported logger features: 0x%0x", features);
6205 } else {
6206 hdd_info("Ring buffer disable");
6207 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006208
6209 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6210 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
6211 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07006212 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006213 return -ENOMEM;
6214 }
6215
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006216 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
6217 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006218 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006219 kfree_skb(reply_skb);
6220 return -EINVAL;
6221 }
6222
6223 return cfg80211_vendor_cmd_reply(reply_skb);
6224}
6225
6226/**
6227 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
6228 * @wiphy: pointer to wireless wiphy structure.
6229 * @wdev: pointer to wireless_dev structure.
6230 * @data: Pointer to the data to be passed via vendor interface
6231 * @data_len:Length of the data to be passed
6232 *
6233 * This is called by userspace to know the supported logger features
6234 *
6235 * Return: Return the Success or Failure code.
6236 */
6237static int
6238wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
6239 struct wireless_dev *wdev,
6240 const void *data, int data_len)
6241{
Dustin Brown363b4792019-02-05 16:11:55 -08006242 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08006243 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05306244
Dustin Brown363b4792019-02-05 16:11:55 -08006245 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08006246 if (errno)
6247 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006248
Dustin Brownf0f00612019-01-31 16:02:24 -08006249 errno = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
6250 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006251
Dustin Brown363b4792019-02-05 16:11:55 -08006252 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05306253
Dustin Brownf0f00612019-01-31 16:02:24 -08006254 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006255}
6256
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306257#ifdef WLAN_FEATURE_GTK_OFFLOAD
6258void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05306259 uint8_t *kck_ptr, uint8_t kck_len,
6260 uint8_t *kek_ptr, uint32_t kek_len,
6261 uint8_t *replay_ctr, bool big_endian)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306262{
6263 struct hdd_station_ctx *hdd_sta_ctx;
6264 uint8_t *buf;
6265 int i;
6266 struct pmo_gtk_req *gtk_req = NULL;
Min Liu8c5d99e2018-09-10 17:18:44 +08006267 struct wlan_objmgr_vdev *vdev;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306268 QDF_STATUS status = QDF_STATUS_E_FAILURE;
6269
6270 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
Min Liu74a1a502018-10-10 19:59:07 +08006271 if (!gtk_req)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306272 return;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306273
6274 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05306275 if (kck_ptr) {
6276 if (kck_len > sizeof(gtk_req->kck)) {
6277 kck_len = sizeof(gtk_req->kck);
6278 QDF_ASSERT(0);
6279 }
6280 qdf_mem_copy(gtk_req->kck, kck_ptr, kck_len);
Yeshwanth Sriram Guntukae6313412019-08-06 14:18:33 +05306281 gtk_req->kck_len = kck_len;
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05306282 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306283
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08006284 if (kek_ptr) {
6285 /* paranoia */
6286 if (kek_len > sizeof(gtk_req->kek)) {
6287 kek_len = sizeof(gtk_req->kek);
6288 QDF_ASSERT(0);
6289 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306290 qdf_mem_copy(gtk_req->kek, kek_ptr, kek_len);
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08006291 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306292
Jeff Johnsone04b6992019-02-27 14:06:55 -08006293 qdf_copy_macaddr(&gtk_req->bssid, &hdd_sta_ctx->conn_info.bssid);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306294
6295 gtk_req->kek_len = kek_len;
gaurank kathpalia82a1b2b2018-07-10 16:49:10 +05306296 gtk_req->is_fils_connection = hdd_is_fils_connection(adapter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306297
6298 /* convert big to little endian since driver work on little endian */
6299 buf = (uint8_t *)&gtk_req->replay_counter;
6300 for (i = 0; i < 8; i++)
6301 buf[7 - i] = replay_ctr[i];
6302
Min Liu8c5d99e2018-09-10 17:18:44 +08006303 vdev = hdd_objmgr_get_vdev(adapter);
6304 if (!vdev)
6305 goto end;
6306 status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05306307 hdd_objmgr_put_vdev(vdev);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306308 if (status != QDF_STATUS_SUCCESS)
6309 hdd_err("Failed to cache GTK Offload");
6310
Min Liu8c5d99e2018-09-10 17:18:44 +08006311end:
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306312 qdf_mem_free(gtk_req);
6313}
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306314#endif
6315
Sridhar Selvaraje5260442017-08-19 10:12:03 +05306316#if defined(WLAN_FEATURE_FILS_SK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306317/**
6318 * wlan_hdd_add_fils_params_roam_auth_event() - Adds FILS params in roam auth
6319 * @skb: SK buffer
6320 * @roam_info: Roam info
6321 *
6322 * API adds fils params[pmk, pmkid, next sequence number] to roam auth event
6323 *
6324 * Return: zero on success, error code on failure
6325 */
Jeff Johnson172237b2017-11-07 15:32:59 -08006326static int
6327wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
6328 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306329{
6330 if (roam_info->pmk_len &&
6331 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK,
6332 roam_info->pmk_len, roam_info->pmk)) {
6333 hdd_err("pmk send fail");
6334 return -EINVAL;
6335 }
6336
6337 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID,
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -07006338 PMKID_LEN, roam_info->pmkid)) {
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306339 hdd_err("pmkid send fail");
6340 return -EINVAL;
6341 }
6342
Vignesh Viswanathan8da68cf2017-09-07 14:00:04 +05306343 hdd_debug("Update ERP Seq Num %d, Next ERP Seq Num %d",
6344 roam_info->update_erp_next_seq_num,
6345 roam_info->next_erp_seq_num);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306346 if (roam_info->update_erp_next_seq_num &&
6347 nla_put_u16(skb,
6348 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM,
6349 roam_info->next_erp_seq_num)) {
6350 hdd_err("ERP seq num send fail");
6351 return -EINVAL;
6352 }
6353
6354 return 0;
6355}
6356#else
Jeff Johnson172237b2017-11-07 15:32:59 -08006357static inline int
6358wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
6359 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306360{
6361 return 0;
6362}
6363#endif
6364
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08006365#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Abhishek Ambure5e9b6a42020-02-12 21:32:35 +05306366void hdd_send_roam_scan_ch_list_event(struct hdd_context *hdd_ctx,
Abhishek Ambure3823c362020-03-18 14:15:08 +05306367 uint8_t vdev_id, uint16_t buf_len,
6368 uint8_t *buf)
Abhishek Ambure5e9b6a42020-02-12 21:32:35 +05306369{
6370 struct sk_buff *vendor_event;
Abhishek Ambure3823c362020-03-18 14:15:08 +05306371 struct hdd_adapter *adapter;
Abhishek Ambure5e9b6a42020-02-12 21:32:35 +05306372 uint32_t len, ret;
6373
6374 if (!hdd_ctx) {
6375 hdd_err_rl("hdd context is null");
6376 return;
6377 }
6378
Abhishek Ambure3823c362020-03-18 14:15:08 +05306379 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
6380 if (!adapter)
6381 return;
6382
Abhishek Ambure5e9b6a42020-02-12 21:32:35 +05306383 len = nla_total_size(buf_len) + NLMSG_HDRLEN;
6384 vendor_event =
6385 cfg80211_vendor_event_alloc(
Abhishek Ambure3823c362020-03-18 14:15:08 +05306386 hdd_ctx->wiphy, &(adapter->wdev), len,
Abhishek Ambure5e9b6a42020-02-12 21:32:35 +05306387 QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO_INDEX,
6388 GFP_KERNEL);
6389
6390 if (!vendor_event) {
6391 hdd_err("cfg80211_vendor_event_alloc failed");
6392 return;
6393 }
6394
6395 ret = nla_put(vendor_event,
6396 QCA_WLAN_VENDOR_ATTR_UPDATE_STA_INFO_CONNECT_CHANNELS,
6397 buf_len, buf);
6398 if (ret) {
6399 hdd_err("OEM event put fails status %d", ret);
6400 kfree_skb(vendor_event);
6401 return;
6402 }
6403
6404 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
6405}
6406
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006407/**
6408 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05306409 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006410 * @bssid: pointer to bssid of roamed AP.
6411 * @req_rsn_ie: Pointer to request RSN IE
6412 * @req_rsn_len: Length of the request RSN IE
6413 * @rsp_rsn_ie: Pointer to response RSN IE
6414 * @rsp_rsn_len: Length of the response RSN IE
6415 * @roam_info_ptr: Pointer to the roaming related information
6416 *
6417 * This is called when wlan driver needs to send the roaming and
6418 * authorization information after roaming.
6419 *
6420 * The information that would be sent is the request RSN IE, response
6421 * RSN IE and BSSID of the newly roamed AP.
6422 *
6423 * If the Authorized status is authenticated, then additional parameters
6424 * like PTK's KCK and KEK and Replay Counter would also be passed to the
6425 * supplicant.
6426 *
6427 * The supplicant upon receiving this event would ignore the legacy
6428 * cfg80211_roamed call and use the entire information from this event.
6429 * The cfg80211_roamed should still co-exist since the kernel will
6430 * make use of the parameters even if the supplicant ignores it.
6431 *
6432 * Return: Return the Success or Failure code.
6433 */
Jeff Johnsone5006672017-08-29 14:39:02 -07006434int wlan_hdd_send_roam_auth_event(struct hdd_adapter *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006435 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
Jeff Johnson172237b2017-11-07 15:32:59 -08006436 uint32_t rsp_rsn_len, struct csr_roam_info *roam_info_ptr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006437{
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006438 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006439 struct sk_buff *skb = NULL;
Pragaspathi Thilagaraj7a1a08e2019-05-29 01:20:29 +05306440 enum csr_akm_type auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306441 uint32_t fils_params_len;
6442 int status;
sheenam monga6e49e5c2019-04-04 12:49:04 +05306443 enum qca_roam_reason hdd_roam_reason;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -07006444
Dustin Brown491d54b2018-03-14 12:39:11 -07006445 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006446
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006447 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006448 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006449
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006450 if (!roaming_offload_enabled(hdd_ctx) ||
6451 !roam_info_ptr->roamSynchInProgress)
Prashanth Bhattabfc25292015-11-05 11:16:21 -08006452 return 0;
6453
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306454 /*
6455 * PMK is sent from FW in Roam Synch Event for FILS Roaming.
6456 * In that case, add three more NL attributes.ie. PMK, PMKID
6457 * and ERP next sequence number. Add corresponding lengths
6458 * with 3 extra NL message headers for each of the
6459 * aforementioned params.
6460 */
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -07006461 fils_params_len = roam_info_ptr->pmk_len + PMKID_LEN +
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306462 sizeof(uint16_t) + (3 * NLMSG_HDRLEN);
6463
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006464 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05306465 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006466 ETH_ALEN + req_rsn_len + rsp_rsn_len +
6467 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306468 SIR_KCK_KEY_LEN + roam_info_ptr->kek_len +
sheenam monga6e49e5c2019-04-04 12:49:04 +05306469 sizeof(uint16_t) + sizeof(uint8_t) +
6470 (9 * NLMSG_HDRLEN) + fils_params_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006471 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
6472 GFP_KERNEL);
6473
6474 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07006475 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006476 return -EINVAL;
6477 }
6478
6479 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
6480 ETH_ALEN, bssid) ||
6481 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
6482 req_rsn_len, req_rsn_ie) ||
6483 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
6484 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006485 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006486 goto nla_put_failure;
6487 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006488 if (roam_info_ptr->synchAuthStatus ==
6489 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07006490 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08006491 if (nla_put_u8(skb,
6492 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
6493 hdd_err("nla put fail");
6494 goto nla_put_failure;
6495 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08006496 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
6497 /* if FT or CCKM connection: dont send replay counter */
6498 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
6499 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
Pragaspathi Thilagaraj96259b22019-02-15 01:08:27 +05306500 auth_type != eCSR_AUTH_TYPE_FT_SAE &&
6501 auth_type != eCSR_AUTH_TYPE_FT_SUITEB_EAP_SHA384 &&
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08006502 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
6503 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
6504 nla_put(skb,
6505 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
6506 SIR_REPLAY_CTR_LEN,
6507 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006508 hdd_err("non FT/non CCKM connection");
6509 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08006510 goto nla_put_failure;
6511 }
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05306512 if (roam_info_ptr->kek_len > SIR_KEK_KEY_LEN_FILS ||
6513 nla_put(skb,
Naveen Rawat14298b92015-11-25 16:27:41 -08006514 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05306515 roam_info_ptr->kck_len, roam_info_ptr->kck) ||
Naveen Rawat14298b92015-11-25 16:27:41 -08006516 nla_put(skb,
6517 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306518 roam_info_ptr->kek_len, roam_info_ptr->kek)) {
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05306519 hdd_err("nla put fail, kek_len %d",
6520 roam_info_ptr->kek_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006521 goto nla_put_failure;
6522 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306523
sheenam monga6e49e5c2019-04-04 12:49:04 +05306524 hdd_roam_reason =
6525 hdd_get_roam_reason(roam_info_ptr->roam_reason);
6526
6527 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON,
6528 hdd_roam_reason)) {
6529 hdd_err("roam reason send failure");
6530 goto nla_put_failure;
6531 }
6532
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306533 status = wlan_hdd_add_fils_params_roam_auth_event(skb,
6534 roam_info_ptr);
6535 if (status)
6536 goto nla_put_failure;
6537
6538 /*
6539 * Save the gtk rekey parameters in HDD STA context. They will
6540 * be used next time when host enables GTK offload and goes
6541 * into power save state.
6542 */
6543 wlan_hdd_save_gtk_offload_params(adapter, roam_info_ptr->kck,
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05306544 roam_info_ptr->kck_len,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306545 roam_info_ptr->kek,
6546 roam_info_ptr->kek_len,
6547 roam_info_ptr->replay_ctr,
6548 true);
6549 hdd_debug("roam_info_ptr->replay_ctr 0x%llx",
6550 *((uint64_t *)roam_info_ptr->replay_ctr));
6551
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006552 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07006553 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006554 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
6555 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006556 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006557 goto nla_put_failure;
6558 }
6559 }
6560
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05306561 hdd_debug("Auth Status = %d Subnet Change Status = %d",
6562 roam_info_ptr->synchAuthStatus,
6563 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08006564
6565 /*
6566 * Add subnet change status if subnet has changed
6567 * 0 = unchanged
6568 * 1 = changed
6569 * 2 = unknown
6570 */
6571 if (roam_info_ptr->subnet_change_status) {
6572 if (nla_put_u8(skb,
6573 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
6574 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006575 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08006576 goto nla_put_failure;
6577 }
6578 }
6579
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006580 cfg80211_vendor_event(skb, GFP_KERNEL);
6581 return 0;
6582
6583nla_put_failure:
6584 kfree_skb(skb);
6585 return -EINVAL;
6586}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08006587#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006588
Jeff Johnson91f90ff2018-11-16 07:53:37 -08006589#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
6590 ((1 << 26) | \
6591 (((probe_period) & 0x1fff) << 13) | \
6592 ((stay_period) & 0x1fff))
6593
6594#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
6595 ((1 << 27) | \
6596 ((snr_diff) & 0x1fff))
6597
6598#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
6599 ((1 << 28) | \
6600 ((probe_dwell_time) & 0x1fff))
6601
6602#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
6603 ((1 << 29) | \
6604 (((mgmt_snr_weight) & 0xff) << 16) | \
6605 (((data_snr_weight) & 0xff) << 8) | \
6606 ((ack_snr_weight) & 0xff))
6607
lifeng66831662017-05-19 16:01:35 +08006608#define RX_REORDER_TIMEOUT_VOICE \
6609 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE
6610#define RX_REORDER_TIMEOUT_VIDEO \
6611 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO
6612#define RX_REORDER_TIMEOUT_BESTEFFORT \
6613 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT
6614#define RX_REORDER_TIMEOUT_BACKGROUND \
6615 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND
6616#define RX_BLOCKSIZE_PEER_MAC \
6617 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC
6618#define RX_BLOCKSIZE_WINLIMIT \
6619 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006620static const struct nla_policy
6621wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
6622
6623 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
Sourav Mohapatra0dbdfb42019-03-19 14:31:20 +05306624 [QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED] = {
6625 .type = NLA_U8 },
6626 [QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS] = {.type = NLA_U8 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006627 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
6628 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Jeff Johnson79f6a602017-06-15 09:48:25 -07006629 [QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT] = {.type = NLA_U32},
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05306630 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05306631 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
6632 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006633 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
6634 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
6635 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
6636 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
6637 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08006638 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY] = {
6639 .type = NLA_U32 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05306640 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08006641 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
6642 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
Jeff Johnson91f90ff2018-11-16 07:53:37 -08006643 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
Jeff Johnson77177bc2018-11-16 08:14:20 -08006644 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME] = {
6645 .type = NLA_U32},
Jeff Johnson1350e622018-11-16 18:36:55 -08006646 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT] = {
6647 .type = NLA_U32},
6648 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT] = {
6649 .type = NLA_U32},
6650 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT] = {
6651 .type = NLA_U32},
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306652 [QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL] = {.type = NLA_U8},
lifeng66831662017-05-19 16:01:35 +08006653 [RX_REORDER_TIMEOUT_VOICE] = {.type = NLA_U32},
6654 [RX_REORDER_TIMEOUT_VIDEO] = {.type = NLA_U32},
6655 [RX_REORDER_TIMEOUT_BESTEFFORT] = {.type = NLA_U32},
6656 [RX_REORDER_TIMEOUT_BACKGROUND] = {.type = NLA_U32},
Jeff Johnson19a5a7e2017-06-15 14:51:26 -07006657 [RX_BLOCKSIZE_PEER_MAC] = {
6658 .type = NLA_UNSPEC,
6659 .len = QDF_MAC_ADDR_SIZE},
lifeng66831662017-05-19 16:01:35 +08006660 [RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32},
Mukul Sharma6398b252017-05-01 17:58:12 +05306661 [QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL] = {.type = NLA_U32 },
Poddar, Siddarth4b3f7312017-11-02 17:00:20 +05306662 [QCA_WLAN_VENDOR_ATTR_CONFIG_LRO] = {.type = NLA_U8 },
Jeff Johnson1feb8a62018-11-14 13:18:41 -08006663 [QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER] = {.type = NLA_U8 },
lifengd217d192017-05-09 19:44:16 +08006664 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA] = {.type = NLA_U32 },
6665 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN] = {.type = NLA_U32 },
6666 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST] = {.type = NLA_U32 },
6667 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL] = {.type = NLA_U32 },
Paul Zhang99fe8842017-12-08 14:43:46 +08006668 [QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL] = {.type = NLA_U16 },
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05306669 [QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT] = {.type = NLA_U8},
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07006670 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE] = {.type = NLA_U8 },
Abhishek Singh6454ad32017-12-20 10:42:21 +05306671 [QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] = {.type = NLA_U8},
Ashish Kumar Dhanotiya1e20bcc2018-06-15 11:28:51 +05306672 [QCA_WLAN_VENDOR_ATTR_CONFIG_GTX] = {.type = NLA_U8},
Paul Zhangc9dbaee2019-06-23 22:07:31 +08006673 [QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS] = {.type = NLA_U8},
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08006674 [QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY] = {.type = NLA_U32 },
6675 [QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST] = {
6676 .type = NLA_BINARY,
Srinivas Girigowdacf161402019-03-14 11:37:33 -07006677 .len = WLAN_MAX_IE_LEN + 2},
Srinivas Dasari37e37312019-06-30 23:50:24 +05306678 [QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES] = {
6679 .type = NLA_BINARY,
6680 .len = SIR_MAC_MAX_ADD_IE_LENGTH + 2},
sheenam monga17452ef2020-02-24 13:23:13 +05306681 [QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON] = {.type = NLA_U8 },
Rakesh Pillai6c48d132020-06-30 15:22:01 +05306682 [QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE] = {
6683 .type = NLA_U8 },
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08006684
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006685};
6686
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006687static const struct nla_policy qca_wlan_vendor_twt_add_dialog_policy[
6688 QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1] = {
6689 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP] = {.type = NLA_U8 },
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05306690 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST] = {.type = NLA_FLAG },
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006691 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE] = {.type = NLA_U8 },
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05306692 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER] = {.type = NLA_FLAG },
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006693 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE] = {.type = NLA_U8 },
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05306694 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION] = {.type = NLA_FLAG },
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006695 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME] = {.type = NLA_U32 },
6696 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION] = {.type = NLA_U32 },
6697 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA] = {
6698 .type = NLA_U32 },
6699};
6700
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006701static const struct nla_policy
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08006702qca_wlan_vendor_attr_he_omi_tx_policy [QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX + 1] = {
6703 [QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS] = {.type = NLA_U8 },
6704 [QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW] = {.type = NLA_U8 },
6705 [QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE] = {.type = NLA_U8 },
6706 [QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS] = {.type = NLA_U8 },
Kiran Kumar Lokere49e3aff2019-02-06 17:00:48 -08006707 [QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE] = {.type = NLA_U8 },
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08006708};
6709
6710static const struct nla_policy
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006711wlan_hdd_wifi_test_config_policy[
6712 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1] = {
6713 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE] = {
6714 .type = NLA_U8},
6715 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ] = {
6716 .type = NLA_U8},
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08006717 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS] = {
6718 .type = NLA_U8},
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08006719 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ] = {
6720 .type = NLA_U8},
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08006721 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION] = {
6722 .type = NLA_U8},
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006723 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE] = {
6724 .type = NLA_U8},
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006725 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION] = {
6726 .type = NLA_U8},
6727 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID] = {
6728 .type = NLA_U8},
6729 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE] = {
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07006730 .type = NLA_U16},
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08006731 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK] = {
6732 .type = NLA_U8},
6733 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC] = {
6734 .type = NLA_U8},
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08006735 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF] = {
6736 .type = NLA_U8},
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07006737 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE] = {
6738 .type = NLA_U8},
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07006739 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS] = {
6740 .type = NLA_U8},
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07006741 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR] = {
6742 .type = NLA_U8},
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07006743 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AC] = {
6744 .type = NLA_U8},
6745 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA] = {
6746 .type = NLA_U8},
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07006747 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP] = {
6748 .type = NLA_U8},
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07006749 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_BW] = {
6750 .type = NLA_U8},
6751 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_NSS] = {
6752 .type = NLA_U8},
6753 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG] = {
6754 .type = NLA_FLAG},
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07006755 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU] = {
6756 .type = NLA_U8},
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08006757 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP] = {
6758 .type = NLA_U8},
6759 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX] = {
6760 .type = NLA_NESTED},
Kiran Kumar Lokereee205772018-09-27 00:27:27 -07006761 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU] = {
6762 .type = NLA_U8},
Kiran Kumar Lokere921b5a52019-02-24 21:53:20 -08006763 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS]
6764 = {.type = NLA_U8},
Kiran Kumar Lokerea1c29ec2019-02-25 18:19:00 -08006765 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT] = {
6766 .type = NLA_U8},
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006767 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP] = {
6768 .type = NLA_NESTED},
6769 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE] = {
6770 .type = NLA_NESTED},
6771 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT] = {
6772 .type = NLA_U8},
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006773};
6774
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006775/**
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306776 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
6777 * @hdd_ctx: HDD context
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306778 * @adapter: Pointer to HDD adapter
6779 * @ie_data: Pointer to Scan IEs buffer
6780 * @ie_len: Length of Scan IEs
6781 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306782 * This API is used to store the default scan ies received from
6783 * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
6784 *
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306785 * Return: 0 on success; error number otherwise
6786 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006787static int wlan_hdd_save_default_scan_ies(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07006788 struct hdd_adapter *adapter,
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306789 uint8_t *ie_data, uint16_t ie_len)
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306790{
Jeff Johnson37588942017-08-15 16:11:41 -07006791 struct hdd_scan_info *scan_info = &adapter->scan_info;
Wu Gao93816212018-08-31 16:49:54 +08006792 bool add_qcn_ie;
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306793
6794 if (!scan_info)
6795 return -EINVAL;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306796
6797 if (scan_info->default_scan_ies) {
6798 qdf_mem_free(scan_info->default_scan_ies);
6799 scan_info->default_scan_ies = NULL;
6800 }
6801
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306802 scan_info->default_scan_ies_len = ie_len;
Dustin Brown1dbefe62018-09-11 16:32:03 -07006803 ucfg_mlme_get_qcn_ie_support(hdd_ctx->psoc, &add_qcn_ie);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306804 if (add_qcn_ie)
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306805 ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306806
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306807 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306808 if (!scan_info->default_scan_ies) {
6809 scan_info->default_scan_ies_len = 0;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306810 return -ENOMEM;
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306811 }
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306812
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306813 qdf_mem_copy(scan_info->default_scan_ies, ie_data,
6814 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306815
6816 /* Add QCN IE if g_qcn_ie_support INI is enabled */
6817 if (add_qcn_ie)
Kiran Kumar Lokere89f01f02019-08-06 18:22:39 -07006818 sme_add_qcn_ie(hdd_ctx->mac_handle,
6819 scan_info->default_scan_ies,
6820 &scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306821
Abhishek Singh74d06cf2019-09-06 09:23:22 +05306822 hdd_debug("Saved default scan IE:len %d",
6823 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306824 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
6825 (uint8_t *) scan_info->default_scan_ies,
6826 scan_info->default_scan_ies_len);
6827
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306828 return 0;
6829}
6830
6831/**
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306832 * wlan_hdd_handle_restrict_offchan_config() -
6833 * Handle wifi configuration attribute :
6834 * QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL
6835 * @adapter: Pointer to HDD adapter
6836 * @restrict_offchan: Restrict offchannel setting done by
6837 * application
6838 *
6839 * Return: 0 on success; error number otherwise
6840 */
Jeff Johnsone5006672017-08-29 14:39:02 -07006841static int wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter *adapter,
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306842 u8 restrict_offchan)
6843{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006844 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonc1e62782017-11-09 09:50:17 -08006845 enum QDF_OPMODE dev_mode = adapter->device_mode;
Min Liu8c5d99e2018-09-10 17:18:44 +08006846 struct wlan_objmgr_vdev *vdev;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306847 int ret_val = 0;
6848
6849 if (!(dev_mode == QDF_SAP_MODE || dev_mode == QDF_P2P_GO_MODE)) {
6850 hdd_err("Invalid interface type:%d", dev_mode);
6851 return -EINVAL;
6852 }
Min Liu8c5d99e2018-09-10 17:18:44 +08006853 vdev = hdd_objmgr_get_vdev(adapter);
6854 if (!vdev)
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006855 return -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306856 if (restrict_offchan == 1) {
6857 enum policy_mgr_con_mode pmode =
6858 policy_mgr_convert_device_mode_to_qdf_type(dev_mode);
6859 int chan;
6860
Min Liu8c5d99e2018-09-10 17:18:44 +08006861 u32 vdev_id = wlan_vdev_get_id(vdev);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306862
Min Liu8c5d99e2018-09-10 17:18:44 +08006863 wlan_vdev_obj_lock(vdev);
6864 wlan_vdev_mlme_cap_set(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
6865 wlan_vdev_obj_unlock(vdev);
Manikandan Mohan7fdb0252019-08-14 16:49:02 -07006866 chan = wlan_freq_to_chan(
6867 policy_mgr_get_channel(hdd_ctx->psoc, pmode, &vdev_id));
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006868 if (!chan ||
6869 wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, chan)) {
6870 hdd_err("unable to send avoid_freq");
6871 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306872 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006873 hdd_info("vdev %d mode %d dnbs enabled", vdev_id, dev_mode);
6874 } else if (restrict_offchan == 0) {
Min Liu8c5d99e2018-09-10 17:18:44 +08006875 wlan_vdev_obj_lock(vdev);
6876 wlan_vdev_mlme_cap_clear(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
6877 wlan_vdev_obj_unlock(vdev);
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006878 if (wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0)) {
6879 hdd_err("unable to clear avoid_freq");
6880 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306881 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006882 hdd_info("vdev mode %d dnbs disabled", dev_mode);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306883 } else {
6884 ret_val = -EINVAL;
6885 hdd_err("Invalid RESTRICT_OFFCHAN setting");
6886 }
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05306887 hdd_objmgr_put_vdev(vdev);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306888 return ret_val;
6889}
6890
6891/**
Jeff Johnson0dd687e2018-11-16 20:11:27 -08006892 * wlan_hdd_cfg80211_wifi_set_reorder_timeout() - set reorder timeout
6893 * @adapter: Pointer to HDD adapter
lifeng66831662017-05-19 16:01:35 +08006894 * @tb: array of pointer to struct nlattr
6895 *
6896 * Return: 0 on success; error number otherwise
6897 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006898static
Jeff Johnson0dd687e2018-11-16 20:11:27 -08006899int wlan_hdd_cfg80211_wifi_set_reorder_timeout(struct hdd_adapter *adapter,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006900 struct nlattr *tb[])
lifeng66831662017-05-19 16:01:35 +08006901{
Jeff Johnson0dd687e2018-11-16 20:11:27 -08006902 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Min Liuab6ed4f2018-01-09 13:13:57 +08006903 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08006904 QDF_STATUS qdf_status;
6905 struct sir_set_rx_reorder_timeout_val reorder_timeout;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006906 mac_handle_t mac_handle;
lifeng66831662017-05-19 16:01:35 +08006907
6908#define RX_TIMEOUT_VAL_MIN 10
6909#define RX_TIMEOUT_VAL_MAX 1000
6910
6911 if (tb[RX_REORDER_TIMEOUT_VOICE] ||
6912 tb[RX_REORDER_TIMEOUT_VIDEO] ||
6913 tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
6914 tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
6915
6916 /* if one is specified, all must be specified */
6917 if (!tb[RX_REORDER_TIMEOUT_VOICE] ||
6918 !tb[RX_REORDER_TIMEOUT_VIDEO] ||
6919 !tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
6920 !tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
6921 hdd_err("four AC timeout val are required MAC");
6922 return -EINVAL;
6923 }
6924
6925 reorder_timeout.rx_timeout_pri[0] = nla_get_u32(
6926 tb[RX_REORDER_TIMEOUT_VOICE]);
6927 reorder_timeout.rx_timeout_pri[1] = nla_get_u32(
6928 tb[RX_REORDER_TIMEOUT_VIDEO]);
6929 reorder_timeout.rx_timeout_pri[2] = nla_get_u32(
6930 tb[RX_REORDER_TIMEOUT_BESTEFFORT]);
6931 reorder_timeout.rx_timeout_pri[3] = nla_get_u32(
6932 tb[RX_REORDER_TIMEOUT_BACKGROUND]);
6933 /* timeout value is required to be in the rang 10 to 1000ms */
6934 if (reorder_timeout.rx_timeout_pri[0] >= RX_TIMEOUT_VAL_MIN &&
6935 reorder_timeout.rx_timeout_pri[0] <= RX_TIMEOUT_VAL_MAX &&
6936 reorder_timeout.rx_timeout_pri[1] >= RX_TIMEOUT_VAL_MIN &&
6937 reorder_timeout.rx_timeout_pri[1] <= RX_TIMEOUT_VAL_MAX &&
6938 reorder_timeout.rx_timeout_pri[2] >= RX_TIMEOUT_VAL_MIN &&
6939 reorder_timeout.rx_timeout_pri[2] <= RX_TIMEOUT_VAL_MAX &&
6940 reorder_timeout.rx_timeout_pri[3] >= RX_TIMEOUT_VAL_MIN &&
6941 reorder_timeout.rx_timeout_pri[3] <= RX_TIMEOUT_VAL_MAX) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006942 mac_handle = hdd_ctx->mac_handle;
6943 qdf_status = sme_set_reorder_timeout(mac_handle,
lifeng66831662017-05-19 16:01:35 +08006944 &reorder_timeout);
6945 if (qdf_status != QDF_STATUS_SUCCESS) {
6946 hdd_err("failed to set reorder timeout err %d",
6947 qdf_status);
6948 ret_val = -EPERM;
6949 }
6950 } else {
6951 hdd_err("one of the timeout value is not in range");
6952 ret_val = -EINVAL;
6953 }
6954 }
6955
6956 return ret_val;
6957}
6958
6959/**
Jeff Johnson339ede82018-11-16 20:27:52 -08006960 * wlan_hdd_cfg80211_wifi_set_rx_blocksize() - set rx blocksize
lifeng66831662017-05-19 16:01:35 +08006961 * @adapter: hdd adapter
6962 * @tb: array of pointer to struct nlattr
6963 *
6964 * Return: 0 on success; error number otherwise
6965 */
Jeff Johnson339ede82018-11-16 20:27:52 -08006966static int wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct hdd_adapter *adapter,
lifeng66831662017-05-19 16:01:35 +08006967 struct nlattr *tb[])
6968{
Jeff Johnson339ede82018-11-16 20:27:52 -08006969 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Min Liuab6ed4f2018-01-09 13:13:57 +08006970 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08006971 uint32_t set_value;
6972 QDF_STATUS qdf_status;
6973 struct sir_peer_set_rx_blocksize rx_blocksize;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006974 mac_handle_t mac_handle;
lifeng66831662017-05-19 16:01:35 +08006975
6976#define WINDOW_SIZE_VAL_MIN 1
6977#define WINDOW_SIZE_VAL_MAX 64
6978
6979 if (tb[RX_BLOCKSIZE_PEER_MAC] ||
6980 tb[RX_BLOCKSIZE_WINLIMIT]) {
6981
6982 /* if one is specified, both must be specified */
6983 if (!tb[RX_BLOCKSIZE_PEER_MAC] ||
6984 !tb[RX_BLOCKSIZE_WINLIMIT]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07006985 hdd_err("Both Peer MAC and windows limit required");
lifeng66831662017-05-19 16:01:35 +08006986 return -EINVAL;
6987 }
6988
6989 memcpy(&rx_blocksize.peer_macaddr,
6990 nla_data(tb[RX_BLOCKSIZE_PEER_MAC]),
6991 sizeof(rx_blocksize.peer_macaddr)),
6992
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006993 rx_blocksize.vdev_id = adapter->vdev_id;
lifeng66831662017-05-19 16:01:35 +08006994 set_value = nla_get_u32(tb[RX_BLOCKSIZE_WINLIMIT]);
6995 /* maximum window size is 64 */
6996 if (set_value >= WINDOW_SIZE_VAL_MIN &&
6997 set_value <= WINDOW_SIZE_VAL_MAX) {
6998 rx_blocksize.rx_block_ack_win_limit = set_value;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006999 mac_handle = hdd_ctx->mac_handle;
7000 qdf_status = sme_set_rx_set_blocksize(mac_handle,
lifeng66831662017-05-19 16:01:35 +08007001 &rx_blocksize);
7002 if (qdf_status != QDF_STATUS_SUCCESS) {
7003 hdd_err("failed to set aggr sizes err %d",
7004 qdf_status);
7005 ret_val = -EPERM;
7006 }
7007 } else {
7008 hdd_err("window size val is not in range");
7009 ret_val = -EINVAL;
7010 }
7011 }
7012
7013 return ret_val;
7014}
7015
sheenam monga17452ef2020-02-24 13:23:13 +05307016/**
7017 * hdd_set_roam_reason_vsie_status() - enable/disable inclusion of
7018 * roam reason vsie in Reassoc
7019 *
7020 * @adapter: hdd adapter
7021 * @attr: nla attr sent by supplicant
7022 *
7023 * Return: 0 on success, negative errno on failure
7024 */
7025#ifdef WLAN_FEATURE_ROAM_OFFLOAD
7026static int hdd_set_roam_reason_vsie_status(struct hdd_adapter *adapter,
7027 const struct nlattr *attr)
7028{
7029 uint8_t roam_reason_vsie_enabled;
7030 int errno;
7031 QDF_STATUS status = QDF_STATUS_SUCCESS;
7032 struct hdd_context *hdd_ctx = NULL;
7033
7034 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7035 if (!hdd_ctx) {
7036 hdd_err("hdd_ctx failure");
7037 return -EINVAL;
7038 }
7039
7040 roam_reason_vsie_enabled = nla_get_u8(attr);
7041 if (roam_reason_vsie_enabled > 1)
7042 roam_reason_vsie_enabled = 1;
7043
7044 status =
7045 ucfg_mlme_set_roam_reason_vsie_status(hdd_ctx->psoc,
7046 roam_reason_vsie_enabled);
7047 if (QDF_IS_STATUS_ERROR(status)) {
7048 hdd_err("set roam reason vsie failed");
7049 return -EINVAL;
7050 }
7051
7052 errno = sme_cli_set_command
7053 (adapter->vdev_id,
7054 WMI_VDEV_PARAM_ENABLE_DISABLE_ROAM_REASON_VSIE,
7055 roam_reason_vsie_enabled, VDEV_CMD);
7056 if (errno) {
7057 hdd_err("Failed to set beacon report error vsie");
7058 status = QDF_STATUS_E_FAILURE;
7059 }
7060
7061 return qdf_status_to_os_return(status);
7062}
7063#else
7064static int hdd_set_roam_reason_vsie_status(struct hdd_adapter *adapter,
7065 const struct nlattr *attr)
7066{
7067 return -ENOTSUPP;
7068}
7069#endif
7070
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08007071static int hdd_config_access_policy(struct hdd_adapter *adapter,
7072 struct nlattr *tb[])
7073{
7074 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7075 struct nlattr *policy_attr =
7076 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY];
7077 struct nlattr *ielist_attr =
7078 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST];
7079 uint32_t access_policy;
Srinivas Girigowdacf161402019-03-14 11:37:33 -07007080 uint8_t ie[WLAN_MAX_IE_LEN + 2];
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08007081 QDF_STATUS status;
7082
7083 /* nothing to do if neither attribute is present */
7084 if (!ielist_attr && !policy_attr)
7085 return 0;
7086
7087 /* if one is present, both must be present */
7088 if (!ielist_attr || !policy_attr) {
7089 hdd_err("Missing attribute for %s",
7090 policy_attr ?
7091 "ACCESS_POLICY_IE_LIST" : "ACCESS_POLICY");
7092 return -EINVAL;
7093 }
7094
7095 /* validate the access policy */
7096 access_policy = nla_get_u32(policy_attr);
7097 switch (access_policy) {
7098 case QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED:
7099 case QCA_ACCESS_POLICY_DENY_UNLESS_LISTED:
7100 /* valid */
7101 break;
7102 default:
7103 hdd_err("Invalid value. access_policy %u", access_policy);
7104 return -EINVAL;
7105 }
7106
7107 /*
7108 * ie length is validated by the nla_policy. need to make a
Srinivas Girigowdacf161402019-03-14 11:37:33 -07007109 * copy since SME will always read WLAN_MAX_IE_LEN+2 bytes
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08007110 */
7111 nla_memcpy(ie, ielist_attr, sizeof(ie));
7112
7113 hdd_debug("calling sme_update_access_policy_vendor_ie");
7114 status = sme_update_access_policy_vendor_ie(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007115 adapter->vdev_id,
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08007116 ie, access_policy);
7117 if (QDF_IS_STATUS_ERROR(status))
7118 hdd_err("Failed to set vendor ie and access policy, %d",
7119 status);
7120
7121 return qdf_status_to_os_return(status);
7122}
7123
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08007124static int hdd_config_mpdu_aggregation(struct hdd_adapter *adapter,
7125 struct nlattr *tb[])
7126{
7127 struct nlattr *tx_attr =
7128 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION];
7129 struct nlattr *rx_attr =
7130 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION];
7131 uint8_t tx_size, rx_size;
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08007132 QDF_STATUS status;
7133
7134 /* nothing to do if neither attribute is present */
7135 if (!tx_attr && !rx_attr)
7136 return 0;
7137
7138 /* if one is present, both must be present */
7139 if (!tx_attr || !rx_attr) {
7140 hdd_err("Missing attribute for %s",
7141 tx_attr ? "RX" : "TX");
7142 return -EINVAL;
7143 }
7144
7145 tx_size = nla_get_u8(tx_attr);
7146 rx_size = nla_get_u8(rx_attr);
7147 if (!cfg_in_range(CFG_TX_AGGREGATION_SIZE, tx_size) ||
7148 !cfg_in_range(CFG_RX_AGGREGATION_SIZE, rx_size)) {
7149 hdd_err("TX %d RX %d MPDU aggr size not in range",
7150 tx_size, rx_size);
7151
7152 return -EINVAL;
7153 }
7154
Abhishek Ambure74709762019-05-27 19:43:26 +05307155 status = wma_set_tx_rx_aggr_size(adapter->vdev_id,
7156 tx_size,
7157 rx_size,
7158 WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU);
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08007159
7160 return qdf_status_to_os_return(status);
7161}
7162
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08007163static int hdd_config_ant_div_period(struct hdd_adapter *adapter,
7164 struct nlattr *tb[])
7165{
7166 struct nlattr *probe_attr =
7167 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD];
7168 struct nlattr *stay_attr =
7169 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD];
7170 uint32_t probe_period, stay_period, ant_div_usrcfg;
7171 int errno;
7172
7173 /* nothing to do if neither attribute is present */
7174 if (!probe_attr && !stay_attr)
7175 return 0;
7176
7177 /* if one is present, both must be present */
7178 if (!probe_attr || !stay_attr) {
7179 hdd_err("Missing attribute for %s",
7180 probe_attr ? "STAY" : "PROBE");
7181 return -EINVAL;
7182 }
7183
7184 probe_period = nla_get_u32(probe_attr);
7185 stay_period = nla_get_u32(stay_attr);
7186 ant_div_usrcfg = ANT_DIV_SET_PERIOD(probe_period, stay_period);
7187 hdd_debug("ant div set period: %x", ant_div_usrcfg);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007188 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08007189 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7190 ant_div_usrcfg, PDEV_CMD);
7191 if (errno)
7192 hdd_err("Failed to set ant div period, %d", errno);
7193
7194 return errno;
7195}
7196
Jeff Johnson1350e622018-11-16 18:36:55 -08007197static int hdd_config_ant_div_snr_weight(struct hdd_adapter *adapter,
7198 struct nlattr *tb[])
7199{
7200 struct nlattr *mgmt_attr =
7201 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT];
7202 struct nlattr *data_attr =
7203 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT];
7204 struct nlattr *ack_attr =
7205 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT];
7206 uint32_t mgmt_snr, data_snr, ack_snr, ant_div_usrcfg;
7207 int errno;
7208
7209 /* nothing to do if none of the attributes are present */
7210 if (!mgmt_attr && !data_attr && !ack_attr)
7211 return 0;
7212
7213 /* if one is present, all must be present */
7214 if (!mgmt_attr || !data_attr || !ack_attr) {
7215 hdd_err("Missing attribute");
7216 return -EINVAL;
7217 }
7218
7219 mgmt_snr = nla_get_u32(mgmt_attr);
7220 data_snr = nla_get_u32(data_attr);
7221 ack_snr = nla_get_u32(ack_attr);
7222 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(mgmt_snr, data_snr, ack_snr);
7223 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007224 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson1350e622018-11-16 18:36:55 -08007225 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7226 ant_div_usrcfg, PDEV_CMD);
7227 if (errno)
7228 hdd_err("Failed to set ant div weight, %d", errno);
7229
7230 return errno;
7231}
7232
Jeff Johnson7f4fd702018-11-14 11:19:52 -08007233static int hdd_config_fine_time_measurement(struct hdd_adapter *adapter,
7234 const struct nlattr *attr)
7235{
7236 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7237 uint32_t user_capability;
7238 uint32_t target_capability;
7239 uint32_t final_capability;
7240 QDF_STATUS status;
7241
7242 user_capability = nla_get_u32(attr);
7243 target_capability = hdd_ctx->fine_time_meas_cap_target;
7244 final_capability = user_capability & target_capability;
7245
7246 status = ucfg_mlme_set_fine_time_meas_cap(hdd_ctx->psoc,
7247 final_capability);
7248 if (QDF_IS_STATUS_ERROR(status)) {
7249 hdd_err("Unable to set value, status %d", status);
7250 return -EINVAL;
7251 }
7252
7253 sme_update_fine_time_measurement_capab(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007254 adapter->vdev_id,
Jeff Johnson7f4fd702018-11-14 11:19:52 -08007255 final_capability);
7256 ucfg_wifi_pos_set_ftm_cap(hdd_ctx->psoc, final_capability);
7257
7258 hdd_debug("user: 0x%x, target: 0x%x, final: 0x%x",
7259 user_capability, target_capability, final_capability);
7260
7261 return 0;
7262}
7263
Jeff Johnsonbcaeafb2018-11-14 12:14:24 -08007264static int hdd_config_modulated_dtim(struct hdd_adapter *adapter,
7265 const struct nlattr *attr)
7266{
7267 struct wlan_objmgr_vdev *vdev;
7268 uint32_t modulated_dtim;
7269 QDF_STATUS status;
7270
7271 modulated_dtim = nla_get_u32(attr);
7272
7273 vdev = hdd_objmgr_get_vdev(adapter);
7274 if (!vdev)
7275 return -EINVAL;
7276
7277 status = ucfg_pmo_config_modulated_dtim(vdev, modulated_dtim);
7278
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05307279 hdd_objmgr_put_vdev(vdev);
Jeff Johnsonbcaeafb2018-11-14 12:14:24 -08007280
7281 return qdf_status_to_os_return(status);
7282}
7283
Jeff Johnson6db91622018-11-14 12:33:28 -08007284static int hdd_config_listen_interval(struct hdd_adapter *adapter,
7285 const struct nlattr *attr)
7286{
7287 struct wlan_objmgr_vdev *vdev;
7288 uint32_t listen_interval;
7289 QDF_STATUS status;
7290
7291 listen_interval = nla_get_u32(attr);
7292 if (listen_interval > cfg_max(CFG_PMO_ENABLE_DYNAMIC_DTIM)) {
7293 hdd_err_rl("Invalid value for listen interval - %d",
7294 listen_interval);
7295 return -EINVAL;
7296 }
7297
7298 vdev = hdd_objmgr_get_vdev(adapter);
7299 if (!vdev)
7300 return -EINVAL;
7301
7302 status = ucfg_pmo_config_listen_interval(vdev, listen_interval);
7303
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05307304 hdd_objmgr_put_vdev(vdev);
Jeff Johnson6db91622018-11-14 12:33:28 -08007305
7306 return qdf_status_to_os_return(status);
7307}
7308
Jeff Johnson9381d032018-11-14 12:42:22 -08007309static int hdd_config_lro(struct hdd_adapter *adapter,
7310 const struct nlattr *attr)
7311{
7312 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7313 uint8_t enable_flag;
7314
7315 enable_flag = nla_get_u8(attr);
7316
7317 return hdd_lro_set_reset(hdd_ctx, adapter, enable_flag);
7318}
7319
Jeff Johnson3d4f64c2018-11-14 13:13:04 -08007320static int hdd_config_scan_enable(struct hdd_adapter *adapter,
7321 const struct nlattr *attr)
7322{
7323 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7324 uint8_t enable_flag;
7325
7326 enable_flag = nla_get_u8(attr);
7327 if (enable_flag)
7328 ucfg_scan_psoc_set_enable(hdd_ctx->psoc,
7329 REASON_USER_SPACE);
7330 else
7331 ucfg_scan_psoc_set_disable(hdd_ctx->psoc,
7332 REASON_USER_SPACE);
7333
7334 return 0;
7335}
7336
Rakesh Pillai6c48d132020-06-30 15:22:01 +05307337/**
7338 * hdd_config_udp_qos_upgrade_threshold() - NL attribute handler to parse
7339 * priority upgrade threshold value.
7340 * @adapter: adapter for which this configuration is to be applied
7341 * @attr: NL attribute
7342 *
7343 * Returns: 0 on success, -EINVAL on failure
7344 */
7345static int hdd_config_udp_qos_upgrade_threshold(struct hdd_adapter *adapter,
7346 const struct nlattr *attr)
7347{
7348 uint8_t priority = nla_get_u8(attr);
7349
7350 return hdd_set_udp_qos_upgrade_config(adapter, priority);
7351}
7352
Alan Chen10989ba2020-04-01 18:06:25 -07007353static int hdd_config_power(struct hdd_adapter *adapter,
7354 const struct nlattr *attr)
Jeff Johnson1feb8a62018-11-14 13:18:41 -08007355{
7356 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Alan Chen10989ba2020-04-01 18:06:25 -07007357 uint8_t power;
Jeff Johnson1feb8a62018-11-14 13:18:41 -08007358
Alan Chen10989ba2020-04-01 18:06:25 -07007359 power = nla_get_u8(attr);
Jeff Johnson1feb8a62018-11-14 13:18:41 -08007360
Alan Chen10989ba2020-04-01 18:06:25 -07007361 return hdd_set_power_config(hdd_ctx, adapter, power);
Jeff Johnson1feb8a62018-11-14 13:18:41 -08007362}
7363
Jeff Johnsonf15ede02018-11-14 13:27:13 -08007364static int hdd_config_stats_avg_factor(struct hdd_adapter *adapter,
7365 const struct nlattr *attr)
7366{
7367 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7368 uint16_t stats_avg_factor;
7369 QDF_STATUS status;
7370
7371 stats_avg_factor = nla_get_u16(attr);
7372 status = sme_configure_stats_avg_factor(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007373 adapter->vdev_id,
Jeff Johnsonf15ede02018-11-14 13:27:13 -08007374 stats_avg_factor);
7375
7376 return qdf_status_to_os_return(status);
7377}
7378
Jeff Johnsonf3827502018-11-14 14:00:58 -08007379static int hdd_config_non_agg_retry(struct hdd_adapter *adapter,
7380 const struct nlattr *attr)
7381{
7382 uint8_t retry;
7383 int param_id;
7384
7385 retry = nla_get_u8(attr);
7386 retry = retry > CFG_NON_AGG_RETRY_MAX ?
7387 CFG_NON_AGG_RETRY_MAX : retry;
7388 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
7389
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007390 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnsonf3827502018-11-14 14:00:58 -08007391 retry, PDEV_CMD);
7392}
7393
Jeff Johnsonb9021002018-11-15 15:51:36 -08007394static int hdd_config_agg_retry(struct hdd_adapter *adapter,
7395 const struct nlattr *attr)
7396{
7397 uint8_t retry;
7398 int param_id;
7399
7400 retry = nla_get_u8(attr);
7401 retry = retry > CFG_AGG_RETRY_MAX ?
7402 CFG_AGG_RETRY_MAX : retry;
7403
7404 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
7405 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
7406 CFG_AGG_RETRY_MIN : retry;
7407 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
7408
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007409 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnsonb9021002018-11-15 15:51:36 -08007410 retry, PDEV_CMD);
7411}
7412
Jeff Johnson0e8259c2018-11-15 19:44:57 -08007413static int hdd_config_mgmt_retry(struct hdd_adapter *adapter,
7414 const struct nlattr *attr)
7415{
7416 uint8_t retry;
7417 int param_id;
sheenam monga451c68c2019-12-11 20:00:17 +05307418 uint8_t max_mgmt_retry;
Jeff Johnson0e8259c2018-11-15 19:44:57 -08007419
7420 retry = nla_get_u8(attr);
sheenam monga451c68c2019-12-11 20:00:17 +05307421 max_mgmt_retry = (cfg_max(CFG_MGMT_RETRY_MAX));
7422 retry = retry > max_mgmt_retry ?
7423 max_mgmt_retry : retry;
Jeff Johnson0e8259c2018-11-15 19:44:57 -08007424 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
7425
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007426 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson0e8259c2018-11-15 19:44:57 -08007427 retry, PDEV_CMD);
7428}
7429
Jeff Johnson6b48a2f2018-11-15 19:48:47 -08007430static int hdd_config_ctrl_retry(struct hdd_adapter *adapter,
7431 const struct nlattr *attr)
7432{
7433 uint8_t retry;
7434 int param_id;
7435
7436 retry = nla_get_u8(attr);
7437 retry = retry > CFG_CTRL_RETRY_MAX ?
7438 CFG_CTRL_RETRY_MAX : retry;
7439 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
7440
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007441 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson6b48a2f2018-11-15 19:48:47 -08007442 retry, PDEV_CMD);
7443}
7444
Jeff Johnson98214742018-11-15 19:56:37 -08007445static int hdd_config_propagation_delay(struct hdd_adapter *adapter,
7446 const struct nlattr *attr)
7447{
7448 uint8_t delay;
7449 uint32_t abs_delay;
7450 int param_id;
7451
7452 delay = nla_get_u8(attr);
7453 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
7454 CFG_PROPAGATION_DELAY_MAX : delay;
7455 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
7456 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
7457
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007458 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson98214742018-11-15 19:56:37 -08007459 abs_delay, PDEV_CMD);
7460}
7461
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08007462static int hdd_config_propagation_abs_delay(struct hdd_adapter *adapter,
7463 const struct nlattr *attr)
7464{
7465 uint32_t abs_delay;
7466 int param_id;
7467
7468 abs_delay = nla_get_u32(attr);
7469 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
7470
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007471 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08007472 abs_delay, PDEV_CMD);
7473}
7474
Jeff Johnson7c5e6dc2018-11-15 21:20:18 -08007475static int hdd_config_tx_fail_count(struct hdd_adapter *adapter,
7476 const struct nlattr *attr)
7477{
7478 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7479 uint32_t tx_fail_count;
7480 QDF_STATUS status;
7481
7482 tx_fail_count = nla_get_u32(attr);
7483 if (!tx_fail_count)
7484 return 0;
7485
7486 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007487 adapter->vdev_id,
Jeff Johnson7c5e6dc2018-11-15 21:20:18 -08007488 tx_fail_count);
7489 if (QDF_IS_STATUS_ERROR(status))
7490 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
7491 status);
7492
7493 return qdf_status_to_os_return(status);
7494}
7495
Jeff Johnson7766fd22018-11-15 21:52:37 -08007496static int hdd_config_channel_avoidance_ind(struct hdd_adapter *adapter,
7497 const struct nlattr *attr)
7498{
7499 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7500 uint8_t set_value;
7501
7502 set_value = nla_get_u8(attr);
7503 hdd_debug("set_value: %d", set_value);
7504
7505 return hdd_enable_disable_ca_event(hdd_ctx, set_value);
7506}
7507
Jeff Johnson47e2e842018-11-14 13:49:43 -08007508static int hdd_config_guard_time(struct hdd_adapter *adapter,
7509 const struct nlattr *attr)
7510{
7511 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7512 uint32_t guard_time;
7513 QDF_STATUS status;
7514
7515 guard_time = nla_get_u32(attr);
7516 status = sme_configure_guard_time(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007517 adapter->vdev_id,
Jeff Johnson47e2e842018-11-14 13:49:43 -08007518 guard_time);
7519
7520 return qdf_status_to_os_return(status);
7521}
7522
Jeff Johnson3b2abe92017-12-15 09:03:47 -08007523static int hdd_config_scan_default_ies(struct hdd_adapter *adapter,
7524 const struct nlattr *attr)
7525{
7526 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7527 uint8_t *scan_ie;
7528 uint16_t scan_ie_len;
7529 QDF_STATUS status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007530 mac_handle_t mac_handle;
Jeff Johnson3b2abe92017-12-15 09:03:47 -08007531
Jeff Johnson3b2abe92017-12-15 09:03:47 -08007532 scan_ie_len = nla_len(attr);
7533 hdd_debug("IE len %d session %d device mode %d",
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007534 scan_ie_len, adapter->vdev_id, adapter->device_mode);
Jeff Johnson3b2abe92017-12-15 09:03:47 -08007535
7536 if (!scan_ie_len) {
7537 hdd_err("zero-length IE prohibited");
7538 return -EINVAL;
7539 }
7540
7541 if (scan_ie_len > MAX_DEFAULT_SCAN_IE_LEN) {
7542 hdd_err("IE length %d exceeds max of %d",
7543 scan_ie_len, MAX_DEFAULT_SCAN_IE_LEN);
7544 return -EINVAL;
7545 }
7546
7547 scan_ie = nla_data(attr);
Jeff Johnson4933c3a2018-01-10 19:33:33 -08007548 if (!wlan_is_ie_valid(scan_ie, scan_ie_len)) {
Jeff Johnson3b2abe92017-12-15 09:03:47 -08007549 hdd_err("Invalid default scan IEs");
7550 return -EINVAL;
7551 }
7552
7553 if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
7554 scan_ie, scan_ie_len))
7555 hdd_err("Failed to save default scan IEs");
7556
7557 if (adapter->device_mode == QDF_STA_MODE) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007558 mac_handle = hdd_ctx->mac_handle;
7559 status = sme_set_default_scan_ie(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007560 adapter->vdev_id, scan_ie,
Jeff Johnson3b2abe92017-12-15 09:03:47 -08007561 scan_ie_len);
7562 if (QDF_STATUS_SUCCESS != status) {
7563 hdd_err("failed to set default scan IEs in sme: %d",
7564 status);
7565 return -EPERM;
7566 }
7567 }
7568
7569 return 0;
7570}
7571
Jeff Johnsonf9871e42018-11-15 22:24:06 -08007572static int hdd_config_ant_div_ena(struct hdd_adapter *adapter,
7573 const struct nlattr *attr)
7574{
7575 uint32_t antdiv_enable;
7576 int errno;
7577
7578 antdiv_enable = nla_get_u32(attr);
7579 hdd_debug("antdiv_enable: %d", antdiv_enable);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007580 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonf9871e42018-11-15 22:24:06 -08007581 WMI_PDEV_PARAM_ENA_ANT_DIV,
7582 antdiv_enable, PDEV_CMD);
7583 if (errno)
7584 hdd_err("Failed to set antdiv_enable, %d", errno);
7585
7586 return errno;
7587}
7588
Jeff Johnson91f90ff2018-11-16 07:53:37 -08007589static int hdd_config_ant_div_snr_diff(struct hdd_adapter *adapter,
7590 const struct nlattr *attr)
7591{
7592 uint32_t ant_div_snr_diff;
7593 uint32_t ant_div_usrcfg;
7594 int errno;
7595
7596 ant_div_snr_diff = nla_get_u32(attr);
7597 hdd_debug("snr diff: %x", ant_div_snr_diff);
7598
7599 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(ant_div_snr_diff);
7600 hdd_debug("usrcfg: %x", ant_div_usrcfg);
7601
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007602 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson91f90ff2018-11-16 07:53:37 -08007603 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7604 ant_div_usrcfg, PDEV_CMD);
7605 if (errno)
7606 hdd_err("Failed to set snr diff, %d", errno);
7607
7608 return errno;
7609}
7610
Jeff Johnson77177bc2018-11-16 08:14:20 -08007611static int hdd_config_ant_div_probe_dwell_time(struct hdd_adapter *adapter,
7612 const struct nlattr *attr)
7613{
7614 uint32_t dwell_time;
7615 uint32_t ant_div_usrcfg;
7616 int errno;
7617
7618 dwell_time = nla_get_u32(attr);
7619 hdd_debug("dwell time: %x", dwell_time);
7620
7621 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(dwell_time);
7622 hdd_debug("usrcfg: %x", ant_div_usrcfg);
7623
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007624 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson77177bc2018-11-16 08:14:20 -08007625 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7626 ant_div_usrcfg, PDEV_CMD);
7627 if (errno)
7628 hdd_err("Failed to set probe dwell time, %d", errno);
7629
7630 return errno;
7631}
7632
Jeff Johnsonaa172222018-11-16 09:16:11 -08007633static int hdd_config_ant_div_chain(struct hdd_adapter *adapter,
7634 const struct nlattr *attr)
7635{
7636 uint32_t antdiv_chain;
7637 int errno;
7638
7639 antdiv_chain = nla_get_u32(attr);
7640 hdd_debug("antdiv_chain: %d", antdiv_chain);
7641
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007642 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonaa172222018-11-16 09:16:11 -08007643 WMI_PDEV_PARAM_FORCE_CHAIN_ANT,
7644 antdiv_chain, PDEV_CMD);
7645 if (errno)
7646 hdd_err("Failed to set chain, %d", errno);
7647
7648 return errno;
7649}
7650
Jeff Johnsonef427ad2018-11-16 09:22:17 -08007651static int hdd_config_ant_div_selftest(struct hdd_adapter *adapter,
7652 const struct nlattr *attr)
7653{
7654 uint32_t antdiv_selftest;
7655 int errno;
7656
7657 antdiv_selftest = nla_get_u32(attr);
7658 hdd_debug("antdiv_selftest: %d", antdiv_selftest);
7659
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007660 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonef427ad2018-11-16 09:22:17 -08007661 WMI_PDEV_PARAM_ANT_DIV_SELFTEST,
7662 antdiv_selftest, PDEV_CMD);
7663 if (errno)
7664 hdd_err("Failed to set selftest, %d", errno);
7665
7666 return errno;
7667}
7668
Jeff Johnsonae21be82018-11-16 09:43:53 -08007669static int hdd_config_ant_div_selftest_intvl(struct hdd_adapter *adapter,
7670 const struct nlattr *attr)
7671{
7672 uint32_t antdiv_selftest_intvl;
7673 int errno;
7674
7675 antdiv_selftest_intvl = nla_get_u32(attr);
7676 hdd_debug("antdiv_selftest_intvl: %d", antdiv_selftest_intvl);
7677
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007678 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonae21be82018-11-16 09:43:53 -08007679 WMI_PDEV_PARAM_ANT_DIV_SELFTEST_INTVL,
7680 antdiv_selftest_intvl, PDEV_CMD);
7681 if (errno)
7682 hdd_err("Failed to set selftest interval, %d", errno);
7683
7684 return errno;
7685}
7686
Jeff Johnson3a25de82018-11-16 07:26:46 -08007687static int hdd_config_ignore_assoc_disallowed(struct hdd_adapter *adapter,
7688 const struct nlattr *attr)
7689{
7690 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7691 uint8_t ignore_assoc_disallowed;
7692
7693 ignore_assoc_disallowed = nla_get_u8(attr);
7694 hdd_debug("%u", ignore_assoc_disallowed);
7695 if ((ignore_assoc_disallowed < QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
7696 (ignore_assoc_disallowed > QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
7697 return -EINVAL;
7698
7699 sme_update_session_param(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007700 adapter->vdev_id,
Jeff Johnson3a25de82018-11-16 07:26:46 -08007701 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
7702 ignore_assoc_disallowed);
7703
7704 return 0;
7705}
7706
Jeff Johnson72dc91e2018-11-16 08:46:12 -08007707static int hdd_config_restrict_offchannel(struct hdd_adapter *adapter,
7708 const struct nlattr *attr)
7709{
7710 uint8_t restrict_offchan;
7711
7712 restrict_offchan = nla_get_u8(attr);
7713 hdd_debug("%u", restrict_offchan);
7714
7715 if (restrict_offchan > 1) {
7716 hdd_err("Invalid value %u", restrict_offchan);
7717 return -EINVAL;
7718 }
7719
7720 return wlan_hdd_handle_restrict_offchan_config(adapter,
7721 restrict_offchan);
7722}
7723
Jeff Johnson320feeb2018-11-16 10:14:24 -08007724static int hdd_config_total_beacon_miss_count(struct hdd_adapter *adapter,
7725 const struct nlattr *attr)
7726{
7727 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7728 uint8_t first_miss_count;
7729 uint8_t final_miss_count;
7730 uint8_t total_miss_count;
7731 QDF_STATUS status;
7732
7733 total_miss_count = nla_get_u8(attr);
7734 ucfg_mlme_get_roam_bmiss_first_bcnt(hdd_ctx->psoc,
7735 &first_miss_count);
7736 if (total_miss_count <= first_miss_count) {
7737 hdd_err("Total %u needs to exceed first %u",
7738 total_miss_count, first_miss_count);
7739 return -EINVAL;
7740 }
7741
7742 final_miss_count = total_miss_count - first_miss_count;
7743
7744 hdd_debug("First count %u, final count %u",
7745 first_miss_count, final_miss_count);
7746
7747 /*****
Jeff Johnson55d2ab42019-03-06 11:43:49 -08007748 * TODO: research why is 0 being passed for vdev id???
Jeff Johnson320feeb2018-11-16 10:14:24 -08007749 */
7750 status = sme_set_roam_bmiss_final_bcnt(hdd_ctx->mac_handle,
7751 0,
7752 final_miss_count);
7753 if (QDF_IS_STATUS_ERROR(status)) {
7754 hdd_err("Failed to set final count, status %u", status);
7755 return qdf_status_to_os_return(status);
7756 }
7757
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007758 status = sme_set_bmiss_bcnt(adapter->vdev_id,
Jeff Johnson320feeb2018-11-16 10:14:24 -08007759 first_miss_count,
7760 final_miss_count);
7761 if (QDF_IS_STATUS_ERROR(status))
7762 hdd_err("Failed to set count, status %u", status);
7763
7764 return qdf_status_to_os_return(status);
7765}
7766
Jeff Johnson2502ddd2018-11-16 10:59:30 -08007767static int hdd_config_latency_level(struct hdd_adapter *adapter,
7768 const struct nlattr *attr)
7769{
7770 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7771 uint16_t latency_level;
7772 QDF_STATUS status;
7773
7774 latency_level = nla_get_u16(attr);
7775 switch (latency_level) {
7776 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL:
7777 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE:
7778 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW:
7779 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW:
7780 /* valid values */
7781 break;
7782 default:
7783 hdd_err("Invalid value %u", latency_level);
7784 return -EINVAL;
7785 }
7786
7787 /* Map the latency value to the level which fw expected
7788 * 0 - normal, 1 - moderate, 2 - low, 3 - ultralow
7789 */
Paul Zhang1ef2b7c2019-10-31 16:09:55 +08007790 adapter->latency_level = latency_level - 1;
Jeff Johnson2502ddd2018-11-16 10:59:30 -08007791 status = sme_set_wlm_latency_level(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007792 adapter->vdev_id,
Paul Zhang1ef2b7c2019-10-31 16:09:55 +08007793 adapter->latency_level);
Jeff Johnson2502ddd2018-11-16 10:59:30 -08007794 if (QDF_IS_STATUS_ERROR(status))
7795 hdd_err("set latency level failed, %u", status);
7796
7797 return qdf_status_to_os_return(status);
7798}
7799
Jeff Johnson0a315912018-11-16 11:18:21 -08007800static int hdd_config_disable_fils(struct hdd_adapter *adapter,
7801 const struct nlattr *attr)
7802{
7803 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7804 uint8_t disable_fils;
7805 bool enabled;
7806 QDF_STATUS status;
7807
7808 /* ignore unless in STA mode */
7809 if (adapter->device_mode != QDF_STA_MODE)
7810 return 0;
7811
7812 disable_fils = nla_get_u8(attr);
7813 hdd_debug("%u", disable_fils);
7814
7815 enabled = !disable_fils;
7816 status = ucfg_mlme_set_fils_enabled_info(hdd_ctx->psoc, enabled);
7817 if (QDF_IS_STATUS_ERROR(status))
7818 hdd_err("could not set fils enabled info, %d", status);
7819
7820 status = ucfg_mlme_set_enable_bcast_probe_rsp(hdd_ctx->psoc, enabled);
7821 if (QDF_IS_STATUS_ERROR(status))
7822 hdd_err("could not set enable bcast probe resp info, %d",
7823 status);
7824
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007825 status = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson0a315912018-11-16 11:18:21 -08007826 WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE,
7827 !disable_fils, VDEV_CMD);
7828 if (QDF_IS_STATUS_ERROR(status))
7829 hdd_err("failed to set enable bcast probe resp, %d",
7830 status);
7831
7832 return qdf_status_to_os_return(status);
7833}
7834
Jeff Johnson0bdbb962018-11-16 11:42:10 -08007835static int hdd_config_rsn_ie(struct hdd_adapter *adapter,
7836 const struct nlattr *attr)
7837{
7838 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson0bdbb962018-11-16 11:42:10 -08007839 uint8_t force_rsne_override;
7840
Jeff Johnson0bdbb962018-11-16 11:42:10 -08007841 force_rsne_override = nla_get_u8(attr);
7842 if (force_rsne_override > 1) {
7843 hdd_err("Invalid value %d", force_rsne_override);
7844 return -EINVAL;
7845 }
7846
7847 hdd_ctx->force_rsne_override = force_rsne_override;
7848 hdd_debug("force_rsne_override - %d", force_rsne_override);
7849
7850 return 0;
7851}
7852
Jeff Johnson7acca0d2018-11-16 11:53:18 -08007853static int hdd_config_gtx(struct hdd_adapter *adapter,
7854 const struct nlattr *attr)
7855{
7856 uint8_t config_gtx;
7857 int errno;
7858
7859 config_gtx = nla_get_u8(attr);
7860 if (config_gtx > 1) {
7861 hdd_err_rl("Invalid config_gtx value %d", config_gtx);
7862 return -EINVAL;
7863 }
7864
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007865 errno = sme_cli_set_command(adapter->vdev_id,
Jeff Johnson7acca0d2018-11-16 11:53:18 -08007866 WMI_VDEV_PARAM_GTX_ENABLE,
7867 config_gtx, VDEV_CMD);
7868 if (errno)
7869 hdd_err("Failed to set GTX, %d", errno);
7870
7871 return errno;
7872}
7873
lifeng66831662017-05-19 16:01:35 +08007874/**
Srinivas Dasari37e37312019-06-30 23:50:24 +05307875 * hdd_config_disconnect_ies() - Configure disconnect IEs
7876 * @adapter: Pointer to HDD adapter
7877 * @attr: array of pointer to struct nlattr
7878 *
7879 * Return: 0 on success; error number otherwise
7880 */
7881static int hdd_config_disconnect_ies(struct hdd_adapter *adapter,
7882 const struct nlattr *attr)
7883{
7884 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7885 QDF_STATUS status;
7886
7887 hdd_debug("IE len %u session %u device mode %u",
7888 nla_len(attr), adapter->vdev_id, adapter->device_mode);
7889 if (!nla_len(attr) ||
7890 nla_len(attr) > SIR_MAC_MAX_ADD_IE_LENGTH + 2 ||
7891 !wlan_is_ie_valid(nla_data(attr), nla_len(attr))) {
7892 hdd_err("Invalid disconnect IEs");
7893 return -EINVAL;
7894 }
7895
7896 status = sme_set_disconnect_ies(hdd_ctx->mac_handle,
7897 adapter->vdev_id,
7898 nla_data(attr),
7899 nla_len(attr));
7900 if (QDF_IS_STATUS_ERROR(status))
7901 hdd_err("Failed to set disconnect_ies");
7902
7903 return qdf_status_to_os_return(status);
7904}
7905
Paul Zhangc9dbaee2019-06-23 22:07:31 +08007906#ifdef WLAN_FEATURE_ELNA
7907/**
7908 * hdd_set_elna_bypass() - Set eLNA bypass
7909 * @adapter: Pointer to HDD adapter
7910 * @attr: Pointer to struct nlattr
7911 *
7912 * Return: 0 on success; error number otherwise
7913 */
7914static int hdd_set_elna_bypass(struct hdd_adapter *adapter,
7915 const struct nlattr *attr)
7916{
7917 int ret;
7918 struct wlan_objmgr_vdev *vdev;
7919
7920 vdev = hdd_objmgr_get_vdev(adapter);
7921 if (!vdev)
7922 return -EINVAL;
7923
7924 ret = os_if_fwol_set_elna_bypass(vdev, attr);
7925
7926 hdd_objmgr_put_vdev(vdev);
7927
7928 return ret;
7929}
7930#endif
7931
Srinivas Dasari37e37312019-06-30 23:50:24 +05307932/**
Jeff Johnsonb48efe22018-11-15 11:53:09 -08007933 * typedef independent_setter_fn - independent attribute handler
7934 * @adapter: The adapter being configured
7935 * @attr: The nl80211 attribute being applied
7936 *
7937 * Defines the signature of functions in the independent attribute vtable
7938 *
7939 * Return: 0 if the attribute was handled successfully, otherwise an errno
7940 */
7941typedef int (*independent_setter_fn)(struct hdd_adapter *adapter,
7942 const struct nlattr *attr);
7943
7944/**
7945 * struct independent_setters
7946 * @id: vendor attribute which this entry handles
7947 * @cb: callback function to invoke to process the attribute when present
7948 */
7949struct independent_setters {
7950 uint32_t id;
7951 independent_setter_fn cb;
7952};
7953
7954/* vtable for independent setters */
7955static const struct independent_setters independent_setters[] = {
Jeff Johnson522464b2018-11-15 13:07:26 -08007956 {QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES,
7957 hdd_config_scan_default_ies},
Jeff Johnson7f4fd702018-11-14 11:19:52 -08007958 {QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT,
7959 hdd_config_fine_time_measurement},
Jeff Johnsonbcaeafb2018-11-14 12:14:24 -08007960 {QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM,
7961 hdd_config_modulated_dtim},
Jeff Johnson6db91622018-11-14 12:33:28 -08007962 {QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL,
7963 hdd_config_listen_interval},
Jeff Johnson9381d032018-11-14 12:42:22 -08007964 {QCA_WLAN_VENDOR_ATTR_CONFIG_LRO,
7965 hdd_config_lro},
Jeff Johnson3d4f64c2018-11-14 13:13:04 -08007966 {QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE,
7967 hdd_config_scan_enable},
Jeff Johnson1feb8a62018-11-14 13:18:41 -08007968 {QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER,
Alan Chen10989ba2020-04-01 18:06:25 -07007969 hdd_config_power},
Jeff Johnsonf15ede02018-11-14 13:27:13 -08007970 {QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR,
7971 hdd_config_stats_avg_factor},
Jeff Johnson47e2e842018-11-14 13:49:43 -08007972 {QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME,
7973 hdd_config_guard_time},
Jeff Johnsonf3827502018-11-14 14:00:58 -08007974 {QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY,
7975 hdd_config_non_agg_retry},
Jeff Johnsonb9021002018-11-15 15:51:36 -08007976 {QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY,
7977 hdd_config_agg_retry},
Jeff Johnson0e8259c2018-11-15 19:44:57 -08007978 {QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY,
7979 hdd_config_mgmt_retry},
Jeff Johnson6b48a2f2018-11-15 19:48:47 -08007980 {QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY,
7981 hdd_config_ctrl_retry},
Jeff Johnson98214742018-11-15 19:56:37 -08007982 {QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY,
7983 hdd_config_propagation_delay},
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08007984 {QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY,
7985 hdd_config_propagation_abs_delay},
Jeff Johnson7c5e6dc2018-11-15 21:20:18 -08007986 {QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT,
7987 hdd_config_tx_fail_count},
Jeff Johnson7766fd22018-11-15 21:52:37 -08007988 {QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND,
7989 hdd_config_channel_avoidance_ind},
Jeff Johnsonf9871e42018-11-15 22:24:06 -08007990 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA,
7991 hdd_config_ant_div_ena},
Jeff Johnson91f90ff2018-11-16 07:53:37 -08007992 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF,
7993 hdd_config_ant_div_snr_diff},
Jeff Johnson77177bc2018-11-16 08:14:20 -08007994 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME,
7995 hdd_config_ant_div_probe_dwell_time},
Jeff Johnsonaa172222018-11-16 09:16:11 -08007996 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN,
7997 hdd_config_ant_div_chain},
Jeff Johnsonef427ad2018-11-16 09:22:17 -08007998 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST,
7999 hdd_config_ant_div_selftest},
Jeff Johnsonae21be82018-11-16 09:43:53 -08008000 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL,
8001 hdd_config_ant_div_selftest_intvl},
Jeff Johnson3a25de82018-11-16 07:26:46 -08008002 {QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED,
8003 hdd_config_ignore_assoc_disallowed},
Jeff Johnson72dc91e2018-11-16 08:46:12 -08008004 {QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL,
8005 hdd_config_restrict_offchannel},
Jeff Johnson320feeb2018-11-16 10:14:24 -08008006 {QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT,
8007 hdd_config_total_beacon_miss_count},
Jeff Johnson2502ddd2018-11-16 10:59:30 -08008008 {QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL,
8009 hdd_config_latency_level},
Jeff Johnson0a315912018-11-16 11:18:21 -08008010 {QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS,
8011 hdd_config_disable_fils},
Jeff Johnson0bdbb962018-11-16 11:42:10 -08008012 {QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE,
8013 hdd_config_rsn_ie},
Jeff Johnson7acca0d2018-11-16 11:53:18 -08008014 {QCA_WLAN_VENDOR_ATTR_CONFIG_GTX,
8015 hdd_config_gtx},
Srinivas Dasari37e37312019-06-30 23:50:24 +05308016 {QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES,
8017 hdd_config_disconnect_ies},
Paul Zhangc9dbaee2019-06-23 22:07:31 +08008018#ifdef WLAN_FEATURE_ELNA
8019 {QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
8020 hdd_set_elna_bypass},
8021#endif
sheenam monga17452ef2020-02-24 13:23:13 +05308022 {QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
8023 hdd_set_roam_reason_vsie_status},
Alan Chen140cc3f2020-06-16 18:41:55 -07008024 {QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT,
8025 hdd_config_power},
Rakesh Pillai6c48d132020-06-30 15:22:01 +05308026 {QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE,
8027 hdd_config_udp_qos_upgrade_threshold},
Jeff Johnsonb48efe22018-11-15 11:53:09 -08008028};
8029
Paul Zhangc9dbaee2019-06-23 22:07:31 +08008030#ifdef WLAN_FEATURE_ELNA
8031/**
8032 * hdd_get_elna_bypass() - Get eLNA bypass
8033 * @adapter: Pointer to HDD adapter
8034 * @skb: sk buffer to hold nl80211 attributes
8035 * @attr: Pointer to struct nlattr
8036 *
8037 * Return: 0 on success; error number otherwise
8038 */
8039static int hdd_get_elna_bypass(struct hdd_adapter *adapter,
8040 struct sk_buff *skb,
8041 const struct nlattr *attr)
8042{
8043 int ret;
8044 struct wlan_objmgr_vdev *vdev;
8045
8046 vdev = hdd_objmgr_get_vdev(adapter);
8047 if (!vdev)
8048 return -EINVAL;
8049
8050 ret = os_if_fwol_get_elna_bypass(vdev, skb, attr);
8051
8052 hdd_objmgr_put_vdev(vdev);
8053
8054 return ret;
8055}
8056#endif
8057
8058/**
sheenam monga17452ef2020-02-24 13:23:13 +05308059 * hdd_get_roam_reason_vsie_status() - Get roam_reason_vsie
8060 * @adapter: Pointer to HDD adapter
8061 * @skb: sk buffer to hold nl80211 attributes
8062 * @attr: Pointer to struct nlattr
8063 *
8064 * Return: 0 on success; error number otherwise
8065 */
8066#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8067static int hdd_get_roam_reason_vsie_status(struct hdd_adapter *adapter,
8068 struct sk_buff *skb,
8069 const struct nlattr *attr)
8070{
8071 uint8_t roam_reason_vsie_enabled;
8072 struct hdd_context *hdd_ctx = NULL;
8073 QDF_STATUS status;
8074
8075 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8076
8077 status = ucfg_mlme_get_roam_reason_vsie_status
8078 (hdd_ctx->psoc,
8079 &roam_reason_vsie_enabled);
8080 if (QDF_IS_STATUS_ERROR(status)) {
8081 hdd_err("get roam reason vsie failed");
8082 return -EINVAL;
8083 }
8084 hdd_debug("is roam_reason_vsie_enabled %d", roam_reason_vsie_enabled);
8085 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
8086 roam_reason_vsie_enabled)) {
8087 hdd_err("nla_put failure");
8088 return -EINVAL;
8089 }
8090
8091 return 0;
8092}
8093#else
8094static int hdd_get_roam_reason_vsie_status(struct hdd_adapter *adapter,
8095 struct sk_buff *skb,
8096 const struct nlattr *attr)
8097{
8098 return -EINVAL;
8099}
8100#endif
8101
8102/**
Paul Zhangc9dbaee2019-06-23 22:07:31 +08008103 * typedef config_getter_fn - get configuration handler
8104 * @adapter: The adapter being configured
8105 * @skb: sk buffer to hold nl80211 attributes
8106 * @attr: The nl80211 attribute being applied
8107 *
8108 * Defines the signature of functions in the attribute vtable
8109 *
8110 * Return: 0 if the attribute was handled successfully, otherwise an errno
8111 */
8112typedef int (*config_getter_fn)(struct hdd_adapter *adapter,
8113 struct sk_buff *skb,
8114 const struct nlattr *attr);
8115
8116/**
8117 * struct config_getters
8118 * @id: vendor attribute which this entry handles
8119 * @cb: callback function to invoke to process the attribute when present
8120 */
8121struct config_getters {
8122 uint32_t id;
8123 size_t max_attr_len;
8124 config_getter_fn cb;
8125};
8126
Alan Chen140cc3f2020-06-16 18:41:55 -07008127/**
8128 * hdd_get_optimized_power_config() - Get the number of spatial streams
8129 * supported by the adapter
8130 * @adapter: Pointer to HDD adapter
8131 * @skb: sk buffer to hold nl80211 attributes
8132 * @attr: Pointer to struct nlattr
8133 *
8134 * Return: 0 on success; error number otherwise
8135 */
8136static int hdd_get_optimized_power_config(struct hdd_adapter *adapter,
8137 struct sk_buff *skb,
8138 const struct nlattr *attr)
8139{
8140 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8141 uint8_t optimized_power_cfg;
8142 int errno;
8143
8144 errno = wlan_hdd_validate_context(hdd_ctx);
8145 if (errno)
8146 return errno;
8147
8148 optimized_power_cfg = ucfg_pmo_get_power_save_mode(hdd_ctx->psoc);
8149
8150 if (nla_put_u8(skb,
8151 QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT,
8152 optimized_power_cfg)) {
8153 hdd_err("nla_put failure");
8154 return -EINVAL;
8155 }
8156
8157 return 0;
8158}
8159
Paul Zhangc9dbaee2019-06-23 22:07:31 +08008160/* vtable for config getters */
8161static const struct config_getters config_getters[] = {
8162#ifdef WLAN_FEATURE_ELNA
8163 {QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
8164 sizeof(uint8_t),
8165 hdd_get_elna_bypass},
8166#endif
sheenam monga17452ef2020-02-24 13:23:13 +05308167 {QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
8168 sizeof(uint8_t),
8169 hdd_get_roam_reason_vsie_status},
Alan Chen140cc3f2020-06-16 18:41:55 -07008170 {QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT,
8171 sizeof(uint8_t),
8172 hdd_get_optimized_power_config},
Paul Zhangc9dbaee2019-06-23 22:07:31 +08008173};
8174
8175/**
8176 * hdd_get_configuration() - Handle get configuration
8177 * @adapter: adapter upon which the vendor command was received
8178 * @tb: parsed attribute array
8179 *
8180 * This is a table-driven function which dispatches attributes
8181 * in a QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION
8182 * vendor command.
8183 *
8184 * Return: 0 if there were no issues, otherwise errno of the last issue
8185 */
8186static int hdd_get_configuration(struct hdd_adapter *adapter,
8187 struct nlattr **tb)
8188{
8189 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8190 uint32_t i, id;
8191 unsigned long nl_buf_len = NLMSG_HDRLEN;
8192 struct sk_buff *skb;
8193 struct nlattr *attr;
8194 config_getter_fn cb;
8195 int errno = 0;
8196
8197 for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
8198 id = config_getters[i].id;
8199 attr = tb[id];
8200 if (!attr)
8201 continue;
8202
8203 nl_buf_len += NLA_HDRLEN +
8204 NLA_ALIGN(config_getters[i].max_attr_len);
8205 }
8206
8207 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8208 if (!skb) {
8209 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8210 return -ENOMEM;
8211 }
8212
8213 for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
8214 id = config_getters[i].id;
8215 attr = tb[id];
8216 if (!attr)
8217 continue;
8218
8219 cb = config_getters[i].cb;
8220 errno = cb(adapter, skb, attr);
8221 if (errno)
8222 break;
8223 }
8224
8225 if (errno) {
8226 hdd_err("Failed to get wifi configuration, errno = %d", errno);
8227 kfree_skb(skb);
8228 return -EINVAL;
8229 }
8230
8231 cfg80211_vendor_cmd_reply(skb);
8232
8233 return errno;
8234}
8235
Jeff Johnsonb48efe22018-11-15 11:53:09 -08008236/**
8237 * hdd_set_independent_configuration() - Handle independent attributes
8238 * @adapter: adapter upon which the vendor command was received
8239 * @tb: parsed attribute array
8240 *
8241 * This is a table-driven function which dispatches independent
8242 * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
8243 * vendor command. An attribute is considered independent if it
8244 * doesn't depend upon any other attributes
8245 *
8246 * Return: 0 if there were no issues, otherwise errno of the last issue
8247 */
8248static int hdd_set_independent_configuration(struct hdd_adapter *adapter,
8249 struct nlattr **tb)
8250{
8251 uint32_t i;
8252 uint32_t id;
8253 struct nlattr *attr;
8254 independent_setter_fn cb;
8255 int errno = 0;
8256 int ret;
8257
8258 for (i = 0; i < QDF_ARRAY_SIZE(independent_setters); i++) {
8259 id = independent_setters[i].id;
8260 attr = tb[id];
8261 if (!attr)
8262 continue;
8263
8264 cb = independent_setters[i].cb;
8265 ret = cb(adapter, attr);
8266 if (ret)
8267 errno = ret;
8268 }
8269
8270 return errno;
8271}
8272
8273/**
8274 * typedef interdependent_setter_fn - interdependent attribute handler
8275 * @adapter: The adapter being configured
8276 * @tb: The parsed nl80211 attributes being applied
8277 *
8278 * Defines the signature of functions in the interdependent attribute vtable
8279 *
8280 * Return: 0 if attributes were handled successfully, otherwise an errno
8281 */
8282typedef int (*interdependent_setter_fn)(struct hdd_adapter *adapter,
8283 struct nlattr **tb);
8284
8285/* vtable for interdependent setters */
8286static const interdependent_setter_fn interdependent_setters[] = {
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08008287 hdd_config_access_policy,
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08008288 hdd_config_mpdu_aggregation,
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08008289 hdd_config_ant_div_period,
Jeff Johnson1350e622018-11-16 18:36:55 -08008290 hdd_config_ant_div_snr_weight,
Jeff Johnson0dd687e2018-11-16 20:11:27 -08008291 wlan_hdd_cfg80211_wifi_set_reorder_timeout,
Jeff Johnson339ede82018-11-16 20:27:52 -08008292 wlan_hdd_cfg80211_wifi_set_rx_blocksize,
Jeff Johnsonb48efe22018-11-15 11:53:09 -08008293};
8294
8295/**
8296 * hdd_set_interdependent_configuration() - Handle interdependent attributes
8297 * @adapter: adapter upon which the vendor command was received
8298 * @tb: parsed attribute array
8299 *
8300 * This is a table-driven function which handles interdependent
8301 * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
8302 * vendor command. A set of attributes is considered interdependent if
8303 * they depend upon each other. In the typical case if one of the
8304 * attributes is present in the the attribute array, then all of the
8305 * attributes must be present.
8306 *
8307 * Return: 0 if there were no issues, otherwise errno of the last issue
8308 */
8309static int hdd_set_interdependent_configuration(struct hdd_adapter *adapter,
8310 struct nlattr **tb)
8311{
8312 uint32_t i;
8313 interdependent_setter_fn cb;
8314 int errno = 0;
8315 int ret;
8316
8317 for (i = 0; i < QDF_ARRAY_SIZE(interdependent_setters); i++) {
8318 cb = interdependent_setters[i];
8319 ret = cb(adapter, tb);
8320 if (ret)
8321 errno = ret;
8322 }
8323
8324 return errno;
8325}
8326
8327/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008328 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
8329 * vendor command
8330 *
8331 * @wiphy: wiphy device pointer
8332 * @wdev: wireless device pointer
8333 * @data: Vendor command data buffer
8334 * @data_len: Buffer length
8335 *
8336 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
8337 *
8338 * Return: Error code.
8339 */
8340static int
8341__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
8342 struct wireless_dev *wdev,
8343 const void *data,
8344 int data_len)
8345{
8346 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008347 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008348 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008349 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
Jeff Johnsonb48efe22018-11-15 11:53:09 -08008350 int errno;
Jeff Johnson3b2abe92017-12-15 09:03:47 -08008351 int ret;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05308352
Dustin Brownfdf17c12018-03-14 12:55:34 -07008353 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08008354
Anurag Chouhan6d760662016-02-20 16:05:43 +05308355 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008356 hdd_err("Command not allowed in FTM mode");
8357 return -EPERM;
8358 }
8359
Jeff Johnsonb48efe22018-11-15 11:53:09 -08008360 errno = wlan_hdd_validate_context(hdd_ctx);
8361 if (errno)
8362 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008363
Dustin Brown4ea21db2018-01-05 14:13:17 -08008364 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
8365 data_len, wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008366 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008367 return -EINVAL;
8368 }
8369
Jeff Johnsonb48efe22018-11-15 11:53:09 -08008370 ret = hdd_set_independent_configuration(adapter, tb);
8371 if (ret)
8372 errno = ret;
8373
8374 ret = hdd_set_interdependent_configuration(adapter, tb);
8375 if (ret)
8376 errno = ret;
8377
Jeff Johnsonb48efe22018-11-15 11:53:09 -08008378 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008379}
8380
8381/**
8382 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
8383 * vendor command
8384 *
8385 * @wiphy: wiphy device pointer
8386 * @wdev: wireless device pointer
8387 * @data: Vendor command data buffer
8388 * @data_len: Buffer length
8389 *
8390 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
8391 *
8392 * Return: EOK or other error codes.
8393 */
8394static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
8395 struct wireless_dev *wdev,
8396 const void *data,
8397 int data_len)
8398{
Dustin Browna09acf42018-11-08 12:32:26 +05308399 int errno;
8400 struct osif_vdev_sync *vdev_sync;
8401
8402 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
8403 if (errno)
8404 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008405
Dustin Browna09acf42018-11-08 12:32:26 +05308406 errno = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
8407 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008408
Dustin Browna09acf42018-11-08 12:32:26 +05308409 osif_vdev_sync_op_stop(vdev_sync);
8410
8411 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008412}
8413
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008414/**
Paul Zhangc9dbaee2019-06-23 22:07:31 +08008415 * __wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
8416 * vendor command
8417 * @wiphy: wiphy device pointer
8418 * @wdev: wireless device pointer
8419 * @data: Vendor command data buffer
8420 * @data_len: Buffer length
8421 *
8422 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
8423 *
8424 * Return: Error code.
8425 */
8426static int
8427__wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
8428 struct wireless_dev *wdev,
8429 const void *data,
8430 int data_len)
8431{
8432 struct net_device *dev = wdev->netdev;
8433 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8434 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
8435 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
8436 int errno;
8437 int ret;
8438
8439 hdd_enter_dev(dev);
8440
8441 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8442 hdd_err("Command not allowed in FTM mode");
8443 return -EPERM;
8444 }
8445
8446 errno = wlan_hdd_validate_context(hdd_ctx);
8447 if (errno)
8448 return errno;
8449
8450 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
8451 data_len, wlan_hdd_wifi_config_policy)) {
8452 hdd_err("invalid attr");
8453 return -EINVAL;
8454 }
8455
8456 ret = hdd_get_configuration(adapter, tb);
8457 if (ret)
8458 errno = ret;
8459
8460 return errno;
8461}
8462
8463/**
8464 * wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
8465 * vendor command
8466 *
8467 * @wiphy: wiphy device pointer
8468 * @wdev: wireless device pointer
8469 * @data: Vendor command data buffer
8470 * @data_len: Buffer length
8471 *
8472 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
8473 *
8474 * Return: EOK or other error codes.
8475 */
8476static int wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
8477 struct wireless_dev *wdev,
8478 const void *data,
8479 int data_len)
8480{
8481 int errno;
8482 struct osif_vdev_sync *vdev_sync;
8483
8484 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
8485 if (errno)
8486 return errno;
8487
8488 errno = __wlan_hdd_cfg80211_wifi_configuration_get(wiphy, wdev,
8489 data, data_len);
8490
8491 osif_vdev_sync_op_stop(vdev_sync);
8492
8493 return errno;
8494}
8495
Alan Chendf858ef2019-10-10 15:44:29 -07008496static void hdd_disable_runtime_pm_for_user(struct hdd_context *hdd_ctx)
8497{
8498 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
8499
8500 if (!ctx)
8501 return;
8502
8503 if (ctx->is_user_wakelock_acquired)
8504 return;
8505
8506 ctx->is_user_wakelock_acquired = true;
8507 qdf_runtime_pm_prevent_suspend(&ctx->user);
8508}
8509
Paul Zhangc9dbaee2019-06-23 22:07:31 +08008510/**
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008511 * __wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
8512 * vendor command
8513 *
8514 * @wiphy: wiphy device pointer
8515 * @wdev: wireless device pointer
8516 * @data: Vendor command data buffer
8517 * @data_len: Buffer length
8518 *
8519 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
8520 *
8521 * Return: Error code.
8522 */
8523static int
8524__wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
Srinivas Girigowdaa19eafd2018-09-07 15:28:21 -07008525 struct wireless_dev *wdev, const void *data, int data_len)
8526{
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008527 struct net_device *dev = wdev->netdev;
8528 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8529 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
8530 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1];
8531 int ret_val = 0;
8532 uint8_t cfg_val = 0;
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08008533 uint8_t set_val = 0;
Jeff Johnson46b4f0e2019-03-08 10:48:35 -08008534 struct sme_config_params *sme_config;
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008535 bool update_sme_cfg = false;
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08008536 uint8_t tid = 0, ac;
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008537 uint16_t buff_size = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008538 mac_handle_t mac_handle;
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308539 QDF_STATUS status;
8540 bool bval = false;
8541 uint8_t value = 0;
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +05308542 uint8_t wmm_mode = 0;
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07008543 uint32_t cmd_id;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008544
Dustin Brownfdf17c12018-03-14 12:55:34 -07008545 hdd_enter_dev(dev);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008546
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008547 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Min Liu74a1a502018-10-10 19:59:07 +08008548 if (!sme_config)
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008549 return -ENOMEM;
Min Liu74a1a502018-10-10 19:59:07 +08008550
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008551 mac_handle = hdd_ctx->mac_handle;
8552 sme_get_config_param(mac_handle, sme_config);
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008553
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008554 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8555 hdd_err("Command not allowed in FTM mode");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008556 ret_val = -EPERM;
8557 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008558 }
8559
8560 ret_val = wlan_hdd_validate_context(hdd_ctx);
8561 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008562 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008563
8564 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
8565 hdd_err("Driver Modules are closed, can not start logger");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008566 ret_val = -EINVAL;
8567 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008568 }
8569
8570 if (wlan_cfg80211_nla_parse(tb,
8571 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX,
8572 data, data_len, wlan_hdd_wifi_test_config_policy)) {
8573 hdd_err("invalid attr");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008574 ret_val = -EINVAL;
8575 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008576 }
8577
8578 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]) {
8579 cfg_val = nla_get_u8(tb[
8580 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]
8581 );
8582 hdd_debug("set addba accept req from peer value %d", cfg_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008583 ret_val = sme_set_addba_accept(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008584 cfg_val);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008585 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008586 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008587 }
8588
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08008589 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]) {
8590 cfg_val = nla_get_u8(tb[
8591 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]);
8592 hdd_debug("set HE MCS value 0x%0X", cfg_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008593 ret_val = sme_update_he_mcs(mac_handle, adapter->vdev_id,
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08008594 cfg_val);
8595 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008596 goto send_err;
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08008597 }
8598
Krunal Soni707eb782018-01-18 12:04:19 -08008599 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]) {
8600 cfg_val = nla_get_u8(tb[
8601 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]);
Krunal Soni707eb782018-01-18 12:04:19 -08008602 if (!cfg_val) {
Jeff Johnsone94ccd02019-04-02 15:02:56 -07008603 sme_config->csr_config.WMMSupportMode =
Krunal Soni707eb782018-01-18 12:04:19 -08008604 hdd_to_csr_wmm_mode(HDD_WMM_USER_MODE_NO_QOS);
8605 hdd_debug("wmm is disabled");
8606 } else {
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +05308607 status = ucfg_mlme_get_wmm_mode(hdd_ctx->psoc,
8608 &wmm_mode);
8609 if (!QDF_IS_STATUS_SUCCESS(status)) {
8610 hdd_err("Get wmm_mode failed");
8611 return QDF_STATUS_E_FAILURE;
8612 }
Jeff Johnsone94ccd02019-04-02 15:02:56 -07008613 sme_config->csr_config.WMMSupportMode =
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +05308614 hdd_to_csr_wmm_mode(wmm_mode);
Krunal Soni707eb782018-01-18 12:04:19 -08008615 hdd_debug("using wmm default value");
8616 }
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008617 update_sme_cfg = true;
Krunal Soni707eb782018-01-18 12:04:19 -08008618 }
8619
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08008620 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]) {
8621 cfg_val = nla_get_u8(tb[
8622 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]);
8623 if (cfg_val) {
8624 /*Auto BA mode*/
8625 set_val = 0;
8626 hdd_debug("BA operating mode is set to auto");
8627 } else {
8628 /*Manual BA mode*/
8629 set_val = 1;
8630 hdd_debug("BA operating mode is set to Manual");
8631 }
8632
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008633 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08008634 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
Kiran Kumar Lokere015f77f2018-04-24 18:25:28 -07008635 if (ret_val) {
8636 hdd_err("Set BA operating mode failed");
8637 goto send_err;
8638 }
8639 if (!cfg_val) {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008640 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere015f77f2018-04-24 18:25:28 -07008641 WMI_VDEV_PARAM_AMSDU_AGGREGATION_SIZE_OPTIMIZATION,
8642 0, VDEV_CMD);
8643 }
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08008644 }
8645
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08008646 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]) {
8647 cfg_val = nla_get_u8(tb[
8648 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]
8649 );
8650 if (cfg_val > HE_FRAG_LEVEL1)
8651 set_val = HE_FRAG_LEVEL1;
8652 else
8653 set_val = cfg_val;
8654
8655 hdd_debug("set HE fragmention to %d", set_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008656 ret_val = sme_update_he_frag_supp(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008657 adapter->vdev_id, set_val);
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08008658 }
8659
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008660 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]) {
8661 cfg_val = nla_get_u8(tb[
8662 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]);
Jeff Johnsone94ccd02019-04-02 15:02:56 -07008663 sme_config->csr_config.wep_tkip_in_he = cfg_val;
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008664 hdd_debug("Set WEP/TKIP allow in HE %d", cfg_val);
8665
8666 update_sme_cfg = true;
8667 }
8668
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008669 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]) {
8670 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]) {
8671 tid = nla_get_u8(tb[
8672 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]);
8673 } else {
8674 hdd_err("TID is not set for ADD/DEL BA cfg");
8675 ret_val = -EINVAL;
8676 goto send_err;
8677 }
8678 cfg_val = nla_get_u8(tb[
8679 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]);
8680 if (cfg_val == QCA_WLAN_ADD_BA) {
8681 if (tb[
8682 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE])
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07008683 buff_size = nla_get_u16(tb[
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008684 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008685 ret_val = sme_send_addba_req(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008686 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008687 tid, buff_size);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008688 } else if (cfg_val == QCA_WLAN_DELETE_BA) {
8689 } else {
8690 hdd_err("Invalid BA session cfg");
8691 ret_val = -EINVAL;
8692 goto send_err;
8693 }
8694 } else if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]) {
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07008695 buff_size = nla_get_u16(tb[
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008696 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
8697 hdd_debug("set buff size to %d for all tids", buff_size);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008698 ret_val = sme_set_ba_buff_size(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008699 adapter->vdev_id, buff_size);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008700 if (ret_val)
8701 goto send_err;
8702 if (buff_size > 64)
8703 /* Configure ADDBA req buffer size to 256 */
8704 set_val = 3;
8705 else
8706 /* Configure ADDBA req buffer size to 64 */
8707 set_val = 2;
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008708 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008709 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07008710 if (ret_val)
8711 hdd_err("Failed to set BA operating mode %d", set_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008712 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07008713 GEN_VDEV_PARAM_AMPDU,
8714 buff_size, GEN_CMD);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008715 }
8716
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08008717 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]) {
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07008718 int he_mcs_val;
Srinivas Girigowda50335342018-09-07 15:21:01 -07008719
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08008720 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]) {
8721 ac = nla_get_u8(tb[
8722 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]);
8723 } else {
8724 hdd_err("AC is not set for NO ACK policy config");
8725 ret_val = -EINVAL;
8726 goto send_err;
8727 }
8728 cfg_val = nla_get_u8(tb[
8729 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]);
8730 hdd_debug("Set NO_ACK to %d for ac %d", cfg_val, ac);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008731 ret_val = sme_set_no_ack_policy(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008732 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008733 cfg_val, ac);
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07008734 if (cfg_val) {
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308735 status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc,
8736 &bval);
8737 if (!QDF_IS_STATUS_SUCCESS(status))
8738 hdd_err("unable to get vht_enable2x2");
8739 if (bval)
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07008740 /*2x2 MCS 5 value*/
8741 he_mcs_val = 0x45;
8742 else
8743 /*1x1 MCS 5 value*/
8744 he_mcs_val = 0x25;
8745
8746 if (hdd_set_11ax_rate(adapter, he_mcs_val, NULL))
8747 hdd_err("HE MCS set failed, MCS val %0x",
8748 he_mcs_val);
8749 } else {
8750 if (hdd_set_11ax_rate(adapter, 0xFF, NULL))
8751 hdd_err("disable fixed rate failed");
8752 }
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08008753 }
8754
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08008755 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]) {
8756 cfg_val = nla_get_u8(tb[
8757 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]);
8758 hdd_debug("Set HE LTF to %d", cfg_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008759 ret_val = sme_set_auto_rate_he_ltf(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008760 adapter->vdev_id,
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08008761 cfg_val);
8762 if (ret_val)
8763 sme_err("Failed to set auto rate HE LTF");
8764
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008765 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08008766 WMI_VDEV_PARAM_HE_LTF,
8767 cfg_val, VDEV_CMD);
8768 if (ret_val)
8769 goto send_err;
8770 }
8771
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07008772 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]) {
8773 cfg_val = nla_get_u8(tb[
8774 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]);
8775 hdd_debug("Set Tx beamformee to %d", cfg_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008776 ret_val = sme_update_tx_bfee_supp(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008777 adapter->vdev_id,
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07008778 cfg_val);
8779 if (ret_val)
8780 sme_err("Failed to set Tx beamformee cap");
8781
8782 }
8783
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008784 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]) {
8785 cfg_val = nla_get_u8(tb[
8786 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]);
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308787 status = ucfg_mlme_cfg_get_vht_tx_bfee_ant_supp(hdd_ctx->psoc,
Abhinav Kumare057b412018-10-09 17:28:16 +05308788 &value);
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308789 if (!QDF_IS_STATUS_SUCCESS(status))
8790 hdd_err("unable to get tx_bfee_ant_supp");
8791
Kiran Kumar Lokerea67af052018-12-12 19:18:51 -08008792 if (!cfg_in_range(CFG_VHT_BEAMFORMEE_ANT_SUPP, cfg_val)) {
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008793 hdd_err("NSTS %d not supported, supp_val %d", cfg_val,
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308794 value);
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008795 ret_val = -ENOTSUPP;
8796 goto send_err;
8797 }
8798 hdd_debug("Set Tx beamformee NSTS to %d", cfg_val);
8799 ret_val = sme_update_tx_bfee_nsts(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008800 adapter->vdev_id,
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008801 cfg_val,
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308802 value);
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008803 if (ret_val)
8804 sme_err("Failed to set Tx beamformee cap");
8805
8806 }
8807
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008808 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]) {
8809 cfg_val = nla_get_u8(tb[
8810 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]);
8811 if (cfg_val) {
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07008812 hdd_debug("Set HE mac padding dur to %d", cfg_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008813 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008814 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
8815 0, VDEV_CMD);
8816 if (ret_val)
8817 hdd_err("MU_EDCA update disable failed");
8818 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
8819 sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
8820 if (sme_update_mu_edca_params(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008821 adapter->vdev_id))
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008822 hdd_err("Failed to send mu edca params");
8823 } else {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008824 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008825 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
8826 1, VDEV_CMD);
8827 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
8828 }
8829 ret_val = sme_update_he_trigger_frm_mac_pad(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008830 adapter->vdev_id,
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008831 cfg_val);
8832 if (ret_val)
8833 hdd_err("Failed to set Trig frame mac padding cap");
8834 }
8835
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07008836 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]) {
8837 cfg_val = nla_get_u8(tb[
8838 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]);
8839 if (cfg_val) {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008840 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07008841 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
8842 0, VDEV_CMD);
8843 if (ret_val)
8844 hdd_err("MU_EDCA update disable failed");
8845 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
8846 sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
8847 if (sme_update_mu_edca_params(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008848 adapter->vdev_id))
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07008849 hdd_err("Failed to send mu edca params");
8850 } else {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008851 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07008852 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
8853 1, VDEV_CMD);
8854 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
8855 }
8856 }
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07008857
8858 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]) {
8859 cfg_val = nla_get_u8(tb[
8860 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]);
8861 ret_val = sme_update_he_om_ctrl_supp(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008862 adapter->vdev_id,
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07008863 cfg_val);
8864 }
8865
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008866 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX;
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07008867 if (tb[cmd_id]) {
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008868 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX + 1];
8869 struct nlattr *curr_attr;
8870 int tmp, rc;
8871 nla_for_each_nested(curr_attr, tb[cmd_id], tmp) {
8872 rc = wlan_cfg80211_nla_parse(
8873 tb2, QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX,
8874 nla_data(curr_attr),
8875 nla_len(curr_attr),
8876 qca_wlan_vendor_attr_he_omi_tx_policy);
8877 if (rc) {
8878 hdd_err("Invalid ATTR");
8879 goto send_err;
8880 }
8881 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW;
8882 if (tb2[cmd_id]) {
8883 cfg_val = nla_get_u8(tb2[cmd_id]);
8884 ret_val = sme_set_he_om_ctrl_param(
8885 hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008886 adapter->vdev_id,
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008887 cmd_id, cfg_val);
8888 }
8889 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS;
8890 if (tb2[cmd_id]) {
8891 cfg_val = nla_get_u8(tb2[cmd_id]);
8892 ret_val = sme_set_he_om_ctrl_param(
8893 hdd_ctx->mac_handle,
8894 adapter->vdev_id,
8895 cmd_id, cfg_val);
8896 }
8897
8898 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE;
8899 if (tb2[cmd_id]) {
8900 cfg_val = nla_get_u8(tb2[cmd_id]);
8901 ret_val = sme_set_he_om_ctrl_param(
8902 hdd_ctx->mac_handle,
8903 adapter->vdev_id,
8904 cmd_id, cfg_val);
8905 }
8906
8907 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS;
8908 if (tb2[cmd_id]) {
8909 cfg_val = nla_get_u8(tb2[cmd_id]);
8910 ret_val = sme_set_he_om_ctrl_param(
8911 hdd_ctx->mac_handle,
8912 adapter->vdev_id,
8913 cmd_id, cfg_val);
8914 }
Kiran Kumar Lokere49e3aff2019-02-06 17:00:48 -08008915
8916 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE;
8917 if (tb2[cmd_id]) {
8918 cfg_val = nla_get_u8(tb2[cmd_id]);
8919 ret_val = sme_set_he_om_ctrl_param(
8920 hdd_ctx->mac_handle,
8921 adapter->vdev_id,
8922 cmd_id, cfg_val);
8923 }
8924
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008925 }
8926 if (ret_val) {
8927 sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
8928 goto send_err;
8929 }
8930 ret_val = sme_send_he_om_ctrl_update(hdd_ctx->mac_handle,
8931 adapter->vdev_id);
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07008932 }
8933
8934 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG])
8935 sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
8936
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07008937 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU;
8938 if (tb[cmd_id]) {
8939 cfg_val = nla_get_u8(tb[cmd_id]);
8940 hdd_debug("Configure Tx SU PPDU enable %d", cfg_val);
8941 if (cfg_val)
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008942 sme_config_su_ppdu_queue(adapter->vdev_id, true);
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07008943 else
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008944 sme_config_su_ppdu_queue(adapter->vdev_id, false);
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07008945 }
8946
Kiran Kumar Lokerea1c29ec2019-02-25 18:19:00 -08008947 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT;
8948 if (tb[cmd_id]) {
8949 cfg_val = nla_get_u8(tb[cmd_id]);
8950 hdd_debug("Configure 2G VHT support %d", cfg_val);
8951 ucfg_mlme_set_vht_for_24ghz(hdd_ctx->psoc,
8952 (cfg_val ? true : false));
8953 }
8954
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008955 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP;
8956 if (tb[cmd_id]) {
8957 cfg_val = nla_get_u8(tb[cmd_id]);
8958 hdd_debug("Configure +HTC_HE support %d", cfg_val);
8959 sme_update_he_htc_he_supp(hdd_ctx->mac_handle,
8960 adapter->vdev_id,
8961 (cfg_val ? true : false));
8962 }
8963
Kiran Kumar Lokere921b5a52019-02-24 21:53:20 -08008964 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS;
8965 if (tb[cmd_id]) {
Alan Chendf858ef2019-10-10 15:44:29 -07008966 hdd_disable_runtime_pm_for_user(hdd_ctx);
Kiran Kumar Lokere921b5a52019-02-24 21:53:20 -08008967 cfg_val = nla_get_u8(tb[cmd_id]);
8968 hdd_debug("Configure HE testbed defaults %d", cfg_val);
8969 if (!cfg_val)
8970 sme_reset_he_caps(hdd_ctx->mac_handle,
8971 adapter->vdev_id);
8972 else
8973 sme_set_he_testbed_def(hdd_ctx->mac_handle,
8974 adapter->vdev_id);
8975 }
8976
Kiran Kumar Lokereee205772018-09-27 00:27:27 -07008977 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU;
8978 if (tb[cmd_id]) {
8979 cfg_val = nla_get_u8(tb[cmd_id]);
8980 hdd_debug("Configure Action frame Tx in TB PPDU %d", cfg_val);
8981 sme_config_action_tx_in_tb_ppdu(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008982 adapter->vdev_id, cfg_val);
Kiran Kumar Lokereee205772018-09-27 00:27:27 -07008983 }
8984
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008985 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP]) {
8986 struct wmi_twt_add_dialog_param params = {0};
8987 struct hdd_station_ctx *hdd_sta_ctx =
8988 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8989 uint32_t wake_intvl_exp = 0, result = 0;
8990 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1];
8991 struct nlattr *twt_session;
8992 int tmp, rc;
Kiran Kumar Lokere54819a32019-10-04 18:30:43 -07008993 uint32_t congestion_timeout = 0;
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008994
8995 if ((adapter->device_mode != QDF_STA_MODE &&
8996 adapter->device_mode != QDF_P2P_CLIENT_MODE) ||
8997 hdd_sta_ctx->conn_info.conn_state !=
8998 eConnectionState_Associated) {
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308999 hdd_err_rl("Invalid state, vdev %d mode %d state %d",
9000 adapter->vdev_id, adapter->device_mode,
9001 hdd_sta_ctx->conn_info.conn_state);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009002 goto send_err;
9003 }
9004
9005 qdf_mem_copy(params.peer_macaddr,
9006 hdd_sta_ctx->conn_info.bssid.bytes,
9007 QDF_MAC_ADDR_SIZE);
9008 params.vdev_id = adapter->vdev_id;
9009 params.dialog_id = 0;
9010
9011 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP;
9012 nla_for_each_nested(twt_session, tb[cmd_id], tmp) {
9013 rc = wlan_cfg80211_nla_parse(
9014 tb2, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX,
9015 nla_data(twt_session),
9016 nla_len(twt_session),
9017 qca_wlan_vendor_twt_add_dialog_policy);
9018 if (rc) {
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05309019 hdd_err_rl("Invalid twt ATTR");
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009020 goto send_err;
9021 }
9022
9023 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05309024 if (!tb2[cmd_id]) {
9025 hdd_err_rl("TWT_SETUP_WAKE_INTVL_EXP is must");
9026 goto send_err;
9027 }
9028 wake_intvl_exp = nla_get_u8(tb2[cmd_id]);
9029 if (wake_intvl_exp > TWT_SETUP_WAKE_INTVL_EXP_MAX) {
9030 hdd_err_rl("Invalid wake_intvl_exp %u > %u",
9031 wake_intvl_exp,
9032 TWT_SETUP_WAKE_INTVL_EXP_MAX);
9033 goto send_err;
9034 }
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009035
9036 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST;
9037 if (tb2[cmd_id])
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05309038 params.flag_bcast = nla_get_flag(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009039
9040 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05309041 if (!tb2[cmd_id]) {
9042 hdd_err_rl("TWT_SETUP_REQ_TYPE is must");
9043 goto send_err;
9044 }
9045 params.twt_cmd = nla_get_u8(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009046
9047 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER;
9048 if (tb2[cmd_id])
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05309049 params.flag_trigger = nla_get_flag(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009050
9051 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05309052 if (!tb2[cmd_id]) {
9053 hdd_err_rl("TWT_SETUP_FLOW_TYPE is must");
9054 goto send_err;
9055 }
9056 params.flag_flow_type = nla_get_u8(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009057
9058 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION;
9059 if (tb2[cmd_id])
9060 params.flag_protection =
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05309061 nla_get_flag(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009062
9063 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME;
9064 if (tb2[cmd_id])
9065 params.sp_offset_us = nla_get_u32(tb2[cmd_id]);
9066
9067 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05309068 if (!tb2[cmd_id]) {
9069 hdd_err_rl("TWT_SETUP_WAKE_DURATION is must");
9070 goto send_err;
9071 }
9072 params.wake_dura_us = 256 * nla_get_u32(tb2[cmd_id]);
9073 if (params.wake_dura_us > TWT_SETUP_WAKE_DURATION_MAX) {
9074 hdd_err_rl("Invalid wake_dura_us %u",
9075 params.wake_dura_us);
9076 goto send_err;
9077 }
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009078
9079 cmd_id =
9080 QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05309081 if (!tb2[cmd_id]) {
9082 hdd_err_rl("SETUP_WAKE_INTVL_MANTISSA is must");
9083 goto send_err;
9084 }
9085 params.wake_intvl_mantis = nla_get_u32(tb2[cmd_id]);
9086 if (params.wake_intvl_mantis >
9087 TWT_SETUP_WAKE_INTVL_MANTISSA_MAX) {
9088 hdd_err_rl("Invalid wake_intvl_mantis %u",
9089 params.wake_dura_us);
9090 goto send_err;
9091 }
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009092
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05309093 if (wake_intvl_exp && params.wake_intvl_mantis) {
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009094 result = 2 << (wake_intvl_exp - 1);
9095 if (result >
9096 (UINT_MAX / params.wake_intvl_mantis)) {
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05309097 hdd_err_rl("Invalid exp %d mantissa %d",
9098 wake_intvl_exp,
9099 params.wake_intvl_mantis);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009100 goto send_err;
9101 }
9102 params.wake_intvl_us =
9103 params.wake_intvl_mantis * result;
9104 } else {
9105 params.wake_intvl_us = params.wake_intvl_mantis;
9106 }
9107
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009108 hdd_debug("twt: vdev %d, intvl_us %d, mantis %d",
9109 params.vdev_id, params.wake_intvl_us,
9110 params.wake_intvl_mantis);
9111 hdd_debug("twt: dura %d, offset %d, cmd %d",
9112 params.wake_dura_us, params.sp_offset_us,
9113 params.twt_cmd);
9114 hdd_debug("twt: bcast %d, trigger %d, type %d, prot %d",
9115 params.flag_bcast, params.flag_trigger,
9116 params.flag_flow_type,
9117 params.flag_protection);
9118
Kiran Kumar Lokere54819a32019-10-04 18:30:43 -07009119 ucfg_mlme_get_twt_congestion_timeout(hdd_ctx->psoc,
9120 &congestion_timeout);
9121 if (congestion_timeout) {
9122 ret_val = qdf_status_to_os_return(
9123 hdd_send_twt_disable_cmd(hdd_ctx));
9124 if (ret_val) {
9125 hdd_err("Failed to disable TWT");
9126 goto send_err;
9127 }
9128 ucfg_mlme_set_twt_congestion_timeout(
9129 hdd_ctx->psoc, 0);
9130 hdd_send_twt_enable_cmd(hdd_ctx);
9131 }
Arif Hussain1f58cbb2019-03-14 17:06:56 -07009132 ret_val = qdf_status_to_os_return(
9133 wma_twt_process_add_dialog(&params));
9134 if (ret_val)
9135 goto send_err;
9136 }
9137 }
9138
9139 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE]) {
9140 struct wmi_twt_del_dialog_param params = {0};
9141 struct hdd_station_ctx *hdd_sta_ctx =
9142 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9143
9144 if ((adapter->device_mode != QDF_STA_MODE &&
9145 adapter->device_mode != QDF_P2P_CLIENT_MODE) ||
9146 hdd_sta_ctx->conn_info.conn_state !=
9147 eConnectionState_Associated) {
9148 hdd_err("Invalid state, vdev %d mode %d state %d",
9149 adapter->vdev_id, adapter->device_mode,
9150 hdd_sta_ctx->conn_info.conn_state);
9151 goto send_err;
9152 }
9153 qdf_mem_copy(params.peer_macaddr,
9154 hdd_sta_ctx->conn_info.bssid.bytes,
9155 QDF_MAC_ADDR_SIZE);
9156 params.vdev_id = adapter->vdev_id;
9157 params.dialog_id = 0;
9158 hdd_debug("twt_terminate: vdev_id %d", params.vdev_id);
9159 ret_val = qdf_status_to_os_return(
9160 wma_twt_process_del_dialog(&params));
9161 if (ret_val)
9162 goto send_err;
9163 }
9164
9165 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT;
9166 if (tb[cmd_id]) {
9167 cfg_val = nla_get_u8(tb[cmd_id]);
9168 hdd_debug("twt_request: val %d", cfg_val);
9169 ret_val = sme_update_he_twt_req_support(hdd_ctx->mac_handle,
9170 adapter->vdev_id,
9171 cfg_val);
9172 }
9173
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08009174 if (update_sme_cfg)
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009175 sme_update_config(mac_handle, sme_config);
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08009176
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08009177send_err:
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08009178 qdf_mem_free(sme_config);
9179
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08009180 return ret_val;
9181}
9182
9183/**
9184 * wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
9185 * vendor command
9186 *
9187 * @wiphy: wiphy device pointer
9188 * @wdev: wireless device pointer
9189 * @data: Vendor command data buffer
9190 * @data_len: Buffer length
9191 *
9192 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
9193 *
9194 * Return: EOK or other error codes.
9195 */
9196static int wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
9197 struct wireless_dev *wdev, const void *data, int data_len)
9198{
Dustin Browna09acf42018-11-08 12:32:26 +05309199 int errno;
9200 struct osif_vdev_sync *vdev_sync;
9201
9202 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
9203 if (errno)
9204 return errno;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08009205
Dustin Browna09acf42018-11-08 12:32:26 +05309206 errno = __wlan_hdd_cfg80211_set_wifi_test_config(wiphy, wdev,
9207 data, data_len);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08009208
Dustin Browna09acf42018-11-08 12:32:26 +05309209 osif_vdev_sync_op_stop(vdev_sync);
9210
9211 return errno;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08009212}
9213
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009214static const struct
9215nla_policy
9216qca_wlan_vendor_wifi_logger_start_policy
9217[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
9218 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
9219 = {.type = NLA_U32 },
9220 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
9221 = {.type = NLA_U32 },
9222 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
9223 = {.type = NLA_U32 },
9224};
9225
9226/**
9227 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
9228 * or disable the collection of packet statistics from the firmware
9229 * @wiphy: WIPHY structure pointer
9230 * @wdev: Wireless device structure pointer
9231 * @data: Pointer to the data received
9232 * @data_len: Length of the data received
9233 *
9234 * This function enables or disables the collection of packet statistics from
9235 * the firmware
9236 *
9237 * Return: 0 on success and errno on failure
9238 */
9239static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
9240 struct wireless_dev *wdev,
9241 const void *data,
9242 int data_len)
9243{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309244 QDF_STATUS status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009245 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009246 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
Hanumanth Reddy Pothulae9af1162018-06-13 13:41:44 +05309247 struct sir_wifi_start_log start_log = { 0 };
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009248 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009249
Dustin Brownfdf17c12018-03-14 12:55:34 -07009250 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08009251
Anurag Chouhan6d760662016-02-20 16:05:43 +05309252 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009253 hdd_err("Command not allowed in FTM mode");
9254 return -EPERM;
9255 }
9256
9257 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309258 if (status)
9259 return status;
9260
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05309261 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
9262 hdd_err("Driver Modules are closed, can not start logger");
9263 return -EINVAL;
9264 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009265
Dustin Brown4ea21db2018-01-05 14:13:17 -08009266 if (wlan_cfg80211_nla_parse(tb,
9267 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
9268 data, data_len,
9269 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009270 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009271 return -EINVAL;
9272 }
9273
9274 /* Parse and fetch ring id */
9275 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009276 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009277 return -EINVAL;
9278 }
9279 start_log.ring_id = nla_get_u32(
9280 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009281 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009282
9283 /* Parse and fetch verbose level */
9284 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009285 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009286 return -EINVAL;
9287 }
9288 start_log.verbose_level = nla_get_u32(
9289 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009290 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009291
9292 /* Parse and fetch flag */
9293 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009294 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009295 return -EINVAL;
9296 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05309297 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009298 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009299
Hanumanth Reddy Pothulae9af1162018-06-13 13:41:44 +05309300 start_log.user_triggered = 1;
9301
Poddar, Siddarth176c4362016-10-03 12:25:00 +05309302 /* size is buff size which can be set using iwpriv command*/
9303 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05309304 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05309305
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009306 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
9307
9308 if (start_log.ring_id == RING_ID_WAKELOCK) {
9309 /* Start/stop wakelock events */
9310 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
9311 cds_set_wakelock_logging(true);
9312 else
9313 cds_set_wakelock_logging(false);
9314 return 0;
9315 }
9316
Yu Tian87b2ae62020-06-18 11:11:46 +08009317 if (start_log.ring_id == RING_ID_PER_PACKET_STATS) {
9318 if (hdd_ctx->is_pktlog_enabled &&
9319 (start_log.verbose_level == WLAN_LOG_LEVEL_ACTIVE))
9320 return 0;
Venkata Sharath Chandra Manchalaf0296dd2019-09-19 13:50:02 -07009321
Yu Tian87b2ae62020-06-18 11:11:46 +08009322 if ((!hdd_ctx->is_pktlog_enabled) &&
9323 (start_log.verbose_level != WLAN_LOG_LEVEL_ACTIVE))
9324 return 0;
9325 }
Venkata Sharath Chandra Manchalaf0296dd2019-09-19 13:50:02 -07009326
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009327 mac_handle = hdd_ctx->mac_handle;
9328 status = sme_wifi_start_logger(mac_handle, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309329 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009330 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009331 status);
9332 return -EINVAL;
9333 }
Venkata Sharath Chandra Manchalaf0296dd2019-09-19 13:50:02 -07009334
Yu Tian87b2ae62020-06-18 11:11:46 +08009335 if (start_log.ring_id == RING_ID_PER_PACKET_STATS) {
9336 if (start_log.verbose_level == WLAN_LOG_LEVEL_ACTIVE)
9337 hdd_ctx->is_pktlog_enabled = true;
9338 else
9339 hdd_ctx->is_pktlog_enabled = false;
9340 }
Venkata Sharath Chandra Manchalaf0296dd2019-09-19 13:50:02 -07009341
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009342 return 0;
9343}
9344
9345/**
9346 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
9347 * or disable the collection of packet statistics from the firmware
9348 * @wiphy: WIPHY structure pointer
9349 * @wdev: Wireless device structure pointer
9350 * @data: Pointer to the data received
9351 * @data_len: Length of the data received
9352 *
9353 * This function is used to enable or disable the collection of packet
9354 * statistics from the firmware
9355 *
9356 * Return: 0 on success and errno on failure
9357 */
9358static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
9359 struct wireless_dev *wdev,
9360 const void *data,
9361 int data_len)
9362{
Dustin Brown363b4792019-02-05 16:11:55 -08009363 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08009364 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309365
Dustin Brown363b4792019-02-05 16:11:55 -08009366 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08009367 if (errno)
9368 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009369
Dustin Brownf0f00612019-01-31 16:02:24 -08009370 errno = __wlan_hdd_cfg80211_wifi_logger_start(wiphy, wdev,
9371 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009372
Dustin Brown363b4792019-02-05 16:11:55 -08009373 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309374
Dustin Brownf0f00612019-01-31 16:02:24 -08009375 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009376}
9377
9378static const struct
9379nla_policy
9380qca_wlan_vendor_wifi_logger_get_ring_data_policy
9381[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
9382 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
9383 = {.type = NLA_U32 },
9384};
9385
9386/**
9387 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
9388 * @wiphy: WIPHY structure pointer
9389 * @wdev: Wireless device structure pointer
9390 * @data: Pointer to the data received
9391 * @data_len: Length of the data received
9392 *
9393 * This function is used to flush or retrieve the per packet statistics from
9394 * the driver
9395 *
9396 * Return: 0 on success and errno on failure
9397 */
9398static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
9399 struct wireless_dev *wdev,
9400 const void *data,
9401 int data_len)
9402{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309403 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009404 uint32_t ring_id;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009405 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009406 struct nlattr *tb
9407 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
9408
Karthik Kantamneni0b95f9e2019-11-21 13:03:22 +05309409 hdd_enter();
Jeff Johnson1f61b612016-02-12 16:28:33 -08009410
Anurag Chouhan6d760662016-02-20 16:05:43 +05309411 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009412 hdd_err("Command not allowed in FTM mode");
9413 return -EPERM;
9414 }
9415
9416 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309417 if (status)
9418 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009419
Dustin Brown4ea21db2018-01-05 14:13:17 -08009420 if (wlan_cfg80211_nla_parse(tb,
9421 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
9422 data, data_len,
9423 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009424 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009425 return -EINVAL;
9426 }
9427
9428 /* Parse and fetch ring id */
9429 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009430 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009431 return -EINVAL;
9432 }
9433
9434 ring_id = nla_get_u32(
9435 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
9436
9437 if (ring_id == RING_ID_PER_PACKET_STATS) {
9438 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009439 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05309440 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
9441 /*
9442 * As part of DRIVER ring ID, flush both driver and fw logs.
9443 * For other Ring ID's driver doesn't have any rings to flush
9444 */
Arun Kumar Khandavalliafcb0552020-01-20 11:46:36 +05309445 hdd_debug("Bug report triggered by framework");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05309446
9447 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
9448 WLAN_LOG_INDICATOR_FRAMEWORK,
9449 WLAN_LOG_REASON_CODE_UNUSED,
Abhishek Singh29405dc2020-02-17 13:08:32 +05309450 false, false);
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05309451 if (QDF_STATUS_SUCCESS != status) {
9452 hdd_err("Failed to trigger bug report");
9453 return -EINVAL;
9454 }
9455 } else {
9456 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
9457 WLAN_LOG_INDICATOR_FRAMEWORK,
Agrawal Ashishaff28982017-05-30 15:25:47 +05309458 WLAN_LOG_REASON_CODE_UNUSED,
9459 ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009460 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009461 return 0;
9462}
9463
9464/**
9465 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
9466 * @wiphy: WIPHY structure pointer
9467 * @wdev: Wireless device structure pointer
9468 * @data: Pointer to the data received
9469 * @data_len: Length of the data received
9470 *
9471 * This function is used to flush or retrieve the per packet statistics from
9472 * the driver
9473 *
9474 * Return: 0 on success and errno on failure
9475 */
9476static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
9477 struct wireless_dev *wdev,
9478 const void *data,
9479 int data_len)
9480{
Dustin Brown363b4792019-02-05 16:11:55 -08009481 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08009482 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309483
Dustin Brown363b4792019-02-05 16:11:55 -08009484 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08009485 if (errno)
9486 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009487
Dustin Brownf0f00612019-01-31 16:02:24 -08009488 errno = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy, wdev,
9489 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009490
Dustin Brown363b4792019-02-05 16:11:55 -08009491 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08009492
9493 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009494}
9495
9496#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9497/**
9498 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
9499 * @hdd_ctx: HDD context
9500 * @request_id: [input] request id
9501 * @pattern_id: [output] pattern id
9502 *
9503 * This function loops through request id to pattern id array
9504 * if the slot is available, store the request id and return pattern id
9505 * if entry exists, return the pattern id
9506 *
9507 * Return: 0 on success and errno on failure
9508 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009509static int hdd_map_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009510 uint32_t request_id,
9511 uint8_t *pattern_id)
9512{
9513 uint32_t i;
9514
9515 mutex_lock(&hdd_ctx->op_ctx.op_lock);
9516 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
9517 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
9518 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
9519 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
9520 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
9521 return 0;
9522 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
9523 request_id) {
9524 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
9525 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
9526 return 0;
9527 }
9528 }
9529 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309530 return -ENOBUFS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009531}
9532
9533/**
9534 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
9535 * @hdd_ctx: HDD context
9536 * @request_id: [input] request id
9537 * @pattern_id: [output] pattern id
9538 *
9539 * This function loops through request id to pattern id array
9540 * reset request id to 0 (slot available again) and
9541 * return pattern id
9542 *
9543 * Return: 0 on success and errno on failure
9544 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009545static int hdd_unmap_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009546 uint32_t request_id,
9547 uint8_t *pattern_id)
9548{
9549 uint32_t i;
9550
9551 mutex_lock(&hdd_ctx->op_ctx.op_lock);
9552 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
9553 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
9554 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
9555 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
9556 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
9557 return 0;
9558 }
9559 }
9560 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
9561 return -EINVAL;
9562}
9563
9564
9565/*
9566 * define short names for the global vendor params
9567 * used by __wlan_hdd_cfg80211_offloaded_packets()
9568 */
9569#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
9570#define PARAM_REQUEST_ID \
9571 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
9572#define PARAM_CONTROL \
9573 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
9574#define PARAM_IP_PACKET \
9575 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
9576#define PARAM_SRC_MAC_ADDR \
9577 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
9578#define PARAM_DST_MAC_ADDR \
9579 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
9580#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05309581#define PARAM_PROTO_TYPE \
9582 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009583
9584/**
9585 * wlan_hdd_add_tx_ptrn() - add tx pattern
9586 * @adapter: adapter pointer
9587 * @hdd_ctx: hdd context
9588 * @tb: nl attributes
9589 *
9590 * This function reads the NL attributes and forms a AddTxPtrn message
9591 * posts it to SME.
9592 *
9593 */
9594static int
Jeff Johnsone5006672017-08-29 14:39:02 -07009595wlan_hdd_add_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009596 struct nlattr **tb)
9597{
9598 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309599 QDF_STATUS status;
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309600 uint32_t request_id, len;
9601 int32_t ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009602 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309603 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009604 uint16_t eth_type = htons(ETH_P_IP);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009605 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009606
9607 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07009608 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009609 return -ENOTSUPP;
9610 }
9611
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309612 add_req = qdf_mem_malloc(sizeof(*add_req));
Min Liu74a1a502018-10-10 19:59:07 +08009613 if (!add_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009614 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009615
9616 /* Parse and fetch request Id */
9617 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009618 hdd_err("attr request id failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309619 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009620 goto fail;
9621 }
9622
9623 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
9624 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07009625 hdd_err("request_id cannot be MAX");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309626 ret = -EINVAL;
SaidiReddy Yenuga466b3ce2017-05-02 18:50:25 +05309627 goto fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009628 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009629 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009630
9631 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009632 hdd_err("attr period failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309633 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009634 goto fail;
9635 }
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05309636
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009637 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009638 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009639 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07009640 hdd_err("Invalid interval zero, return failure");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309641 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009642 goto fail;
9643 }
9644
9645 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009646 hdd_err("attr source mac address failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309647 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009648 goto fail;
9649 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08009650 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05309651 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07009652 hdd_debug("input src mac address: "QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07009653 QDF_MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009654
Anurag Chouhanc5548422016-02-24 18:33:27 +05309655 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Jeff Johnson1e851a12017-10-28 14:36:12 -07009656 &adapter->mac_addr)) {
Srinivas Girigowda31896552015-11-18 22:59:52 -08009657 hdd_err("input src mac address and connected ap bssid are different");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309658 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009659 goto fail;
9660 }
9661
9662 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009663 hdd_err("attr dst mac address failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309664 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009665 goto fail;
9666 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05309667 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07009668 hdd_debug("input dst mac address: "QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07009669 QDF_MAC_ADDR_ARRAY(dst_addr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009670
9671 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009672 hdd_err("attr ip packet failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309673 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009674 goto fail;
9675 }
9676 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009677 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009678
9679 if (add_req->ucPtrnSize < 0 ||
9680 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
9681 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009682 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009683 add_req->ucPtrnSize);
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309684 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009685 goto fail;
9686 }
9687
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05309688 if (!tb[PARAM_PROTO_TYPE])
9689 eth_type = htons(ETH_P_IP);
9690 else
9691 eth_type = htons(nla_get_u16(tb[PARAM_PROTO_TYPE]));
9692
9693 hdd_debug("packet proto type: %u", eth_type);
9694
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009695 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309696 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05309697 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309698 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309699 QDF_MAC_ADDR_SIZE);
9700 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309701 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009702 len += 2;
9703
9704 /*
9705 * This is the IP packet, add 14 bytes Ethernet (802.3) header
9706 * ------------------------------------------------------------
9707 * | 14 bytes Ethernet (802.3) header | IP header and payload |
9708 * ------------------------------------------------------------
9709 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309710 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009711 nla_data(tb[PARAM_IP_PACKET]),
9712 add_req->ucPtrnSize);
9713 add_req->ucPtrnSize += len;
9714
9715 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
9716 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009717 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009718 goto fail;
9719 }
9720 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009721 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009722
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009723 mac_handle = hdd_ctx->mac_handle;
9724 status = sme_add_periodic_tx_ptrn(mac_handle, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309725 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009726 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309727 ret = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009728 goto fail;
9729 }
9730
Dustin Browne74003f2018-03-14 12:51:58 -07009731 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009732
9733fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309734 qdf_mem_free(add_req);
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309735 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009736}
9737
9738/**
9739 * wlan_hdd_del_tx_ptrn() - delete tx pattern
9740 * @adapter: adapter pointer
9741 * @hdd_ctx: hdd context
9742 * @tb: nl attributes
9743 *
9744 * This function reads the NL attributes and forms a DelTxPtrn message
9745 * posts it to SME.
9746 *
9747 */
9748static int
Jeff Johnsone5006672017-08-29 14:39:02 -07009749wlan_hdd_del_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009750 struct nlattr **tb)
9751{
9752 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309753 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009754 uint32_t request_id, ret;
9755 uint8_t pattern_id = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009756 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009757
9758 /* Parse and fetch request Id */
9759 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009760 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009761 return -EINVAL;
9762 }
9763 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
9764 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07009765 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009766 return -EINVAL;
9767 }
9768
9769 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
9770 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009771 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009772 return -EINVAL;
9773 }
9774
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309775 del_req = qdf_mem_malloc(sizeof(*del_req));
Min Liu74a1a502018-10-10 19:59:07 +08009776 if (!del_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009777 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009778
Jeff Johnson1e851a12017-10-28 14:36:12 -07009779 qdf_copy_macaddr(&del_req->mac_address, &adapter->mac_addr);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07009780 hdd_debug(QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07009781 QDF_MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009782 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009783 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009784 request_id, del_req->ucPtrnId);
9785
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009786 mac_handle = hdd_ctx->mac_handle;
9787 status = sme_del_periodic_tx_ptrn(mac_handle, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309788 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009789 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009790 goto fail;
9791 }
9792
Dustin Browne74003f2018-03-14 12:51:58 -07009793 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309794 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009795 return 0;
9796
9797fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309798 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009799 return -EINVAL;
9800}
9801
9802
9803/**
9804 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
9805 * @wiphy: Pointer to wireless phy
9806 * @wdev: Pointer to wireless device
9807 * @data: Pointer to data
9808 * @data_len: Data length
9809 *
9810 * Return: 0 on success, negative errno on failure
9811 */
9812static int
9813__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
9814 struct wireless_dev *wdev,
9815 const void *data,
9816 int data_len)
9817{
9818 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009819 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009820 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009821 struct nlattr *tb[PARAM_MAX + 1];
9822 uint8_t control;
9823 int ret;
9824 static const struct nla_policy policy[PARAM_MAX + 1] = {
9825 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
9826 [PARAM_CONTROL] = { .type = NLA_U32 },
9827 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309828 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009829 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309830 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009831 [PARAM_PERIOD] = { .type = NLA_U32 },
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05309832 [PARAM_PROTO_TYPE] = {.type = NLA_U16},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009833 };
9834
Dustin Brownfdf17c12018-03-14 12:55:34 -07009835 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009836
Anurag Chouhan6d760662016-02-20 16:05:43 +05309837 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009838 hdd_err("Command not allowed in FTM mode");
9839 return -EPERM;
9840 }
9841
9842 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309843 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009844 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009845
9846 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009847 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009848 return -ENOTSUPP;
9849 }
9850
Dustin Brown4ea21db2018-01-05 14:13:17 -08009851 if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009852 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009853 return -EINVAL;
9854 }
9855
9856 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009857 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009858 return -EINVAL;
9859 }
9860 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009861 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009862
9863 if (control == WLAN_START_OFFLOADED_PACKETS)
9864 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08009865 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009866 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08009867
9868 hdd_err("Invalid control: %d", control);
Jeff Johnson68755312017-02-10 11:46:55 -08009869 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009870}
9871
9872/*
9873 * done with short names for the global vendor params
9874 * used by __wlan_hdd_cfg80211_offloaded_packets()
9875 */
9876#undef PARAM_MAX
9877#undef PARAM_REQUEST_ID
9878#undef PARAM_CONTROL
9879#undef PARAM_IP_PACKET
9880#undef PARAM_SRC_MAC_ADDR
9881#undef PARAM_DST_MAC_ADDR
9882#undef PARAM_PERIOD
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05309883#undef PARAM_PROTO_TYPE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009884
9885/**
9886 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
9887 * @wiphy: wiphy structure pointer
9888 * @wdev: Wireless device structure pointer
9889 * @data: Pointer to the data received
9890 * @data_len: Length of @data
9891 *
9892 * Return: 0 on success; errno on failure
9893 */
9894static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
9895 struct wireless_dev *wdev,
9896 const void *data,
9897 int data_len)
9898{
Dustin Browna09acf42018-11-08 12:32:26 +05309899 int errno;
9900 struct osif_vdev_sync *vdev_sync;
9901
9902 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
9903 if (errno)
9904 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009905
Dustin Browna09acf42018-11-08 12:32:26 +05309906 errno = __wlan_hdd_cfg80211_offloaded_packets(wiphy, wdev,
9907 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009908
Dustin Browna09acf42018-11-08 12:32:26 +05309909 osif_vdev_sync_op_stop(vdev_sync);
9910
9911 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009912}
9913#endif
9914
Qiwei Cai1083f5b2018-07-02 19:10:11 +08009915#ifdef WLAN_NS_OFFLOAD
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309916static const struct nla_policy
9917ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
9918 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
9919};
9920
9921/**
9922 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
9923 * @wiphy: Pointer to wireless phy
9924 * @wdev: Pointer to wireless device
9925 * @data: Pointer to data
9926 * @data_len: Length of @data
9927 *
9928 * Return: 0 on success, negative errno on failure
9929 */
9930static int
9931__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
9932 struct wireless_dev *wdev,
9933 const void *data, int data_len)
9934{
9935 int status;
9936 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
Jeff Johnsonb8944722017-09-03 09:03:19 -07009937 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07009938 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009939 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309940
Dustin Brownfdf17c12018-03-14 12:55:34 -07009941 hdd_enter_dev(wdev->netdev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309942
Jeff Johnsonb8944722017-09-03 09:03:19 -07009943 status = wlan_hdd_validate_context(hdd_ctx);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309944 if (0 != status)
9945 return status;
Wu Gao66454f12018-09-26 19:55:41 +08009946
9947 if (!ucfg_pmo_is_ns_offloaded(hdd_ctx->psoc)) {
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309948 hdd_err("ND Offload not supported");
9949 return -EINVAL;
9950 }
9951
Wu Gao66454f12018-09-26 19:55:41 +08009952 if (!ucfg_pmo_is_active_mode_offloaded(hdd_ctx->psoc)) {
Mukul Sharma495df602017-09-25 14:52:18 +05309953 hdd_warn("Active mode offload is disabled");
9954 return -EINVAL;
9955 }
9956
Dustin Brown4ea21db2018-01-05 14:13:17 -08009957 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
9958 (struct nlattr *)data, data_len,
9959 ns_offload_set_policy)) {
9960 hdd_err("nla_parse failed");
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309961 return -EINVAL;
9962 }
9963
9964 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
9965 hdd_err("ND Offload flag attribute not present");
9966 return -EINVAL;
9967 }
9968
Jeff Johnsonb8944722017-09-03 09:03:19 -07009969 hdd_ctx->ns_offload_enable =
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309970 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
9971
Nachiket Kukadedbffab82017-04-25 19:26:02 +05309972 if (QDF_IBSS_MODE == adapter->device_mode) {
9973 hdd_debug("NS Offload is not supported in IBSS mode");
9974 return -EINVAL;
9975 }
9976
Dustin Brownd8279d22016-09-07 14:52:57 -07009977 /* update ns offload in case it is already enabled/disabled */
Jeff Johnsonb8944722017-09-03 09:03:19 -07009978 if (hdd_ctx->ns_offload_enable)
Mukul Sharma3ba26b82017-01-12 21:59:41 +05309979 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
9980 else
9981 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07009982
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309983 return 0;
9984}
9985
9986/**
9987 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
9988 * @wiphy: pointer to wireless wiphy structure.
9989 * @wdev: pointer to wireless_dev structure.
9990 * @data: Pointer to the data to be passed via vendor interface
9991 * @data_len:Length of the data to be passed
9992 *
9993 * Return: Return the Success or Failure code.
9994 */
9995static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
9996 struct wireless_dev *wdev,
9997 const void *data, int data_len)
9998{
Dustin Browna09acf42018-11-08 12:32:26 +05309999 int errno;
10000 struct osif_vdev_sync *vdev_sync;
10001
10002 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
10003 if (errno)
10004 return errno;
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053010005
Dustin Browna09acf42018-11-08 12:32:26 +053010006 errno = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053010007
Dustin Browna09acf42018-11-08 12:32:26 +053010008 osif_vdev_sync_op_stop(vdev_sync);
10009
10010 return errno;
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053010011}
Qiwei Cai1083f5b2018-07-02 19:10:11 +080010012#endif /* WLAN_NS_OFFLOAD */
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053010013
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010014/**
10015 * struct weighed_pcl: Preferred channel info
10016 * @freq: Channel frequency
10017 * @weight: Weightage of the channel
10018 * @flag: Validity of the channel in p2p negotiation
10019 */
10020struct weighed_pcl {
10021 u32 freq;
10022 u32 weight;
10023 u32 flag;
10024};
10025
Jeff Johnsondd7bd3e2017-06-05 13:25:24 -070010026static const struct nla_policy get_preferred_freq_list_policy
10027 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1] = {
10028 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE] = {
10029 .type = NLA_U32},
10030};
10031
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010032static uint32_t wlan_hdd_populate_weigh_pcl(
10033 struct policy_mgr_pcl_chan_weights *
10034 chan_weights,
10035 struct weighed_pcl *w_pcl,
10036 enum policy_mgr_con_mode intf_mode)
10037{
10038 int i, j;
10039 uint32_t chan_idx = 0;
10040 uint32_t set = 0;
10041 uint32_t pcl_len = chan_weights->pcl_len;
10042 uint32_t valid_weight;
10043
10044 /* convert channel number to frequency */
10045 for (i = 0; i < chan_weights->pcl_len; i++) {
Liangwei Dongc213d8e2019-10-28 12:57:43 +080010046 w_pcl[i].freq = chan_weights->pcl_list[i];
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010047 w_pcl[i].weight = chan_weights->weight_list[i];
10048
10049 if (intf_mode == PM_SAP_MODE || intf_mode == PM_P2P_GO_MODE)
10050 w_pcl[i].flag = set | PCL_CHANNEL_SUPPORT_GO;
10051 else
10052 w_pcl[i].flag = set | PCL_CHANNEL_SUPPORT_CLI;
10053 }
10054 chan_idx = pcl_len;
Rajeev Kumar Sirasanagandla50b2c102019-07-18 19:27:49 +053010055 if (pcl_len && chan_weights->weight_list[pcl_len - 1] >
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010056 PCL_GROUPS_WEIGHT_DIFFERENCE)
10057 /* Set non-pcl channels weight 20 point less than the last PCL entry */
10058 valid_weight = chan_weights->weight_list[pcl_len - 1] -
10059 PCL_GROUPS_WEIGHT_DIFFERENCE;
10060 else
10061 valid_weight = 1;
10062
10063 /* Include rest of the valid channels */
10064 for (i = 0; i < chan_weights->saved_num_chan; i++) {
10065 for (j = 0; j < chan_weights->pcl_len; j++) {
10066 if (chan_weights->saved_chan_list[i] ==
10067 chan_weights->pcl_list[j])
10068 break;
10069 }
10070 if (j == chan_weights->pcl_len) {
Liangwei Dongc213d8e2019-10-28 12:57:43 +080010071 w_pcl[chan_idx].freq =
10072 chan_weights->saved_chan_list[i];
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010073
10074 if (!chan_weights->weighed_valid_list[i]) {
10075 w_pcl[chan_idx].flag =
10076 set | PCL_CHANNEL_EXCLUDE_IN_GO_NEG;
10077 w_pcl[chan_idx].weight = 0;
10078 } else {
10079 if (intf_mode == PM_SAP_MODE ||
10080 intf_mode == PM_P2P_GO_MODE)
10081 w_pcl[chan_idx].flag =
10082 set | PCL_CHANNEL_SUPPORT_GO;
10083 else
10084 w_pcl[chan_idx].flag =
10085 set | PCL_CHANNEL_SUPPORT_CLI;
10086 w_pcl[chan_idx].weight = valid_weight;
10087 }
10088 chan_idx++;
10089 }
10090 }
10091 return chan_idx;
10092}
10093
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010094/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
10095 * @wiphy: Pointer to wireless phy
10096 * @wdev: Pointer to wireless device
10097 * @data: Pointer to data
10098 * @data_len: Data length
10099 *
10100 * This function return the preferred frequency list generated by the policy
10101 * manager.
10102 *
10103 * Return: success or failure code
10104 */
10105static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
10106 struct wireless_dev
10107 *wdev, const void *data,
10108 int data_len)
10109{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010110 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010111 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010112 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010113 uint32_t pcl_len = 0;
Tushnim Bhattacharyya36b1a8a2020-01-28 11:42:28 -080010114 uint32_t pcl_len_legacy = 0;
Qun Zhang3a5bd1a2020-03-20 12:05:25 +080010115 uint32_t freq_list[NUM_CHANNELS];
10116 uint32_t freq_list_legacy[NUM_CHANNELS];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010117 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010118 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
10119 struct sk_buff *reply_skb;
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010120 struct weighed_pcl *w_pcl;
10121 struct nlattr *nla_attr, *channel;
10122 struct policy_mgr_pcl_chan_weights *chan_weights;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010123
Dustin Brownfdf17c12018-03-14 12:55:34 -070010124 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -080010125
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010126 ret = wlan_hdd_validate_context(hdd_ctx);
10127 if (ret)
10128 return -EINVAL;
10129
Dustin Brown4ea21db2018-01-05 14:13:17 -080010130 if (wlan_cfg80211_nla_parse(tb,
10131 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
10132 data, data_len,
10133 get_preferred_freq_list_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010134 hdd_err("Invalid ATTR");
10135 return -EINVAL;
10136 }
10137
10138 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
10139 hdd_err("attr interface type failed");
10140 return -EINVAL;
10141 }
10142
10143 intf_mode = nla_get_u32(tb
10144 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
10145
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010146 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010147 hdd_err("Invalid interface type");
10148 return -EINVAL;
10149 }
10150
10151 hdd_debug("Userspace requested pref freq list");
10152
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010153 chan_weights =
10154 qdf_mem_malloc(sizeof(struct policy_mgr_pcl_chan_weights));
10155 if (!chan_weights)
10156 return -ENOMEM;
10157
Manikandan Mohan19f36092019-08-15 15:54:02 -070010158 status = policy_mgr_get_pcl(
Manikandan Mohan932c11e2019-08-14 14:09:08 -070010159 hdd_ctx->psoc, intf_mode, chan_weights->pcl_list,
10160 &chan_weights->pcl_len, chan_weights->weight_list,
10161 QDF_ARRAY_SIZE(chan_weights->weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010162 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010163 hdd_err("Get pcl failed");
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010164 qdf_mem_free(chan_weights);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010165 return -EINVAL;
10166 }
Tushnim Bhattacharyya36b1a8a2020-01-28 11:42:28 -080010167 /*
10168 * save the pcl in freq_list_legacy to be sent up with
10169 * QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST.
10170 * freq_list will carry the extended pcl in
10171 * QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL.
10172 */
10173 pcl_len_legacy = chan_weights->pcl_len;
10174 for (i = 0; i < pcl_len_legacy; i++)
10175 freq_list_legacy[i] = chan_weights->pcl_list[i];
Qun Zhang3a5bd1a2020-03-20 12:05:25 +080010176 chan_weights->saved_num_chan = NUM_CHANNELS;
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010177 sme_get_valid_channels(chan_weights->saved_chan_list,
10178 &chan_weights->saved_num_chan);
10179 policy_mgr_get_valid_chan_weights(hdd_ctx->psoc, chan_weights);
Qun Zhang3a5bd1a2020-03-20 12:05:25 +080010180 w_pcl = qdf_mem_malloc(sizeof(struct weighed_pcl) * NUM_CHANNELS);
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010181 if (!w_pcl) {
10182 qdf_mem_free(chan_weights);
10183 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010184 }
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010185 pcl_len = wlan_hdd_populate_weigh_pcl(chan_weights, w_pcl, intf_mode);
10186 qdf_mem_free(chan_weights);
10187
10188 for (i = 0; i < pcl_len; i++)
10189 freq_list[i] = w_pcl[i].freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010190
10191 /* send the freq_list back to supplicant */
Liangwei Dongc213d8e2019-10-28 12:57:43 +080010192 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(
10193 wiphy,
10194 (sizeof(u32) + NLA_HDRLEN) +
Tushnim Bhattacharyya36b1a8a2020-01-28 11:42:28 -080010195 (sizeof(u32) * pcl_len_legacy + NLA_HDRLEN) +
Liangwei Dongc213d8e2019-10-28 12:57:43 +080010196 NLA_HDRLEN +
10197 (NLA_HDRLEN * 4 + sizeof(u32) * 3) * pcl_len +
10198 NLMSG_HDRLEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010199
10200 if (!reply_skb) {
10201 hdd_err("Allocate reply_skb failed");
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010202 qdf_mem_free(w_pcl);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010203 return -EINVAL;
10204 }
10205
10206 if (nla_put_u32(reply_skb,
10207 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
10208 intf_mode) ||
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010209 nla_put(reply_skb,
10210 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
Tushnim Bhattacharyya36b1a8a2020-01-28 11:42:28 -080010211 sizeof(uint32_t) * pcl_len_legacy,
10212 freq_list_legacy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010213 hdd_err("nla put fail");
10214 kfree_skb(reply_skb);
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010215 qdf_mem_free(w_pcl);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010216 return -EINVAL;
10217 }
10218
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010219 i = QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL;
10220 nla_attr = nla_nest_start(reply_skb, i);
10221
10222 if (!nla_attr) {
10223 hdd_err("nla nest start fail");
10224 kfree_skb(reply_skb);
10225 qdf_mem_free(w_pcl);
10226 return -EINVAL;
10227 }
10228
10229 for (i = 0; i < pcl_len; i++) {
10230 channel = nla_nest_start(reply_skb, i);
10231 if (!channel) {
10232 hdd_err("updating pcl list failed");
10233 kfree_skb(reply_skb);
10234 qdf_mem_free(w_pcl);
10235 return -EINVAL;
10236 }
10237 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FREQ,
10238 w_pcl[i].freq) ||
10239 nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
10240 w_pcl[i].weight) ||
10241 nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FLAG,
10242 w_pcl[i].flag)) {
10243 hdd_err("nla put fail");
10244 kfree_skb(reply_skb);
10245 qdf_mem_free(w_pcl);
10246 return -EINVAL;
10247 }
10248 nla_nest_end(reply_skb, channel);
10249 }
10250 nla_nest_end(reply_skb, nla_attr);
10251 qdf_mem_free(w_pcl);
10252
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010253 return cfg80211_vendor_cmd_reply(reply_skb);
10254}
10255
10256/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
10257 * @wiphy: Pointer to wireless phy
10258 * @wdev: Pointer to wireless device
10259 * @data: Pointer to data
10260 * @data_len: Data length
10261 *
10262 * This function return the preferred frequency list generated by the policy
10263 * manager.
10264 *
10265 * Return: success or failure code
10266 */
10267static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
10268 struct wireless_dev
10269 *wdev, const void *data,
10270 int data_len)
10271{
Dustin Brown363b4792019-02-05 16:11:55 -080010272 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080010273 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010274
Dustin Brown363b4792019-02-05 16:11:55 -080010275 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080010276 if (errno)
10277 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010278
Dustin Brownf0f00612019-01-31 16:02:24 -080010279 errno = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
10280 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010281
Dustin Brown363b4792019-02-05 16:11:55 -080010282 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010283
Dustin Brownf0f00612019-01-31 16:02:24 -080010284 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010285}
10286
Jeff Johnsone5f33ba2017-06-05 14:48:48 -070010287static const struct nla_policy set_probable_oper_channel_policy
10288 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1] = {
10289 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE] = {
10290 .type = NLA_U32},
10291 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ] = {
10292 .type = NLA_U32},
10293};
10294
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010295/**
10296 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
10297 * @wiphy: Pointer to wireless phy
10298 * @wdev: Pointer to wireless device
10299 * @data: Pointer to data
10300 * @data_len: Data length
10301 *
10302 * Return: 0 on success, negative errno on failure
10303 */
10304static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
10305 struct wireless_dev *wdev,
10306 const void *data,
10307 int data_len)
10308{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +053010309 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010310 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010311 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010312 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010313 enum policy_mgr_con_mode intf_mode;
Jeff Johnsone5f33ba2017-06-05 14:48:48 -070010314 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1];
Tushnim Bhattacharyyac682bfb2019-12-11 17:11:10 -080010315 uint32_t ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010316
Dustin Brownfdf17c12018-03-14 12:55:34 -070010317 hdd_enter_dev(ndev);
Jeff Johnson1f61b612016-02-12 16:28:33 -080010318
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010319 ret = wlan_hdd_validate_context(hdd_ctx);
10320 if (ret)
10321 return ret;
10322
Dustin Brown4ea21db2018-01-05 14:13:17 -080010323 if (wlan_cfg80211_nla_parse(tb,
10324 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
10325 data, data_len,
10326 set_probable_oper_channel_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010327 hdd_err("Invalid ATTR");
10328 return -EINVAL;
10329 }
10330
10331 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
10332 hdd_err("attr interface type failed");
10333 return -EINVAL;
10334 }
10335
10336 intf_mode = nla_get_u32(tb
10337 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
10338
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010339 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010340 hdd_err("Invalid interface type");
10341 return -EINVAL;
10342 }
10343
10344 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
10345 hdd_err("attr probable freq failed");
10346 return -EINVAL;
10347 }
10348
Manikandan Mohan282c4b62019-08-14 17:42:22 -070010349 ch_freq = nla_get_u32(tb[
10350 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010351 /* check pcl table */
Dustin Brown76cd2932018-09-11 16:03:05 -070010352 if (!policy_mgr_allow_concurrency(hdd_ctx->psoc, intf_mode,
Manikandan Mohan282c4b62019-08-14 17:42:22 -070010353 ch_freq, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010354 hdd_err("Set channel hint failed due to concurrency check");
10355 return -EINVAL;
10356 }
10357
Krunal Soni09e55032016-06-07 10:06:55 -070010358 if (0 != wlan_hdd_check_remain_on_channel(adapter))
10359 hdd_warn("Remain On Channel Pending");
10360
Tushnim Bhattacharyyac682bfb2019-12-11 17:11:10 -080010361 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, ch_freq,
Krunal Sonied3bc8e2018-01-26 12:13:34 -080010362 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
10363 hdd_err("Failed to change hw mode");
Krunal Soni3091bcc2016-06-23 12:28:21 -070010364 return -EINVAL;
10365 }
10366
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010367 return 0;
10368}
10369
10370/**
10371 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
10372 * @wiphy: Pointer to wireless phy
10373 * @wdev: Pointer to wireless device
10374 * @data: Pointer to data
10375 * @data_len: Data length
10376 *
10377 * Return: 0 on success, negative errno on failure
10378 */
10379static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
10380 struct wireless_dev *wdev,
10381 const void *data,
10382 int data_len)
10383{
Dustin Browna09acf42018-11-08 12:32:26 +053010384 int errno;
10385 struct osif_vdev_sync *vdev_sync;
10386
10387 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
10388 if (errno)
10389 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010390
Dustin Browna09acf42018-11-08 12:32:26 +053010391 errno = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
10392 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010393
Dustin Browna09acf42018-11-08 12:32:26 +053010394 osif_vdev_sync_op_stop(vdev_sync);
10395
10396 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010397}
10398
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010399static const struct
10400nla_policy
10401qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +053010402 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {
10403 .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010404};
10405
10406/**
10407 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
10408 * @wiphy: WIPHY structure pointer
10409 * @wdev: Wireless device structure pointer
10410 * @data: Pointer to the data received
10411 * @data_len: Length of the data received
10412 *
10413 * This function is used to get link properties like nss, rate flags and
10414 * operating frequency for the active connection with the given peer.
10415 *
10416 * Return: 0 on success and errno on failure
10417 */
10418static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
10419 struct wireless_dev *wdev,
10420 const void *data,
10421 int data_len)
10422{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010423 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010424 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010425 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson40dae4e2017-08-29 14:00:25 -070010426 struct hdd_station_ctx *hdd_sta_ctx;
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053010427 struct hdd_station_info *sta_info;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010428 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +053010429 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010430 struct sk_buff *reply_skb;
10431 uint32_t rate_flags = 0;
10432 uint8_t nss;
10433 uint8_t final_rate_flags = 0;
10434 uint32_t freq;
10435
Dustin Brownfdf17c12018-03-14 12:55:34 -070010436 hdd_enter_dev(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010437
Anurag Chouhan6d760662016-02-20 16:05:43 +053010438 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010439 hdd_err("Command not allowed in FTM mode");
10440 return -EPERM;
10441 }
10442
10443 if (0 != wlan_hdd_validate_context(hdd_ctx))
10444 return -EINVAL;
10445
Dustin Brown4ea21db2018-01-05 14:13:17 -080010446 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
10447 data_len, qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010448 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010449 return -EINVAL;
10450 }
10451
10452 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -070010453 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010454 adapter->device_mode);
10455 return -EINVAL;
10456 }
10457
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +053010458 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) < QDF_MAC_ADDR_SIZE) {
10459 hdd_err("Attribute peerMac is invalid for mode=%d",
10460 adapter->device_mode);
10461 return -EINVAL;
10462 }
10463
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010464 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +053010465 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070010466 hdd_debug("peerMac="QDF_MAC_ADDR_STR" for device_mode:%d",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070010467 QDF_MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010468
Krunal Sonib4326f22016-03-10 13:05:51 -080010469 if (adapter->device_mode == QDF_STA_MODE ||
10470 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010471 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnsone7951512019-02-27 10:02:51 -080010472 if ((hdd_sta_ctx->conn_info.conn_state !=
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010473 eConnectionState_Associated) ||
Jeff Johnsone04b6992019-02-27 14:06:55 -080010474 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssid.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053010475 peer_mac, QDF_MAC_ADDR_SIZE)) {
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070010476 hdd_err("Not Associated to mac "QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070010477 QDF_MAC_ADDR_ARRAY(peer_mac));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010478 return -EINVAL;
10479 }
10480
10481 nss = hdd_sta_ctx->conn_info.nss;
Jingxiang Geae80dc62019-08-13 17:32:22 +080010482 freq = hdd_sta_ctx->conn_info.chan_freq;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010483 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -080010484 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
10485 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010486
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053010487 if (QDF_IS_ADDR_BROADCAST(peer_mac)) {
10488 hdd_err("Ignore bcast/self sta");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010489 return -EINVAL;
10490 }
10491
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053010492 sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
10493 peer_mac);
10494
10495 if (!sta_info) {
10496 hdd_err("No active peer with mac = " QDF_MAC_ADDR_STR,
10497 QDF_MAC_ADDR_ARRAY(peer_mac));
10498 return -EINVAL;
10499 }
10500
10501 nss = sta_info->nss;
Will Huang4b097f52019-08-29 10:51:56 -070010502 freq = (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operating_chan_freq;
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053010503 rate_flags = sta_info->rate_flags;
Sourav Mohapatra11be3492020-04-22 10:09:32 +053010504 hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010505 } else {
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070010506 hdd_err("Not Associated! with mac "QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070010507 QDF_MAC_ADDR_ARRAY(peer_mac));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010508 return -EINVAL;
10509 }
10510
Naveen Rawatea1564b2018-05-17 15:56:11 -070010511 if (!(rate_flags & TX_RATE_LEGACY)) {
10512 if (rate_flags & TX_RATE_VHT80) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010513 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -080010514#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010515 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -080010516#endif
Naveen Rawatea1564b2018-05-17 15:56:11 -070010517 } else if (rate_flags & TX_RATE_VHT40) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010518 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -080010519#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010520 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -080010521#endif
Naveen Rawatea1564b2018-05-17 15:56:11 -070010522 } else if (rate_flags & TX_RATE_VHT20) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010523 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
10524 } else if (rate_flags &
Naveen Rawatea1564b2018-05-17 15:56:11 -070010525 (TX_RATE_HT20 | TX_RATE_HT40)) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010526 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -080010527#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Naveen Rawatea1564b2018-05-17 15:56:11 -070010528 if (rate_flags & TX_RATE_HT40)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010529 final_rate_flags |=
10530 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -080010531#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010532 }
10533
Naveen Rawatea1564b2018-05-17 15:56:11 -070010534 if (rate_flags & TX_RATE_SGI) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010535 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
10536 final_rate_flags |= RATE_INFO_FLAGS_MCS;
10537 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
10538 }
10539 }
10540
10541 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
10542 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
10543
Jeff Johnsond36fa332019-03-18 13:42:25 -070010544 if (!reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -070010545 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010546 return -EINVAL;
10547 }
10548
10549 if (nla_put_u8(reply_skb,
10550 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
10551 nss) ||
10552 nla_put_u8(reply_skb,
10553 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
10554 final_rate_flags) ||
10555 nla_put_u32(reply_skb,
10556 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
10557 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010558 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010559 kfree_skb(reply_skb);
10560 return -EINVAL;
10561 }
10562
10563 return cfg80211_vendor_cmd_reply(reply_skb);
10564}
10565
10566/**
10567 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
10568 * properties.
10569 * @wiphy: WIPHY structure pointer
10570 * @wdev: Wireless device structure pointer
10571 * @data: Pointer to the data received
10572 * @data_len: Length of the data received
10573 *
10574 * This function is used to get link properties like nss, rate flags and
10575 * operating frequency for the active connection with the given peer.
10576 *
10577 * Return: 0 on success and errno on failure
10578 */
10579static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
10580 struct wireless_dev *wdev,
10581 const void *data,
10582 int data_len)
10583{
Dustin Browna09acf42018-11-08 12:32:26 +053010584 int errno;
10585 struct osif_vdev_sync *vdev_sync;
10586
10587 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
10588 if (errno)
10589 return errno;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010590
Dustin Browna09acf42018-11-08 12:32:26 +053010591 errno = __wlan_hdd_cfg80211_get_link_properties(wiphy, wdev,
10592 data, data_len);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010593
Dustin Browna09acf42018-11-08 12:32:26 +053010594 osif_vdev_sync_op_stop(vdev_sync);
10595
10596 return errno;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010597}
10598
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010599static const struct nla_policy
10600wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053010601 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8},
10602 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY] = {.type = NLA_U32},
Ganesh Kondabattini099e6e82017-06-28 12:24:20 +053010603 [QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST] = {
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053010604 .type = NLA_NESTED},
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010605};
10606
Agrawal Ashish65634612016-08-18 13:24:32 +053010607static const struct nla_policy
10608wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
Rajeev Kumar Sirasanagandlae83ac292019-09-19 16:35:26 +053010609 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8},
10610 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8},
10611 [QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT] = {.type = NLA_U32},
Agrawal Ashish65634612016-08-18 13:24:32 +053010612};
10613
10614/**
10615 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
10616 * @wiphy: Pointer to wireless phy
10617 * @wdev: Pointer to wireless device
10618 * @data: Pointer to data
10619 * @data_len: Length of @data
10620 *
10621 * This function parses the incoming NL vendor command data attributes and
10622 * updates the SAP context about channel_hint and DFS mode.
10623 * If channel_hint is set, SAP will choose that channel
10624 * as operating channel.
10625 *
10626 * If DFS mode is enabled, driver will include DFS channels
10627 * in ACS else driver will skip DFS channels.
10628 *
10629 * Return: 0 on success, negative errno on failure
10630 */
10631static int
10632__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
10633 struct wireless_dev *wdev,
10634 const void *data, int data_len)
10635{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010636 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish65634612016-08-18 13:24:32 +053010637 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
10638 int ret;
10639 struct acs_dfs_policy *acs_policy;
10640 int mode = DFS_MODE_NONE;
Rajeev Kumar Sirasanagandlae83ac292019-09-19 16:35:26 +053010641 uint32_t freq_hint = 0;
Agrawal Ashish65634612016-08-18 13:24:32 +053010642
Dustin Brownfdf17c12018-03-14 12:55:34 -070010643 hdd_enter_dev(wdev->netdev);
Agrawal Ashish65634612016-08-18 13:24:32 +053010644
10645 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10646 hdd_err("Command not allowed in FTM mode");
10647 return -EINVAL;
10648 }
10649
10650 ret = wlan_hdd_validate_context(hdd_ctx);
10651 if (0 != ret)
10652 return ret;
10653
Dustin Brown4ea21db2018-01-05 14:13:17 -080010654 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
10655 data, data_len,
10656 wlan_hdd_set_acs_dfs_config_policy)) {
Agrawal Ashish65634612016-08-18 13:24:32 +053010657 hdd_err("invalid attr");
10658 return -EINVAL;
10659 }
10660
10661 acs_policy = &hdd_ctx->acs_policy;
10662 /*
10663 * SCM sends this attribute to restrict SAP from choosing
10664 * DFS channels from ACS.
10665 */
10666 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
10667 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
10668
10669 if (!IS_DFS_MODE_VALID(mode)) {
10670 hdd_err("attr acs dfs mode is not valid");
10671 return -EINVAL;
10672 }
10673 acs_policy->acs_dfs_mode = mode;
10674
10675 /*
10676 * SCM sends this attribute to provide an active channel,
10677 * to skip redundant ACS between drivers, and save driver start up time
10678 */
Rajeev Kumar Sirasanagandlae83ac292019-09-19 16:35:26 +053010679 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT]) {
10680 freq_hint = nla_get_u32(
10681 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT]);
10682 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]) {
10683 uint32_t channel_hint = nla_get_u8(
Agrawal Ashish65634612016-08-18 13:24:32 +053010684 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
10685
Rajeev Kumar Sirasanagandlae83ac292019-09-19 16:35:26 +053010686 freq_hint = wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev,
10687 channel_hint);
10688 }
10689
10690 if (freq_hint && !WLAN_REG_IS_24GHZ_CH_FREQ(freq_hint) &&
10691 !WLAN_REG_IS_5GHZ_CH_FREQ(freq_hint) &&
10692 !WLAN_REG_IS_6GHZ_CHAN_FREQ(freq_hint)) {
10693 hdd_err("acs channel frequency is not valid");
Agrawal Ashish65634612016-08-18 13:24:32 +053010694 return -EINVAL;
10695 }
Rajeev Kumar Sirasanagandlae83ac292019-09-19 16:35:26 +053010696
10697 acs_policy->acs_chan_freq = freq_hint;
Agrawal Ashish65634612016-08-18 13:24:32 +053010698
10699 return 0;
10700}
10701
10702/**
10703 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
10704 * @wiphy: wiphy structure pointer
10705 * @wdev: Wireless device structure pointer
10706 * @data: Pointer to the data received
10707 * @data_len: Length of @data
10708 *
10709 * This function parses the incoming NL vendor command data attributes and
10710 * updates the SAP context about channel_hint and DFS mode.
10711 *
10712 * Return: 0 on success; errno on failure
10713 */
10714static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
10715 struct wireless_dev *wdev,
10716 const void *data, int data_len)
10717{
Dustin Brown363b4792019-02-05 16:11:55 -080010718 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080010719 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010720
Dustin Brown363b4792019-02-05 16:11:55 -080010721 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080010722 if (errno)
10723 return errno;
Agrawal Ashish65634612016-08-18 13:24:32 +053010724
Dustin Brownf0f00612019-01-31 16:02:24 -080010725 errno = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
Agrawal Ashish65634612016-08-18 13:24:32 +053010726
Dustin Brown363b4792019-02-05 16:11:55 -080010727 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010728
Dustin Brownf0f00612019-01-31 16:02:24 -080010729 return errno;
Agrawal Ashish65634612016-08-18 13:24:32 +053010730}
10731
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010732/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010733 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
10734 * @mode : cfg80211 dfs mode
10735 *
10736 * Return: return csr sta roam dfs mode else return NONE
10737 */
10738static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
10739 enum dfs_mode mode)
10740{
10741 switch (mode) {
10742 case DFS_MODE_ENABLE:
10743 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010744 case DFS_MODE_DISABLE:
10745 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010746 case DFS_MODE_DEPRIORITIZE:
10747 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010748 default:
10749 hdd_err("STA Roam policy dfs mode is NONE");
10750 return CSR_STA_ROAM_POLICY_NONE;
10751 }
10752}
10753
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010754/*
10755 * hdd_get_sap_operating_band: Get current operating channel
10756 * for sap.
10757 * @hdd_ctx: hdd context
10758 *
10759 * Return : Corresponding band for SAP operating channel
10760 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010761uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010762{
Jeff Johnsone5006672017-08-29 14:39:02 -070010763 struct hdd_adapter *adapter;
Will Huang4b097f52019-08-29 10:51:56 -070010764 uint32_t operating_chan_freq;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010765 uint8_t sap_operating_band = 0;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070010766
Dustin Brown920397d2017-12-13 16:27:50 -080010767 hdd_for_each_adapter(hdd_ctx, adapter) {
10768 if (adapter->device_mode != QDF_SAP_MODE)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010769 continue;
Dustin Brown920397d2017-12-13 16:27:50 -080010770
Will Huang4b097f52019-08-29 10:51:56 -070010771 operating_chan_freq = adapter->session.ap.operating_chan_freq;
10772 if (WLAN_REG_IS_24GHZ_CH_FREQ(operating_chan_freq))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010773 sap_operating_band = BAND_2G;
wadesong88378bd2020-03-24 13:25:21 +080010774 else if (WLAN_REG_IS_5GHZ_CH_FREQ(operating_chan_freq) ||
10775 WLAN_REG_IS_6GHZ_CHAN_FREQ(operating_chan_freq))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010776 sap_operating_band = BAND_5G;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010777 else
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010778 sap_operating_band = BAND_ALL;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010779 }
Dustin Brown920397d2017-12-13 16:27:50 -080010780
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010781 return sap_operating_band;
10782}
10783
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010784static const struct nla_policy
10785wlan_hdd_set_sta_roam_config_policy[
10786QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
10787 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
10788 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
10789};
10790
10791/**
10792 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
10793 * for station connection or roaming.
10794 * @wiphy: Pointer to wireless phy
10795 * @wdev: Pointer to wireless device
10796 * @data: Pointer to data
10797 * @data_len: Length of @data
10798 *
10799 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
10800 * channels needs to be skipped in scanning or not.
10801 * If dfs_mode is disabled, driver will not scan DFS channels.
10802 * If skip_unsafe_channels is set, driver will skip unsafe channels
10803 * in Scanning.
10804 *
10805 * Return: 0 on success, negative errno on failure
10806 */
10807static int
10808__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
10809 struct wireless_dev *wdev,
10810 const void *data, int data_len)
10811{
10812 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010813 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010814 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010815 struct nlattr *tb[
10816 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
10817 int ret;
10818 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
10819 enum dfs_mode mode = DFS_MODE_NONE;
10820 bool skip_unsafe_channels = false;
10821 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010822 uint8_t sap_operating_band;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010823 mac_handle_t mac_handle;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010824
Dustin Brownfdf17c12018-03-14 12:55:34 -070010825 hdd_enter_dev(dev);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010826
10827 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10828 hdd_err("Command not allowed in FTM mode");
10829 return -EINVAL;
10830 }
10831
10832 ret = wlan_hdd_validate_context(hdd_ctx);
10833 if (0 != ret)
10834 return ret;
Dustin Brown4ea21db2018-01-05 14:13:17 -080010835 if (wlan_cfg80211_nla_parse(tb,
10836 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
10837 data, data_len,
10838 wlan_hdd_set_sta_roam_config_policy)) {
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010839 hdd_err("invalid attr");
10840 return -EINVAL;
10841 }
10842 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
10843 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
10844 if (!IS_DFS_MODE_VALID(mode)) {
10845 hdd_err("attr sta roam dfs mode policy is not valid");
10846 return -EINVAL;
10847 }
10848
10849 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
10850
10851 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
10852 skip_unsafe_channels = nla_get_u8(
10853 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010854 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010855 mac_handle = hdd_ctx->mac_handle;
10856 status = sme_update_sta_roam_policy(mac_handle, sta_roam_dfs_mode,
10857 skip_unsafe_channels,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080010858 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010859 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010860
10861 if (!QDF_IS_STATUS_SUCCESS(status)) {
10862 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
10863 return -EINVAL;
10864 }
10865 return 0;
10866}
10867
10868/**
10869 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
10870 * connection and roaming for station.
10871 * @wiphy: wiphy structure pointer
10872 * @wdev: Wireless device structure pointer
10873 * @data: Pointer to the data received
10874 * @data_len: Length of @data
10875 *
10876 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
10877 * channels needs to be skipped in scanning or not.
10878 * If dfs_mode is disabled, driver will not scan DFS channels.
10879 * If skip_unsafe_channels is set, driver will skip unsafe channels
10880 * in Scanning.
10881 * Return: 0 on success; errno on failure
10882 */
10883static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
10884 struct wireless_dev *wdev,
10885 const void *data, int data_len)
10886{
Dustin Browna09acf42018-11-08 12:32:26 +053010887 int errno;
10888 struct osif_vdev_sync *vdev_sync;
10889
10890 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
10891 if (errno)
10892 return errno;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010893
Dustin Browna09acf42018-11-08 12:32:26 +053010894 errno = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev,
10895 data, data_len);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010896
Dustin Browna09acf42018-11-08 12:32:26 +053010897 osif_vdev_sync_op_stop(vdev_sync);
10898
10899 return errno;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010900}
10901
Agrawal Ashish467dde42016-09-08 18:44:22 +053010902#ifdef FEATURE_WLAN_CH_AVOID
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010903
10904static int hdd_validate_avoid_freq_chanlist(
10905 struct hdd_context *hdd_ctx,
10906 struct ch_avoid_ind_type *channel_list)
10907{
10908 unsigned int range_idx, ch_idx;
10909 unsigned int unsafe_channel_index, unsafe_channel_count = 0;
10910 bool ch_found = false;
hqubcd0a8f2019-11-25 21:56:35 +080010911 uint32_t ch_idx_freq;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010912
10913 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
10914 (uint16_t)NUM_CHANNELS);
10915
10916 for (range_idx = 0; range_idx < channel_list->ch_avoid_range_cnt;
10917 range_idx++) {
10918 if ((channel_list->avoid_freq_range[range_idx].start_freq <
10919 CDS_24_GHZ_CHANNEL_1) ||
10920 (channel_list->avoid_freq_range[range_idx].end_freq >
10921 CDS_5_GHZ_CHANNEL_165) ||
10922 (channel_list->avoid_freq_range[range_idx].start_freq >
10923 channel_list->avoid_freq_range[range_idx].end_freq))
10924 continue;
10925
10926 for (ch_idx = channel_list->
10927 avoid_freq_range[range_idx].start_freq;
10928 ch_idx <= channel_list->
10929 avoid_freq_range[range_idx].end_freq;
10930 ch_idx++) {
Ashish Kumar Dhanotiyaaa9fdbb2018-12-14 15:29:14 +053010931 if (INVALID_CHANNEL == wlan_reg_get_chan_enum(ch_idx))
Ashish Kumar Dhanotiyabf00f822018-11-30 20:29:09 +053010932 continue;
hqubcd0a8f2019-11-25 21:56:35 +080010933 ch_idx_freq = wlan_reg_chan_to_freq(hdd_ctx->pdev,
10934 ch_idx);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010935 for (unsafe_channel_index = 0;
10936 unsafe_channel_index < unsafe_channel_count;
10937 unsafe_channel_index++) {
hqubcd0a8f2019-11-25 21:56:35 +080010938 if (ch_idx_freq ==
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010939 hdd_ctx->unsafe_channel_list[
10940 unsafe_channel_index]) {
hqubcd0a8f2019-11-25 21:56:35 +080010941 hdd_info("Duplicate channel freq %d",
10942 ch_idx_freq);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010943 ch_found = true;
10944 break;
10945 }
10946 }
10947 if (!ch_found) {
10948 hdd_ctx->unsafe_channel_list[
hqubcd0a8f2019-11-25 21:56:35 +080010949 unsafe_channel_count++] = (uint16_t)ch_idx_freq;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010950 }
10951 ch_found = false;
10952 }
10953 }
10954 return unsafe_channel_count;
10955}
10956
Agrawal Ashish467dde42016-09-08 18:44:22 +053010957/**
10958 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
10959 * is on unsafe channel.
10960 * @wiphy: wiphy structure pointer
10961 * @wdev: Wireless device structure pointer
10962 * @data: Pointer to the data received
10963 * @data_len: Length of @data
10964 *
10965 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
10966 * on any of unsafe channels.
10967 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
10968 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
10969 *
10970 * Return: 0 on success; errno on failure
10971 */
10972static int
10973__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
10974 struct wireless_dev *wdev,
10975 const void *data, int data_len)
10976{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010977 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010978 int ret;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010979 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
Liangwei Dong6e1a2092017-08-30 16:29:06 +080010980 uint16_t *local_unsafe_list;
hqubf1b6182018-08-14 17:22:41 +080010981 uint16_t unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010982 uint16_t unsafe_channel_index, local_unsafe_list_count;
10983 struct ch_avoid_ind_type *channel_list;
Jeff Johnson2e60a142018-05-20 12:08:12 -070010984 enum QDF_GLOBAL_MODE curr_mode;
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +053010985 uint8_t num_args = 0;
hqubf1b6182018-08-14 17:22:41 +080010986 bool user_set_avoid_channel = true;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010987
Dustin Brownfdf17c12018-03-14 12:55:34 -070010988 hdd_enter_dev(wdev->netdev);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010989
10990 if (!qdf_ctx) {
Jeff Johnson6867ec32017-09-29 20:30:20 -070010991 hdd_err("qdf_ctx is NULL");
Agrawal Ashish467dde42016-09-08 18:44:22 +053010992 return -EINVAL;
10993 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010994 curr_mode = hdd_get_conparam();
10995 if (QDF_GLOBAL_FTM_MODE == curr_mode ||
10996 QDF_GLOBAL_MONITOR_MODE == curr_mode) {
10997 hdd_err("Command not allowed in FTM/MONITOR mode");
Agrawal Ashish467dde42016-09-08 18:44:22 +053010998 return -EINVAL;
10999 }
11000
11001 ret = wlan_hdd_validate_context(hdd_ctx);
11002 if (0 != ret)
11003 return ret;
hqubf1b6182018-08-14 17:22:41 +080011004 if (!data && data_len == 0) {
11005 hdd_debug("Userspace doesn't set avoid frequency channel list");
11006 user_set_avoid_channel = false;
11007 goto process_unsafe_channel;
11008 }
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +053011009 if (!data || data_len < (sizeof(channel_list->ch_avoid_range_cnt) +
11010 sizeof(struct ch_avoid_freq_type))) {
11011 hdd_err("Avoid frequency channel list empty");
11012 return -EINVAL;
11013 }
11014 num_args = (data_len - sizeof(channel_list->ch_avoid_range_cnt)) /
11015 sizeof(channel_list->avoid_freq_range[0].start_freq);
11016
11017 if (num_args < 2 || num_args > CH_AVOID_MAX_RANGE * 2 ||
11018 num_args % 2 != 0) {
11019 hdd_err("Invalid avoid frequency channel list");
11020 return -EINVAL;
11021 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053011022
11023 channel_list = (struct ch_avoid_ind_type *)data;
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +053011024 if (channel_list->ch_avoid_range_cnt == 0 ||
11025 channel_list->ch_avoid_range_cnt > CH_AVOID_MAX_RANGE ||
11026 2 * channel_list->ch_avoid_range_cnt != num_args) {
11027 hdd_err("Invalid frequency range count %d",
11028 channel_list->ch_avoid_range_cnt);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053011029 return -EINVAL;
11030 }
11031
hqubf1b6182018-08-14 17:22:41 +080011032process_unsafe_channel:
Liangwei Dong6e1a2092017-08-30 16:29:06 +080011033 ret = hdd_clone_local_unsafe_chan(hdd_ctx,
11034 &local_unsafe_list,
11035 &local_unsafe_list_count);
11036 if (0 != ret) {
11037 hdd_err("failed to clone the cur unsafe chan list");
11038 return ret;
11039 }
11040
Agrawal Ashish467dde42016-09-08 18:44:22 +053011041 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
11042 &(hdd_ctx->unsafe_channel_count),
11043 sizeof(hdd_ctx->unsafe_channel_list));
hqubf1b6182018-08-14 17:22:41 +080011044 if (user_set_avoid_channel) {
11045 hdd_ctx->unsafe_channel_count =
11046 hdd_validate_avoid_freq_chanlist(
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053011047 hdd_ctx,
11048 channel_list);
hqubf1b6182018-08-14 17:22:41 +080011049 unsafe_channel_count = hdd_ctx->unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053011050
hqubf1b6182018-08-14 17:22:41 +080011051 pld_set_wlan_unsafe_channel(qdf_ctx->dev,
11052 hdd_ctx->unsafe_channel_list,
11053 hdd_ctx->unsafe_channel_count);
11054 } else {
11055 unsafe_channel_count = QDF_MIN(
11056 (uint16_t)hdd_ctx->unsafe_channel_count,
11057 (uint16_t)NUM_CHANNELS);
11058 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053011059
Agrawal Ashish467dde42016-09-08 18:44:22 +053011060 for (unsafe_channel_index = 0;
hqubf1b6182018-08-14 17:22:41 +080011061 unsafe_channel_index < unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053011062 unsafe_channel_index++) {
hqubcd0a8f2019-11-25 21:56:35 +080011063 hdd_debug("Channel frequency %d is not safe",
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053011064 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
Agrawal Ashish467dde42016-09-08 18:44:22 +053011065 }
Liangwei Dong6e1a2092017-08-30 16:29:06 +080011066 if (hdd_local_unsafe_channel_updated(hdd_ctx, local_unsafe_list,
11067 local_unsafe_list_count))
11068 hdd_unsafe_channel_restart_sap(hdd_ctx);
11069 qdf_mem_free(local_unsafe_list);
11070
Agrawal Ashish467dde42016-09-08 18:44:22 +053011071 return 0;
11072}
11073
11074/**
11075 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
11076 * is on unsafe channel.
11077 * @wiphy: wiphy structure pointer
11078 * @wdev: Wireless device structure pointer
11079 * @data: Pointer to the data received
11080 * @data_len: Length of @data
11081 *
11082 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
11083 * on any of unsafe channels.
11084 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
11085 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
11086 *
11087 * Return: 0 on success; errno on failure
11088 */
11089static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
11090 struct wireless_dev *wdev,
11091 const void *data, int data_len)
11092{
Dustin Brown363b4792019-02-05 16:11:55 -080011093 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080011094 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053011095
Dustin Brown363b4792019-02-05 16:11:55 -080011096 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080011097 if (errno)
11098 return errno;
Agrawal Ashish467dde42016-09-08 18:44:22 +053011099
Dustin Brownf0f00612019-01-31 16:02:24 -080011100 errno = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
Agrawal Ashish467dde42016-09-08 18:44:22 +053011101
Dustin Brown363b4792019-02-05 16:11:55 -080011102 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053011103
Dustin Brownf0f00612019-01-31 16:02:24 -080011104 return errno;
Agrawal Ashish467dde42016-09-08 18:44:22 +053011105}
11106
11107#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053011108/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011109 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
11110 * SAP is on unsafe channel.
11111 * @wiphy: wiphy structure pointer
11112 * @wdev: Wireless device structure pointer
11113 * @data: Pointer to the data received
11114 * @data_len: Length of @data
11115 *
11116 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
11117 * driver.
11118 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
11119 * will initiate restart of sap.
11120 *
11121 * Return: 0 on success; errno on failure
11122 */
11123static int
11124__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
11125 struct wireless_dev *wdev,
11126 const void *data, int data_len)
11127{
11128 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070011129 struct hdd_adapter *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011130 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011131 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
Jeff Johnson87251032017-08-29 13:31:11 -070011132 struct hdd_ap_ctx *ap_ctx;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011133 int ret;
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053011134 uint32_t chan_freq = 0;
Min Liu71abe092019-11-25 14:09:25 +080011135 bool chan_freq_present = false;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053011136 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011137
Dustin Brown491d54b2018-03-14 12:39:11 -070011138 hdd_enter();
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011139
11140 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011141 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011142 return -EINVAL;
11143 }
11144
11145 ret = wlan_hdd_validate_context(hdd_ctx);
11146 if (0 != ret)
11147 return -EINVAL;
11148
Dustin Brown4ea21db2018-01-05 14:13:17 -080011149 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
11150 data, data_len,
11151 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011152 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011153 return -EINVAL;
11154 }
11155
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053011156 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY]) {
11157 chan_freq = nla_get_u32(
11158 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY]);
Min Liu71abe092019-11-25 14:09:25 +080011159 chan_freq_present = true;
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053011160 } else if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
11161 uint32_t config_channel =
11162 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
11163
11164 chan_freq = wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev,
11165 config_channel);
Min Liu71abe092019-11-25 14:09:25 +080011166 chan_freq_present = true;
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053011167 }
11168
Min Liu71abe092019-11-25 14:09:25 +080011169 if (chan_freq_present) {
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011170 if (!test_bit(SOFTAP_BSS_STARTED,
11171 &hostapd_adapter->event_flags)) {
11172 hdd_err("SAP is not started yet. Restart sap will be invalid");
11173 return -EINVAL;
11174 }
11175
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053011176 if (!WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq) &&
11177 !WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq) &&
11178 !WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq)) {
11179 hdd_err("Channel frequency %u is invalid to restart SAP",
11180 chan_freq);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011181 return -ENOTSUPP;
11182 }
11183
11184 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053011185 ap_ctx->sap_config.chan_freq = chan_freq;
Jeff Johnson91df29d2017-10-27 19:29:50 -070011186 ap_ctx->sap_config.ch_params.ch_width =
11187 ap_ctx->sap_config.ch_width_orig;
hqu73bccf22017-10-28 15:34:17 +080011188 ap_ctx->bss_stop_reason = BSS_STOP_DUE_TO_VENDOR_CONFIG_CHAN;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011189
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053011190 wlan_reg_set_channel_params_for_freq(
11191 hdd_ctx->pdev, chan_freq,
11192 ap_ctx->sap_config.sec_ch_freq,
11193 &ap_ctx->sap_config.ch_params);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011194
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011195 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011196 }
11197
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053011198 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
11199 uint32_t freq_len, i;
11200 uint32_t *freq;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053011201
11202 hdd_debug("setting mandatory freq/chan list");
11203
11204 freq_len = nla_len(
11205 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
11206 sizeof(uint32_t);
11207
Qun Zhang3a5bd1a2020-03-20 12:05:25 +080011208 if (freq_len > NUM_CHANNELS) {
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053011209 hdd_err("insufficient space to hold channels");
11210 return -ENOMEM;
11211 }
11212
11213 freq = nla_data(
11214 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
11215
11216 hdd_debug("freq_len=%d", freq_len);
11217
11218 for (i = 0; i < freq_len; i++) {
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053011219 hdd_debug("freq[%d]=%d", i, freq[i]);
11220 }
11221
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011222 status = policy_mgr_set_sap_mandatory_channels(
Manikandan Mohan19f36092019-08-15 15:54:02 -070011223 hdd_ctx->psoc, freq, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053011224 if (QDF_IS_STATUS_ERROR(status))
11225 return -EINVAL;
11226 }
11227
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011228 return 0;
11229}
11230
11231/**
11232 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
11233 * @wiphy: wiphy structure pointer
11234 * @wdev: Wireless device structure pointer
11235 * @data: Pointer to the data received
11236 * @data_len: Length of @data
11237 *
11238 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
11239 * driver.
11240 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
11241 * will initiate restart of sap.
11242 *
11243 * Return: 0 on success; errno on failure
11244 */
11245static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
11246 struct wireless_dev *wdev,
11247 const void *data, int data_len)
11248{
Dustin Browna09acf42018-11-08 12:32:26 +053011249 int errno;
11250 struct osif_vdev_sync *vdev_sync;
11251
11252 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
11253 if (errno)
11254 return errno;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011255
Dustin Browna09acf42018-11-08 12:32:26 +053011256 errno = __wlan_hdd_cfg80211_sap_configuration_set(wiphy, wdev,
11257 data, data_len);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011258
Dustin Browna09acf42018-11-08 12:32:26 +053011259 osif_vdev_sync_op_stop(vdev_sync);
11260
11261 return errno;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011262}
11263
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011264/**
11265 * wlan_hdd_process_wake_lock_stats() - wrapper function to absract cp_stats
11266 * or legacy get_wake_lock_stats API.
11267 * @hdd_ctx: pointer to hdd_ctx
11268 *
11269 * Return: 0 on success; error number otherwise.
11270 */
11271static int wlan_hdd_process_wake_lock_stats(struct hdd_context *hdd_ctx)
11272{
Ashish Kumar Dhanotiya136bc8e2019-06-04 16:20:31 +053011273 return wlan_cfg80211_mc_cp_stats_get_wakelock_stats(hdd_ctx->psoc,
11274 hdd_ctx->wiphy);
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011275}
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011276
11277/**
11278 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
11279 * @wiphy: wiphy pointer
11280 * @wdev: pointer to struct wireless_dev
11281 * @data: pointer to incoming NL vendor data
11282 * @data_len: length of @data
11283 *
11284 * This function parses the incoming NL vendor command data attributes and
11285 * invokes the SME Api and blocks on a completion variable.
11286 * WMA copies required data and invokes callback
11287 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
11288 *
11289 * Return: 0 on success; error number otherwise.
11290 */
11291static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
11292 struct wireless_dev *wdev,
11293 const void *data,
11294 int data_len)
11295{
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011296 int ret;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011297 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011298
Dustin Brown491d54b2018-03-14 12:39:11 -070011299 hdd_enter();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011300
11301 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -070011302 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011303 return -EINVAL;
11304 }
11305
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011306 ret = wlan_hdd_validate_context(hdd_ctx);
11307 if (0 != ret)
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011308 return -EINVAL;
11309
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011310 ret = wlan_hdd_process_wake_lock_stats(hdd_ctx);
Dustin Browne74003f2018-03-14 12:51:58 -070011311 hdd_exit();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011312 return ret;
11313}
11314
11315/**
11316 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
11317 * @wiphy: wiphy pointer
11318 * @wdev: pointer to struct wireless_dev
11319 * @data: pointer to incoming NL vendor data
11320 * @data_len: length of @data
11321 *
11322 * This function parses the incoming NL vendor command data attributes and
11323 * invokes the SME Api and blocks on a completion variable.
11324 * WMA copies required data and invokes callback
11325 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
11326 *
11327 * Return: 0 on success; error number otherwise.
11328 */
11329static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
11330 struct wireless_dev *wdev,
11331 const void *data, int data_len)
11332{
Dustin Brown363b4792019-02-05 16:11:55 -080011333 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080011334 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053011335
Dustin Brown363b4792019-02-05 16:11:55 -080011336 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080011337 if (errno)
11338 return errno;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011339
Dustin Brownf0f00612019-01-31 16:02:24 -080011340 errno = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev,
11341 data, data_len);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011342
Dustin Brown363b4792019-02-05 16:11:55 -080011343 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080011344
11345 return errno;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011346}
11347
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011348/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011349 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
11350 * @wiphy: wiphy structure pointer
11351 * @wdev: Wireless device structure pointer
11352 * @data: Pointer to the data received
11353 * @data_len: Length of @data
11354 *
11355 * This function reads wmi max bus size and fill in the skb with
11356 * NL attributes and send up the NL event.
11357 * Return: 0 on success; errno on failure
11358 */
11359static int
11360__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
11361 struct wireless_dev *wdev,
11362 const void *data, int data_len)
11363{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011364 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011365 int ret_val;
11366 struct sk_buff *skb;
11367 uint32_t nl_buf_len;
11368
Dustin Brown491d54b2018-03-14 12:39:11 -070011369 hdd_enter();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011370
11371 ret_val = wlan_hdd_validate_context(hdd_ctx);
11372 if (ret_val)
11373 return ret_val;
11374
11375 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
11376 hdd_err("Command not allowed in FTM mode");
11377 return -EINVAL;
11378 }
11379
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011380 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011381
11382 nl_buf_len = NLMSG_HDRLEN;
11383 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
11384
11385 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
11386 if (!skb) {
11387 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
11388 return -ENOMEM;
11389 }
11390
11391 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
11392 hdd_ctx->wmi_max_len)) {
11393 hdd_err("nla put failure");
11394 goto nla_put_failure;
11395 }
11396
11397 cfg80211_vendor_cmd_reply(skb);
11398
Dustin Browne74003f2018-03-14 12:51:58 -070011399 hdd_exit();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011400
11401 return 0;
11402
11403nla_put_failure:
11404 kfree_skb(skb);
11405 return -EINVAL;
11406}
11407
11408/**
11409 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
11410 * @wiphy: wiphy structure pointer
11411 * @wdev: Wireless device structure pointer
11412 * @data: Pointer to the data received
11413 * @data_len: Length of @data
11414 *
11415 * Return: 0 on success; errno on failure
11416 */
11417static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
11418 struct wireless_dev *wdev,
11419 const void *data, int data_len)
11420{
Dustin Brown363b4792019-02-05 16:11:55 -080011421 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080011422 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053011423
Dustin Brown363b4792019-02-05 16:11:55 -080011424 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080011425 if (errno)
11426 return errno;
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011427
Dustin Brownf0f00612019-01-31 16:02:24 -080011428 errno = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011429
Dustin Brown363b4792019-02-05 16:11:55 -080011430 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080011431
11432 return errno;
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011433}
11434
11435/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011436 *__wlan_hdd_cfg80211_setband() - set band
11437 * @wiphy: Pointer to wireless phy
11438 * @wdev: Pointer to wireless device
11439 * @data: Pointer to data
11440 * @data_len: Length of @data
11441 *
11442 * Return: 0 on success, negative errno on failure
11443 */
11444static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
11445 struct wireless_dev *wdev,
11446 const void *data, int data_len)
11447{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011448 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -070011449 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011450 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
11451 int ret;
11452 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
11453 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
11454
Dustin Brown491d54b2018-03-14 12:39:11 -070011455 hdd_enter();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011456
11457 ret = wlan_hdd_validate_context(hdd_ctx);
11458 if (ret)
11459 return ret;
11460
Dustin Brown4ea21db2018-01-05 14:13:17 -080011461 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
11462 data, data_len, policy)) {
Dustin Brownbacc48f2018-03-14 14:48:44 -070011463 hdd_err("Invalid ATTR");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011464 return -EINVAL;
11465 }
11466
11467 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -070011468 hdd_err("attr SETBAND_VALUE failed");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011469 return -EINVAL;
11470 }
11471
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -070011472 ret = hdd_reg_set_band(dev,
11473 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011474
Dustin Browne74003f2018-03-14 12:51:58 -070011475 hdd_exit();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011476 return ret;
11477}
11478
11479/**
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011480 *wlan_hdd_validate_acs_channel() - validate channel frequency provided by ACS
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011481 * @adapter: hdd adapter
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011482 * @chan_freq: channel frequency in MHz
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011483 *
11484 * return: QDF status based on success or failure
11485 */
Jeff Johnsone5006672017-08-29 14:39:02 -070011486static QDF_STATUS wlan_hdd_validate_acs_channel(struct hdd_adapter *adapter,
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011487 uint32_t chan_freq, int chan_bw)
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011488{
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070011489 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011490 uint8_t channel;
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070011491
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011492 if (QDF_STATUS_SUCCESS !=
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011493 wlan_hdd_validate_operation_channel(adapter, chan_freq))
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011494 return QDF_STATUS_E_FAILURE;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011495
11496 channel = (uint8_t)wlan_reg_freq_to_chan(hdd_ctx->pdev, chan_freq);
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011497 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
11498 channel,
11499 PHY_SINGLE_CHANNEL_CENTERED))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -070011500 hdd_info("channel %d is in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011501 return -EINVAL;
11502 }
11503
11504 if ((wlansap_is_channel_leaking_in_nol(
11505 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
11506 channel, chan_bw))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -070011507 hdd_info("channel %d is leaking in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011508 return -EINVAL;
11509 }
11510
11511 return 0;
11512
11513}
11514
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011515static void hdd_update_acs_sap_config(struct hdd_context *hdd_ctx,
Jeff Johnson8f8ceb92019-03-24 08:16:55 -070011516 struct sap_config *sap_config,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011517 struct hdd_vendor_chan_info *channel_list)
11518{
Abhinav Kumarb074f2f2018-09-15 15:32:11 +053011519 uint8_t ch_width;
11520 QDF_STATUS status;
Wu Gaoed616a12019-01-16 15:19:21 +080011521 uint32_t channel_bonding_mode;
11522
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011523 sap_config->chan_freq = channel_list->pri_chan_freq;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011524
11525 sap_config->ch_params.center_freq_seg0 =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011526 wlan_reg_freq_to_chan(hdd_ctx->pdev,
11527 channel_list->vht_seg0_center_chan_freq);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011528 sap_config->ch_params.center_freq_seg1 =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011529 wlan_reg_freq_to_chan(hdd_ctx->pdev,
11530 channel_list->vht_seg1_center_chan_freq);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011531
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011532 sap_config->ch_params.sec_ch_offset =
11533 wlan_reg_freq_to_chan(hdd_ctx->pdev,
11534 channel_list->ht_sec_chan_freq);
11535
Kapil Gupta8878ad92017-02-13 11:56:04 +053011536 sap_config->ch_params.ch_width = channel_list->chan_width;
wadesong88378bd2020-03-24 13:25:21 +080011537 if (!WLAN_REG_IS_24GHZ_CH_FREQ(sap_config->chan_freq)) {
Abhinav Kumarb074f2f2018-09-15 15:32:11 +053011538 status =
11539 ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
11540 &ch_width);
11541 if (!QDF_IS_STATUS_SUCCESS(status))
11542 hdd_err("Failed to set channel_width");
11543 sap_config->ch_width_orig = ch_width;
11544 } else {
Wu Gaoed616a12019-01-16 15:19:21 +080011545 ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
11546 &channel_bonding_mode);
11547 sap_config->ch_width_orig = channel_bonding_mode ?
11548 eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ;
Abhinav Kumarb074f2f2018-09-15 15:32:11 +053011549 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011550 sap_config->acs_cfg.pri_ch_freq = channel_list->pri_chan_freq;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011551 sap_config->acs_cfg.ch_width = channel_list->chan_width;
Liangwei Dong0e18c472019-11-08 17:59:09 +080011552 sap_config->acs_cfg.vht_seg0_center_ch_freq =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011553 channel_list->vht_seg0_center_chan_freq;
Liangwei Dong0e18c472019-11-08 17:59:09 +080011554 sap_config->acs_cfg.vht_seg1_center_ch_freq =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011555 channel_list->vht_seg1_center_chan_freq;
gaurank kathpalia92b81ce2019-10-30 17:21:48 +053011556 sap_config->acs_cfg.ht_sec_ch_freq =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011557 channel_list->ht_sec_chan_freq;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011558}
11559
Jeff Johnsone5006672017-08-29 14:39:02 -070011560static int hdd_update_acs_channel(struct hdd_adapter *adapter, uint8_t reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011561 uint8_t channel_cnt,
11562 struct hdd_vendor_chan_info *channel_list)
11563{
Jeff Johnson8f8ceb92019-03-24 08:16:55 -070011564 struct sap_config *sap_config;
Jeff Johnson87251032017-08-29 13:31:11 -070011565 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011566 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011567 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011568 mac_handle_t mac_handle;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011569 uint32_t ch;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011570
Min Liuab6ed4f2018-01-09 13:13:57 +080011571 if (!channel_list) {
11572 hdd_err("channel_list is NULL");
11573 return -EINVAL;
11574 }
11575
Kapil Gupta8878ad92017-02-13 11:56:04 +053011576 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnsonb9424862017-10-30 08:49:35 -070011577 sap_config = &adapter->session.ap.sap_config;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011578
11579 if (QDF_TIMER_STATE_RUNNING ==
Jeff Johnsonb9424862017-10-30 08:49:35 -070011580 qdf_mc_timer_get_current_state(&adapter->session.
Kapil Gupta8878ad92017-02-13 11:56:04 +053011581 ap.vendor_acs_timer)) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070011582 qdf_mc_timer_stop(&adapter->session.ap.vendor_acs_timer);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011583 }
11584
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011585 if (channel_list->pri_chan_freq == 0) {
Kapil Gupta8878ad92017-02-13 11:56:04 +053011586 /* Check mode, set default channel */
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011587 channel_list->pri_chan_freq = 2437;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011588 /*
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011589 * sap_select_default_oper_chan(mac_handle,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011590 * sap_config->acs_cfg.hw_mode);
11591 */
11592 }
11593
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011594 mac_handle = hdd_ctx->mac_handle;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011595 switch (reason) {
11596 /* SAP init case */
11597 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
11598 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
11599 /* Update Hostapd */
11600 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
11601 break;
11602
11603 /* DFS detected on current channel */
11604 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011605 ch = wlan_reg_freq_to_chan(hdd_ctx->pdev,
11606 channel_list->pri_chan_freq);
11607
Kapil Gupta8878ad92017-02-13 11:56:04 +053011608 wlan_sap_update_next_channel(
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011609 WLAN_HDD_GET_SAP_CTX_PTR(adapter), (uint8_t)ch,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011610 channel_list->chan_width);
11611 status = sme_update_new_channel_event(
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011612 mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080011613 adapter->vdev_id);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011614 break;
11615
11616 /* LTE coex event on current channel */
11617 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011618 ch = wlan_reg_freq_to_chan(hdd_ctx->pdev,
11619 channel_list->pri_chan_freq);
11620 sap_config->acs_cfg.pri_ch_freq = channel_list->pri_chan_freq;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011621 sap_config->acs_cfg.ch_width = channel_list->chan_width;
Jeff Johnson91df29d2017-10-27 19:29:50 -070011622 hdd_ap_ctx->sap_config.ch_width_orig =
Kapil Gupta8878ad92017-02-13 11:56:04 +053011623 channel_list->chan_width;
Bala Venkatesh8b9bbde2019-07-03 16:25:16 +053011624 wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->vdev_id,
11625 CSA_REASON_LTE_COEX);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011626 hdd_switch_sap_channel(adapter, (uint8_t)ch, true);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011627 break;
11628
11629 default:
11630 hdd_info("invalid reason for timer invoke");
11631 }
Dustin Browne74003f2018-03-14 12:51:58 -070011632 hdd_exit();
Min Liuab6ed4f2018-01-09 13:13:57 +080011633 return qdf_status_to_os_return(status);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011634}
11635
11636/**
11637 * Define short name for vendor channel set config
11638 */
11639#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
Kapil Gupta8878ad92017-02-13 11:56:04 +053011640#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
11641#define SET_CHAN_PRIMARY_CHANNEL \
11642 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
11643#define SET_CHAN_SECONDARY_CHANNEL \
11644 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
11645#define SET_CHAN_SEG0_CENTER_CHANNEL \
11646 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
11647#define SET_CHAN_SEG1_CENTER_CHANNEL \
11648 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
11649#define SET_CHAN_CHANNEL_WIDTH \
11650 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011651
11652#define SET_CHAN_FREQ_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_LIST
11653#define SET_CHAN_FREQUENCY_PRIMARY \
11654 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_PRIMARY
11655#define SET_CHAN_FREQUENCY_SECONDARY \
11656 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY
11657#define SET_CHAN_SEG0_CENTER_FREQUENCY \
11658 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0
11659#define SET_CHAN_SEG1_CENTER_FREQUENCY \
11660 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1
11661
11662#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
Kapil Gupta63e75282017-05-18 20:55:10 +053011663#define SET_EXT_ACS_BAND QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND
Kapil Gupta8878ad92017-02-13 11:56:04 +053011664
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011665static const struct nla_policy acs_chan_config_policy[SET_CHAN_MAX + 1] = {
11666 [SET_CHAN_REASON] = {.type = NLA_U8},
11667 [SET_CHAN_CHAN_LIST] = {.type = NLA_NESTED},
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011668 [SET_CHAN_FREQ_LIST] = {.type = NLA_NESTED},
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011669};
11670
11671static const struct nla_policy acs_chan_list_policy[SET_CHAN_MAX + 1] = {
11672 [SET_CHAN_PRIMARY_CHANNEL] = {.type = NLA_U8},
11673 [SET_CHAN_SECONDARY_CHANNEL] = {.type = NLA_U8},
11674 [SET_CHAN_SEG0_CENTER_CHANNEL] = {.type = NLA_U8},
11675 [SET_CHAN_SEG1_CENTER_CHANNEL] = {.type = NLA_U8},
11676 [SET_CHAN_CHANNEL_WIDTH] = {.type = NLA_U8},
11677 [SET_EXT_ACS_BAND] = {.type = NLA_U8},
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011678
11679 [SET_CHAN_FREQUENCY_PRIMARY] = {.type = NLA_U32},
11680 [SET_CHAN_FREQUENCY_SECONDARY] = {.type = NLA_U32},
11681 [SET_CHAN_SEG0_CENTER_FREQUENCY] = {.type = NLA_U32},
11682 [SET_CHAN_SEG1_CENTER_FREQUENCY] = {.type = NLA_U32},
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011683};
11684
Kapil Gupta8878ad92017-02-13 11:56:04 +053011685/**
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011686 * hdd_extract_external_acs_frequencies() - API to parse and extract vendor acs
11687 * channel frequency (in MHz) configuration.
11688 * @hdd_ctx: pointer to hdd context
11689 * @list_ptr: pointer to hdd_vendor_chan_info
Kapil Gupta8878ad92017-02-13 11:56:04 +053011690 * @channel_cnt: channel count
11691 * @data: data
11692 * @data_len: data len
11693 *
11694 * Return: 0 on success, negative errno on failure
11695 */
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011696static int
11697hdd_extract_external_acs_frequencies(struct hdd_context *hdd_ctx,
11698 struct hdd_vendor_chan_info **list_ptr,
11699 uint8_t *channel_cnt,
11700 const void *data, int data_len)
Kapil Gupta8878ad92017-02-13 11:56:04 +053011701{
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011702 int rem;
11703 uint32_t i = 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011704 struct nlattr *tb[SET_CHAN_MAX + 1];
11705 struct nlattr *tb2[SET_CHAN_MAX + 1];
11706 struct nlattr *curr_attr;
11707 struct hdd_vendor_chan_info *channel_list;
11708
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011709 if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
11710 acs_chan_config_policy)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +053011711 hdd_err("Invalid ATTR");
11712 return -EINVAL;
11713 }
11714
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011715 nla_for_each_nested(curr_attr, tb[SET_CHAN_FREQ_LIST], rem)
11716 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011717
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011718 if (!i) {
11719 hdd_err_rl("Error: channel count is zero");
11720 return -EINVAL;
11721 }
11722
11723 if (i > NUM_CHANNELS) {
11724 hdd_err_rl("Error: Exceeded max channels: %u", NUM_CHANNELS);
11725 return -ENOMEM;
11726 }
11727
11728 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) * i);
11729 if (!channel_list)
11730 return -ENOMEM;
11731
11732 *channel_cnt = (uint8_t)i;
11733 i = 0;
11734 nla_for_each_nested(curr_attr, tb[SET_CHAN_FREQ_LIST], rem) {
11735 if (wlan_cfg80211_nla_parse_nested(tb2, SET_CHAN_MAX,
11736 curr_attr,
11737 acs_chan_list_policy)) {
11738 hdd_err_rl("nla_parse failed");
11739 qdf_mem_free(channel_list);
11740 *channel_cnt = 0;
11741 return -EINVAL;
11742 }
11743
11744 if (tb2[SET_EXT_ACS_BAND])
11745 channel_list[i].band =
11746 nla_get_u8(tb2[SET_EXT_ACS_BAND]);
11747
11748 if (tb2[SET_CHAN_FREQUENCY_PRIMARY])
11749 channel_list[i].pri_chan_freq =
11750 nla_get_u32(tb2[SET_CHAN_FREQUENCY_PRIMARY]);
11751
11752 if (tb2[SET_CHAN_FREQUENCY_SECONDARY])
11753 channel_list[i].ht_sec_chan_freq =
11754 nla_get_u32(tb2[SET_CHAN_FREQUENCY_SECONDARY]);
11755
11756 if (tb2[SET_CHAN_SEG0_CENTER_FREQUENCY])
11757 channel_list[i].vht_seg0_center_chan_freq =
11758 nla_get_u32(tb2[SET_CHAN_SEG0_CENTER_FREQUENCY]);
11759
11760 if (tb2[SET_CHAN_SEG1_CENTER_FREQUENCY])
11761 channel_list[i].vht_seg1_center_chan_freq =
11762 nla_get_u32(tb2[SET_CHAN_SEG1_CENTER_FREQUENCY]);
11763
11764 if (tb2[SET_CHAN_CHANNEL_WIDTH])
11765 channel_list[i].chan_width =
11766 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
11767
11768 hdd_debug("index %d, pri_chan_freq %u, ht_sec_chan_freq %u seg0_freq %u seg1_freq %u width %u",
11769 i, channel_list[i].pri_chan_freq,
11770 channel_list[i].ht_sec_chan_freq,
11771 channel_list[i].vht_seg0_center_chan_freq,
11772 channel_list[i].vht_seg1_center_chan_freq,
11773 channel_list[i].chan_width);
11774 i++;
11775 }
11776 *list_ptr = channel_list;
11777
11778 return 0;
11779}
11780
11781/**
11782 * hdd_extract_external_acs_channels() - API to parse and extract vendor acs
11783 * channel configuration.
11784 * @hdd_ctx: pointer to hdd context
11785 * @list_ptr: pointer to hdd_vendor_chan_info
11786 * @channel_cnt: channel count
11787 * @data: data
11788 * @data_len: data len
11789 *
11790 * Return: 0 on success, negative errno on failure
11791 */
11792static int
11793hdd_extract_external_acs_channels(struct hdd_context *hdd_ctx,
11794 struct hdd_vendor_chan_info **list_ptr,
11795 uint8_t *channel_cnt,
11796 const void *data, int data_len)
11797{
11798 int rem;
11799 uint32_t i = 0;
11800 struct nlattr *tb[SET_CHAN_MAX + 1];
11801 struct nlattr *tb2[SET_CHAN_MAX + 1];
11802 struct nlattr *curr_attr;
11803 struct hdd_vendor_chan_info *channel_list;
11804
11805 if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
11806 acs_chan_config_policy)) {
11807 hdd_err("Invalid ATTR");
sheenam monga5440bdd2019-03-11 17:32:37 +053011808 return -EINVAL;
11809 }
11810
Kapil Gupta63e75282017-05-18 20:55:10 +053011811 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem)
11812 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011813
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011814 if (!i) {
11815 hdd_err_rl("Error: channel count is zero");
11816 return -EINVAL;
11817 }
11818
Liangwei Dong2eb654f2019-09-11 15:54:09 +080011819 if (i > NUM_CHANNELS) {
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011820 hdd_err_rl("Error: Exceeded max channels: %u", NUM_CHANNELS);
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011821 return -ENOMEM;
11822 }
11823
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011824 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) * i);
Min Liu74a1a502018-10-10 19:59:07 +080011825 if (!channel_list)
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011826 return -ENOMEM;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011827
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011828 *channel_cnt = (uint8_t)i;
Kapil Gupta63e75282017-05-18 20:55:10 +053011829 i = 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011830 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011831 if (wlan_cfg80211_nla_parse_nested(tb2, SET_CHAN_MAX,
11832 curr_attr,
11833 acs_chan_list_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -080011834 hdd_err("nla_parse failed");
Rajeev Kumar Sirasanagandla2feb4212019-03-14 22:15:02 +053011835 qdf_mem_free(channel_list);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011836 *channel_cnt = 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011837 return -EINVAL;
11838 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011839
Kapil Gupta63e75282017-05-18 20:55:10 +053011840 if (tb2[SET_EXT_ACS_BAND]) {
11841 channel_list[i].band =
11842 nla_get_u8(tb2[SET_EXT_ACS_BAND]);
11843 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011844
Kapil Gupta8878ad92017-02-13 11:56:04 +053011845 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011846 uint32_t ch =
11847 nla_get_u8(tb2[SET_CHAN_PRIMARY_CHANNEL]);
11848
11849 channel_list[i].pri_chan_freq =
11850 wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011851 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011852
Kapil Gupta8878ad92017-02-13 11:56:04 +053011853 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011854 uint32_t ch =
Kapil Gupta8878ad92017-02-13 11:56:04 +053011855 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011856
11857 channel_list[i].ht_sec_chan_freq =
11858 wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011859 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011860
Kapil Gupta8878ad92017-02-13 11:56:04 +053011861 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011862 uint32_t ch =
Kapil Gupta8878ad92017-02-13 11:56:04 +053011863 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011864
11865 channel_list[i].vht_seg0_center_chan_freq =
11866 wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011867 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011868
Kapil Gupta8878ad92017-02-13 11:56:04 +053011869 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011870 uint32_t ch =
Kapil Gupta8878ad92017-02-13 11:56:04 +053011871 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011872
11873 channel_list[i].vht_seg1_center_chan_freq =
11874 wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011875 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011876
Kapil Gupta8878ad92017-02-13 11:56:04 +053011877 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
11878 channel_list[i].chan_width =
11879 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
11880 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011881 hdd_debug("index %d, pri_chan_freq %u, ht_sec_chan_freq %u seg0_freq %u seg1_freq %u width %u",
11882 i, channel_list[i].pri_chan_freq,
11883 channel_list[i].ht_sec_chan_freq,
11884 channel_list[i].vht_seg0_center_chan_freq,
11885 channel_list[i].vht_seg1_center_chan_freq,
11886 channel_list[i].chan_width);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011887 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011888 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011889 *list_ptr = channel_list;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011890
11891 return 0;
11892}
11893
11894/**
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011895 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
11896 * @hdd_ctx: pointer to hdd context
11897 * @channel_list: pointer to hdd_vendor_chan_info
11898 * @reason: channel change reason
11899 * @channel_cnt: channel count
11900 * @data: data
11901 * @data_len: data len
11902 *
11903 * Return: 0 on success, negative errno on failure
11904 */
11905static int
11906hdd_parse_vendor_acs_chan_config(struct hdd_context *hdd_ctx,
11907 struct hdd_vendor_chan_info **chan_list_ptr,
11908 uint8_t *reason, uint8_t *channel_cnt,
11909 const void *data, int data_len)
11910{
11911 struct nlattr *tb[SET_CHAN_MAX + 1];
11912 int ret;
11913
11914 if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
11915 acs_chan_config_policy)) {
11916 hdd_err("Invalid ATTR");
11917 return -EINVAL;
11918 }
11919
11920 if (tb[SET_CHAN_REASON])
11921 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
11922
11923 if (!tb[SET_CHAN_FREQ_LIST] && !tb[SET_CHAN_CHAN_LIST]) {
11924 hdd_err("Both channel list and frequency list are empty");
11925 return -EINVAL;
11926 }
11927
11928 if (tb[SET_CHAN_FREQ_LIST]) {
11929 ret = hdd_extract_external_acs_frequencies(hdd_ctx,
11930 chan_list_ptr,
11931 channel_cnt,
11932 data, data_len);
11933 if (ret) {
11934 hdd_err("Failed to extract frequencies");
11935 return ret;
11936 }
11937
11938 return 0;
11939 }
11940
11941 ret = hdd_extract_external_acs_channels(hdd_ctx, chan_list_ptr,
11942 channel_cnt, data, data_len);
11943 if (ret)
11944 hdd_err("Failed to extract channels");
11945
11946 return ret;
11947}
11948
11949/**
Kapil Gupta8878ad92017-02-13 11:56:04 +053011950 * Undef short names for vendor set channel configuration
11951 */
11952#undef SET_CHAN_REASON
Kapil Gupta8878ad92017-02-13 11:56:04 +053011953#undef SET_CHAN_CHAN_LIST
11954#undef SET_CHAN_PRIMARY_CHANNEL
11955#undef SET_CHAN_SECONDARY_CHANNEL
11956#undef SET_CHAN_SEG0_CENTER_CHANNEL
11957#undef SET_CHAN_SEG1_CENTER_CHANNEL
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011958
11959#undef SET_CHAN_FREQ_LIST
11960#undef SET_CHAN_FREQUENCY_PRIMARY
11961#undef SET_CHAN_FREQUENCY_SECONDARY
11962#undef SET_CHAN_SEG0_CENTER_FREQUENCY
11963#undef SET_CHAN_SEG1_CENTER_FREQUENCY
11964
Kapil Gupta8878ad92017-02-13 11:56:04 +053011965#undef SET_CHAN_CHANNEL_WIDTH
11966#undef SET_CHAN_MAX
11967
11968/**
11969 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
11970 * @wiphy: Pointer to wireless phy
11971 * @wdev: Pointer to wireless device
11972 * @data: Pointer to data
11973 * @data_len: Length of @data
11974 *
11975 * Return: 0 on success, negative errno on failure
11976 */
11977static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
11978 struct wireless_dev *wdev,
11979 const void *data, int data_len)
11980{
11981 int ret_val;
11982 QDF_STATUS qdf_status;
11983 uint8_t channel_cnt = 0, reason = -1;
11984 struct hdd_vendor_chan_info *channel_list = NULL;
Jeff Johnsone5006672017-08-29 14:39:02 -070011985 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011986 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011987 struct hdd_vendor_chan_info *channel_list_ptr;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011988
Dustin Brown491d54b2018-03-14 12:39:11 -070011989 hdd_enter();
Kapil Gupta8878ad92017-02-13 11:56:04 +053011990
11991 ret_val = wlan_hdd_validate_context(hdd_ctx);
11992 if (ret_val)
11993 return ret_val;
11994
11995 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
11996 hdd_err("Command not allowed in FTM mode");
11997 return -EINVAL;
11998 }
11999
12000 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
12001 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
12002 else {
12003 hdd_err("already timeout happened for acs");
12004 return -EINVAL;
12005 }
12006
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053012007 ret_val = hdd_parse_vendor_acs_chan_config(hdd_ctx, &channel_list,
12008 &reason, &channel_cnt, data,
12009 data_len);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053012010 channel_list_ptr = channel_list;
Kapil Gupta8878ad92017-02-13 11:56:04 +053012011 if (ret_val)
12012 return ret_val;
12013
12014 /* Validate channel to be set */
12015 while (channel_cnt && channel_list) {
12016 qdf_status = wlan_hdd_validate_acs_channel(adapter,
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053012017 channel_list->pri_chan_freq,
Kapil Gupta8878ad92017-02-13 11:56:04 +053012018 channel_list->chan_width);
12019 if (qdf_status == QDF_STATUS_SUCCESS)
12020 break;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053012021 else if (channel_cnt == 1) {
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053012022 hdd_err("invalid channel frequ %u received from app",
12023 channel_list->pri_chan_freq);
12024 channel_list->pri_chan_freq = 0;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053012025 break;
12026 }
12027
Kapil Gupta8878ad92017-02-13 11:56:04 +053012028 channel_cnt--;
12029 channel_list++;
12030 }
Min Liuab6ed4f2018-01-09 13:13:57 +080012031
Kapil Gupta8878ad92017-02-13 11:56:04 +053012032 if ((channel_cnt <= 0) || !channel_list) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070012033 hdd_err("no available channel/chanlist %d/%pK", channel_cnt,
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053012034 channel_list);
12035 qdf_mem_free(channel_list_ptr);
Kapil Gupta8878ad92017-02-13 11:56:04 +053012036 return -EINVAL;
12037 }
12038
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053012039 hdd_debug("received primary channel freq as %d",
12040 channel_list->pri_chan_freq);
Min Liuab6ed4f2018-01-09 13:13:57 +080012041
12042 ret_val = hdd_update_acs_channel(adapter, reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +053012043 channel_cnt, channel_list);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053012044 qdf_mem_free(channel_list_ptr);
Min Liuab6ed4f2018-01-09 13:13:57 +080012045 return ret_val;
Kapil Gupta8878ad92017-02-13 11:56:04 +053012046}
12047
12048/**
12049 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
12050 * @wiphy: Pointer to wireless phy
12051 * @wdev: Pointer to wireless device
12052 * @data: Pointer to data
12053 * @data_len: Length of @data
12054 *
12055 * Return: 0 on success, negative errno on failure
12056 */
12057static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
12058 struct wireless_dev *wdev,
12059 const void *data, int data_len)
12060{
Dustin Browna09acf42018-11-08 12:32:26 +053012061 int errno;
12062 struct osif_vdev_sync *vdev_sync;
12063
12064 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
12065 if (errno)
12066 return errno;
Kapil Gupta8878ad92017-02-13 11:56:04 +053012067
Dustin Browna09acf42018-11-08 12:32:26 +053012068 errno = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev,
12069 data, data_len);
Kapil Gupta8878ad92017-02-13 11:56:04 +053012070
Dustin Browna09acf42018-11-08 12:32:26 +053012071 osif_vdev_sync_op_stop(vdev_sync);
12072
12073 return errno;
Kapil Gupta8878ad92017-02-13 11:56:04 +053012074}
Kapil Gupta94ca6f62016-12-11 18:43:12 +053012075
12076/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053012077 * wlan_hdd_cfg80211_setband() - Wrapper to setband
12078 * @wiphy: wiphy structure pointer
12079 * @wdev: Wireless device structure pointer
12080 * @data: Pointer to the data received
12081 * @data_len: Length of @data
12082 *
12083 * Return: 0 on success; errno on failure
12084 */
12085static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
12086 struct wireless_dev *wdev,
12087 const void *data, int data_len)
12088{
Dustin Browna09acf42018-11-08 12:32:26 +053012089 int errno;
12090 struct osif_vdev_sync *vdev_sync;
12091
12092 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
12093 if (errno)
12094 return errno;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053012095
Dustin Browna09acf42018-11-08 12:32:26 +053012096 errno = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053012097
Dustin Browna09acf42018-11-08 12:32:26 +053012098 osif_vdev_sync_op_stop(vdev_sync);
12099
12100 return errno;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053012101}
12102
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012103/**
12104 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
12105 * @nl80211_value: Vendor command attribute value
12106 * @wmi_value: Pointer to return converted WMI return value
12107 *
12108 * Convert NL80211 vendor command value for SAR limit set to WMI value
12109 * Return: 0 on success, -1 on invalid value
12110 */
12111static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
12112 u32 *wmi_value)
12113{
12114 int ret = 0;
12115
12116 switch (nl80211_value) {
12117 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
12118 *wmi_value = WMI_SAR_FEATURE_OFF;
12119 break;
12120 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
12121 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
12122 break;
12123 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
12124 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
12125 break;
12126 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
12127 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
12128 break;
12129 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
12130 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
12131 break;
12132 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
12133 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
12134 break;
12135 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
12136 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
12137 break;
Kabilan Kannancaa85502018-04-13 18:04:58 -070012138 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0:
12139 *wmi_value = WMI_SAR_FEATURE_ON_SAR_V2_0;
12140 break;
12141
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012142 default:
12143 ret = -1;
12144 }
12145 return ret;
12146}
12147
Jeff Johnson354c20b2018-07-17 20:15:56 -070012148#ifdef WLAN_FEATURE_SARV1_TO_SARV2
12149/**
12150 * hdd_convert_sarv1_to_sarv2() - convert SAR V1 BDF reference to SAR V2
12151 * @hdd_ctx: The HDD global context
12152 * @tb: The parsed array of netlink attributes
12153 * @sar_limit_cmd: The WMI command to be filled
12154 *
12155 * This feature/function is designed to solve the following problem:
12156 * 1) Userspace application was written to use SARv1 BDF entries
12157 * 2) Product is configured with SAR V2 BDF entries
12158 *
12159 * So if this feature is enabled, and if the firmware is configured
12160 * with SAR V2 support, and if the incoming request is to enable a SAR
12161 * V1 BDF entry, then the WMI command is generated to actually
12162 * configure a SAR V2 BDF entry.
12163 *
12164 * Return: true if conversion was performed and @sar_limit_cmd is
12165 * ready to be sent to firmware. Otherwise false in which case the
12166 * normal parsing logic should be applied.
12167 */
12168
12169static bool
12170hdd_convert_sarv1_to_sarv2(struct hdd_context *hdd_ctx,
12171 struct nlattr *tb[],
12172 struct sar_limit_cmd_params *sar_limit_cmd)
12173{
12174 struct nlattr *attr;
12175 uint32_t bdf_index, set;
12176 struct sar_limit_cmd_row *row;
12177
Ashish Kumar Dhanotiya3257cee2019-12-13 20:30:03 +053012178 hdd_enter();
Jeff Johnson354c20b2018-07-17 20:15:56 -070012179 if (hdd_ctx->sar_version != SAR_VERSION_2) {
12180 hdd_debug("SAR version: %d", hdd_ctx->sar_version);
12181 return false;
12182 }
12183
12184 attr = tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE];
12185 if (!attr)
12186 return false;
12187
12188 bdf_index = nla_get_u32(attr);
12189
12190 if ((bdf_index >= QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0) &&
12191 (bdf_index <= QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4)) {
12192 set = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0;
12193 } else if (bdf_index == QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE) {
12194 set = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE;
12195 bdf_index = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0;
12196 } else {
12197 return false;
12198 }
12199
12200 /* Need two rows to hold the per-chain V2 power index
12201 * To disable SARv2 limit, send chain, num_limits_row and
12202 * power limit set to 0 (except power index 0xff)
12203 */
12204 row = qdf_mem_malloc(2 * sizeof(*row));
12205 if (!row)
12206 return false;
12207
12208 if (wlan_hdd_cfg80211_sar_convert_limit_set(
12209 set, &sar_limit_cmd->sar_enable)) {
12210 hdd_err("Failed to convert SAR limit to WMI value");
12211 return false;
12212 }
12213
12214 sar_limit_cmd->commit_limits = 1;
12215 sar_limit_cmd->num_limit_rows = 2;
12216 sar_limit_cmd->sar_limit_row_list = row;
12217 row[0].limit_value = bdf_index;
12218 row[1].limit_value = row[0].limit_value;
12219 row[0].chain_id = 0;
12220 row[1].chain_id = 1;
12221 row[0].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
12222 row[1].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
12223
Ashish Kumar Dhanotiya3257cee2019-12-13 20:30:03 +053012224 hdd_exit();
Jeff Johnson354c20b2018-07-17 20:15:56 -070012225 return true;
12226}
12227
12228#else /* WLAN_FEATURE_SARV1_TO_SARV2 */
Jeff Johnson354c20b2018-07-17 20:15:56 -070012229static bool
12230hdd_convert_sarv1_to_sarv2(struct hdd_context *hdd_ctx,
12231 struct nlattr *tb[],
12232 struct sar_limit_cmd_params *sar_limit_cmd)
12233{
12234 return false;
12235}
12236
12237#endif /* WLAN_FEATURE_SARV1_TO_SARV2 */
12238
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012239/**
12240 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
12241 * @nl80211_value: Vendor command attribute value
12242 * @wmi_value: Pointer to return converted WMI return value
12243 *
12244 * Convert NL80211 vendor command value for SAR BAND to WMI value
12245 * Return: 0 on success, -1 on invalid value
12246 */
12247static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
12248{
12249 int ret = 0;
12250
12251 switch (nl80211_value) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012252 case HDD_NL80211_BAND_2GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012253 *wmi_value = WMI_SAR_2G_ID;
12254 break;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012255 case HDD_NL80211_BAND_5GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012256 *wmi_value = WMI_SAR_5G_ID;
12257 break;
12258 default:
12259 ret = -1;
12260 }
12261 return ret;
12262}
12263
12264/**
12265 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
12266 * @nl80211_value: Vendor command attribute value
12267 * @wmi_value: Pointer to return converted WMI return value
12268 *
12269 * Convert NL80211 vendor command value for SAR Modulation to WMI value
12270 * Return: 0 on success, -1 on invalid value
12271 */
12272static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
12273 u32 *wmi_value)
12274{
12275 int ret = 0;
12276
12277 switch (nl80211_value) {
12278 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
12279 *wmi_value = WMI_SAR_MOD_CCK;
12280 break;
12281 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
12282 *wmi_value = WMI_SAR_MOD_OFDM;
12283 break;
12284 default:
12285 ret = -1;
12286 }
12287 return ret;
12288}
12289
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012290void hdd_store_sar_config(struct hdd_context *hdd_ctx,
12291 struct sar_limit_cmd_params *sar_limit_cmd)
12292{
12293 /* Free the previously stored sar_limit_cmd */
12294 wlan_hdd_free_sar_config(hdd_ctx);
12295
12296 hdd_ctx->sar_cmd_params = sar_limit_cmd;
12297}
12298
12299void wlan_hdd_free_sar_config(struct hdd_context *hdd_ctx)
12300{
12301 struct sar_limit_cmd_params *sar_limit_cmd;
12302
12303 if (!hdd_ctx->sar_cmd_params)
12304 return;
12305
12306 sar_limit_cmd = hdd_ctx->sar_cmd_params;
12307 hdd_ctx->sar_cmd_params = NULL;
12308 qdf_mem_free(sar_limit_cmd->sar_limit_row_list);
12309 qdf_mem_free(sar_limit_cmd);
12310}
12311
12312#define SAR_LIMITS_SAR_ENABLE QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE
12313#define SAR_LIMITS_NUM_SPECS QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS
12314#define SAR_LIMITS_SPEC QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC
12315#define SAR_LIMITS_SPEC_BAND QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND
12316#define SAR_LIMITS_SPEC_CHAIN QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN
12317#define SAR_LIMITS_SPEC_MODULATION \
12318 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION
12319#define SAR_LIMITS_SPEC_POWER_LIMIT \
12320 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT
12321#define SAR_LIMITS_SPEC_POWER_LIMIT_INDEX \
12322 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX
12323#define SAR_LIMITS_MAX QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX
12324
Jeff Johnsonb17a93c2017-06-02 12:26:55 -070012325static const struct nla_policy
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012326sar_limits_policy[SAR_LIMITS_MAX + 1] = {
12327 [SAR_LIMITS_SAR_ENABLE] = {.type = NLA_U32},
12328 [SAR_LIMITS_NUM_SPECS] = {.type = NLA_U32},
12329 [SAR_LIMITS_SPEC_BAND] = {.type = NLA_U32},
12330 [SAR_LIMITS_SPEC_CHAIN] = {.type = NLA_U32},
12331 [SAR_LIMITS_SPEC_MODULATION] = {.type = NLA_U32},
12332 [SAR_LIMITS_SPEC_POWER_LIMIT] = {.type = NLA_U32},
12333 [SAR_LIMITS_SPEC_POWER_LIMIT_INDEX] = {.type = NLA_U32},
Jeff Johnsonb17a93c2017-06-02 12:26:55 -070012334};
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012335
12336/**
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012337 * hdd_extract_sar_nested_attrs() - Extract nested SAR attribute
12338 * @spec: nested nla attribue
12339 * @row: output to hold extract nested attribute
12340 *
12341 * This function extracts nested SAR attribute one at a time which means
12342 * for each nested attribute this has to be invoked from
12343 * __wlan_hdd_set_sar_power_limits().
12344 *
12345 * Return: On success - 0
12346 * On Failure - Negative value
12347 */
12348static int hdd_extract_sar_nested_attrs(struct nlattr *spec[],
12349 struct sar_limit_cmd_row *row)
12350{
12351 uint32_t limit;
12352 uint32_t band;
12353 uint32_t modulation;
12354 int ret;
12355
12356 row->validity_bitmap = 0;
12357
12358 if (spec[SAR_LIMITS_SPEC_POWER_LIMIT]) {
12359 limit = nla_get_u32(spec[SAR_LIMITS_SPEC_POWER_LIMIT]);
12360 row->limit_value = limit;
12361 } else if (spec[SAR_LIMITS_SPEC_POWER_LIMIT_INDEX]) {
12362 limit = nla_get_u32(spec[SAR_LIMITS_SPEC_POWER_LIMIT_INDEX]);
12363 row->limit_value = limit;
12364 } else {
12365 hdd_err("SAR Spec does not have power limit or index value");
12366 return -EINVAL;
12367 }
12368
12369 if (spec[SAR_LIMITS_SPEC_BAND]) {
12370 band = nla_get_u32(spec[SAR_LIMITS_SPEC_BAND]);
12371 ret = wlan_hdd_cfg80211_sar_convert_band(band, &row->band_id);
12372 if (ret) {
12373 hdd_err("Invalid SAR Band attr");
12374 return ret;
12375 }
12376
12377 row->validity_bitmap |= WMI_SAR_BAND_ID_VALID_MASK;
12378 }
12379
12380 if (spec[SAR_LIMITS_SPEC_CHAIN]) {
12381 row->chain_id = nla_get_u32(spec[SAR_LIMITS_SPEC_CHAIN]);
12382 row->validity_bitmap |= WMI_SAR_CHAIN_ID_VALID_MASK;
12383 }
12384
12385 if (spec[SAR_LIMITS_SPEC_MODULATION]) {
12386 modulation = nla_get_u32(spec[SAR_LIMITS_SPEC_MODULATION]);
12387 ret = wlan_hdd_cfg80211_sar_convert_modulation(modulation,
12388 &row->mod_id);
12389 if (ret) {
12390 hdd_err("Invalid SAR Modulation attr");
12391 return ret;
12392 }
12393
12394 row->validity_bitmap |= WMI_SAR_MOD_ID_VALID_MASK;
12395 }
12396
12397 return 0;
12398}
12399
12400/**
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012401 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
12402 * @wiphy: Pointer to wireless phy
12403 * @wdev: Pointer to wireless device
12404 * @data: Pointer to data
12405 * @data_len: Length of @data
12406 *
12407 * This function is used to setup Specific Absorption Rate limit specs.
12408 *
12409 * Return: 0 on success, negative errno on failure
12410 */
12411static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
12412 struct wireless_dev *wdev,
12413 const void *data, int data_len)
12414{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012415 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012416 struct nlattr *spec[SAR_LIMITS_MAX + 1];
12417 struct nlattr *tb[SAR_LIMITS_MAX + 1];
12418 struct nlattr *spec_list;
12419 struct sar_limit_cmd_params *sar_limit_cmd;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012420 int ret = -EINVAL, i = 0, rem = 0;
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012421 QDF_STATUS status;
12422 uint32_t num_limit_rows = 0;
12423 struct sar_limit_cmd_row *row;
Ashish Kumar Dhanotiya3257cee2019-12-13 20:30:03 +053012424 uint32_t sar_enable;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012425
Dustin Brown491d54b2018-03-14 12:39:11 -070012426 hdd_enter();
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012427
12428 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12429 hdd_err("Command not allowed in FTM mode");
12430 return -EPERM;
12431 }
12432
12433 if (wlan_hdd_validate_context(hdd_ctx))
12434 return -EINVAL;
12435
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012436 if (wlan_cfg80211_nla_parse(tb, SAR_LIMITS_MAX, data, data_len,
12437 sar_limits_policy)) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012438 hdd_err("Invalid SAR attributes");
12439 return -EINVAL;
12440 }
12441
Ashish Kumar Dhanotiya3257cee2019-12-13 20:30:03 +053012442 if (tb[SAR_LIMITS_SAR_ENABLE]) {
12443 sar_enable = nla_get_u32(tb[SAR_LIMITS_SAR_ENABLE]);
12444
12445 if ((sar_enable >=
12446 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0 &&
12447 sar_enable <=
12448 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4) &&
12449 hdd_ctx->sar_version == SAR_VERSION_2 &&
12450 !hdd_ctx->config->enable_sar_conversion) {
12451 hdd_err("SARV1 to SARV2 is disabled from ini");
12452 return -EINVAL;
12453 } else if (sar_enable ==
12454 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0 &&
12455 hdd_ctx->sar_version == SAR_VERSION_1) {
12456 hdd_err("FW expects SARV1 given command is SARV2");
12457 return -EINVAL;
12458 }
12459 }
12460
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012461 sar_limit_cmd = qdf_mem_malloc(sizeof(struct sar_limit_cmd_params));
12462 if (!sar_limit_cmd)
12463 return -ENOMEM;
12464
Ashish Kumar Dhanotiya97de5e62020-01-17 21:15:26 +053012465 wlan_hdd_sar_timers_reset(hdd_ctx);
12466
Jeff Johnson354c20b2018-07-17 20:15:56 -070012467 /* is special SAR V1 => SAR V2 logic enabled and applicable? */
Ashish Kumar Dhanotiya3257cee2019-12-13 20:30:03 +053012468 if (hdd_ctx->config->enable_sar_conversion &&
Ashish Kumar Dhanotiya95498182019-04-29 13:59:20 +053012469 (hdd_convert_sarv1_to_sarv2(hdd_ctx, tb, sar_limit_cmd)))
Jeff Johnson354c20b2018-07-17 20:15:56 -070012470 goto send_sar_limits;
12471
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012472 /* Vendor command manadates all SAR Specs in single call */
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012473 sar_limit_cmd->commit_limits = 1;
12474 sar_limit_cmd->sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
12475 if (tb[SAR_LIMITS_SAR_ENABLE]) {
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012476 uint32_t *sar_ptr = &sar_limit_cmd->sar_enable;
12477
Ashish Kumar Dhanotiya3257cee2019-12-13 20:30:03 +053012478 sar_enable = nla_get_u32(tb[SAR_LIMITS_SAR_ENABLE]);
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012479 ret = wlan_hdd_cfg80211_sar_convert_limit_set(sar_enable,
12480 sar_ptr);
12481 if (ret) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012482 hdd_err("Invalid SAR Enable attr");
12483 goto fail;
12484 }
12485 }
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012486
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012487 hdd_debug("attr sar sar_enable %d", sar_limit_cmd->sar_enable);
12488
12489 if (tb[SAR_LIMITS_NUM_SPECS]) {
12490 num_limit_rows = nla_get_u32(tb[SAR_LIMITS_NUM_SPECS]);
12491 hdd_debug("attr sar num_limit_rows %u", num_limit_rows);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012492 }
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012493
12494 if (num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012495 hdd_err("SAR Spec list exceed supported size");
12496 goto fail;
12497 }
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012498
12499 if (num_limit_rows == 0)
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012500 goto send_sar_limits;
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012501
12502 row = qdf_mem_malloc(sizeof(*row) * num_limit_rows);
12503 if (!row) {
12504 hdd_err("Failed to allocate memory for sar_limit_row_list");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012505 goto fail;
12506 }
12507
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012508 sar_limit_cmd->num_limit_rows = num_limit_rows;
12509 sar_limit_cmd->sar_limit_row_list = row;
12510
12511 if (!tb[SAR_LIMITS_SPEC]) {
12512 hdd_err("Invalid SAR specification list");
12513 goto fail;
12514 }
12515
12516 nla_for_each_nested(spec_list, tb[SAR_LIMITS_SPEC], rem) {
12517 if (i == num_limit_rows) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012518 hdd_warn("SAR Cmd has excess SPECs in list");
12519 break;
12520 }
12521
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012522 if (wlan_cfg80211_nla_parse(spec,
12523 SAR_LIMITS_MAX,
12524 nla_data(spec_list),
12525 nla_len(spec_list),
Dustin Brown4ea21db2018-01-05 14:13:17 -080012526 sar_limits_policy)) {
12527 hdd_err("nla_parse failed for SAR Spec list");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012528 goto fail;
12529 }
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012530
12531 ret = hdd_extract_sar_nested_attrs(spec, row);
12532 if (ret) {
12533 hdd_err("Failed to extract SAR nested attrs");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012534 goto fail;
12535 }
12536
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012537 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012538 i, row->band_id, row->chain_id, row->mod_id,
12539 row->limit_value, row->validity_bitmap);
12540
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012541 i++;
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012542 row++;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012543 }
12544
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012545 if (i < sar_limit_cmd->num_limit_rows) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012546 hdd_warn("SAR Cmd has less SPECs in list");
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012547 sar_limit_cmd->num_limit_rows = i;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012548 }
12549
12550send_sar_limits:
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012551 status = sme_set_sar_power_limits(hdd_ctx->mac_handle, sar_limit_cmd);
12552 if (QDF_IS_STATUS_ERROR(status)) {
12553 hdd_err("Failed to set sar power limits");
12554 goto fail;
12555 }
12556
12557 /* After SSR, the SAR configuration is lost. As SSR is hidden from
12558 * userland, this command will not come from userspace after a SSR. To
12559 * restore this configuration, save this in hdd context and restore
12560 * after re-init.
12561 */
12562 hdd_store_sar_config(hdd_ctx, sar_limit_cmd);
12563 return 0;
12564
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012565fail:
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012566 if (sar_limit_cmd) {
12567 qdf_mem_free(sar_limit_cmd->sar_limit_row_list);
12568 qdf_mem_free(sar_limit_cmd);
12569 }
12570
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012571 return ret;
12572}
12573
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012574#undef SAR_LIMITS_SAR_ENABLE
12575#undef SAR_LIMITS_NUM_SPECS
12576#undef SAR_LIMITS_SPEC
12577#undef SAR_LIMITS_SPEC_BAND
12578#undef SAR_LIMITS_SPEC_CHAIN
12579#undef SAR_LIMITS_SPEC_MODULATION
12580#undef SAR_LIMITS_SPEC_POWER_LIMIT
12581#undef SAR_LIMITS_SPEC_POWER_LIMIT_INDEX
12582#undef SAR_LIMITS_MAX
12583
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012584/**
12585 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
12586 * @wiphy: Pointer to wireless phy
12587 * @wdev: Pointer to wireless device
12588 * @data: Pointer to data
12589 * @data_len: Length of @data
12590 *
12591 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
12592 *
12593 * Return: 0 on success, negative errno on failure
12594 */
12595static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
12596 struct wireless_dev *wdev,
12597 const void *data,
12598 int data_len)
12599{
Dustin Brown363b4792019-02-05 16:11:55 -080012600 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080012601 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053012602
Dustin Brown363b4792019-02-05 16:11:55 -080012603 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080012604 if (errno)
12605 return errno;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012606
Dustin Brownf0f00612019-01-31 16:02:24 -080012607 errno = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data, data_len);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012608
Dustin Brown363b4792019-02-05 16:11:55 -080012609 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053012610
Dustin Brownf0f00612019-01-31 16:02:24 -080012611 return errno;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012612}
12613
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012614static const struct
12615nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
12616 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
12617 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
12618 .len = QDF_MAC_ADDR_SIZE},
12619};
12620
Jeff Johnson43975142018-07-04 15:33:47 -070012621void wlan_hdd_rso_cmd_status_cb(hdd_handle_t hdd_handle,
12622 struct rso_cmd_status *rso_status)
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012623{
Jeff Johnson43975142018-07-04 15:33:47 -070012624 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Jeff Johnsone5006672017-08-29 14:39:02 -070012625 struct hdd_adapter *adapter;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012626
12627 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
12628 if (!adapter) {
12629 hdd_err("adapter NULL");
12630 return;
12631 }
12632
12633 adapter->lfr_fw_status.is_disabled = rso_status->status;
12634 complete(&adapter->lfr_fw_status.disable_lfr_event);
12635}
12636
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012637/**
12638 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
12639 * @wiphy: Pointer to wireless phy
12640 * @wdev: Pointer to wireless device
12641 * @data: Pointer to data
12642 * @data_len: Length of @data
12643 *
12644 * This function is used to enable/disable roaming using vendor commands
12645 *
12646 * Return: 0 on success, negative errno on failure
12647 */
12648static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
12649 struct wireless_dev *wdev,
12650 const void *data, int data_len)
12651{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012652 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012653 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070012654 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012655 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012656 uint32_t is_fast_roam_enabled;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012657 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +053012658 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012659 unsigned long rc;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012660 struct hdd_station_ctx *hdd_sta_ctx =
12661 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
12662 mac_handle_t mac_handle;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012663
Dustin Brownfdf17c12018-03-14 12:55:34 -070012664 hdd_enter_dev(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012665
12666 ret = wlan_hdd_validate_context(hdd_ctx);
12667 if (0 != ret)
12668 return ret;
12669
12670 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12671 hdd_err("Command not allowed in FTM mode");
12672 return -EINVAL;
12673 }
12674
Dustin Brown4ea21db2018-01-05 14:13:17 -080012675 ret = wlan_cfg80211_nla_parse(tb,
12676 QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
12677 qca_wlan_vendor_attr);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012678 if (ret) {
12679 hdd_err("Invalid ATTR");
12680 return -EINVAL;
12681 }
12682
12683 /* Parse and fetch Enable flag */
12684 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
12685 hdd_err("attr enable failed");
12686 return -EINVAL;
12687 }
12688
12689 is_fast_roam_enabled = nla_get_u32(
12690 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012691 hdd_debug("isFastRoamEnabled %d", is_fast_roam_enabled);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012692
12693 /* Update roaming */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012694 mac_handle = hdd_ctx->mac_handle;
Jeff Johnsoncf07c312019-02-04 13:53:29 -080012695 qdf_status = sme_config_fast_roaming(mac_handle, adapter->vdev_id,
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012696 is_fast_roam_enabled);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +053012697 if (qdf_status != QDF_STATUS_SUCCESS)
12698 hdd_err("sme_config_fast_roaming failed with status=%d",
12699 qdf_status);
12700 ret = qdf_status_to_os_return(qdf_status);
12701
Jeff Johnsone7951512019-02-27 10:02:51 -080012702 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.conn_state &&
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012703 QDF_IS_STATUS_SUCCESS(qdf_status) && !is_fast_roam_enabled) {
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +053012704
12705 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012706 /*
12707 * wait only for LFR disable in fw as LFR enable
12708 * is always success
12709 */
12710 rc = wait_for_completion_timeout(
12711 &adapter->lfr_fw_status.disable_lfr_event,
12712 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
12713 if (!rc) {
12714 hdd_err("Timed out waiting for RSO CMD status");
12715 return -ETIMEDOUT;
12716 }
12717
12718 if (!adapter->lfr_fw_status.is_disabled) {
12719 hdd_err("Roam disable attempt in FW fails");
12720 return -EBUSY;
12721 }
12722 }
12723
Dustin Browne74003f2018-03-14 12:51:58 -070012724 hdd_exit();
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012725 return ret;
12726}
12727
12728/**
12729 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
12730 * @wiphy: Pointer to wireless phy
12731 * @wdev: Pointer to wireless device
12732 * @data: Pointer to data
12733 * @data_len: Length of @data
12734 *
12735 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
12736 *
12737 * Return: 0 on success, negative errno on failure
12738 */
12739static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
12740 struct wireless_dev *wdev,
12741 const void *data, int data_len)
12742{
Dustin Browna09acf42018-11-08 12:32:26 +053012743 int errno;
12744 struct osif_vdev_sync *vdev_sync;
12745
12746 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
12747 if (errno)
12748 return errno;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012749
Dustin Browna09acf42018-11-08 12:32:26 +053012750 errno = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev,
12751 data, data_len);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012752
Dustin Browna09acf42018-11-08 12:32:26 +053012753 osif_vdev_sync_op_stop(vdev_sync);
12754
12755 return errno;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012756}
12757
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012758/*
12759 * define short names for the global vendor params
12760 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
12761 */
12762#define STATS_SET_INVALID \
12763 QCA_ATTR_NUD_STATS_SET_INVALID
12764#define STATS_SET_START \
12765 QCA_ATTR_NUD_STATS_SET_START
12766#define STATS_GW_IPV4 \
12767 QCA_ATTR_NUD_STATS_GW_IPV4
12768#define STATS_SET_DATA_PKT_INFO \
12769 QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
12770#define STATS_SET_MAX \
12771 QCA_ATTR_NUD_STATS_SET_MAX
12772
12773const struct nla_policy
12774qca_wlan_vendor_set_nud_stats[STATS_SET_MAX + 1] = {
12775 [STATS_SET_START] = {.type = NLA_FLAG },
12776 [STATS_GW_IPV4] = {.type = NLA_U32 },
12777 [STATS_SET_DATA_PKT_INFO] = {.type = NLA_U32 },
12778};
12779
12780/* define short names for the global vendor params */
12781#define CONNECTIVITY_STATS_SET_INVALID \
12782 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
12783#define STATS_PKT_INFO_TYPE \
12784 QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
12785#define STATS_DNS_DOMAIN_NAME \
12786 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
12787#define STATS_SRC_PORT \
12788 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
12789#define STATS_DEST_PORT \
12790 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
12791#define STATS_DEST_IPV4 \
12792 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
12793#define STATS_DEST_IPV6 \
12794 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
12795#define CONNECTIVITY_STATS_SET_MAX \
12796 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
12797
12798const struct nla_policy
12799qca_wlan_vendor_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
12800 [STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
Sourav Mohapatraaaa0f882019-03-07 09:28:40 +053012801 [STATS_DNS_DOMAIN_NAME] = {.type = NLA_NUL_STRING,
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012802 .len = DNS_DOMAIN_NAME_MAX_LEN },
12803 [STATS_SRC_PORT] = {.type = NLA_U32 },
12804 [STATS_DEST_PORT] = {.type = NLA_U32 },
12805 [STATS_DEST_IPV4] = {.type = NLA_U32 },
12806 [STATS_DEST_IPV6] = {.type = NLA_BINARY,
12807 .len = ICMPv6_ADDR_LEN },
12808};
12809
12810/**
12811 * hdd_dns_unmake_name_query() - Convert an uncompressed DNS name to a
12812 * NUL-terminated string
12813 * @name: DNS name
12814 *
12815 * Return: Produce a printable version of a DNS name.
12816 */
12817static inline uint8_t *hdd_dns_unmake_name_query(uint8_t *name)
12818{
12819 uint8_t *p;
12820 unsigned int len;
12821
12822 p = name;
12823 while ((len = *p)) {
12824 *(p++) = '.';
12825 p += len;
12826 }
12827
12828 return name + 1;
12829}
12830
12831/**
12832 * hdd_dns_make_name_query() - Convert a standard NUL-terminated string
12833 * to DNS name
12834 * @string: Name as a NUL-terminated string
12835 * @buf: Buffer in which to place DNS name
12836 *
12837 * DNS names consist of "<length>element" pairs.
12838 *
12839 * Return: Byte following constructed DNS name
12840 */
Sourav Mohapatra47710c32018-11-30 16:27:05 +053012841static uint8_t *hdd_dns_make_name_query(const uint8_t *string,
12842 uint8_t *buf, uint8_t len)
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012843{
12844 uint8_t *length_byte = buf++;
12845 uint8_t c;
12846
Sourav Mohapatra47710c32018-11-30 16:27:05 +053012847 if (string[len - 1]) {
12848 hdd_debug("DNS name is not null terminated");
12849 return NULL;
12850 }
12851
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012852 while ((c = *(string++))) {
12853 if (c == '.') {
12854 *length_byte = buf - length_byte - 1;
12855 length_byte = buf;
12856 }
12857 *(buf++) = c;
12858 }
12859 *length_byte = buf - length_byte - 1;
12860 *(buf++) = '\0';
12861 return buf;
12862}
12863
12864/**
12865 * hdd_set_clear_connectivity_check_stats_info() - set/clear stats info
12866 * @adapter: Pointer to hdd adapter
12867 * @arp_stats_params: arp stats structure to be sent to FW
12868 * @tb: nl attribute
12869 * @is_set_stats: set/clear stats
12870 *
12871 *
12872 * Return: 0 on success, negative errno on failure
12873 */
12874static int hdd_set_clear_connectivity_check_stats_info(
12875 struct hdd_adapter *adapter,
12876 struct set_arp_stats_params *arp_stats_params,
12877 struct nlattr **tb, bool is_set_stats)
12878{
12879 struct nlattr *tb2[CONNECTIVITY_STATS_SET_MAX + 1];
12880 struct nlattr *curr_attr = NULL;
12881 int err = 0;
12882 uint32_t pkt_bitmap;
12883 int rem;
12884
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012885 /* Set NUD command for start tracking is received. */
12886 nla_for_each_nested(curr_attr,
12887 tb[STATS_SET_DATA_PKT_INFO],
12888 rem) {
12889
12890 if (wlan_cfg80211_nla_parse(tb2,
12891 CONNECTIVITY_STATS_SET_MAX,
12892 nla_data(curr_attr), nla_len(curr_attr),
12893 qca_wlan_vendor_set_connectivity_check_stats)) {
12894 hdd_err("nla_parse failed");
12895 err = -EINVAL;
12896 goto end;
12897 }
12898
12899 if (tb2[STATS_PKT_INFO_TYPE]) {
12900 pkt_bitmap = nla_get_u32(tb2[STATS_PKT_INFO_TYPE]);
12901 if (!pkt_bitmap) {
12902 hdd_err("pkt tracking bitmap is empty");
12903 err = -EINVAL;
12904 goto end;
12905 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012906
12907 if (is_set_stats) {
12908 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
12909 arp_stats_params->flag = true;
12910 adapter->pkt_type_bitmap |=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012911 arp_stats_params->pkt_type_bitmap;
12912
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012913 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
Srinivas Girigowda683726a2018-09-07 15:10:40 -070012914 if (!tb[STATS_GW_IPV4]) {
12915 hdd_err("GW ipv4 address is not present");
12916 err = -EINVAL;
12917 goto end;
12918 }
12919 arp_stats_params->ip_addr =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012920 nla_get_u32(tb[STATS_GW_IPV4]);
Srinivas Girigowda683726a2018-09-07 15:10:40 -070012921 arp_stats_params->pkt_type =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012922 WLAN_NUD_STATS_ARP_PKT_TYPE;
Srinivas Girigowda683726a2018-09-07 15:10:40 -070012923 adapter->track_arp_ip =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012924 arp_stats_params->ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012925 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012926
12927 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
12928 uint8_t *domain_name;
12929
12930 if (!tb2[STATS_DNS_DOMAIN_NAME]) {
12931 hdd_err("DNS domain id is not present");
12932 err = -EINVAL;
12933 goto end;
12934 }
12935 domain_name = nla_data(
12936 tb2[STATS_DNS_DOMAIN_NAME]);
12937 adapter->track_dns_domain_len =
12938 nla_len(tb2[
12939 STATS_DNS_DOMAIN_NAME]);
Sourav Mohapatra47710c32018-11-30 16:27:05 +053012940 if (!hdd_dns_make_name_query(
12941 domain_name,
12942 adapter->dns_payload,
12943 adapter->track_dns_domain_len))
12944 adapter->track_dns_domain_len =
12945 0;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012946 /* DNStracking isn't supported in FW. */
12947 arp_stats_params->pkt_type_bitmap &=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012948 ~CONNECTIVITY_CHECK_SET_DNS;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012949 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012950
12951 if (pkt_bitmap &
12952 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
12953 if (!tb2[STATS_SRC_PORT] ||
12954 !tb2[STATS_DEST_PORT]) {
12955 hdd_err("Source/Dest port is not present");
12956 err = -EINVAL;
12957 goto end;
12958 }
12959 arp_stats_params->tcp_src_port =
12960 nla_get_u32(
12961 tb2[STATS_SRC_PORT]);
12962 arp_stats_params->tcp_dst_port =
12963 nla_get_u32(
12964 tb2[STATS_DEST_PORT]);
12965 adapter->track_src_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012966 arp_stats_params->tcp_src_port;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012967 adapter->track_dest_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012968 arp_stats_params->tcp_dst_port;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012969 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012970
12971 if (pkt_bitmap &
12972 CONNECTIVITY_CHECK_SET_ICMPV4) {
12973 if (!tb2[STATS_DEST_IPV4]) {
12974 hdd_err("destination ipv4 address to track ping packets is not present");
12975 err = -EINVAL;
12976 goto end;
12977 }
12978 arp_stats_params->icmp_ipv4 =
12979 nla_get_u32(
12980 tb2[STATS_DEST_IPV4]);
12981 adapter->track_dest_ipv4 =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012982 arp_stats_params->icmp_ipv4;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012983 }
12984 } else {
12985 /* clear stats command received */
12986 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
12987 arp_stats_params->flag = false;
12988 adapter->pkt_type_bitmap &=
12989 (~arp_stats_params->pkt_type_bitmap);
12990
12991 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
12992 arp_stats_params->pkt_type =
12993 WLAN_NUD_STATS_ARP_PKT_TYPE;
12994 qdf_mem_zero(&adapter->hdd_stats.
12995 hdd_arp_stats,
12996 sizeof(adapter->hdd_stats.
12997 hdd_arp_stats));
12998 adapter->track_arp_ip = 0;
12999 }
13000
13001 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
13002 /* DNStracking isn't supported in FW. */
13003 arp_stats_params->pkt_type_bitmap &=
13004 ~CONNECTIVITY_CHECK_SET_DNS;
13005 qdf_mem_zero(&adapter->hdd_stats.
13006 hdd_dns_stats,
13007 sizeof(adapter->hdd_stats.
13008 hdd_dns_stats));
13009 qdf_mem_zero(adapter->dns_payload,
13010 adapter->track_dns_domain_len);
13011 adapter->track_dns_domain_len = 0;
13012 }
13013
13014 if (pkt_bitmap &
13015 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
13016 qdf_mem_zero(&adapter->hdd_stats.
13017 hdd_tcp_stats,
13018 sizeof(adapter->hdd_stats.
13019 hdd_tcp_stats));
13020 adapter->track_src_port = 0;
13021 adapter->track_dest_port = 0;
13022 }
13023
13024 if (pkt_bitmap &
13025 CONNECTIVITY_CHECK_SET_ICMPV4) {
13026 qdf_mem_zero(&adapter->hdd_stats.
13027 hdd_icmpv4_stats,
13028 sizeof(adapter->hdd_stats.
13029 hdd_icmpv4_stats));
13030 adapter->track_dest_ipv4 = 0;
13031 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013032 }
13033 } else {
13034 hdd_err("stats list empty");
13035 err = -EINVAL;
13036 goto end;
13037 }
13038 }
13039
13040end:
13041 return err;
13042}
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053013043
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053013044static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
13045 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
13046 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
13047 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
13048 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
13049};
13050
13051/**
13052 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
13053 * @wiphy: Pointer to wireless phy
13054 * @wdev: Pointer to wireless device
13055 * @data: Pointer to data
13056 * @data_len: Length of @data
13057 *
13058 * Return: 0 on success, negative errno on failure
13059 */
13060static int
13061__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
13062 struct wireless_dev *wdev,
13063 const void *data,
13064 int data_len)
13065{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013066 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053013067 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
13068 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
13069 struct nlattr *apth;
13070 int rem;
13071 int ret = 1;
13072 int print_idx = -1;
13073 int module_id = -1;
13074 int bit_mask = -1;
13075 int status;
13076
Dustin Brown491d54b2018-03-14 12:39:11 -070013077 hdd_enter();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053013078
13079 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
13080 hdd_err("Command not allowed in FTM mode");
13081 return -EINVAL;
13082 }
13083
13084 ret = wlan_hdd_validate_context(hdd_ctx);
13085 if (ret != 0)
13086 return -EINVAL;
13087
13088 print_idx = qdf_get_pidx();
13089 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
13090 hdd_err("Invalid print controle object index");
13091 return -EINVAL;
13092 }
13093
Dustin Brown4ea21db2018-01-05 14:13:17 -080013094 if (wlan_cfg80211_nla_parse(tb1,
13095 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
13096 data, data_len,
13097 qca_wlan_vendor_set_trace_level_policy)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053013098 hdd_err("Invalid attr");
13099 return -EINVAL;
13100 }
13101
13102 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
13103 hdd_err("attr trace level param failed");
13104 return -EINVAL;
13105 }
13106
13107 nla_for_each_nested(apth,
13108 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -080013109 if (wlan_cfg80211_nla_parse(tb2,
Ashish Kumar Dhanotiya69903252019-03-18 20:23:47 +053013110 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
13111 nla_data(apth), nla_len(apth),
13112 qca_wlan_vendor_set_trace_level_policy)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053013113 hdd_err("Invalid attr");
13114 return -EINVAL;
13115 }
13116
13117 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
13118 hdd_err("attr Module ID failed");
13119 return -EINVAL;
13120 }
13121 module_id = nla_get_u32
13122 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
13123
13124 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
13125 hdd_err("attr Verbose mask failed");
13126 return -EINVAL;
13127 }
13128 bit_mask = nla_get_u32
13129 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
13130
13131 status = hdd_qdf_trace_enable(module_id, bit_mask);
13132
13133 if (status != 0)
13134 hdd_err("can not set verbose mask %d for the category %d",
13135 bit_mask, module_id);
13136 }
13137
Dustin Browne74003f2018-03-14 12:51:58 -070013138 hdd_exit();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053013139 return ret;
13140}
13141
13142/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +053013143 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
13144 * @wiphy: Pointer to wireless phy
13145 * @wdev: Pointer to wireless device
13146 * @data: Pointer to data
13147 * @data_len: Length of @data
13148 *
13149 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
13150 *
13151 * Return: 0 on success, negative errno on failure
13152 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053013153
13154static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
13155 struct wireless_dev *wdev,
13156 const void *data,
13157 int data_len)
13158{
Dustin Brown363b4792019-02-05 16:11:55 -080013159 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080013160 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053013161
Dustin Brown363b4792019-02-05 16:11:55 -080013162 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080013163 if (errno)
13164 return errno;
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053013165
Dustin Brownf0f00612019-01-31 16:02:24 -080013166 errno = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev,
13167 data, data_len);
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053013168
Dustin Brown363b4792019-02-05 16:11:55 -080013169 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053013170
Dustin Brownf0f00612019-01-31 16:02:24 -080013171 return errno;
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053013172}
13173
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013174/**
13175 * __wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
13176 * @wiphy: pointer to wireless wiphy structure.
13177 * @wdev: pointer to wireless_dev structure.
13178 * @data: pointer to apfind configuration data.
13179 * @data_len: the length in byte of apfind data.
13180 *
13181 * This is called when wlan driver needs to send arp stats to
13182 * firmware.
13183 *
13184 * Return: An error code or 0 on success.
13185 */
13186static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
13187 struct wireless_dev *wdev,
13188 const void *data, int data_len)
13189{
13190 struct nlattr *tb[STATS_SET_MAX + 1];
13191 struct net_device *dev = wdev->netdev;
13192 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Alan Chen7890beb2020-01-27 11:11:03 -080013193 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013194 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013195 struct set_arp_stats_params arp_stats_params = {0};
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013196 int err = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013197 mac_handle_t mac_handle;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013198
Dustin Brown491d54b2018-03-14 12:39:11 -070013199 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013200
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053013201 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13202 hdd_err("Command not allowed in FTM mode");
13203 return -EINVAL;
13204 }
13205
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013206 err = wlan_hdd_validate_context(hdd_ctx);
13207 if (0 != err)
13208 return err;
13209
Jeff Johnson912b1bb2019-03-06 10:12:36 -080013210 if (adapter->vdev_id == WLAN_UMAC_VDEV_ID_MAX) {
13211 hdd_err("Invalid vdev id");
Yeshwanth Sriram Guntukad5aae7f2017-11-27 14:33:51 +053013212 return -EINVAL;
13213 }
13214
Poddar, Siddarthdf076672018-02-26 14:21:45 +053013215 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070013216 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053013217 return -EINVAL;
13218 }
13219
Alan Chen7890beb2020-01-27 11:11:03 -080013220 if (eConnectionState_Associated != sta_ctx->conn_info.conn_state) {
13221 hdd_debug("Not Associated");
13222 return 0;
13223 }
13224
Yeshwanth Sriram Guntuka5934f572020-04-29 10:41:46 +053013225 if (hdd_is_roaming_in_progress(hdd_ctx))
13226 return -EINVAL;
13227
Jeff Johnson912b1bb2019-03-06 10:12:36 -080013228 err = wlan_cfg80211_nla_parse(tb, STATS_SET_MAX, data, data_len,
13229 qca_wlan_vendor_set_nud_stats);
13230 if (err) {
13231 hdd_err("STATS_SET_START ATTR");
13232 return err;
13233 }
13234
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013235 if (tb[STATS_SET_START]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013236 /* tracking is enabled for stats other than arp. */
13237 if (tb[STATS_SET_DATA_PKT_INFO]) {
13238 err = hdd_set_clear_connectivity_check_stats_info(
13239 adapter,
13240 &arp_stats_params, tb, true);
13241 if (err)
13242 return -EINVAL;
13243
13244 /*
13245 * if only tracking dns, then don't send
13246 * wmi command to FW.
13247 */
13248 if (!arp_stats_params.pkt_type_bitmap)
13249 return err;
13250 } else {
13251 if (!tb[STATS_GW_IPV4]) {
Dustin Browna2868622018-03-20 11:38:14 -070013252 hdd_err("STATS_SET_START CMD");
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013253 return -EINVAL;
13254 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053013255
13256 arp_stats_params.pkt_type_bitmap =
13257 CONNECTIVITY_CHECK_SET_ARP;
13258 adapter->pkt_type_bitmap |=
13259 arp_stats_params.pkt_type_bitmap;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013260 arp_stats_params.flag = true;
13261 arp_stats_params.ip_addr =
13262 nla_get_u32(tb[STATS_GW_IPV4]);
13263 adapter->track_arp_ip = arp_stats_params.ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013264 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013265 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013266 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053013267 /* clear stats command received. */
13268 if (tb[STATS_SET_DATA_PKT_INFO]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013269 err = hdd_set_clear_connectivity_check_stats_info(
13270 adapter,
13271 &arp_stats_params, tb, false);
13272 if (err)
13273 return -EINVAL;
13274
13275 /*
13276 * if only tracking dns, then don't send
13277 * wmi command to FW.
13278 */
13279 if (!arp_stats_params.pkt_type_bitmap)
13280 return err;
13281 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053013282 arp_stats_params.pkt_type_bitmap =
13283 CONNECTIVITY_CHECK_SET_ARP;
13284 adapter->pkt_type_bitmap &=
13285 (~arp_stats_params.pkt_type_bitmap);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013286 arp_stats_params.flag = false;
13287 qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
13288 sizeof(adapter->hdd_stats.hdd_arp_stats));
13289 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
13290 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013291 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013292
Abhinav Kumar50d4dc72018-06-15 16:35:50 +053013293 hdd_debug("STATS_SET_START Received flag %d!", arp_stats_params.flag);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013294
Jeff Johnsoncf07c312019-02-04 13:53:29 -080013295 arp_stats_params.vdev_id = adapter->vdev_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013296
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013297 mac_handle = hdd_ctx->mac_handle;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013298 if (QDF_STATUS_SUCCESS !=
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013299 sme_set_nud_debug_stats(mac_handle, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070013300 hdd_err("STATS_SET_START CMD Failed!");
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013301 return -EINVAL;
13302 }
13303
Dustin Browne74003f2018-03-14 12:51:58 -070013304 hdd_exit();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013305
13306 return err;
13307}
13308
13309/**
13310 * wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
13311 * @wiphy: pointer to wireless wiphy structure.
13312 * @wdev: pointer to wireless_dev structure.
13313 * @data: pointer to apfind configuration data.
13314 * @data_len: the length in byte of apfind data.
13315 *
13316 * This is called when wlan driver needs to send arp stats to
13317 * firmware.
13318 *
13319 * Return: An error code or 0 on success.
13320 */
13321static int wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
13322 struct wireless_dev *wdev,
13323 const void *data, int data_len)
13324{
Dustin Browna09acf42018-11-08 12:32:26 +053013325 int errno;
13326 struct osif_vdev_sync *vdev_sync;
13327
13328 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
13329 if (errno)
13330 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013331
Dustin Browna09acf42018-11-08 12:32:26 +053013332 errno = __wlan_hdd_cfg80211_set_nud_stats(wiphy, wdev, data, data_len);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013333
Dustin Browna09acf42018-11-08 12:32:26 +053013334 osif_vdev_sync_op_stop(vdev_sync);
13335
13336 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013337}
13338
13339#undef STATS_SET_INVALID
13340#undef STATS_SET_START
13341#undef STATS_GW_IPV4
13342#undef STATS_SET_MAX
13343
13344/*
13345 * define short names for the global vendor params
13346 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
13347 */
13348#define STATS_GET_INVALID \
13349 QCA_ATTR_NUD_STATS_SET_INVALID
13350#define COUNT_FROM_NETDEV \
13351 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
13352#define COUNT_TO_LOWER_MAC \
13353 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
13354#define RX_COUNT_BY_LOWER_MAC \
13355 QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
13356#define COUNT_TX_SUCCESS \
13357 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
13358#define RSP_RX_COUNT_BY_LOWER_MAC \
13359 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
13360#define RSP_RX_COUNT_BY_UPPER_MAC \
13361 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
13362#define RSP_COUNT_TO_NETDEV \
13363 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
13364#define RSP_COUNT_OUT_OF_ORDER_DROP \
13365 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
13366#define AP_LINK_ACTIVE \
13367 QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
13368#define AP_LINK_DAD \
13369 QCA_ATTR_NUD_STATS_IS_DAD
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013370#define DATA_PKT_STATS \
13371 QCA_ATTR_NUD_STATS_DATA_PKT_STATS
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013372#define STATS_GET_MAX \
13373 QCA_ATTR_NUD_STATS_GET_MAX
13374
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013375#define CHECK_STATS_INVALID \
13376 QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
13377#define CHECK_STATS_PKT_TYPE \
13378 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
13379#define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
13380 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
13381#define CHECK_STATS_PKT_SRC_PORT \
13382 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
13383#define CHECK_STATS_PKT_DEST_PORT \
13384 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
13385#define CHECK_STATS_PKT_DEST_IPV4 \
13386 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
13387#define CHECK_STATS_PKT_DEST_IPV6 \
13388 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
13389#define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
13390 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
13391#define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
13392 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
13393#define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
13394 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
13395#define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
13396 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
13397#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
13398 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
13399#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
13400 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
13401#define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
13402 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
13403#define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
13404 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
13405#define CHECK_DATA_STATS_MAX \
13406 QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
13407
13408
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013409const struct nla_policy
13410qca_wlan_vendor_get_nud_stats[STATS_GET_MAX + 1] = {
13411 [COUNT_FROM_NETDEV] = {.type = NLA_U16 },
13412 [COUNT_TO_LOWER_MAC] = {.type = NLA_U16 },
13413 [RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
13414 [COUNT_TX_SUCCESS] = {.type = NLA_U16 },
13415 [RSP_RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
13416 [RSP_RX_COUNT_BY_UPPER_MAC] = {.type = NLA_U16 },
13417 [RSP_COUNT_TO_NETDEV] = {.type = NLA_U16 },
13418 [RSP_COUNT_OUT_OF_ORDER_DROP] = {.type = NLA_U16 },
13419 [AP_LINK_ACTIVE] = {.type = NLA_FLAG },
13420 [AP_LINK_DAD] = {.type = NLA_FLAG },
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013421 [DATA_PKT_STATS] = {.type = NLA_U16 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013422};
13423
13424/**
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013425 * hdd_populate_dns_stats_info() - send dns stats info to network stack
13426 * @adapter: pointer to adapter context
13427 * @skb: pointer to skb
13428 *
13429 *
13430 * Return: An error code or 0 on success.
13431 */
13432static int hdd_populate_dns_stats_info(struct hdd_adapter *adapter,
13433 struct sk_buff *skb)
13434{
13435 uint8_t *dns_query;
13436
13437 dns_query = qdf_mem_malloc(adapter->track_dns_domain_len + 1);
Min Liu74a1a502018-10-10 19:59:07 +080013438 if (!dns_query)
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013439 return -EINVAL;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013440
13441 qdf_mem_copy(dns_query, adapter->dns_payload,
13442 adapter->track_dns_domain_len);
13443
13444 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13445 CONNECTIVITY_CHECK_SET_DNS) ||
13446 nla_put(skb, CHECK_STATS_PKT_DNS_DOMAIN_NAME,
13447 adapter->track_dns_domain_len,
13448 hdd_dns_unmake_name_query(dns_query)) ||
13449 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13450 adapter->hdd_stats.hdd_dns_stats.tx_dns_req_count) ||
13451 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13452 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
13453 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13454 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
13455 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13456 adapter->hdd_stats.hdd_dns_stats.tx_ack_cnt) ||
13457 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
13458 adapter->hdd_stats.hdd_dns_stats.rx_dns_rsp_count) ||
13459 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
13460 adapter->hdd_stats.hdd_dns_stats.rx_delivered) ||
13461 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
13462 adapter->hdd_stats.hdd_dns_stats.rx_host_drop)) {
13463 hdd_err("nla put fail");
13464 qdf_mem_free(dns_query);
13465 kfree_skb(skb);
13466 return -EINVAL;
13467 }
13468 qdf_mem_free(dns_query);
13469 return 0;
13470}
13471
13472/**
13473 * hdd_populate_tcp_stats_info() - send tcp stats info to network stack
13474 * @adapter: pointer to adapter context
13475 * @skb: pointer to skb
13476 * @pkt_type: tcp pkt type
13477 *
13478 * Return: An error code or 0 on success.
13479 */
13480static int hdd_populate_tcp_stats_info(struct hdd_adapter *adapter,
13481 struct sk_buff *skb,
13482 uint8_t pkt_type)
13483{
13484 switch (pkt_type) {
13485 case CONNECTIVITY_CHECK_SET_TCP_SYN:
13486 /* Fill info for tcp syn packets (tx packet) */
13487 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13488 CONNECTIVITY_CHECK_SET_TCP_SYN) ||
13489 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
13490 adapter->track_src_port) ||
13491 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
13492 adapter->track_dest_port) ||
13493 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13494 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_count) ||
13495 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13496 adapter->hdd_stats.hdd_tcp_stats.
13497 tx_tcp_syn_host_fw_sent) ||
13498 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13499 adapter->hdd_stats.hdd_tcp_stats.
13500 tx_tcp_syn_host_fw_sent) ||
13501 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13502 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_ack_cnt)) {
13503 hdd_err("nla put fail");
13504 kfree_skb(skb);
13505 return -EINVAL;
13506 }
13507 break;
13508 case CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
13509 /* Fill info for tcp syn-ack packets (rx packet) */
13510 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13511 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK) ||
13512 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
13513 adapter->track_src_port) ||
13514 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
13515 adapter->track_dest_port) ||
13516 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
13517 adapter->hdd_stats.hdd_tcp_stats.rx_fw_cnt) ||
13518 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
13519 adapter->hdd_stats.hdd_tcp_stats.
13520 rx_tcp_syn_ack_count) ||
13521 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
13522 adapter->hdd_stats.hdd_tcp_stats.rx_delivered) ||
13523 nla_put_u16(skb,
13524 CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
13525 adapter->hdd_stats.hdd_tcp_stats.rx_host_drop)) {
13526 hdd_err("nla put fail");
13527 kfree_skb(skb);
13528 return -EINVAL;
13529 }
13530 break;
13531 case CONNECTIVITY_CHECK_SET_TCP_ACK:
13532 /* Fill info for tcp ack packets (tx packet) */
13533 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13534 CONNECTIVITY_CHECK_SET_TCP_ACK) ||
13535 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
13536 adapter->track_src_port) ||
13537 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
13538 adapter->track_dest_port) ||
13539 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13540 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_count) ||
13541 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13542 adapter->hdd_stats.hdd_tcp_stats.
13543 tx_tcp_ack_host_fw_sent) ||
13544 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13545 adapter->hdd_stats.hdd_tcp_stats.
13546 tx_tcp_ack_host_fw_sent) ||
13547 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13548 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_ack_cnt)) {
13549 hdd_err("nla put fail");
13550 kfree_skb(skb);
13551 return -EINVAL;
13552 }
13553 break;
13554 default:
13555 break;
13556 }
13557 return 0;
13558}
13559
13560/**
13561 * hdd_populate_icmpv4_stats_info() - send icmpv4 stats info to network stack
13562 * @adapter: pointer to adapter context
13563 * @skb: pointer to skb
13564 *
13565 *
13566 * Return: An error code or 0 on success.
13567 */
13568static int hdd_populate_icmpv4_stats_info(struct hdd_adapter *adapter,
13569 struct sk_buff *skb)
13570{
13571 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13572 CONNECTIVITY_CHECK_SET_ICMPV4) ||
13573 nla_put_u32(skb, CHECK_STATS_PKT_DEST_IPV4,
13574 adapter->track_dest_ipv4) ||
13575 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13576 adapter->hdd_stats.hdd_icmpv4_stats.tx_icmpv4_req_count) ||
13577 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13578 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
13579 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13580 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
13581 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13582 adapter->hdd_stats.hdd_icmpv4_stats.tx_ack_cnt) ||
13583 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
13584 adapter->hdd_stats.hdd_icmpv4_stats.rx_fw_cnt) ||
13585 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
13586 adapter->hdd_stats.hdd_icmpv4_stats.rx_icmpv4_rsp_count) ||
13587 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
13588 adapter->hdd_stats.hdd_icmpv4_stats.rx_delivered) ||
13589 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
13590 adapter->hdd_stats.hdd_icmpv4_stats.rx_host_drop)) {
13591 hdd_err("nla put fail");
13592 kfree_skb(skb);
13593 return -EINVAL;
13594 }
13595 return 0;
13596}
13597
13598/**
13599 * hdd_populate_connectivity_check_stats_info() - send connectivity stats info
13600 * to network stack
13601 * @adapter: pointer to adapter context
13602 * @skb: pointer to skb
13603 *
13604 *
13605 * Return: An error code or 0 on success.
13606 */
13607
13608static int hdd_populate_connectivity_check_stats_info(
13609 struct hdd_adapter *adapter, struct sk_buff *skb)
13610{
13611 struct nlattr *connect_stats, *connect_info;
13612 uint32_t count = 0;
13613
13614 connect_stats = nla_nest_start(skb, DATA_PKT_STATS);
Jeff Johnsond36fa332019-03-18 13:42:25 -070013615 if (!connect_stats) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013616 hdd_err("nla_nest_start failed");
13617 return -EINVAL;
13618 }
13619
13620 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
13621 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070013622 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013623 hdd_err("nla_nest_start failed count %u", count);
13624 return -EINVAL;
13625 }
13626
13627 if (hdd_populate_dns_stats_info(adapter, skb))
13628 goto put_attr_fail;
13629 nla_nest_end(skb, connect_info);
13630 count++;
13631 }
13632
13633 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
13634 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070013635 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013636 hdd_err("nla_nest_start failed count %u", count);
13637 return -EINVAL;
13638 }
13639 if (hdd_populate_tcp_stats_info(adapter, skb,
13640 CONNECTIVITY_CHECK_SET_TCP_SYN))
13641 goto put_attr_fail;
13642 nla_nest_end(skb, connect_info);
13643 count++;
13644
13645 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070013646 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013647 hdd_err("nla_nest_start failed count %u", count);
13648 return -EINVAL;
13649 }
13650 if (hdd_populate_tcp_stats_info(adapter, skb,
13651 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK))
13652 goto put_attr_fail;
13653 nla_nest_end(skb, connect_info);
13654 count++;
13655
13656 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070013657 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013658 hdd_err("nla_nest_start failed count %u", count);
13659 return -EINVAL;
13660 }
13661 if (hdd_populate_tcp_stats_info(adapter, skb,
13662 CONNECTIVITY_CHECK_SET_TCP_ACK))
13663 goto put_attr_fail;
13664 nla_nest_end(skb, connect_info);
13665 count++;
13666 }
13667
13668 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ICMPV4) {
13669 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070013670 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013671 hdd_err("nla_nest_start failed count %u", count);
13672 return -EINVAL;
13673 }
13674
13675 if (hdd_populate_icmpv4_stats_info(adapter, skb))
13676 goto put_attr_fail;
13677 nla_nest_end(skb, connect_info);
13678 count++;
13679 }
13680
13681 nla_nest_end(skb, connect_stats);
13682 return 0;
13683
13684put_attr_fail:
13685 hdd_err("QCA_WLAN_VENDOR_ATTR put fail. count %u", count);
13686 return -EINVAL;
13687}
13688
13689
13690/**
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013691 * __wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
13692 * @wiphy: pointer to wireless wiphy structure.
13693 * @wdev: pointer to wireless_dev structure.
13694 * @data: pointer to apfind configuration data.
13695 * @data_len: the length in byte of apfind data.
13696 *
13697 * This is called when wlan driver needs to get arp stats to
13698 * firmware.
13699 *
13700 * Return: An error code or 0 on success.
13701 */
13702static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
13703 struct wireless_dev *wdev,
13704 const void *data, int data_len)
13705{
13706 int err = 0;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013707 struct net_device *dev = wdev->netdev;
13708 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13709 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
13710 struct get_arp_stats_params arp_stats_params;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013711 mac_handle_t mac_handle;
Poddar, Siddarthdb568162017-07-27 18:16:38 +053013712 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013713 uint32_t pkt_type_bitmap;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013714 struct sk_buff *skb;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013715 struct osif_request *request = NULL;
13716 static const struct osif_request_params params = {
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013717 .priv_size = 0,
13718 .timeout_ms = WLAN_WAIT_TIME_NUD_STATS,
13719 };
13720 void *cookie = NULL;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013721
Dustin Brown491d54b2018-03-14 12:39:11 -070013722 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013723
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053013724 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13725 hdd_err("Command not allowed in FTM mode");
13726 return -EINVAL;
13727 }
13728
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013729 err = wlan_hdd_validate_context(hdd_ctx);
13730 if (0 != err)
13731 return err;
13732
Rajeev Kumar7f28e8a32017-08-23 15:41:30 -070013733 err = hdd_validate_adapter(adapter);
13734 if (err)
13735 return err;
13736
Poddar, Siddarthdf076672018-02-26 14:21:45 +053013737 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070013738 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053013739 return -EINVAL;
13740 }
13741
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013742 request = osif_request_alloc(&params);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013743 if (!request) {
13744 hdd_err("Request allocation failure");
13745 return -ENOMEM;
13746 }
13747
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013748 cookie = osif_request_cookie(request);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013749
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013750 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Jeff Johnsoncf07c312019-02-04 13:53:29 -080013751 arp_stats_params.vdev_id = adapter->vdev_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013752
Poddar, Siddarth762c5472018-03-20 14:55:35 +053013753 pkt_type_bitmap = adapter->pkt_type_bitmap;
13754
13755 /* send NUD failure event only when ARP tracking is enabled. */
jitiphil377bcc12018-10-05 19:46:08 +053013756 if (cdp_cfg_get(soc, cfg_dp_enable_data_stall) &&
Alok Kumar939ca502019-11-11 11:34:37 +053013757 (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ARP)) {
13758 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
13759 "Data stall due to NUD failure");
Poddar, Siddarth37033032017-10-11 15:47:40 +053013760 cdp_post_data_stall_event(soc,
13761 DATA_STALL_LOG_INDICATOR_FRAMEWORK,
Poddar, Siddarthdb568162017-07-27 18:16:38 +053013762 DATA_STALL_LOG_NUD_FAILURE,
Rakesh Pillai6a36b0a2019-09-06 16:30:05 +053013763 OL_TXRX_PDEV_ID, 0XFF,
Poddar, Siddarthdb568162017-07-27 18:16:38 +053013764 DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
Alok Kumar939ca502019-11-11 11:34:37 +053013765 }
Poddar, Siddarthdb568162017-07-27 18:16:38 +053013766
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013767 mac_handle = hdd_ctx->mac_handle;
13768 if (sme_set_nud_debug_stats_cb(mac_handle, hdd_get_nud_stats_cb,
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013769 cookie) != QDF_STATUS_SUCCESS) {
13770 hdd_err("Setting NUD debug stats callback failure");
13771 err = -EINVAL;
13772 goto exit;
13773 }
13774
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013775 if (QDF_STATUS_SUCCESS !=
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013776 sme_get_nud_debug_stats(mac_handle, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070013777 hdd_err("STATS_SET_START CMD Failed!");
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013778 err = -EINVAL;
13779 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013780 }
13781
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013782 err = osif_request_wait_for_response(request);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013783 if (err) {
13784 hdd_err("SME timedout while retrieving NUD stats");
13785 err = -ETIMEDOUT;
13786 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013787 }
13788
13789 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
13790 WLAN_NUD_STATS_LEN);
13791 if (!skb) {
13792 hdd_err("%s: cfg80211_vendor_cmd_alloc_reply_skb failed",
13793 __func__);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013794 err = -ENOMEM;
13795 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013796 }
13797
Yeshwanth Sriram Guntukab31170f2020-04-02 16:16:47 +053013798 hdd_update_sta_arp_stats(adapter);
13799
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013800 if (nla_put_u16(skb, COUNT_FROM_NETDEV,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053013801 adapter->hdd_stats.hdd_arp_stats.tx_arp_req_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013802 nla_put_u16(skb, COUNT_TO_LOWER_MAC,
13803 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
13804 nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053013805 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013806 nla_put_u16(skb, COUNT_TX_SUCCESS,
13807 adapter->hdd_stats.hdd_arp_stats.tx_ack_cnt) ||
13808 nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC,
13809 adapter->hdd_stats.hdd_arp_stats.rx_fw_cnt) ||
13810 nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053013811 adapter->hdd_stats.hdd_arp_stats.rx_arp_rsp_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013812 nla_put_u16(skb, RSP_COUNT_TO_NETDEV,
13813 adapter->hdd_stats.hdd_arp_stats.rx_delivered) ||
13814 nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP,
13815 adapter->hdd_stats.hdd_arp_stats.
13816 rx_host_drop_reorder)) {
13817 hdd_err("nla put fail");
13818 kfree_skb(skb);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013819 err = -EINVAL;
13820 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013821 }
13822 if (adapter->con_status)
13823 nla_put_flag(skb, AP_LINK_ACTIVE);
13824 if (adapter->dad)
13825 nla_put_flag(skb, AP_LINK_DAD);
13826
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013827 /* ARP tracking is done above. */
13828 pkt_type_bitmap &= ~CONNECTIVITY_CHECK_SET_ARP;
13829
13830 if (pkt_type_bitmap) {
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013831 if (hdd_populate_connectivity_check_stats_info(adapter, skb)) {
13832 err = -EINVAL;
13833 goto exit;
13834 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013835 }
13836
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013837 cfg80211_vendor_cmd_reply(skb);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013838exit:
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013839 osif_request_put(request);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013840 return err;
13841}
13842
13843/**
13844 * wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
13845 * @wiphy: pointer to wireless wiphy structure.
13846 * @wdev: pointer to wireless_dev structure.
13847 * @data: pointer to apfind configuration data.
13848 * @data_len: the length in byte of apfind data.
13849 *
13850 * This is called when wlan driver needs to get arp stats to
13851 * firmware.
13852 *
13853 * Return: An error code or 0 on success.
13854 */
13855static int wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
13856 struct wireless_dev *wdev,
13857 const void *data, int data_len)
13858{
Dustin Browna09acf42018-11-08 12:32:26 +053013859 int errno;
13860 struct osif_vdev_sync *vdev_sync;
13861
13862 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
13863 if (errno)
13864 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013865
Dustin Browna09acf42018-11-08 12:32:26 +053013866 errno = __wlan_hdd_cfg80211_get_nud_stats(wiphy, wdev, data, data_len);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013867
Dustin Browna09acf42018-11-08 12:32:26 +053013868 osif_vdev_sync_op_stop(vdev_sync);
13869
13870 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013871}
13872
13873#undef QCA_ATTR_NUD_STATS_SET_INVALID
13874#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
13875#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
13876#undef QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
13877#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
13878#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
13879#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
13880#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
13881#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
13882#undef QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
13883#undef QCA_ATTR_NUD_STATS_GET_MAX
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013884
Jeff Johnsond0b6c7e2018-07-04 14:53:06 -070013885void hdd_bt_activity_cb(hdd_handle_t hdd_handle, uint32_t bt_activity)
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013886{
Jeff Johnsond0b6c7e2018-07-04 14:53:06 -070013887 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013888 int status;
13889
13890 status = wlan_hdd_validate_context(hdd_ctx);
13891 if (0 != status)
13892 return;
13893
13894 if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_ADD)
13895 hdd_ctx->bt_a2dp_active = 1;
13896 else if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_REMOVE)
13897 hdd_ctx->bt_a2dp_active = 0;
13898 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_ADD)
13899 hdd_ctx->bt_vo_active = 1;
13900 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_REMOVE)
13901 hdd_ctx->bt_vo_active = 0;
13902 else
13903 return;
13904
Dustin Brown76cd2932018-09-11 16:03:05 -070013905 ucfg_scan_set_bt_activity(hdd_ctx->psoc, hdd_ctx->bt_a2dp_active);
Srinivas Girigowda6598eea2017-07-06 19:26:19 -070013906 hdd_debug("a2dp_active: %d vo_active: %d", hdd_ctx->bt_a2dp_active,
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013907 hdd_ctx->bt_vo_active);
13908}
13909
lifengd217d192017-05-09 19:44:16 +080013910struct chain_rssi_priv {
13911 struct chain_rssi_result chain_rssi;
13912};
13913
13914/**
13915 * hdd_get_chain_rssi_cb() - Callback function to get chain rssi
13916 * @context: opaque context originally passed to SME. HDD always passes
13917 * a cookie for the request context
13918 * @data: struct for get chain rssi
13919 *
13920 * This function receives the response/data from the lower layer and
13921 * checks to see if the thread is still waiting then post the results to
13922 * upper layer, if the request has timed out then ignore.
13923 *
13924 * Return: None
13925 */
13926static void hdd_get_chain_rssi_cb(void *context,
13927 struct chain_rssi_result *data)
13928{
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013929 struct osif_request *request;
lifengd217d192017-05-09 19:44:16 +080013930 struct chain_rssi_priv *priv;
13931
Dustin Brown491d54b2018-03-14 12:39:11 -070013932 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080013933
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013934 request = osif_request_get(context);
lifengd217d192017-05-09 19:44:16 +080013935 if (!request) {
13936 hdd_err("Obsolete request");
13937 return;
13938 }
13939
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013940 priv = osif_request_priv(request);
lifengd217d192017-05-09 19:44:16 +080013941 priv->chain_rssi = *data;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013942 osif_request_complete(request);
13943 osif_request_put(request);
lifengd217d192017-05-09 19:44:16 +080013944}
13945
13946/**
13947 * hdd_post_get_chain_rssi_rsp - send rsp to user space
13948 * @hdd_ctx: pointer to hdd context
13949 * @result: chain rssi result
13950 *
13951 * Return: 0 for success, non-zero for failure
13952 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013953static int hdd_post_get_chain_rssi_rsp(struct hdd_context *hdd_ctx,
lifengd217d192017-05-09 19:44:16 +080013954 struct chain_rssi_result *result)
13955{
13956 struct sk_buff *skb;
lifengd217d192017-05-09 19:44:16 +080013957
13958 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
lifengfe6c3e22018-04-03 12:10:04 +080013959 (sizeof(result->chain_rssi) + NLA_HDRLEN) +
stonez396a9732019-01-16 12:29:16 +080013960 (sizeof(result->chain_evm) + NLA_HDRLEN) +
lifengfe6c3e22018-04-03 12:10:04 +080013961 (sizeof(result->ant_id) + NLA_HDRLEN) +
13962 NLMSG_HDRLEN);
lifengd217d192017-05-09 19:44:16 +080013963
13964 if (!skb) {
13965 hdd_err("cfg80211_vendor_event_alloc failed");
13966 return -ENOMEM;
13967 }
13968
lifengfe6c3e22018-04-03 12:10:04 +080013969 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI,
stonez396a9732019-01-16 12:29:16 +080013970 sizeof(result->chain_rssi),
13971 result->chain_rssi)) {
13972 hdd_err("put fail");
13973 goto nla_put_failure;
13974 }
13975
13976 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_EVM,
13977 sizeof(result->chain_evm),
13978 result->chain_evm)) {
lifengd217d192017-05-09 19:44:16 +080013979 hdd_err("put fail");
13980 goto nla_put_failure;
13981 }
13982
lifengfe6c3e22018-04-03 12:10:04 +080013983 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO,
stonez396a9732019-01-16 12:29:16 +080013984 sizeof(result->ant_id),
13985 result->ant_id)) {
lifengfe6c3e22018-04-03 12:10:04 +080013986 hdd_err("put fail");
13987 goto nla_put_failure;
13988 }
13989
lifengd217d192017-05-09 19:44:16 +080013990 cfg80211_vendor_cmd_reply(skb);
13991 return 0;
13992
13993nla_put_failure:
13994 kfree_skb(skb);
13995 return -EINVAL;
13996}
13997
13998/**
13999 * __wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
14000 * @wiphy: wiphy pointer
14001 * @wdev: pointer to struct wireless_dev
14002 * @data: pointer to incoming NL vendor data
14003 * @data_len: length of @data
14004 *
14005 * Return: 0 on success; error number otherwise.
14006 */
14007static int __wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
14008 struct wireless_dev *wdev,
14009 const void *data,
14010 int data_len)
14011{
Jeff Johnsone5006672017-08-29 14:39:02 -070014012 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070014013 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014014 mac_handle_t mac_handle;
lifengd217d192017-05-09 19:44:16 +080014015 struct get_chain_rssi_req_params req_msg;
14016 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
14017 QDF_STATUS status;
14018 int retval;
14019 void *cookie;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070014020 struct osif_request *request;
lifengd217d192017-05-09 19:44:16 +080014021 struct chain_rssi_priv *priv;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070014022 static const struct osif_request_params params = {
lifengd217d192017-05-09 19:44:16 +080014023 .priv_size = sizeof(*priv),
14024 .timeout_ms = WLAN_WAIT_TIME_STATS,
14025 };
14026
Dustin Brown491d54b2018-03-14 12:39:11 -070014027 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080014028
14029 retval = wlan_hdd_validate_context(hdd_ctx);
14030 if (0 != retval)
14031 return retval;
14032
Dustin Brown4ea21db2018-01-05 14:13:17 -080014033 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
14034 data, data_len, NULL)) {
lifengd217d192017-05-09 19:44:16 +080014035 hdd_err("Invalid ATTR");
14036 return -EINVAL;
14037 }
14038
14039 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
14040 hdd_err("attr mac addr failed");
14041 return -EINVAL;
14042 }
14043 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) !=
14044 QDF_MAC_ADDR_SIZE) {
14045 hdd_err("incorrect mac size");
14046 return -EINVAL;
14047 }
14048 memcpy(&req_msg.peer_macaddr,
14049 nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
14050 QDF_MAC_ADDR_SIZE);
Jeff Johnsoncf07c312019-02-04 13:53:29 -080014051 req_msg.session_id = adapter->vdev_id;
lifengd217d192017-05-09 19:44:16 +080014052
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070014053 request = osif_request_alloc(&params);
lifengd217d192017-05-09 19:44:16 +080014054 if (!request) {
14055 hdd_err("Request allocation failure");
14056 return -ENOMEM;
14057 }
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070014058 cookie = osif_request_cookie(request);
lifengd217d192017-05-09 19:44:16 +080014059
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014060 mac_handle = hdd_ctx->mac_handle;
14061 status = sme_get_chain_rssi(mac_handle,
14062 &req_msg,
14063 hdd_get_chain_rssi_cb,
14064 cookie);
lifengd217d192017-05-09 19:44:16 +080014065 if (QDF_STATUS_SUCCESS != status) {
14066 hdd_err("Unable to get chain rssi");
14067 retval = qdf_status_to_os_return(status);
14068 } else {
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070014069 retval = osif_request_wait_for_response(request);
lifengd217d192017-05-09 19:44:16 +080014070 if (retval) {
14071 hdd_err("Target response timed out");
14072 } else {
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070014073 priv = osif_request_priv(request);
lifengd217d192017-05-09 19:44:16 +080014074 retval = hdd_post_get_chain_rssi_rsp(hdd_ctx,
14075 &priv->chain_rssi);
14076 if (retval)
14077 hdd_err("Failed to post chain rssi");
14078 }
14079 }
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070014080 osif_request_put(request);
lifengd217d192017-05-09 19:44:16 +080014081
Dustin Browne74003f2018-03-14 12:51:58 -070014082 hdd_exit();
lifengd217d192017-05-09 19:44:16 +080014083 return retval;
14084}
14085
14086/**
14087 * wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
14088 * @wiphy: wiphy pointer
14089 * @wdev: pointer to struct wireless_dev
14090 * @data: pointer to incoming NL vendor data
14091 * @data_len: length of @data
14092 *
14093 * Return: 0 on success; error number otherwise.
14094 */
14095static int wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
14096 struct wireless_dev *wdev,
14097 const void *data,
14098 int data_len)
14099{
Dustin Browna09acf42018-11-08 12:32:26 +053014100 int errno;
14101 struct osif_vdev_sync *vdev_sync;
14102
14103 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
14104 if (errno)
14105 return errno;
lifengd217d192017-05-09 19:44:16 +080014106
Dustin Browna09acf42018-11-08 12:32:26 +053014107 errno = __wlan_hdd_cfg80211_get_chain_rssi(wiphy, wdev, data, data_len);
lifengd217d192017-05-09 19:44:16 +080014108
Dustin Browna09acf42018-11-08 12:32:26 +053014109 osif_vdev_sync_op_stop(vdev_sync);
14110
14111 return errno;
lifengd217d192017-05-09 19:44:16 +080014112}
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053014113
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053014114/**
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014115 * wlan_hdd_fill_intf_info() - Fill skb buffer with interface info
14116 * @skb: Pointer to skb
14117 * @info: mac mode info
14118 * @index: attribute type index for nla_nest_start()
14119 *
14120 * Return : 0 on success and errno on failure
14121 */
14122static int wlan_hdd_fill_intf_info(struct sk_buff *skb,
14123 struct connection_info *info, int index)
14124{
14125 struct nlattr *attr;
14126 uint32_t freq;
14127 struct hdd_context *hdd_ctx;
14128 struct hdd_adapter *hdd_adapter;
14129
14130 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
14131 if (!hdd_ctx)
14132 goto error;
14133
14134 hdd_adapter = hdd_get_adapter_by_vdev(hdd_ctx, info->vdev_id);
14135 if (!hdd_adapter)
14136 goto error;
14137
14138 attr = nla_nest_start(skb, index);
14139 if (!attr)
14140 goto error;
14141
14142 freq = sme_chn_to_freq(info->channel);
14143
14144 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX,
14145 hdd_adapter->dev->ifindex) ||
14146 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ, freq))
14147 goto error;
14148
14149 nla_nest_end(skb, attr);
14150
14151 return 0;
14152error:
14153 hdd_err("Fill buffer with interface info failed");
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014154 return -EINVAL;
14155}
14156
14157/**
14158 * wlan_hdd_fill_mac_info() - Fill skb buffer with mac info
14159 * @skb: Pointer to skb
14160 * @info: mac mode info
14161 * @mac_id: MAC id
14162 * @conn_count: number of current connections
14163 *
14164 * Return : 0 on success and errno on failure
14165 */
14166static int wlan_hdd_fill_mac_info(struct sk_buff *skb,
14167 struct connection_info *info, uint32_t mac_id,
14168 uint32_t conn_count)
14169{
14170 struct nlattr *attr, *intf_attr;
14171 uint32_t band = 0, i = 0, j = 0;
14172 bool present = false;
14173
14174 while (i < conn_count) {
14175 if (info[i].mac_id == mac_id) {
14176 present = true;
14177 if (info[i].channel <= SIR_11B_CHANNEL_END)
14178 band |= 1 << NL80211_BAND_2GHZ;
14179 else if (info[i].channel <= SIR_11A_CHANNEL_END)
14180 band |= 1 << NL80211_BAND_5GHZ;
14181 }
14182 i++;
14183 }
14184
14185 if (!present)
14186 return 0;
14187
14188 i = 0;
14189 attr = nla_nest_start(skb, mac_id);
14190 if (!attr)
14191 goto error;
14192
14193 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID, mac_id) ||
14194 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND, band))
14195 goto error;
14196
14197 intf_attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO);
14198 if (!intf_attr)
14199 goto error;
14200
14201 while (i < conn_count) {
14202 if (info[i].mac_id == mac_id) {
14203 if (wlan_hdd_fill_intf_info(skb, &info[i], j))
14204 return -EINVAL;
14205 j++;
14206 }
14207 i++;
14208 }
14209
14210 nla_nest_end(skb, intf_attr);
14211
14212 nla_nest_end(skb, attr);
14213
14214 return 0;
14215error:
14216 hdd_err("Fill buffer with mac info failed");
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014217 return -EINVAL;
14218}
14219
14220
14221int wlan_hdd_send_mode_change_event(void)
14222{
14223 int err;
14224 struct hdd_context *hdd_ctx;
14225 struct sk_buff *skb;
14226 struct nlattr *attr;
14227 struct connection_info info[MAX_NUMBER_OF_CONC_CONNECTIONS];
14228 uint32_t conn_count, mac_id;
14229
Dustin Brown491d54b2018-03-14 12:39:11 -070014230 hdd_enter();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014231 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
14232 if (!hdd_ctx) {
14233 hdd_err("HDD context is NULL");
14234 return -EINVAL;
14235 }
14236
14237 err = wlan_hdd_validate_context(hdd_ctx);
14238 if (0 != err)
14239 return err;
14240
Dustin Brown76cd2932018-09-11 16:03:05 -070014241 conn_count = policy_mgr_get_connection_info(hdd_ctx->psoc, info);
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014242 if (!conn_count)
14243 return -EINVAL;
14244
14245 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
14246 (sizeof(uint32_t) * 4) *
14247 MAX_NUMBER_OF_CONC_CONNECTIONS + NLMSG_HDRLEN,
14248 QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX,
14249 GFP_KERNEL);
14250 if (!skb) {
14251 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
14252 return -ENOMEM;
14253 }
14254
14255 attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO);
14256 if (!attr) {
14257 hdd_err("nla_nest_start failed");
14258 kfree_skb(skb);
14259 return -EINVAL;
14260 }
14261
14262 for (mac_id = 0; mac_id < MAX_MAC; mac_id++) {
Lin Baifac77972018-07-05 19:51:49 +080014263 if (wlan_hdd_fill_mac_info(skb, info, mac_id, conn_count)) {
14264 kfree_skb(skb);
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014265 return -EINVAL;
Lin Baifac77972018-07-05 19:51:49 +080014266 }
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014267 }
14268
14269 nla_nest_end(skb, attr);
14270
14271 cfg80211_vendor_event(skb, GFP_KERNEL);
Dustin Browne74003f2018-03-14 12:51:58 -070014272 hdd_exit();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014273
14274 return err;
14275}
14276
Ashish Kumar Dhanotiya1a720e72019-09-06 15:42:05 +053014277
14278/* Short name for QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS command */
14279
14280#define EXTSCAN_CONFIG_MAX \
14281 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
14282#define EXTSCAN_CONFIG_REQUEST_ID \
14283 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
14284#define EXTSCAN_CONFIG_WIFI_BAND \
14285 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND
14286#define ETCAN_CONFIG_MAX_CHANNELS \
14287QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS
14288#define EXTSCAN_RESULTS_NUM_CHANNELS \
14289 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS
14290#define EXTSCAN_RESULTS_CHANNELS \
14291 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS
14292
14293/**
14294 * hdd_remove_dsrc_channels () - remove dsrc chanels
14295 * @hdd_ctx: hdd context
14296 * @wiphy: Pointer to wireless phy
14297 * @chan_list: channel list
14298 * @num_channels: number of channels
14299 *
14300 * Return: none
14301 */
14302static void hdd_remove_dsrc_channels(struct hdd_context *hdd_ctx,
14303 struct wiphy *wiphy, uint32_t *chan_list,
14304 uint8_t *num_channels)
14305{
14306 uint8_t num_chan_temp = 0;
14307 int i;
14308
14309 for (i = 0; i < *num_channels; i++) {
14310 if (!wlan_reg_is_dsrc_chan(hdd_ctx->pdev,
14311 wlan_reg_freq_to_chan(
14312 hdd_ctx->pdev,
14313 chan_list[i]))) {
14314 chan_list[num_chan_temp] = chan_list[i];
14315 num_chan_temp++;
14316 }
14317 }
14318 *num_channels = num_chan_temp;
14319}
14320
14321/**
14322 * hdd_remove_passive_channels () - remove passive channels
14323 * @wiphy: Pointer to wireless phy
14324 * @chan_list: channel list
14325 * @num_channels: number of channels
14326 *
14327 * Return: none
14328 */
14329static void hdd_remove_passive_channels(struct wiphy *wiphy,
14330 uint32_t *chan_list,
14331 uint8_t *num_channels)
14332{
14333 uint8_t num_chan_temp = 0;
14334 int i, j, k;
14335
14336 for (i = 0; i < *num_channels; i++)
14337 for (j = 0; j < HDD_NUM_NL80211_BANDS; j++) {
14338 if (!wiphy->bands[j])
14339 continue;
14340 for (k = 0; k < wiphy->bands[j]->n_channels; k++) {
14341 if ((chan_list[i] ==
14342 wiphy->bands[j]->channels[k].center_freq)
14343 && (!(wiphy->bands[j]->channels[k].flags &
14344 IEEE80211_CHAN_PASSIVE_SCAN))
14345 ) {
14346 chan_list[num_chan_temp] = chan_list[i];
14347 num_chan_temp++;
14348 }
14349 }
14350 }
14351
14352 *num_channels = num_chan_temp;
14353}
14354
14355/**
14356 * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels
14357 * @wiphy: Pointer to wireless phy
14358 * @wdev: Pointer to wireless device
14359 * @data: Pointer to data
14360 * @data_len: Data length
14361 *
14362 * Return: none
14363 */
14364static int
14365__wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
14366 struct wireless_dev
14367 *wdev, const void *data,
14368 int data_len)
14369{
14370 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
14371 struct net_device *dev = wdev->netdev;
14372 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14373 uint32_t chan_list[CFG_VALID_CHANNEL_LIST_LEN] = {0};
14374 uint8_t num_channels = 0, i, buf[256] = {0};
14375 struct nlattr *tb[EXTSCAN_CONFIG_MAX +
14376 1];
14377 uint32_t requestId, maxChannels;
14378 tWifiBand wifi_band;
14379 QDF_STATUS status;
14380 struct sk_buff *reply_skb;
14381 int ret, len = 0;
14382
14383 /* ENTER_DEV() intentionally not used in a frequently invoked API */
14384
14385 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
14386 hdd_err("Command not allowed in FTM mode");
14387 return -EPERM;
14388 }
14389
14390 ret = wlan_hdd_validate_context(hdd_ctx);
14391 if (0 != ret)
14392 return -EINVAL;
14393
14394 if (wlan_cfg80211_nla_parse(
14395 tb,
14396 EXTSCAN_CONFIG_MAX,
14397 data, data_len, wlan_hdd_extscan_config_policy)) {
14398 hdd_err("Invalid ATTR");
14399 return -EINVAL;
14400 }
14401
14402 /* Parse and fetch request Id */
14403 if (!tb[EXTSCAN_CONFIG_REQUEST_ID]) {
14404 hdd_err("attr request id failed");
14405 return -EINVAL;
14406 }
14407 requestId =
14408 nla_get_u32(tb
14409 [EXTSCAN_CONFIG_REQUEST_ID]);
14410
14411 /* Parse and fetch wifi band */
14412 if (!tb
14413 [EXTSCAN_CONFIG_WIFI_BAND]) {
14414 hdd_err("attr wifi band failed");
14415 return -EINVAL;
14416 }
14417 wifi_band =
14418 nla_get_u32(tb
14419 [EXTSCAN_CONFIG_WIFI_BAND]);
14420 if (!tb
14421 [ETCAN_CONFIG_MAX_CHANNELS]) {
14422 hdd_err("attr max channels failed");
14423 return -EINVAL;
14424 }
14425 maxChannels =
14426 nla_get_u32(tb
14427 [ETCAN_CONFIG_MAX_CHANNELS]);
14428
14429 if (maxChannels > CFG_VALID_CHANNEL_LIST_LEN) {
14430 hdd_err("Max channels %d exceeded Valid channel list len %d",
14431 maxChannels, CFG_VALID_CHANNEL_LIST_LEN);
14432 return -EINVAL;
14433 }
14434
14435 hdd_err("Req Id: %u Wifi band: %d Max channels: %d", requestId,
14436 wifi_band, maxChannels);
14437 status = sme_get_valid_channels_by_band(hdd_ctx->mac_handle,
14438 wifi_band, chan_list,
14439 &num_channels);
14440 if (QDF_STATUS_SUCCESS != status) {
14441 hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
14442 status);
14443 return -EINVAL;
14444 }
14445
14446 num_channels = QDF_MIN(num_channels, maxChannels);
14447
14448 hdd_remove_dsrc_channels(hdd_ctx, wiphy, chan_list, &num_channels);
14449 if ((QDF_SAP_MODE == adapter->device_mode) ||
14450 !strncmp(hdd_get_fwpath(), "ap", 2))
14451 hdd_remove_passive_channels(wiphy, chan_list,
14452 &num_channels);
14453
14454 hdd_debug("Number of channels: %d", num_channels);
14455 for (i = 0; i < num_channels; i++)
14456 len += scnprintf(buf + len, sizeof(buf) - len,
14457 "%u ", chan_list[i]);
14458
14459 hdd_debug("Channels: %s", buf);
14460
14461 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
14462 sizeof(u32) *
14463 num_channels +
14464 NLMSG_HDRLEN);
14465
14466 if (reply_skb) {
14467 if (nla_put_u32(
14468 reply_skb,
14469 EXTSCAN_RESULTS_NUM_CHANNELS,
14470 num_channels) ||
14471 nla_put(
14472 reply_skb,
14473 EXTSCAN_RESULTS_CHANNELS,
14474 sizeof(u32) * num_channels, chan_list)) {
14475 hdd_err("nla put fail");
14476 kfree_skb(reply_skb);
14477 return -EINVAL;
14478 }
14479 ret = cfg80211_vendor_cmd_reply(reply_skb);
14480 return ret;
14481 }
14482
14483 hdd_err("valid channels: buffer alloc fail");
14484 return -EINVAL;
14485}
14486
14487#undef EXTSCAN_CONFIG_MAX
14488#undef EXTSCAN_CONFIG_REQUEST_ID
14489#undef EXTSCAN_CONFIG_WIFI_BAND
14490#undef ETCAN_CONFIG_MAX_CHANNELS
14491#undef EXTSCAN_RESULTS_NUM_CHANNELS
14492#undef EXTSCAN_RESULTS_CHANNELS
14493
14494/**
14495 * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
14496 * @wiphy: Pointer to wireless phy
14497 * @wdev: Pointer to wireless device
14498 * @data: Pointer to data
14499 * @data_len: Data length
14500 *
14501 * Return: 0 on success, negative errno on failure
14502 */
14503static int wlan_hdd_cfg80211_extscan_get_valid_channels(
14504 struct wiphy *wiphy,
14505 struct wireless_dev *wdev,
14506 const void *data, int data_len)
14507{
14508 struct osif_psoc_sync *psoc_sync;
14509 int errno;
14510
14511 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
14512 if (errno)
14513 return errno;
14514
14515 errno = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev,
14516 data, data_len);
14517
14518 osif_psoc_sync_op_stop(psoc_sync);
14519
14520 return errno;
14521}
14522
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014523const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
14524 {
14525 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14526 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
14527 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +053014528 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014529 .doit = is_driver_dfs_capable
14530 },
Ashish Kumar Dhanotiya1a720e72019-09-06 15:42:05 +053014531 {
14532 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14533 .info.subcmd =
14534 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
14535 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14536 WIPHY_VENDOR_CMD_NEED_NETDEV |
14537 WIPHY_VENDOR_CMD_NEED_RUNNING,
14538 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
14539 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014540#ifdef WLAN_FEATURE_STATS_EXT
14541 {
14542 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14543 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
14544 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14545 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14546 .doit = wlan_hdd_cfg80211_stats_ext_request
14547 },
14548#endif
14549#ifdef FEATURE_WLAN_EXTSCAN
14550 {
14551 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14552 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
14553 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14554 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14555 .doit = wlan_hdd_cfg80211_extscan_start
14556 },
14557 {
14558 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14559 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
14560 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14561 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14562 .doit = wlan_hdd_cfg80211_extscan_stop
14563 },
14564 {
14565 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014566 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
14567 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14568 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14569 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
14570 },
14571 {
14572 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14573 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
14574 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14575 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14576 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
14577 },
14578 {
14579 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14580 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
14581 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14582 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14583 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
14584 },
14585 {
14586 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14587 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
14588 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14589 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14590 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
14591 },
14592 {
14593 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14594 .info.subcmd =
14595 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
14596 .flags =
14597 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
14598 WIPHY_VENDOR_CMD_NEED_RUNNING,
14599 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
14600 },
14601 {
14602 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14603 .info.subcmd =
14604 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
14605 .flags =
14606 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
14607 WIPHY_VENDOR_CMD_NEED_RUNNING,
14608 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
14609 },
14610 {
14611 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14612 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
14613 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14614 WIPHY_VENDOR_CMD_NEED_NETDEV |
14615 WIPHY_VENDOR_CMD_NEED_RUNNING,
14616 .doit = wlan_hdd_cfg80211_set_epno_list
14617 },
14618#endif /* FEATURE_WLAN_EXTSCAN */
14619
14620#ifdef WLAN_FEATURE_LINK_LAYER_STATS
14621 {
14622 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14623 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
14624 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14625 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14626 .doit = wlan_hdd_cfg80211_ll_stats_clear
14627 },
14628
14629 {
14630 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14631 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
14632 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14633 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14634 .doit = wlan_hdd_cfg80211_ll_stats_set
14635 },
14636
14637 {
14638 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14639 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
14640 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14641 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14642 .doit = wlan_hdd_cfg80211_ll_stats_get
14643 },
14644#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
14645#ifdef FEATURE_WLAN_TDLS
14646 {
14647 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14648 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
14649 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14650 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14651 .doit = wlan_hdd_cfg80211_exttdls_enable
14652 },
14653 {
14654 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14655 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
14656 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14657 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14658 .doit = wlan_hdd_cfg80211_exttdls_disable
14659 },
14660 {
14661 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14662 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
14663 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
14664 .doit = wlan_hdd_cfg80211_exttdls_get_status
14665 },
14666#endif
14667 {
14668 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14669 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
14670 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
14671 .doit = wlan_hdd_cfg80211_get_supported_features
14672 },
14673 {
14674 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14675 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014676 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14677 WIPHY_VENDOR_CMD_NEED_NETDEV |
14678 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014679 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
14680 },
Qiwei Caie689a262018-07-26 15:50:22 +080014681
14682 FEATURE_CONCURRENCY_MATRIX_VENDOR_COMMANDS
14683
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014684 {
14685 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14686 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
14687 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014688 WIPHY_VENDOR_CMD_NEED_NETDEV |
14689 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014690 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
14691 },
Manikandan Mohan80dea792016-04-28 16:36:48 -070014692 {
14693 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14694 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
14695 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014696 WIPHY_VENDOR_CMD_NEED_NETDEV |
14697 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -070014698 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
14699 },
Qiwei Caie689a262018-07-26 15:50:22 +080014700
14701 FEATURE_STATION_INFO_VENDOR_COMMANDS
14702
Anurag Chouhan96919482016-07-13 16:36:57 +053014703 {
14704 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014705 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
14706 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14707 WIPHY_VENDOR_CMD_NEED_NETDEV |
14708 WIPHY_VENDOR_CMD_NEED_RUNNING,
14709 .doit = wlan_hdd_cfg80211_do_acs
14710 },
14711
14712 {
14713 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14714 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
14715 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14716 WIPHY_VENDOR_CMD_NEED_NETDEV,
14717 .doit = wlan_hdd_cfg80211_get_features
14718 },
14719#ifdef WLAN_FEATURE_ROAM_OFFLOAD
14720 {
14721 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14722 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
14723 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14724 WIPHY_VENDOR_CMD_NEED_NETDEV |
14725 WIPHY_VENDOR_CMD_NEED_RUNNING,
14726 .doit = wlan_hdd_cfg80211_keymgmt_set_key
14727 },
14728#endif
14729#ifdef FEATURE_WLAN_EXTSCAN
14730 {
14731 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14732 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
14733 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14734 WIPHY_VENDOR_CMD_NEED_NETDEV |
14735 WIPHY_VENDOR_CMD_NEED_RUNNING,
14736 .doit = wlan_hdd_cfg80211_set_passpoint_list
14737 },
14738 {
14739 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14740 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
14741 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14742 WIPHY_VENDOR_CMD_NEED_NETDEV |
14743 WIPHY_VENDOR_CMD_NEED_RUNNING,
14744 .doit = wlan_hdd_cfg80211_reset_passpoint_list
14745 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014746#endif /* FEATURE_WLAN_EXTSCAN */
14747 {
14748 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14749 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
14750 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14751 WIPHY_VENDOR_CMD_NEED_NETDEV,
14752 .doit = wlan_hdd_cfg80211_get_wifi_info
14753 },
14754 {
14755 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14756 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
14757 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14758 WIPHY_VENDOR_CMD_NEED_NETDEV |
14759 WIPHY_VENDOR_CMD_NEED_RUNNING,
14760 .doit = wlan_hdd_cfg80211_wifi_configuration_set
14761 },
14762 {
14763 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Paul Zhangc9dbaee2019-06-23 22:07:31 +080014764 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION,
14765 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14766 WIPHY_VENDOR_CMD_NEED_NETDEV |
14767 WIPHY_VENDOR_CMD_NEED_RUNNING,
14768 .doit = wlan_hdd_cfg80211_wifi_configuration_get
14769 },
14770 {
14771 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -080014772 .info.subcmd =
14773 QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION,
14774 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14775 WIPHY_VENDOR_CMD_NEED_NETDEV |
14776 WIPHY_VENDOR_CMD_NEED_RUNNING,
14777 .doit = wlan_hdd_cfg80211_set_wifi_test_config
14778 },
14779
14780 {
14781 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014782 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
14783 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014784 WIPHY_VENDOR_CMD_NEED_NETDEV |
14785 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014786 .doit = wlan_hdd_cfg80211_set_ext_roam_params
14787 },
14788 {
14789 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14790 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
14791 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014792 WIPHY_VENDOR_CMD_NEED_NETDEV |
14793 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014794 .doit = wlan_hdd_cfg80211_wifi_logger_start
14795 },
14796 {
14797 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14798 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
Karthik Kantamneni0b95f9e2019-11-21 13:03:22 +053014799 .flags = WIPHY_VENDOR_CMD_NEED_WDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014800 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
14801 },
14802 {
14803 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14804 .info.subcmd =
14805 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
14806 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14807 WIPHY_VENDOR_CMD_NEED_NETDEV |
14808 WIPHY_VENDOR_CMD_NEED_RUNNING,
14809 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
14810 },
14811 {
14812 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14813 .info.subcmd =
14814 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
14815 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14816 WIPHY_VENDOR_CMD_NEED_NETDEV |
14817 WIPHY_VENDOR_CMD_NEED_RUNNING,
14818 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
14819 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070014820#ifdef WLAN_FEATURE_TSF
14821 {
14822 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14823 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
14824 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14825 WIPHY_VENDOR_CMD_NEED_NETDEV |
14826 WIPHY_VENDOR_CMD_NEED_RUNNING,
14827 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
14828 },
14829#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014830#ifdef FEATURE_WLAN_TDLS
14831 {
14832 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14833 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
14834 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14835 WIPHY_VENDOR_CMD_NEED_NETDEV |
14836 WIPHY_VENDOR_CMD_NEED_RUNNING,
14837 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
14838 },
14839#endif
14840#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
14841 {
14842 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14843 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
14844 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14845 WIPHY_VENDOR_CMD_NEED_NETDEV |
14846 WIPHY_VENDOR_CMD_NEED_RUNNING,
14847 .doit = wlan_hdd_cfg80211_offloaded_packets
14848 },
14849#endif
Qiwei Caie689a262018-07-26 15:50:22 +080014850 FEATURE_RSSI_MONITOR_VENDOR_COMMANDS
Paul Zhangda2970b2019-06-23 18:16:38 +080014851 FEATURE_OEM_DATA_VENDOR_COMMANDS
Paul Zhang37185672019-05-14 11:20:14 +080014852 FEATURE_INTEROP_ISSUES_AP_VENDOR_COMMANDS
Qiwei Caie689a262018-07-26 15:50:22 +080014853
Qiwei Cai1083f5b2018-07-02 19:10:11 +080014854#ifdef WLAN_NS_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014855 {
14856 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053014857 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
14858 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14859 WIPHY_VENDOR_CMD_NEED_NETDEV |
14860 WIPHY_VENDOR_CMD_NEED_RUNNING,
14861 .doit = wlan_hdd_cfg80211_set_ns_offload
14862 },
Qiwei Cai1083f5b2018-07-02 19:10:11 +080014863#endif /* WLAN_NS_OFFLOAD */
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053014864 {
14865 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014866 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
14867 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Sourav Mohapatra412ceb92018-03-07 18:41:16 +053014868 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014869 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
14870 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014871 {
14872 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14873 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
14874 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14875 WIPHY_VENDOR_CMD_NEED_NETDEV |
14876 WIPHY_VENDOR_CMD_NEED_RUNNING,
14877 .doit = wlan_hdd_cfg80211_vendor_scan
14878 },
14879
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014880 /* Vendor abort scan */
14881 {
14882 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14883 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
14884 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14885 WIPHY_VENDOR_CMD_NEED_NETDEV |
14886 WIPHY_VENDOR_CMD_NEED_RUNNING,
14887 .doit = wlan_hdd_vendor_abort_scan
14888 },
14889
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014890 /* OCB commands */
14891 {
14892 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14893 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
14894 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14895 WIPHY_VENDOR_CMD_NEED_NETDEV |
14896 WIPHY_VENDOR_CMD_NEED_RUNNING,
14897 .doit = wlan_hdd_cfg80211_ocb_set_config
14898 },
14899 {
14900 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14901 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
14902 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14903 WIPHY_VENDOR_CMD_NEED_NETDEV |
14904 WIPHY_VENDOR_CMD_NEED_RUNNING,
14905 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
14906 },
14907 {
14908 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14909 .info.subcmd =
14910 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
14911 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14912 WIPHY_VENDOR_CMD_NEED_NETDEV |
14913 WIPHY_VENDOR_CMD_NEED_RUNNING,
14914 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
14915 },
14916 {
14917 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14918 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
14919 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14920 WIPHY_VENDOR_CMD_NEED_NETDEV |
14921 WIPHY_VENDOR_CMD_NEED_RUNNING,
14922 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
14923 },
14924 {
14925 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14926 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
14927 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14928 WIPHY_VENDOR_CMD_NEED_NETDEV |
14929 WIPHY_VENDOR_CMD_NEED_RUNNING,
14930 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
14931 },
14932 {
14933 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14934 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
14935 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14936 WIPHY_VENDOR_CMD_NEED_NETDEV |
14937 WIPHY_VENDOR_CMD_NEED_RUNNING,
14938 .doit = wlan_hdd_cfg80211_dcc_get_stats
14939 },
14940 {
14941 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14942 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
14943 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14944 WIPHY_VENDOR_CMD_NEED_NETDEV |
14945 WIPHY_VENDOR_CMD_NEED_RUNNING,
14946 .doit = wlan_hdd_cfg80211_dcc_clear_stats
14947 },
14948 {
14949 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14950 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
14951 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14952 WIPHY_VENDOR_CMD_NEED_NETDEV |
14953 WIPHY_VENDOR_CMD_NEED_RUNNING,
14954 .doit = wlan_hdd_cfg80211_dcc_update_ndl
14955 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053014956 {
14957 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14958 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
14959 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14960 WIPHY_VENDOR_CMD_NEED_NETDEV |
14961 WIPHY_VENDOR_CMD_NEED_RUNNING,
14962 .doit = wlan_hdd_cfg80211_get_link_properties
14963 },
Qiwei Caie689a262018-07-26 15:50:22 +080014964
14965 FEATURE_OTA_TEST_VENDOR_COMMANDS
14966
Ravi Joshideb5a8d2015-11-09 19:11:43 -080014967#ifdef FEATURE_LFR_SUBNET_DETECTION
14968 {
14969 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14970 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
14971 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14972 WIPHY_VENDOR_CMD_NEED_NETDEV |
14973 WIPHY_VENDOR_CMD_NEED_RUNNING,
14974 .doit = wlan_hdd_cfg80211_set_gateway_params
14975 },
14976#endif /* FEATURE_LFR_SUBNET_DETECTION */
Qiwei Caie689a262018-07-26 15:50:22 +080014977
14978 FEATURE_TX_POWER_VENDOR_COMMANDS
14979
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053014980#ifdef FEATURE_WLAN_APF
Arun Khandavalli2476ef52016-04-26 20:19:43 +053014981 {
14982 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14983 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
14984 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14985 WIPHY_VENDOR_CMD_NEED_NETDEV |
14986 WIPHY_VENDOR_CMD_NEED_RUNNING,
Nachiket Kukadee547a482018-05-22 16:43:30 +053014987 .doit = wlan_hdd_cfg80211_apf_offload
Arun Khandavalli2476ef52016-04-26 20:19:43 +053014988 },
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053014989#endif /* FEATURE_WLAN_APF */
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053014990 {
14991 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053014992 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
14993 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14994 WIPHY_VENDOR_CMD_NEED_NETDEV |
14995 WIPHY_VENDOR_CMD_NEED_RUNNING,
14996 .doit = wlan_hdd_cfg80211_acs_dfs_mode
14997 },
14998 {
14999 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053015000 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
15001 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15002 WIPHY_VENDOR_CMD_NEED_NETDEV |
15003 WIPHY_VENDOR_CMD_NEED_RUNNING,
15004 .doit = wlan_hdd_cfg80211_sta_roam_policy
15005 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053015006#ifdef FEATURE_WLAN_CH_AVOID
15007 {
15008 .info.vendor_id = QCA_NL80211_VENDOR_ID,
15009 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
15010 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15011 WIPHY_VENDOR_CMD_NEED_NETDEV |
15012 WIPHY_VENDOR_CMD_NEED_RUNNING,
15013 .doit = wlan_hdd_cfg80211_avoid_freq
15014 },
15015#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053015016 {
15017 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053015018 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
15019 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15020 WIPHY_VENDOR_CMD_NEED_NETDEV |
15021 WIPHY_VENDOR_CMD_NEED_RUNNING,
15022 .doit = wlan_hdd_cfg80211_sap_configuration_set
15023 },
Qiwei Caie689a262018-07-26 15:50:22 +080015024
15025 FEATURE_P2P_LISTEN_OFFLOAD_VENDOR_COMMANDS
15026
15027 FEATURE_SAP_COND_CHAN_SWITCH_VENDOR_COMMANDS
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053015028 {
15029 .info.vendor_id = QCA_NL80211_VENDOR_ID,
15030 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
15031 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15032 WIPHY_VENDOR_CMD_NEED_NETDEV |
15033 WIPHY_VENDOR_CMD_NEED_RUNNING,
15034 .doit = wlan_hdd_cfg80211_get_wakelock_stats
15035 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053015036 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053015037 .info.vendor_id = QCA_NL80211_VENDOR_ID,
15038 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
15039 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15040 WIPHY_VENDOR_CMD_NEED_NETDEV |
15041 WIPHY_VENDOR_CMD_NEED_RUNNING,
15042 .doit = wlan_hdd_cfg80211_get_bus_size
15043 },
15044 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053015045 .info.vendor_id = QCA_NL80211_VENDOR_ID,
15046 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
15047 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15048 WIPHY_VENDOR_CMD_NEED_NETDEV |
15049 WIPHY_VENDOR_CMD_NEED_RUNNING,
15050 .doit = wlan_hdd_cfg80211_update_vendor_channel
15051 },
15052 {
bingsd09dea32017-03-17 10:08:26 +080015053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053015054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
15055 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15056 WIPHY_VENDOR_CMD_NEED_NETDEV |
15057 WIPHY_VENDOR_CMD_NEED_RUNNING,
15058 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053015059 },
15060 {
15061 .info.vendor_id = QCA_NL80211_VENDOR_ID,
15062 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
15063 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15064 WIPHY_VENDOR_CMD_NEED_NETDEV |
15065 WIPHY_VENDOR_CMD_NEED_RUNNING,
15066 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053015067 },
15068#ifdef WLAN_FEATURE_DISA
15069 {
15070 .info.vendor_id = QCA_NL80211_VENDOR_ID,
15071 .info.subcmd =
15072 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
15073 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15074 WIPHY_VENDOR_CMD_NEED_NETDEV |
15075 WIPHY_VENDOR_CMD_NEED_RUNNING,
15076 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
15077 },
15078#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070015079#ifdef FEATURE_WLAN_TDLS
15080 {
15081 .info.vendor_id = QCA_NL80211_VENDOR_ID,
15082 .info.subcmd =
15083 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
15084 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15085 WIPHY_VENDOR_CMD_NEED_NETDEV |
15086 WIPHY_VENDOR_CMD_NEED_RUNNING,
15087 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080015088 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070015089#endif
Qiwei Caie689a262018-07-26 15:50:22 +080015090 FEATURE_SAR_LIMITS_VENDOR_COMMANDS
Abhinav Kumardbbfd2c2019-05-07 12:22:06 +053015091 BCN_RECV_FEATURE_VENDOR_COMMANDS
Qiwei Caie689a262018-07-26 15:50:22 +080015092
Jeff Johnson8c83f132017-12-18 16:41:37 -080015093 {
15094 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080015095 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
15096 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15097 WIPHY_VENDOR_CMD_NEED_RUNNING,
15098 .doit = wlan_hdd_cfg80211_set_sar_power_limits
15099 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053015100 {
15101 .info.vendor_id = QCA_NL80211_VENDOR_ID,
15102 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
15103 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15104 WIPHY_VENDOR_CMD_NEED_NETDEV |
15105 WIPHY_VENDOR_CMD_NEED_RUNNING,
15106 .doit = wlan_hdd_cfg80211_set_trace_level
15107 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080015108 {
15109 .info.vendor_id = QCA_NL80211_VENDOR_ID,
15110 .info.subcmd =
15111 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
15112 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15113 WIPHY_VENDOR_CMD_NEED_NETDEV |
15114 WIPHY_VENDOR_CMD_NEED_RUNNING,
15115 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
15116 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053015117 {
15118 .info.vendor_id = QCA_NL80211_VENDOR_ID,
15119 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET,
15120 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15121 WIPHY_VENDOR_CMD_NEED_NETDEV |
15122 WIPHY_VENDOR_CMD_NEED_RUNNING,
15123 .doit = wlan_hdd_cfg80211_set_nud_stats
15124 },
15125 {
15126 .info.vendor_id = QCA_NL80211_VENDOR_ID,
15127 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
15128 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15129 WIPHY_VENDOR_CMD_NEED_NETDEV |
15130 WIPHY_VENDOR_CMD_NEED_RUNNING,
15131 .doit = wlan_hdd_cfg80211_get_nud_stats
15132 },
Qiwei Caie689a262018-07-26 15:50:22 +080015133
15134 FEATURE_BSS_TRANSITION_VENDOR_COMMANDS
Sandeep Puligilla063a4342018-01-10 02:50:14 -080015135 FEATURE_SPECTRAL_SCAN_VENDOR_COMMANDS
Wu Gao29012452020-03-07 17:06:34 +080015136 FEATURE_CFR_VENDOR_COMMANDS
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080015137 FEATURE_11AX_VENDOR_COMMANDS
lifengd217d192017-05-09 19:44:16 +080015138
15139 {
15140 .info.vendor_id = QCA_NL80211_VENDOR_ID,
15141 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI,
15142 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
15143 WIPHY_VENDOR_CMD_NEED_NETDEV |
15144 WIPHY_VENDOR_CMD_NEED_RUNNING,
15145 .doit = wlan_hdd_cfg80211_get_chain_rssi
15146 },
Qiwei Caie689a262018-07-26 15:50:22 +080015147
15148 FEATURE_ACTIVE_TOS_VENDOR_COMMANDS
Nachiket Kukadea6a70a92018-10-09 20:07:21 +053015149 FEATURE_NAN_VENDOR_COMMANDS
Qun Zhangef655622019-02-25 10:48:10 +080015150 FEATURE_FW_STATE_COMMANDS
Jiani Liua5f17222019-03-04 16:22:33 +080015151 FEATURE_COEX_CONFIG_COMMANDS
stonez2d686482019-03-12 14:54:26 +080015152 FEATURE_MPTA_HELPER_COMMANDS
guangde4853c402019-05-06 15:54:04 +080015153 FEATURE_HW_CAPABILITY_COMMANDS
Pankaj Singh50e40422020-01-09 15:29:35 +053015154 FEATURE_THERMAL_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015155};
15156
Dustin Brown92bd8382018-10-31 15:49:46 -070015157struct hdd_context *hdd_cfg80211_wiphy_alloc(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015158{
15159 struct wiphy *wiphy;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015160 struct hdd_context *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080015161
Dustin Brown491d54b2018-03-14 12:39:11 -070015162 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015163
Dustin Brown92bd8382018-10-31 15:49:46 -070015164 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, sizeof(*hdd_ctx));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015165 if (!wiphy) {
Dustin Brown92bd8382018-10-31 15:49:46 -070015166 hdd_err("failed to allocate wiphy!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015167 return NULL;
15168 }
15169
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080015170 hdd_ctx = wiphy_priv(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080015171 hdd_ctx->wiphy = wiphy;
15172
15173 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015174}
15175
Jeff Johnson459d2732019-03-02 10:13:25 -080015176int wlan_hdd_cfg80211_update_band(struct hdd_context *hdd_ctx,
15177 struct wiphy *wiphy,
15178 enum band_info new_band)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015179{
15180 int i, j;
Jeff Johnson9cb757b2019-03-11 15:29:02 -070015181 enum channel_state channel_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015182
Dustin Brown491d54b2018-03-14 12:39:11 -070015183 hdd_enter();
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070015184
15185 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015186
Jeff Johnsond36fa332019-03-18 13:42:25 -070015187 if (!wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015188 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015189
15190 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
15191 struct ieee80211_supported_band *band = wiphy->bands[i];
15192
Jeff Johnson9cb757b2019-03-11 15:29:02 -070015193 channel_state = wlan_reg_get_channel_state(
Dustin Brown07901ec2018-09-07 11:02:41 -070015194 hdd_ctx->pdev,
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070015195 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015196
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015197 if (HDD_NL80211_BAND_2GHZ == i &&
Jeff Johnson459d2732019-03-02 10:13:25 -080015198 BAND_5G == new_band) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015199 /* 5G only */
15200#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
15201 /* Enable Social channels for P2P */
15202 if (WLAN_HDD_IS_SOCIAL_CHANNEL
15203 (band->channels[j].center_freq)
15204 && CHANNEL_STATE_ENABLE ==
Jeff Johnson9cb757b2019-03-11 15:29:02 -070015205 channel_state)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015206 band->channels[j].flags &=
15207 ~IEEE80211_CHAN_DISABLED;
15208 else
15209#endif
15210 band->channels[j].flags |=
15211 IEEE80211_CHAN_DISABLED;
15212 continue;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015213 } else if (HDD_NL80211_BAND_5GHZ == i &&
Jeff Johnson459d2732019-03-02 10:13:25 -080015214 BAND_2G == new_band) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015215 /* 2G only */
15216 band->channels[j].flags |=
15217 IEEE80211_CHAN_DISABLED;
15218 continue;
15219 }
15220
Jeff Johnson9cb757b2019-03-11 15:29:02 -070015221 if (CHANNEL_STATE_DISABLE != channel_state)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015222 band->channels[j].flags &=
15223 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015224 }
15225 }
15226 return 0;
15227}
15228
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053015229#if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \
15230 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
15231static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
15232{
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +053015233 wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
15234 wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053015235}
15236#else
15237static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
15238{
15239}
15240#endif
15241
Peng Xuacfdda12017-02-06 16:15:38 -080015242#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053015243
Liangwei Dong3abfe8f2018-09-20 02:25:44 -040015244#if defined(CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME) || \
15245 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
15246/**
15247 * wlan_hdd_cfg80211_action_frame_randomization_init() - Randomize SA of MA
15248 * frames
15249 * @wiphy: Pointer to wiphy
15250 *
15251 * This function is used to indicate the support of source mac address
15252 * randomization of management action frames
15253 *
15254 * Return: None
15255 */
15256static void
15257wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
15258{
15259 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA);
15260}
15261#else
15262static void
15263wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
15264{
15265}
15266#endif
15267
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053015268#if defined(WLAN_FEATURE_FILS_SK) && \
15269 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
15270 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015271static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
15272{
15273 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
15274}
15275#else
15276static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
15277{
15278}
15279#endif
15280
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053015281#if defined (CFG80211_SCAN_DBS_CONTROL_SUPPORT) || \
15282 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
15283static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
15284{
15285 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
15286 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
15287 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
15288}
15289#else
15290static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
15291{
15292}
15293#endif
15294
Veerendranath Jakkam62fedb92019-03-20 16:32:17 +053015295#if defined(CFG80211_SCAN_OCE_CAPABILITY_SUPPORT) || \
15296 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
15297static void wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy *wiphy)
15298{
15299 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME);
15300 wiphy_ext_feature_set(wiphy,
15301 NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP);
15302 wiphy_ext_feature_set(wiphy,
15303 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE);
15304 wiphy_ext_feature_set(
15305 wiphy, NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION);
15306}
15307#else
15308static void wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy *wiphy)
15309{
15310}
15311#endif
15312
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053015313#if defined(WLAN_FEATURE_SAE) && \
15314 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015315/**
15316 * wlan_hdd_cfg80211_set_wiphy_sae_feature() - Indicates support of SAE feature
15317 * @wiphy: Pointer to wiphy
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015318 *
15319 * This function is used to indicate the support of SAE
15320 *
15321 * Return: None
15322 */
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080015323static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015324{
Manikandan Mohand350c192018-11-29 14:01:12 -080015325 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Manikandan Mohand350c192018-11-29 14:01:12 -080015326
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080015327 if (ucfg_fwol_get_sae_enable(hdd_ctx->psoc))
Manikandan Mohan5dba1c72019-01-07 16:57:03 -080015328 wiphy->features |= NL80211_FEATURE_SAE;
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015329}
15330#else
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080015331static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015332{
15333}
15334#endif
15335
Peng Xu8e8b0392018-04-30 11:32:34 -070015336#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
15337 defined(CFG80211_DFS_OFFLOAD_BACKPORT)
15338static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
15339{
15340 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
15341}
15342#else
15343static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
15344{
15345 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
15346}
15347#endif
15348
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070015349#ifdef WLAN_FEATURE_DSRC
15350static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
15351 int *num_ch, int *ch_len)
15352{
15353 *num_ch = QDF_ARRAY_SIZE(hdd_channels_dot11p);
15354 *ch_len = sizeof(hdd_channels_dot11p);
15355}
15356
15357static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
15358{
15359 if (!ch_arr_len)
15360 return;
15361 qdf_mem_copy(ch_ptr, &hdd_channels_dot11p[0], ch_arr_len);
15362}
15363
15364static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
15365 int *num_ch, int *ch_len)
15366{
15367 *num_ch = 0;
15368 *ch_len = 0;
15369}
15370
15371static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
15372{
15373}
15374
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053015375/**
15376 * wlan_hdd_populate_srd_chan_info() - Populate SRD chan info in hdd context
15377 * @hdd_ctx: pointer to hdd context
15378 * @index: SRD channel beginning index in chan_info of @hdd_ctx
15379 *
15380 * Return: Number of SRD channels populated
15381 */
15382static uint32_t
15383wlan_hdd_populate_srd_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
15384{
15385 return 0;
15386}
15387
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070015388#else
15389
15390static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
15391 int *num_ch, int *ch_len)
15392{
15393 *num_ch = 0;
15394 *ch_len = 0;
15395}
15396
15397static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
15398{
15399}
15400
15401static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
15402 int *num_ch, int *ch_len)
15403{
15404 *num_ch = QDF_ARRAY_SIZE(hdd_etsi13_srd_ch);
15405 *ch_len = sizeof(hdd_etsi13_srd_ch);
15406}
15407
15408static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
15409{
15410 if (!ch_arr_len)
15411 return;
15412 qdf_mem_copy(ch_ptr, &hdd_etsi13_srd_ch[0], ch_arr_len);
15413}
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053015414
15415/**
15416 * wlan_hdd_populate_srd_chan_info() - Populate SRD chan info in hdd context
15417 * @hdd_ctx: pointer to hdd context
15418 * @index: SRD channel beginning index in chan_info of @hdd_ctx
15419 *
15420 * Return: Number of SRD channels populated
15421 */
15422static uint32_t
15423wlan_hdd_populate_srd_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
15424{
15425 uint32_t num_srd_ch, i;
15426 struct scan_chan_info *chan_info;
15427
15428 num_srd_ch = QDF_ARRAY_SIZE(hdd_etsi13_srd_ch);
15429 chan_info = hdd_ctx->chan_info;
15430
15431 for (i = 0; i < num_srd_ch; i++)
15432 chan_info[index + i].freq = hdd_etsi13_srd_ch[i].center_freq;
15433
15434 return num_srd_ch;
15435}
15436
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070015437#endif
15438
bings3d9cd952019-12-23 17:41:52 +080015439#if (defined(CONFIG_BAND_6GHZ) && defined(CFG80211_6GHZ_BAND_SUPPORTED)) || \
15440 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
gaurank kathpalia54bc4a32019-12-05 20:43:15 +053015441#if defined(CONFIG_BAND_6GHZ) && (defined(CFG80211_6GHZ_BAND_SUPPORTED) || \
15442 (KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE))
15443static QDF_STATUS
15444wlan_hdd_iftype_data_alloc_6ghz(struct hdd_context *hdd_ctx)
15445{
15446 hdd_ctx->iftype_data_6g =
15447 qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_6g));
15448
15449 if (!hdd_ctx->iftype_data_6g)
15450 return QDF_STATUS_E_NOMEM;
15451
15452 return QDF_STATUS_SUCCESS;
15453}
bings3d9cd952019-12-23 17:41:52 +080015454
15455static void
15456wlan_hdd_iftype_data_mem_free_6ghz(struct hdd_context *hdd_ctx)
15457{
15458 qdf_mem_free(hdd_ctx->iftype_data_6g);
15459 hdd_ctx->iftype_data_6g = NULL;
15460}
gaurank kathpalia54bc4a32019-12-05 20:43:15 +053015461#else
15462static inline QDF_STATUS
15463wlan_hdd_iftype_data_alloc_6ghz(struct hdd_context *hdd_ctx)
15464{
15465 return QDF_STATUS_SUCCESS;
15466}
bings3d9cd952019-12-23 17:41:52 +080015467
15468static inline void
15469wlan_hdd_iftype_data_mem_free_6ghz(struct hdd_context *hdd_ctx)
15470{
15471}
gaurank kathpalia54bc4a32019-12-05 20:43:15 +053015472#endif
15473
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015474static QDF_STATUS
15475wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx)
15476{
15477 hdd_ctx->iftype_data_2g =
15478 qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_2g));
15479
15480 if (!hdd_ctx->iftype_data_2g) {
15481 hdd_err("mem alloc failed for 2g iftype data");
15482 return QDF_STATUS_E_NOMEM;
15483 }
15484 hdd_ctx->iftype_data_5g =
15485 qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_5g));
15486
15487 if (!hdd_ctx->iftype_data_5g) {
15488 hdd_err("mem alloc failed for 5g iftype data");
15489 qdf_mem_free(hdd_ctx->iftype_data_2g);
15490 hdd_ctx->iftype_data_2g = NULL;
15491 return QDF_STATUS_E_NOMEM;
15492 }
15493
gaurank kathpalia54bc4a32019-12-05 20:43:15 +053015494 if (QDF_IS_STATUS_ERROR(wlan_hdd_iftype_data_alloc_6ghz(hdd_ctx))) {
15495 hdd_err("mem alloc failed for 6g iftype data");
15496 qdf_mem_free(hdd_ctx->iftype_data_5g);
15497 qdf_mem_free(hdd_ctx->iftype_data_2g);
15498 hdd_ctx->iftype_data_2g = NULL;
15499 hdd_ctx->iftype_data_5g = NULL;
15500 return QDF_STATUS_E_NOMEM;
15501 }
15502
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015503 return QDF_STATUS_SUCCESS;
15504}
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015505
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015506static void
15507wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx)
15508{
gaurank kathpalia54bc4a32019-12-05 20:43:15 +053015509 wlan_hdd_iftype_data_mem_free_6ghz(hdd_ctx);
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015510 qdf_mem_free(hdd_ctx->iftype_data_5g);
15511 qdf_mem_free(hdd_ctx->iftype_data_2g);
15512 hdd_ctx->iftype_data_5g = NULL;
15513 hdd_ctx->iftype_data_2g = NULL;
15514}
15515#else
bings3d9cd952019-12-23 17:41:52 +080015516static QDF_STATUS
15517wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx)
15518
15519{
15520 return QDF_STATUS_SUCCESS;
15521}
15522
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015523static inline void
15524wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx)
15525{
15526}
15527#endif
15528
Srinivas Dasarid2ba2612019-12-11 17:27:52 +053015529#if defined(WLAN_FEATURE_NAN) && \
Srinivas Dasarief9a8ad2020-06-10 14:32:21 +053015530 (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE)
Srinivas Dasarid2ba2612019-12-11 17:27:52 +053015531static void wlan_hdd_set_nan_if_mode(struct wiphy *wiphy)
15532{
15533 wiphy->interface_modes |= BIT(NL80211_IFTYPE_NAN);
15534}
15535
15536static void wlan_hdd_set_nan_supported_bands(struct wiphy *wiphy)
15537{
15538 wiphy->nan_supported_bands =
15539 BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ);
15540}
15541#else
15542static void wlan_hdd_set_nan_if_mode(struct wiphy *wiphy)
15543{
15544}
15545
15546static void wlan_hdd_set_nan_supported_bands(struct wiphy *wiphy)
15547{
15548}
15549#endif
15550
sheenam mongacaeb3c22020-03-23 17:03:07 +053015551/**
15552 * wlan_hdd_update_akm_suit_info() - Populate akm suits supported by driver
15553 * @wiphy: wiphy
15554 *
15555 * Return: void
15556 */
15557#if defined(CFG80211_IFTYPE_AKM_SUITES_SUPPORT)
15558static void
15559wlan_hdd_update_akm_suit_info(struct wiphy *wiphy)
15560{
15561 wiphy->iftype_akm_suites = wlan_hdd_akm_suites;
sheenam monga1dcf56c2020-04-15 12:02:10 +053015562 wiphy->num_iftype_akm_suites = QDF_ARRAY_SIZE(wlan_hdd_akm_suites);
sheenam mongacaeb3c22020-03-23 17:03:07 +053015563}
15564#else
15565static void
15566wlan_hdd_update_akm_suit_info(struct wiphy *wiphy)
15567{
15568}
15569#endif
15570
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015571/*
15572 * FUNCTION: wlan_hdd_cfg80211_init
15573 * This function is called by hdd_wlan_startup()
15574 * during initialization.
15575 * This function is used to initialize and register wiphy structure.
15576 */
15577int wlan_hdd_cfg80211_init(struct device *dev,
Jeff Johnson30f5bba2019-03-08 11:58:08 -080015578 struct wiphy *wiphy, struct hdd_config *config)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015579{
Jeff Johnsonb8944722017-09-03 09:03:19 -070015580 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015581 uint32_t *cipher_suites;
Dustin Brown491d54b2018-03-14 12:39:11 -070015582 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015583
15584 /* Now bind the underlying wlan device with wiphy */
15585 set_wiphy_dev(wiphy, dev);
15586
15587 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
sheenam mongacaeb3c22020-03-23 17:03:07 +053015588 wlan_hdd_update_akm_suit_info(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015589 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
15590 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
15591 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
15592#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
15593 | WIPHY_FLAG_4ADDR_STATION
15594#endif
15595 | WIPHY_FLAG_OFFCHAN_TX;
15596
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015597#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
15598 wiphy->wowlan = &wowlan_support_cfg80211_init;
15599#else
15600 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
15601 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
15602 wiphy->wowlan.pattern_min_len = 1;
15603 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
15604#endif
15605
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015606#ifdef FEATURE_WLAN_TDLS
15607 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
15608 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
15609#endif
15610
15611 wiphy->features |= NL80211_FEATURE_HT_IBSS;
15612
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015613#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
15614 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
15615#endif
15616
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053015617 wlan_hdd_cfg80211_set_wiphy_scan_flags(wiphy);
15618
Pragaspathi Thilagaraj24789d32018-12-10 22:28:03 +053015619 wlan_scan_cfg80211_add_connected_pno_support(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015620
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015621 wiphy->max_scan_ssids = MAX_SCAN_SSID;
15622
15623 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
15624
15625 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
15626
Arun Khandavallifae92942016-08-01 13:31:08 +053015627 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
15628 | BIT(NL80211_IFTYPE_ADHOC)
15629 | BIT(NL80211_IFTYPE_P2P_CLIENT)
15630 | BIT(NL80211_IFTYPE_P2P_GO)
15631 | BIT(NL80211_IFTYPE_AP)
15632 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015633
Srinivas Dasarid2ba2612019-12-11 17:27:52 +053015634 wlan_hdd_set_nan_if_mode(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015635
Abhishek Singhf512bf32016-05-04 16:47:46 +053015636 /*
15637 * In case of static linked driver at the time of driver unload,
15638 * module exit doesn't happens. Module cleanup helps in cleaning
15639 * of static memory.
15640 * If driver load happens statically, at the time of driver unload,
15641 * wiphy flags don't get reset because of static memory.
15642 * It's better not to store channel in static memory.
Qun Zhang043635a2019-02-27 15:19:29 +080015643 * The memory is for channels of struct wiphy and shouldn't be
15644 * released during stop modules. So if it's allocated in active
15645 * domain, the memory leak detector would catch the leak during
15646 * stop modules. To avoid this,alloc in init domain in advance.
Abhishek Singhf512bf32016-05-04 16:47:46 +053015647 */
Qun Zhang043635a2019-02-27 15:19:29 +080015648 hdd_ctx->channels_2ghz = qdf_mem_malloc(band_2_ghz_channels_size);
15649 if (!hdd_ctx->channels_2ghz) {
15650 hdd_err("Not enough memory to allocate channels");
Abhishek Singhf512bf32016-05-04 16:47:46 +053015651 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015652 }
Qun Zhang043635a2019-02-27 15:19:29 +080015653 hdd_ctx->channels_5ghz = qdf_mem_malloc(band_5_ghz_chanenls_size);
15654 if (!hdd_ctx->channels_5ghz)
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015655 goto mem_fail_5g;
15656
15657 if (QDF_IS_STATUS_ERROR(wlan_hdd_iftype_data_alloc(hdd_ctx)))
15658 goto mem_fail_iftype_data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015659
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015660 /*Initialise the supported cipher suite details */
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080015661 if (ucfg_fwol_get_gcmp_enable(hdd_ctx->psoc)) {
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015662 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites) +
15663 sizeof(hdd_gcmp_cipher_suits));
Min Liu74a1a502018-10-10 19:59:07 +080015664 if (!cipher_suites)
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015665 goto mem_fail_cipher_suites;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015666 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites) +
15667 QDF_ARRAY_SIZE(hdd_gcmp_cipher_suits);
15668 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
15669 sizeof(hdd_cipher_suites));
15670 qdf_mem_copy(cipher_suites + QDF_ARRAY_SIZE(hdd_cipher_suites),
15671 &hdd_gcmp_cipher_suits,
15672 sizeof(hdd_gcmp_cipher_suits));
15673 } else {
15674 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites));
Min Liu74a1a502018-10-10 19:59:07 +080015675 if (!cipher_suites)
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015676 goto mem_fail_cipher_suites;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015677 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites);
15678 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
15679 sizeof(hdd_cipher_suites));
15680 }
15681 wiphy->cipher_suites = cipher_suites;
15682 cipher_suites = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015683 /*signal strength in mBm (100*dBm) */
15684 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
15685 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
15686
Anurag Chouhan6d760662016-02-20 16:05:43 +053015687 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015688 wiphy->n_vendor_commands =
15689 ARRAY_SIZE(hdd_wiphy_vendor_commands);
15690 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
15691
15692 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
15693 wiphy->n_vendor_events =
15694 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
15695 }
15696
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015697#ifdef QCA_HT_2040_COEX
15698 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
15699#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053015700 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080015701
hangtian821d12d2019-06-11 11:53:50 +080015702 wiphy->features |= NL80211_FEATURE_VIF_TXPOWER;
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053015703#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) || \
wadesonga75734c2017-02-07 16:03:25 +080015704 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
15705 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
15706 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
15707 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
15708#endif
15709
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015710 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080015711 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Liangwei Dong3abfe8f2018-09-20 02:25:44 -040015712 wlan_hdd_cfg80211_action_frame_randomization_init(wiphy);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015713
Srinivas Dasarid2ba2612019-12-11 17:27:52 +053015714 wlan_hdd_set_nan_supported_bands(wiphy);
15715
Dustin Browne74003f2018-03-14 12:51:58 -070015716 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015717 return 0;
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015718
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015719mem_fail_cipher_suites:
15720 wlan_hdd_iftype_data_mem_free(hdd_ctx);
15721mem_fail_iftype_data:
15722 qdf_mem_free(hdd_ctx->channels_5ghz);
15723 hdd_ctx->channels_5ghz = NULL;
15724mem_fail_5g:
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015725 hdd_err("Not enough memory to allocate channels");
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015726 qdf_mem_free(hdd_ctx->channels_2ghz);
15727 hdd_ctx->channels_2ghz = NULL;
15728
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015729 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015730}
15731
Abhishek Singhf512bf32016-05-04 16:47:46 +053015732/**
Yingying Tang80e15f32016-09-27 18:23:01 +080015733 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
15734 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053015735 *
15736 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053015737 * memory allocated in wlan_hdd_cfg80211_init also
15738 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053015739 *
15740 * Return: void
15741 */
15742void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
15743{
15744 int i;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015745 const uint32_t *cipher_suites;
Qun Zhang043635a2019-02-27 15:19:29 +080015746 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +053015747
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070015748 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Jeff Johnsond36fa332019-03-18 13:42:25 -070015749 if (wiphy->bands[i] &&
Qun Zhang043635a2019-02-27 15:19:29 +080015750 (wiphy->bands[i]->channels))
Abhishek Singhf512bf32016-05-04 16:47:46 +053015751 wiphy->bands[i]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053015752 }
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015753 wlan_hdd_iftype_data_mem_free(hdd_ctx);
Qun Zhang043635a2019-02-27 15:19:29 +080015754 qdf_mem_free(hdd_ctx->channels_5ghz);
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015755 qdf_mem_free(hdd_ctx->channels_2ghz);
Qun Zhang043635a2019-02-27 15:19:29 +080015756 hdd_ctx->channels_2ghz = NULL;
15757 hdd_ctx->channels_5ghz = NULL;
Amar Singhal5cccafe2017-02-15 12:42:58 -080015758
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015759 cipher_suites = wiphy->cipher_suites;
15760 wiphy->cipher_suites = NULL;
15761 wiphy->n_cipher_suites = 0;
15762 qdf_mem_free((uint32_t *)cipher_suites);
15763 cipher_suites = NULL;
Abhishek Singh3e6172f2016-05-04 16:56:48 +053015764 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053015765}
15766
Yingying Tang80e15f32016-09-27 18:23:01 +080015767/**
15768 * wlan_hdd_update_band_cap() - update capabilities for supported bands
15769 * @hdd_ctx: HDD context
15770 *
15771 * this function will update capabilities for supported bands
15772 *
15773 * Return: void
15774 */
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053015775static void wlan_hdd_update_ht_cap(struct hdd_context *hdd_ctx)
Yingying Tang80e15f32016-09-27 18:23:01 +080015776{
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053015777 struct mlme_ht_capabilities_info ht_cap_info = {0};
Yingying Tang80e15f32016-09-27 18:23:01 +080015778 QDF_STATUS status;
Wu Gaoed616a12019-01-16 15:19:21 +080015779 uint32_t channel_bonding_mode;
Rajeev Kumar Sirasanagandla7dee7fe2019-08-05 15:55:19 +053015780 struct ieee80211_supported_band *band_2g;
15781 struct ieee80211_supported_band *band_5g;
Ashish Kumar Dhanotiyad90e8422020-02-28 16:24:38 +053015782 uint8_t i;
Yingying Tang80e15f32016-09-27 18:23:01 +080015783
Dustin Brown76cd2932018-09-11 16:03:05 -070015784 status = ucfg_mlme_get_ht_cap_info(hdd_ctx->psoc, &ht_cap_info);
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053015785 if (QDF_STATUS_SUCCESS != status)
Yingying Tang80e15f32016-09-27 18:23:01 +080015786 hdd_err("could not get HT capability info");
Yingying Tang80e15f32016-09-27 18:23:01 +080015787
Rajeev Kumar Sirasanagandla7dee7fe2019-08-05 15:55:19 +053015788 band_2g = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ];
15789 band_5g = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ];
15790
15791 if (band_2g) {
15792 if (ht_cap_info.tx_stbc)
15793 band_2g->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
15794
15795 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
15796 band_2g->vht_cap.vht_supported = 0;
15797 band_2g->vht_cap.cap = 0;
15798 }
15799
15800 if (!ht_cap_info.short_gi_20_mhz)
15801 band_2g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Ashish Kumar Dhanotiyad90e8422020-02-28 16:24:38 +053015802
15803 for (i = 0; i < hdd_ctx->num_rf_chains; i++)
15804 band_2g->ht_cap.mcs.rx_mask[i] = 0xff;
15805
15806 /*
15807 * According to mcs_nss HT MCS parameters highest data rate for
15808 * Nss = 1 is 150 Mbps
15809 */
15810 band_2g->ht_cap.mcs.rx_highest =
15811 cpu_to_le16(150 * hdd_ctx->num_rf_chains);
Yingying Tang80e15f32016-09-27 18:23:01 +080015812 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015813
Rajeev Kumar Sirasanagandla7dee7fe2019-08-05 15:55:19 +053015814 if (band_5g) {
15815 if (ht_cap_info.tx_stbc)
15816 band_5g->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
15817
15818 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
15819 band_5g->vht_cap.vht_supported = 0;
15820 band_5g->vht_cap.cap = 0;
15821 }
15822
15823 if (!ht_cap_info.short_gi_20_mhz)
15824 band_5g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
15825
15826 if (!ht_cap_info.short_gi_40_mhz)
15827 band_5g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
15828
15829 ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc,
15830 &channel_bonding_mode);
15831 if (!channel_bonding_mode)
15832 band_5g->ht_cap.cap &=
15833 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
Ashish Kumar Dhanotiyad90e8422020-02-28 16:24:38 +053015834
15835 for (i = 0; i < hdd_ctx->num_rf_chains; i++)
15836 band_5g->ht_cap.mcs.rx_mask[i] = 0xff;
15837 /*
15838 * According to mcs_nss HT MCS parameters highest data rate for
15839 * Nss = 1 is 150 Mbps
15840 */
15841 band_5g->ht_cap.mcs.rx_highest =
15842 cpu_to_le16(150 * hdd_ctx->num_rf_chains);
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015843 }
Yingying Tang80e15f32016-09-27 18:23:01 +080015844}
15845
Vignesh Viswanathanf97cc112018-10-03 19:17:07 +053015846/**
15847 * wlan_hdd_update_band_cap_in_wiphy() - update channel flags based on band cap
15848 * @hdd_ctx: HDD context
15849 *
15850 * This function updates the channel flags based on the band capability set
15851 * in the MLME CFG
15852 *
15853 * Return: void
15854 */
15855static void wlan_hdd_update_band_cap_in_wiphy(struct hdd_context *hdd_ctx)
15856{
15857 int i, j;
15858 uint8_t band_capability;
15859 QDF_STATUS status;
15860 struct ieee80211_supported_band *band;
15861
15862 status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
15863 if (QDF_IS_STATUS_ERROR(status)) {
15864 hdd_err("Failed to get MLME Band Capability");
15865 return;
15866 }
15867
15868 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Jeff Johnsond36fa332019-03-18 13:42:25 -070015869 if (!hdd_ctx->wiphy->bands[i])
Vignesh Viswanathanf97cc112018-10-03 19:17:07 +053015870 continue;
15871
15872 for (j = 0; j < hdd_ctx->wiphy->bands[i]->n_channels; j++) {
15873 band = hdd_ctx->wiphy->bands[i];
15874
15875 if (HDD_NL80211_BAND_2GHZ == i &&
15876 BAND_5G == band_capability) {
15877 /* 5G only */
15878#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
15879 /* Enable social channels for P2P */
15880 if (WLAN_HDD_IS_SOCIAL_CHANNEL
15881 (band->channels[j].center_freq))
15882 band->channels[j].flags &=
15883 ~IEEE80211_CHAN_DISABLED;
15884 else
15885#endif
15886 band->channels[j].flags |=
15887 IEEE80211_CHAN_DISABLED;
15888 continue;
15889 } else if (HDD_NL80211_BAND_5GHZ == i &&
15890 BAND_2G == band_capability) {
15891 /* 2G only */
15892 band->channels[j].flags |=
15893 IEEE80211_CHAN_DISABLED;
15894 continue;
15895 }
15896 }
15897 }
15898}
15899
Wu Gao1ab05582018-11-08 16:22:49 +080015900#ifdef FEATURE_WLAN_ESE
15901/**
15902 * wlan_hdd_update_lfr_wiphy() - update LFR flag based on configures
15903 * @hdd_ctx: HDD context
15904 *
15905 * This function updates the LFR flag based on LFR configures
15906 *
15907 * Return: void
15908 */
15909static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
15910{
15911 bool fast_transition_enabled;
15912 bool lfr_enabled;
15913 bool ese_enabled;
15914
15915 ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
15916 &fast_transition_enabled);
15917 ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
15918 ucfg_mlme_is_ese_enabled(hdd_ctx->psoc, &ese_enabled);
15919 if (fast_transition_enabled || lfr_enabled || ese_enabled)
15920 hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
15921}
15922#else
15923static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
15924{
15925 bool fast_transition_enabled;
15926 bool lfr_enabled;
15927
15928 ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
15929 &fast_transition_enabled);
15930 ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
15931 if (fast_transition_enabled || lfr_enabled)
15932 hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
15933}
15934#endif
15935
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015936/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053015937 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015938 * initialization. In wlan_hdd_cfg80211_init, only the
15939 * default values will be initialized. The final initialization
15940 * of all required members can be done here.
15941 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015942void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015943{
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053015944 int value;
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053015945 bool fils_enabled, mac_spoofing_enabled;
Srinivas Dasarib264fec2019-05-21 18:56:25 +053015946 bool dfs_master_capable = true, is_oce_sta_enabled = false;
Karthik Kantamneni2231a232018-09-11 15:45:55 +053015947 QDF_STATUS status;
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053015948 struct wiphy *wiphy = hdd_ctx->wiphy;
15949 uint8_t allow_mcc_go_diff_bi = 0, enable_mcc = 0;
Yingying Tang80e15f32016-09-27 18:23:01 +080015950
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053015951 if (!wiphy) {
15952 hdd_err("Invalid wiphy");
15953 return;
15954 }
Dustin Brown05d81302018-09-11 16:49:22 -070015955 ucfg_mlme_get_sap_max_peers(hdd_ctx->psoc, &value);
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053015956 hdd_ctx->wiphy->max_ap_assoc_sta = value;
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053015957 wlan_hdd_update_ht_cap(hdd_ctx);
Vignesh Viswanathanf97cc112018-10-03 19:17:07 +053015958 wlan_hdd_update_band_cap_in_wiphy(hdd_ctx);
Wu Gao1ab05582018-11-08 16:22:49 +080015959 wlan_hdd_update_lfr_wiphy(hdd_ctx);
Karthik Kantamneni2231a232018-09-11 15:45:55 +053015960
15961 fils_enabled = 0;
Dustin Brown05d81302018-09-11 16:49:22 -070015962 status = ucfg_mlme_get_fils_enabled_info(hdd_ctx->psoc,
Karthik Kantamneni2231a232018-09-11 15:45:55 +053015963 &fils_enabled);
15964 if (QDF_IS_STATUS_ERROR(status))
15965 hdd_err("could not get fils enabled info");
15966 if (fils_enabled)
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053015967 wlan_hdd_cfg80211_set_wiphy_fils_feature(wiphy);
Arif Hussain88d1fdd2018-09-26 16:12:24 -070015968
15969 status = ucfg_mlme_get_dfs_master_capability(hdd_ctx->psoc,
15970 &dfs_master_capable);
15971 if (QDF_IS_STATUS_SUCCESS(status) && dfs_master_capable)
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053015972 wlan_hdd_cfg80211_set_dfs_offload_feature(wiphy);
Srinivas Dasarib264fec2019-05-21 18:56:25 +053015973
15974 status = ucfg_mlme_get_oce_sta_enabled_info(hdd_ctx->psoc,
15975 &is_oce_sta_enabled);
15976 if (QDF_IS_STATUS_ERROR(status))
15977 hdd_err("could not get OCE STA enable info");
15978 if (is_oce_sta_enabled)
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053015979 wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(wiphy);
15980
15981 wlan_hdd_cfg80211_set_wiphy_sae_feature(wiphy);
15982
15983 if (QDF_STATUS_SUCCESS !=
15984 ucfg_policy_mgr_get_allow_mcc_go_diff_bi(hdd_ctx->psoc,
15985 &allow_mcc_go_diff_bi))
15986 hdd_err("can't get mcc_go_diff_bi value, use default");
15987
15988 if (QDF_STATUS_SUCCESS !=
15989 ucfg_mlme_get_mcc_feature(hdd_ctx->psoc, &enable_mcc))
15990 hdd_err("can't get enable_mcc value, use default");
15991
15992 if (hdd_ctx->config->advertise_concurrent_operation) {
15993 if (enable_mcc) {
15994 int i;
15995
15996 for (i = 0;
15997 i < ARRAY_SIZE(wlan_hdd_iface_combination);
15998 i++) {
15999 if (!allow_mcc_go_diff_bi)
16000 wlan_hdd_iface_combination[i].
16001 beacon_int_infra_match = true;
16002 }
16003 }
16004 wiphy->n_iface_combinations =
16005 ARRAY_SIZE(wlan_hdd_iface_combination);
16006 wiphy->iface_combinations = wlan_hdd_iface_combination;
16007 }
16008
16009 mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
16010 if (mac_spoofing_enabled)
16011 wlan_hdd_cfg80211_scan_randomization_init(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016012}
16013
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080016014/**
16015 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
16016 * @cfg: hdd cfg
16017 *
16018 * this function update 11n mode in hdd cfg
16019 *
16020 * Return: void
16021 */
Sandeep Puligilla34618782019-01-04 17:42:42 -080016022void wlan_hdd_update_11n_mode(struct hdd_context *hdd_ctx)
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080016023{
Sandeep Puligilla34618782019-01-04 17:42:42 -080016024 struct hdd_config *cfg = hdd_ctx->config;
16025
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080016026 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016027 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080016028 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016029 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080016030 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
16031 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
16032 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
Sandeep Puligilla34618782019-01-04 17:42:42 -080016033 ucfg_mlme_set_sap_11ac_override(hdd_ctx->psoc, 0);
16034 ucfg_mlme_set_go_11ac_override(hdd_ctx->psoc, 0);
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080016035 }
16036 }
16037}
16038
Qun Zhang043635a2019-02-27 15:19:29 +080016039QDF_STATUS wlan_hdd_update_wiphy_supported_band(struct hdd_context *hdd_ctx)
16040{
16041 int len_5g_ch, num_ch;
16042 int num_dsrc_ch, len_dsrc_ch, num_srd_ch, len_srd_ch;
Varuneshwar Petlozu3a18e852019-07-23 15:13:26 +053016043 bool is_vht_for_24ghz = false;
16044 QDF_STATUS status;
Qun Zhang043635a2019-02-27 15:19:29 +080016045 struct hdd_config *cfg = hdd_ctx->config;
16046 struct wiphy *wiphy = hdd_ctx->wiphy;
16047
tinlin5d3721d2019-06-03 16:13:20 +080016048 if (wiphy->registered)
16049 return QDF_STATUS_SUCCESS;
16050
Ashish Kumar Dhanotiya34507e02019-06-12 12:53:59 +053016051 if (hdd_is_2g_supported(hdd_ctx)) {
16052 if (!hdd_ctx->channels_2ghz)
16053 return QDF_STATUS_E_NOMEM;
16054 wiphy->bands[HDD_NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
16055 wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels =
16056 hdd_ctx->channels_2ghz;
16057 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels,
16058 &hdd_channels_2_4_ghz[0],
16059 sizeof(hdd_channels_2_4_ghz));
Varuneshwar Petlozu3a18e852019-07-23 15:13:26 +053016060
16061 status = ucfg_mlme_get_vht_for_24ghz(hdd_ctx->psoc,
16062 &is_vht_for_24ghz);
16063 if (QDF_IS_STATUS_ERROR(status))
16064 hdd_err("could not get VHT capability");
16065
16066 if (is_vht_for_24ghz &&
Sourav Mohapatra92434622020-01-30 09:32:21 +053016067 sme_is_feature_supported_by_fw(DOT11AC) &&
16068 (cfg->dot11Mode == eHDD_DOT11_MODE_AUTO ||
16069 cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY ||
16070 cfg->dot11Mode == eHDD_DOT11_MODE_11ac ||
16071 cfg->dot11Mode == eHDD_DOT11_MODE_11ax ||
16072 cfg->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY))
Varuneshwar Petlozu3a18e852019-07-23 15:13:26 +053016073 wlan_hdd_band_2_4_ghz.vht_cap.vht_supported = 1;
Ashish Kumar Dhanotiya34507e02019-06-12 12:53:59 +053016074 }
Qun Zhang043635a2019-02-27 15:19:29 +080016075 if (!hdd_is_5g_supported(hdd_ctx) ||
16076 (eHDD_DOT11_MODE_11b == cfg->dot11Mode) ||
16077 (eHDD_DOT11_MODE_11g == cfg->dot11Mode) ||
16078 (eHDD_DOT11_MODE_11b_ONLY == cfg->dot11Mode) ||
16079 (eHDD_DOT11_MODE_11g_ONLY == cfg->dot11Mode))
16080 return QDF_STATUS_SUCCESS;
16081
16082 if (!hdd_ctx->channels_5ghz)
16083 return QDF_STATUS_E_NOMEM;
16084 wiphy->bands[HDD_NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
16085 wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels = hdd_ctx->channels_5ghz;
16086 wlan_hdd_get_num_dsrc_ch_and_len(cfg, &num_dsrc_ch, &len_dsrc_ch);
16087 wlan_hdd_get_num_srd_ch_and_len(cfg, &num_srd_ch, &len_srd_ch);
16088 num_ch = QDF_ARRAY_SIZE(hdd_channels_5_ghz) + num_dsrc_ch + num_srd_ch;
16089 len_5g_ch = sizeof(hdd_channels_5_ghz);
16090
16091 wiphy->bands[HDD_NL80211_BAND_5GHZ]->n_channels = num_ch;
16092 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels,
16093 &hdd_channels_5_ghz[0], len_5g_ch);
16094 if (num_dsrc_ch)
16095 wlan_hdd_copy_dsrc_ch((char *)wiphy->bands[
16096 HDD_NL80211_BAND_5GHZ]->channels +
16097 len_5g_ch, len_dsrc_ch);
16098 if (num_srd_ch)
16099 wlan_hdd_copy_srd_ch((char *)wiphy->bands[
16100 HDD_NL80211_BAND_5GHZ]->channels +
16101 len_5g_ch, len_srd_ch);
16102
Sourav Mohapatra92434622020-01-30 09:32:21 +053016103 if (cfg->dot11Mode != eHDD_DOT11_MODE_AUTO &&
16104 cfg->dot11Mode != eHDD_DOT11_MODE_11ac &&
16105 cfg->dot11Mode != eHDD_DOT11_MODE_11ac_ONLY &&
16106 cfg->dot11Mode != eHDD_DOT11_MODE_11ax &&
16107 cfg->dot11Mode != eHDD_DOT11_MODE_11ax_ONLY)
16108 wlan_hdd_band_5_ghz.vht_cap.vht_supported = 0;
16109
Liangwei Dong692455f2019-08-09 17:59:46 +080016110 hdd_init_6ghz(hdd_ctx);
16111
Qun Zhang043635a2019-02-27 15:19:29 +080016112 return QDF_STATUS_SUCCESS;
16113}
16114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016115/* In this function we are registering wiphy. */
16116int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
16117{
Dustin Brown491d54b2018-03-14 12:39:11 -070016118 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016119 /* Register our wiphy dev with cfg80211 */
16120 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070016121 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016122 return -EIO;
16123 }
16124
Dustin Browne74003f2018-03-14 12:51:58 -070016125 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016126 return 0;
16127}
16128
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016129/* This function registers for all frame which supplicant is interested in */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016130int wlan_hdd_cfg80211_register_frames(struct hdd_adapter *adapter)
Wu Gao84d120c2017-03-24 18:46:00 +080016131{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016132 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
Wu Gao84d120c2017-03-24 18:46:00 +080016133 /* Register for all P2P action, public action etc frames */
16134 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016135 QDF_STATUS status;
Wu Gao84d120c2017-03-24 18:46:00 +080016136
Dustin Brown491d54b2018-03-14 12:39:11 -070016137 hdd_enter();
Sourav Mohapatraa0943922018-11-21 21:26:29 +053016138 if (adapter->device_mode == QDF_FTM_MODE) {
16139 hdd_info("No need to register frames in FTM mode");
16140 return 0;
16141 }
Wu Gao84d120c2017-03-24 18:46:00 +080016142
16143 /* Register frame indication call back */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016144 status = sme_register_mgmt_frame_ind_callback(mac_handle,
16145 hdd_indicate_mgmt_frame);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016146 if (status != QDF_STATUS_SUCCESS) {
16147 hdd_err("Failed to register hdd_indicate_mgmt_frame");
16148 goto ret_status;
16149 }
Wu Gao84d120c2017-03-24 18:46:00 +080016150
Wu Gao84d120c2017-03-24 18:46:00 +080016151 /* Right now we are registering these frame when driver is getting
16152 * initialized. Once we will move to 2.6.37 kernel, in which we have
16153 * frame register ops, we will move this code as a part of that
16154 */
16155
16156 /* GAS Initial Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016157 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16158 (uint8_t *) GAS_INITIAL_REQ,
16159 GAS_INITIAL_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016160 if (status != QDF_STATUS_SUCCESS) {
16161 hdd_err("Failed to register GAS_INITIAL_REQ");
16162 goto ret_status;
16163 }
Wu Gao84d120c2017-03-24 18:46:00 +080016164
16165 /* GAS Initial Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016166 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16167 (uint8_t *) GAS_INITIAL_RSP,
16168 GAS_INITIAL_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016169 if (status != QDF_STATUS_SUCCESS) {
16170 hdd_err("Failed to register GAS_INITIAL_RSP");
16171 goto dereg_gas_initial_req;
16172 }
Wu Gao84d120c2017-03-24 18:46:00 +080016173
16174 /* GAS Comeback Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016175 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16176 (uint8_t *) GAS_COMEBACK_REQ,
16177 GAS_COMEBACK_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016178 if (status != QDF_STATUS_SUCCESS) {
16179 hdd_err("Failed to register GAS_COMEBACK_REQ");
16180 goto dereg_gas_initial_rsp;
16181 }
Wu Gao84d120c2017-03-24 18:46:00 +080016182
16183 /* GAS Comeback Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016184 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16185 (uint8_t *) GAS_COMEBACK_RSP,
16186 GAS_COMEBACK_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016187 if (status != QDF_STATUS_SUCCESS) {
16188 hdd_err("Failed to register GAS_COMEBACK_RSP");
16189 goto dereg_gas_comeback_req;
16190 }
Wu Gao84d120c2017-03-24 18:46:00 +080016191
16192 /* WNM BSS Transition Request frame */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016193 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16194 (uint8_t *) WNM_BSS_ACTION_FRAME,
16195 WNM_BSS_ACTION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016196 if (status != QDF_STATUS_SUCCESS) {
16197 hdd_err("Failed to register WNM_BSS_ACTION_FRAME");
16198 goto dereg_gas_comeback_rsp;
16199 }
Wu Gao84d120c2017-03-24 18:46:00 +080016200
16201 /* WNM-Notification */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016202 status = sme_register_mgmt_frame(mac_handle, adapter->vdev_id, type,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016203 (uint8_t *) WNM_NOTIFICATION_FRAME,
16204 WNM_NOTIFICATION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016205 if (status != QDF_STATUS_SUCCESS) {
16206 hdd_err("Failed to register WNM_NOTIFICATION_FRAME");
16207 goto dereg_wnm_bss_action_frm;
16208 }
16209
Dustin Brown237baee2018-05-10 13:22:18 -070016210 return 0;
16211
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016212dereg_wnm_bss_action_frm:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016213 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16214 (uint8_t *) WNM_BSS_ACTION_FRAME,
16215 WNM_BSS_ACTION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016216dereg_gas_comeback_rsp:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016217 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16218 (uint8_t *) GAS_COMEBACK_RSP,
16219 GAS_COMEBACK_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016220dereg_gas_comeback_req:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016221 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16222 (uint8_t *) GAS_COMEBACK_REQ,
16223 GAS_COMEBACK_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016224dereg_gas_initial_rsp:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016225 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16226 (uint8_t *) GAS_INITIAL_RSP,
16227 GAS_INITIAL_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016228dereg_gas_initial_req:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016229 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16230 (uint8_t *) GAS_INITIAL_REQ,
16231 GAS_INITIAL_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016232ret_status:
16233 return qdf_status_to_os_return(status);
Wu Gao84d120c2017-03-24 18:46:00 +080016234}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016235
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016236void wlan_hdd_cfg80211_deregister_frames(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016237{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016238 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
16239 /* Deregister for all P2P action, public action etc frames */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016240 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
16241
Dustin Brown491d54b2018-03-14 12:39:11 -070016242 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016243
16244 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016245 * initialized. Once we will move to 2.6.37 kernel, in which we have
16246 * frame register ops, we will move this code as a part of that
16247 */
16248
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016249 /* GAS Initial Request */
16250
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016251 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016252 (uint8_t *) GAS_INITIAL_REQ,
16253 GAS_INITIAL_REQ_SIZE);
16254
16255 /* GAS Initial Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016256 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016257 (uint8_t *) GAS_INITIAL_RSP,
16258 GAS_INITIAL_RSP_SIZE);
16259
16260 /* GAS Comeback Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016261 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016262 (uint8_t *) GAS_COMEBACK_REQ,
16263 GAS_COMEBACK_REQ_SIZE);
16264
16265 /* GAS Comeback Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016266 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016267 (uint8_t *) GAS_COMEBACK_RSP,
16268 GAS_COMEBACK_RSP_SIZE);
16269
16270 /* P2P Public Action */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016271 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016272 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
16273 P2P_PUBLIC_ACTION_FRAME_SIZE);
16274
16275 /* P2P Action */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016276 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016277 (uint8_t *) P2P_ACTION_FRAME,
16278 P2P_ACTION_FRAME_SIZE);
16279
16280 /* WNM-Notification */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016281 sme_deregister_mgmt_frame(mac_handle, adapter->vdev_id, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016282 (uint8_t *) WNM_NOTIFICATION_FRAME,
16283 WNM_NOTIFICATION_FRAME_SIZE);
16284}
16285
Krunal Soni364e0872017-05-10 21:24:34 -070016286bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
16287{
Naveen Rawat08db88f2017-09-08 15:07:48 -070016288 const uint8_t *vendor_ie;
Krunal Soni364e0872017-05-10 21:24:34 -070016289
16290 if (length < 2) {
16291 hdd_debug("bss size is less than expected");
16292 return true;
16293 }
16294 if (!ies) {
16295 hdd_debug("invalid IE pointer");
16296 return true;
16297 }
Naveen Rawat08db88f2017-09-08 15:07:48 -070016298 vendor_ie = wlan_get_vendor_ie_ptr_from_oui(VENDOR1_AP_OUI_TYPE,
Krunal Soni364e0872017-05-10 21:24:34 -070016299 VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
16300 if (vendor_ie) {
16301 hdd_debug("AP can't support immediate powersave. defer it");
16302 return false;
16303 }
16304 return true;
16305}
16306
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016307/*
16308 * FUNCTION: wlan_hdd_validate_operation_channel
16309 * called by wlan_hdd_cfg80211_start_bss() and
16310 * wlan_hdd_set_channel()
16311 * This function validates whether given channel is part of valid
16312 * channel list.
16313 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016314QDF_STATUS wlan_hdd_validate_operation_channel(struct hdd_adapter *adapter,
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016315 uint32_t ch_freq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016316{
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016317 bool value = 0;
16318 uint32_t i;
16319 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16320 struct regulatory_channel *cur_chan_list;
16321 QDF_STATUS status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016322
Dustin Brown05d81302018-09-11 16:49:22 -070016323 status = ucfg_mlme_get_sap_allow_all_channels(hdd_ctx->psoc, &value);
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053016324 if (status != QDF_STATUS_SUCCESS)
16325 hdd_err("Unable to fetch sap allow all channels");
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016326
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053016327 if (value) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016328 /* Validate the channel */
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016329 for (i = CHAN_ENUM_2412; i < NUM_CHANNELS; i++) {
16330 if (ch_freq == WLAN_REG_CH_TO_FREQ(i)) {
16331 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016332 break;
16333 }
16334 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016335 } else {
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016336 cur_chan_list = qdf_mem_malloc(NUM_CHANNELS *
16337 sizeof(struct regulatory_channel));
16338 if (!cur_chan_list)
16339 return QDF_STATUS_E_NOMEM;
16340
16341 if (wlan_reg_get_current_chan_list(
16342 hdd_ctx->pdev, cur_chan_list) != QDF_STATUS_SUCCESS) {
16343 qdf_mem_free(cur_chan_list);
16344 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016345 }
16346
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016347 for (i = 0; i < NUM_CHANNELS; i++) {
16348 if (ch_freq != cur_chan_list[i].center_freq)
16349 continue;
16350 if (cur_chan_list[i].state != CHANNEL_STATE_DISABLE &&
16351 cur_chan_list[i].state != CHANNEL_STATE_INVALID)
16352 status = QDF_STATUS_SUCCESS;
16353 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016354 }
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016355 qdf_mem_free(cur_chan_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016356 }
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016357
16358 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016359
16360}
16361
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016362static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
16363 struct net_device *dev,
16364 struct bss_parameters *params)
16365{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016366 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16367 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016368 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053016369 QDF_STATUS qdf_ret_status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016370 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016371
Dustin Brown491d54b2018-03-14 12:39:11 -070016372 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016373
Anurag Chouhan6d760662016-02-20 16:05:43 +053016374 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070016375 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016376 return -EINVAL;
16377 }
16378
Jeff Johnson48363022019-02-24 16:26:51 -080016379 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016380 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016381
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016382 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
16383 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016384 adapter->vdev_id, params->ap_isolate);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016385
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016386 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Dustin Brown458027c2018-10-19 12:26:27 -070016387 qdf_opmode_str(adapter->device_mode),
16388 adapter->device_mode, params->ap_isolate);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016389
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016390 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016391 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016392 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016393 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016394
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016395 if (!(adapter->device_mode == QDF_SAP_MODE ||
16396 adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016397 return -EOPNOTSUPP;
16398 }
16399
16400 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016401 * want to update this parameter
16402 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016403 if (-1 != params->ap_isolate) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070016404 adapter->session.ap.disable_intrabss_fwd =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016405 !!params->ap_isolate;
16406
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016407 mac_handle = hdd_ctx->mac_handle;
16408 qdf_ret_status = sme_ap_disable_intra_bss_fwd(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016409 adapter->vdev_id,
Jeff Johnsonb9424862017-10-30 08:49:35 -070016410 adapter->session.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016411 ap.
Jeff Johnson82ceb082017-10-27 14:52:42 -070016412 disable_intrabss_fwd);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070016413 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016414 ret = -EINVAL;
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +053016415
Dustin Brown07901ec2018-09-07 11:02:41 -070016416 ucfg_ipa_set_ap_ibss_fwd(hdd_ctx->pdev,
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +053016417 adapter->session.ap.
16418 disable_intrabss_fwd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016419 }
16420
Dustin Browne74003f2018-03-14 12:51:58 -070016421 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016422 return ret;
16423}
16424
Krunal Soni8c37e322016-02-03 16:08:37 -080016425/**
Dustin Brown56377e12018-10-10 17:04:04 -070016426 * hdd_change_adapter_mode() - change @adapter's operating mode to @new_mode
16427 * @adapter: the adapter to change modes on
16428 * @new_mode: the new operating mode to change to
Krunal Soni8c37e322016-02-03 16:08:37 -080016429 *
Dustin Brown56377e12018-10-10 17:04:04 -070016430 * Return: Errno
Krunal Soni8c37e322016-02-03 16:08:37 -080016431 */
Dustin Brown56377e12018-10-10 17:04:04 -070016432static int hdd_change_adapter_mode(struct hdd_adapter *adapter,
16433 enum QDF_OPMODE new_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016434{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070016435 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown56377e12018-10-10 17:04:04 -070016436 struct net_device *netdev = adapter->dev;
Krunal Soni8c37e322016-02-03 16:08:37 -080016437 struct hdd_config *config = hdd_ctx->config;
Jeff Johnson20227a92018-03-13 09:41:05 -070016438 struct csr_roam_profile *roam_profile;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053016439 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016440
Dustin Brown491d54b2018-03-14 12:39:11 -070016441 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016442
Dustin Browndb2a8be2017-12-20 11:49:56 -080016443 hdd_stop_adapter(hdd_ctx, adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080016444 hdd_deinit_adapter(hdd_ctx, adapter, true);
Dustin Brown194aeca2018-10-12 15:37:36 -070016445 adapter->device_mode = new_mode;
Jeff Johnsonb9424862017-10-30 08:49:35 -070016446 memset(&adapter->session, 0, sizeof(adapter->session));
Dustin Brown56377e12018-10-10 17:04:04 -070016447 hdd_set_station_ops(netdev);
Jeff Johnson20227a92018-03-13 09:41:05 -070016448
16449 roam_profile = hdd_roam_profile(adapter);
16450 roam_profile->pAddIEScan = adapter->scan_info.scan_add_ie.addIEdata;
Dustin Brown56377e12018-10-10 17:04:04 -070016451 roam_profile->nAddIEScanLength = adapter->scan_info.scan_add_ie.length;
16452
16453 if (new_mode == QDF_IBSS_MODE) {
Krunal Sonib51eec72017-11-20 21:53:01 -080016454 status = hdd_start_station_adapter(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016455 roam_profile->BSSType = eCSR_BSS_TYPE_START_IBSS;
16456 roam_profile->phyMode =
Krunal Soni8c37e322016-02-03 16:08:37 -080016457 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
16458 }
Dustin Brown56377e12018-10-10 17:04:04 -070016459
Dustin Browne74003f2018-03-14 12:51:58 -070016460 hdd_exit();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070016461
16462 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016463}
16464
16465static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
16466 struct net_device *dev,
16467 struct bss_parameters *params)
16468{
Dustin Brown1d31b082018-11-22 14:41:20 +053016469 int errno;
16470 struct osif_vdev_sync *vdev_sync;
16471
16472 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
16473 if (errno)
16474 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016475
Dustin Brown1d31b082018-11-22 14:41:20 +053016476 errno = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016477
Dustin Brown1d31b082018-11-22 14:41:20 +053016478 osif_vdev_sync_op_stop(vdev_sync);
16479
16480 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016481}
16482
Dustin Brown63fe4922018-10-12 15:02:26 -070016483static bool hdd_is_client_mode(enum QDF_OPMODE mode)
16484{
16485 switch (mode) {
16486 case QDF_STA_MODE:
16487 case QDF_P2P_CLIENT_MODE:
16488 case QDF_P2P_DEVICE_MODE:
16489 case QDF_IBSS_MODE:
16490 return true;
16491 default:
16492 return false;
16493 }
16494}
16495
16496static bool hdd_is_ap_mode(enum QDF_OPMODE mode)
16497{
16498 switch (mode) {
16499 case QDF_SAP_MODE:
16500 case QDF_P2P_GO_MODE:
16501 return true;
16502 default:
16503 return false;
16504 }
16505}
16506
16507/**
Rajeev Kumar98edb772016-01-19 12:42:19 -080016508 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
16509 * @wiphy: Pointer to the wiphy structure
16510 * @ndev: Pointer to the net device
16511 * @type: Interface type
16512 * @flags: Flags for change interface
16513 * @params: Pointer to change interface parameters
16514 *
16515 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016516 */
16517static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16518 struct net_device *ndev,
16519 enum nl80211_iftype type,
16520 u32 *flags,
16521 struct vif_params *params)
16522{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016523 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016524 struct hdd_context *hdd_ctx;
Dustin Brown56377e12018-10-10 17:04:04 -070016525 bool iff_up = ndev->flags & IFF_UP;
16526 enum QDF_OPMODE new_mode;
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053016527 bool ap_random_bssid_enabled;
Dustin Brown56377e12018-10-10 17:04:04 -070016528 QDF_STATUS status;
Dustin Brown63fe4922018-10-12 15:02:26 -070016529 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016530
Dustin Brown491d54b2018-03-14 12:39:11 -070016531 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016532
Dustin Brown63fe4922018-10-12 15:02:26 -070016533 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
Jeff Johnson77848112016-06-29 14:52:06 -070016534 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016535 return -EINVAL;
16536 }
16537
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016538 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown2ab5a972018-10-09 17:19:37 -070016539 errno = wlan_hdd_validate_context(hdd_ctx);
16540 if (errno)
16541 return errno;
Nachiket Kukade08b9f292017-11-17 18:27:37 +053016542
Alok Kumar57305242019-07-23 12:27:18 +053016543 if (wlan_hdd_check_mon_concurrency())
16544 return -EINVAL;
16545
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016546 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
16547 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016548 adapter->vdev_id, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016549
Dustin Brown56377e12018-10-10 17:04:04 -070016550 status = hdd_nl_to_qdf_iface_type(type, &new_mode);
16551 if (QDF_IS_STATUS_ERROR(status))
16552 return qdf_status_to_os_return(status);
16553
Dustin Brown194aeca2018-10-12 15:37:36 -070016554 /* A userspace issue leads to it sending a 'change to station mode'
16555 * request on a "p2p" device, expecting the driver do execute a 'change
16556 * to p2p-device mode' request instead. The (unfortunate) work around
16557 * here is implemented by overriding the new mode if the net_device name
16558 * starts with "p2p" and the requested mode was station.
16559 */
16560 if (strnstr(ndev->name, "p2p", 3) && new_mode == QDF_STA_MODE)
16561 new_mode = QDF_P2P_DEVICE_MODE;
16562
Dustin Brown56377e12018-10-10 17:04:04 -070016563 hdd_debug("Changing mode for '%s' from %s to %s",
16564 ndev->name,
16565 qdf_opmode_str(adapter->device_mode),
16566 qdf_opmode_str(new_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016567
Rajeev Kumar473f9af2019-04-05 14:25:56 -070016568 errno = hdd_trigger_psoc_idle_restart(hdd_ctx);
Dustin Brown2ab5a972018-10-09 17:19:37 -070016569 if (errno) {
Dustin Brown3ecc8782018-09-19 16:37:13 -070016570 hdd_err("Failed to restart psoc; errno:%d", errno);
Arun Khandavallifae92942016-08-01 13:31:08 +053016571 return -EINVAL;
16572 }
16573
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016574 /* Reset the current device mode bit mask */
Dustin Brown2ab5a972018-10-09 17:19:37 -070016575 policy_mgr_clear_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016576
Dustin Brown63fe4922018-10-12 15:02:26 -070016577 if (hdd_is_client_mode(adapter->device_mode)) {
16578 if (hdd_is_client_mode(new_mode)) {
Visweswara Tanukub5a61242019-03-26 12:24:13 +053016579 if (new_mode == QDF_IBSS_MODE) {
16580 hdd_deregister_hl_netdev_fc_timer(adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016581 hdd_deregister_tx_flow_control(adapter);
Visweswara Tanukub5a61242019-03-26 12:24:13 +053016582 }
Dustin Brown56377e12018-10-10 17:04:04 -070016583
16584 errno = hdd_change_adapter_mode(adapter, new_mode);
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016585 if (errno) {
16586 hdd_err("change intf mode fail %d", errno);
16587 goto err;
16588 }
Dustin Brown63fe4922018-10-12 15:02:26 -070016589 } else if (hdd_is_ap_mode(new_mode)) {
16590 if (new_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016591 wlan_hdd_cancel_existing_remain_on_channel
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016592 (adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016593
Dustin Browndb2a8be2017-12-20 11:49:56 -080016594 hdd_stop_adapter(hdd_ctx, adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016595 hdd_deinit_adapter(hdd_ctx, adapter, true);
Dustin Brown2ab5a972018-10-09 17:19:37 -070016596 memset(&adapter->session, 0, sizeof(adapter->session));
Dustin Brown56377e12018-10-10 17:04:04 -070016597 adapter->device_mode = new_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016598
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053016599 status = ucfg_mlme_get_ap_random_bssid_enable(
16600 hdd_ctx->psoc,
16601 &ap_random_bssid_enabled);
16602 if (QDF_IS_STATUS_ERROR(status))
16603 return qdf_status_to_os_return(status);
16604
Dustin Brown2ab5a972018-10-09 17:19:37 -070016605 if (adapter->device_mode == QDF_SAP_MODE &&
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053016606 ap_random_bssid_enabled) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016607 /* To meet Android requirements create
16608 * a randomized MAC address of the
16609 * form 02:1A:11:Fx:xx:xx
16610 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016611 get_random_bytes(&ndev->dev_addr[3], 3);
16612 ndev->dev_addr[0] = 0x02;
16613 ndev->dev_addr[1] = 0x1A;
16614 ndev->dev_addr[2] = 0x11;
16615 ndev->dev_addr[3] |= 0xF0;
Dustin Brown2ab5a972018-10-09 17:19:37 -070016616 memcpy(adapter->mac_addr.bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053016617 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016618 pr_info("wlan: Generated HotSpot BSSID "
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070016619 QDF_MAC_ADDR_STR "\n",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070016620 QDF_MAC_ADDR_ARRAY(ndev->dev_addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016621 }
16622
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016623 hdd_set_ap_ops(adapter->dev);
Dustin Brown63fe4922018-10-12 15:02:26 -070016624 } else {
Dustin Brown56377e12018-10-10 17:04:04 -070016625 hdd_err("Changing to device mode '%s' is not supported",
16626 qdf_opmode_str(new_mode));
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016627 errno = -EOPNOTSUPP;
16628 goto err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016629 }
Dustin Brown63fe4922018-10-12 15:02:26 -070016630 } else if (hdd_is_ap_mode(adapter->device_mode)) {
16631 if (hdd_is_client_mode(new_mode)) {
Dustin Brown56377e12018-10-10 17:04:04 -070016632 errno = hdd_change_adapter_mode(adapter, new_mode);
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016633 if (errno) {
16634 hdd_err("change mode fail %d", errno);
16635 goto err;
16636 }
Dustin Brown63fe4922018-10-12 15:02:26 -070016637 } else if (hdd_is_ap_mode(new_mode)) {
Dustin Brown56377e12018-10-10 17:04:04 -070016638 adapter->device_mode = new_mode;
16639
Dustin Brown63fe4922018-10-12 15:02:26 -070016640 /* avoid starting the adapter, since it never stopped */
16641 iff_up = false;
16642 } else {
Dustin Brown56377e12018-10-10 17:04:04 -070016643 hdd_err("Changing to device mode '%s' is not supported",
16644 qdf_opmode_str(new_mode));
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016645 errno = -EOPNOTSUPP;
16646 goto err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016647 }
16648 } else {
Dustin Brown56377e12018-10-10 17:04:04 -070016649 hdd_err("Changing from device mode '%s' is not supported",
16650 qdf_opmode_str(adapter->device_mode));
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016651 errno = -EOPNOTSUPP;
16652 goto err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016653 }
Dustin Brown56377e12018-10-10 17:04:04 -070016654
Dustin Brown63fe4922018-10-12 15:02:26 -070016655 /* restart the adapter if it was up before the change iface request */
16656 if (iff_up) {
16657 errno = hdd_start_adapter(adapter);
16658 if (errno) {
16659 hdd_err("Failed to start adapter");
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016660 errno = -EINVAL;
16661 goto err;
Dustin Brown63fe4922018-10-12 15:02:26 -070016662 }
16663 }
16664
16665 ndev->ieee80211_ptr->iftype = type;
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016666 hdd_lpass_notify_mode_change(adapter);
16667err:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016668 /* Set bitmask based on updated value */
Dustin Brown2ab5a972018-10-09 17:19:37 -070016669 policy_mgr_set_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016670
Dustin Browne74003f2018-03-14 12:51:58 -070016671 hdd_exit();
Dustin Brown2ab5a972018-10-09 17:19:37 -070016672
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016673 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016674}
16675
Dustin Brown0e1e1622019-01-17 11:00:22 -080016676static int _wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16677 struct net_device *net_dev,
16678 enum nl80211_iftype type,
16679 u32 *flags,
16680 struct vif_params *params)
16681{
16682 int errno;
16683 struct osif_vdev_sync *vdev_sync;
16684
16685 errno = osif_vdev_sync_trans_start(net_dev, &vdev_sync);
16686 if (errno)
16687 return errno;
16688
Dustin Brown0e1e1622019-01-17 11:00:22 -080016689 errno = __wlan_hdd_cfg80211_change_iface(wiphy, net_dev, type,
16690 flags, params);
Dustin Brown0e1e1622019-01-17 11:00:22 -080016691
16692 osif_vdev_sync_trans_stop(vdev_sync);
16693
16694 return errno;
16695}
16696
Dustin Brown9ed30a52017-08-16 13:59:38 -070016697#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
Rajeev Kumar98edb772016-01-19 12:42:19 -080016698/**
16699 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
16700 * @wiphy: Pointer to the wiphy structure
16701 * @ndev: Pointer to the net device
16702 * @type: Interface type
16703 * @flags: Flags for change interface
16704 * @params: Pointer to change interface parameters
16705 *
16706 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016707 */
16708static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16709 struct net_device *ndev,
16710 enum nl80211_iftype type,
16711 u32 *flags,
16712 struct vif_params *params)
16713{
Dustin Brown0e1e1622019-01-17 11:00:22 -080016714 return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
16715 flags, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016716}
Dustin Brown9ed30a52017-08-16 13:59:38 -070016717#else
16718static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16719 struct net_device *ndev,
16720 enum nl80211_iftype type,
16721 struct vif_params *params)
16722{
Dustin Brown0e1e1622019-01-17 11:00:22 -080016723 return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
Dustin Brown9ed30a52017-08-16 13:59:38 -070016724 &params->flags, params);
Dustin Brown9ed30a52017-08-16 13:59:38 -070016725}
16726#endif /* KERNEL_VERSION(4, 12, 0) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016727
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053016728QDF_STATUS wlan_hdd_send_sta_authorized_event(
16729 struct hdd_adapter *adapter,
16730 struct hdd_context *hdd_ctx,
16731 const struct qdf_mac_addr *mac_addr)
16732{
16733 struct sk_buff *vendor_event;
16734 QDF_STATUS status;
16735 struct nl80211_sta_flag_update sta_flags;
16736
16737 hdd_enter();
16738 if (!hdd_ctx) {
16739 hdd_err("HDD context is null");
16740 return QDF_STATUS_E_INVAL;
16741 }
16742
16743 vendor_event =
16744 cfg80211_vendor_event_alloc(
16745 hdd_ctx->wiphy, &adapter->wdev, sizeof(sta_flags) +
16746 QDF_MAC_ADDR_SIZE + NLMSG_HDRLEN,
16747 QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX,
16748 GFP_KERNEL);
16749 if (!vendor_event) {
16750 hdd_err("cfg80211_vendor_event_alloc failed");
16751 return QDF_STATUS_E_FAILURE;
16752 }
16753
Ashish Kumar Dhanotiya0dd9b8b2019-06-04 20:21:06 +053016754 qdf_mem_zero(&sta_flags, sizeof(sta_flags));
16755
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053016756 sta_flags.mask |= BIT(NL80211_STA_FLAG_AUTHORIZED);
16757 sta_flags.set = true;
16758
16759 status = nla_put(vendor_event,
16760 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS,
16761 sizeof(struct nl80211_sta_flag_update),
16762 &sta_flags);
16763 if (status) {
16764 hdd_err("STA flag put fails");
16765 kfree_skb(vendor_event);
16766 return QDF_STATUS_E_FAILURE;
16767 }
16768 status = nla_put(vendor_event,
16769 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR,
16770 QDF_MAC_ADDR_SIZE, mac_addr->bytes);
16771 if (status) {
16772 hdd_err("STA MAC put fails");
16773 kfree_skb(vendor_event);
16774 return QDF_STATUS_E_FAILURE;
16775 }
16776
16777 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
16778
16779 hdd_exit();
16780 return QDF_STATUS_SUCCESS;
16781}
16782
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016783/**
16784 * __wlan_hdd_change_station() - change station
16785 * @wiphy: Pointer to the wiphy structure
16786 * @dev: Pointer to the net device.
16787 * @mac: bssid
16788 * @params: Pointer to station parameters
16789 *
16790 * Return: 0 for success, error number on failure.
16791 */
16792#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
16793static int __wlan_hdd_change_station(struct wiphy *wiphy,
16794 struct net_device *dev,
16795 const uint8_t *mac,
16796 struct station_parameters *params)
16797#else
16798static int __wlan_hdd_change_station(struct wiphy *wiphy,
16799 struct net_device *dev,
16800 uint8_t *mac,
16801 struct station_parameters *params)
16802#endif
16803{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016804 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016805 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016806 struct hdd_context *hdd_ctx;
Jeff Johnsond377dce2017-10-04 10:32:42 -070016807 struct hdd_station_ctx *sta_ctx;
Vignesh Viswanathan597d9012018-07-06 15:26:08 +053016808 struct hdd_ap_ctx *ap_ctx;
Jeff Johnsonf31df632019-03-23 11:53:28 -070016809 struct qdf_mac_addr sta_macaddr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016810 int ret;
16811
Dustin Brown491d54b2018-03-14 12:39:11 -070016812 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016813
Anurag Chouhan6d760662016-02-20 16:05:43 +053016814 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016815 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016816 return -EINVAL;
16817 }
16818
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016819 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
16820 TRACE_CODE_HDD_CHANGE_STATION,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016821 adapter->vdev_id, params->listen_interval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016822
Jeff Johnson48363022019-02-24 16:26:51 -080016823 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016824 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016825
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016826 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016827 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016828 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016829 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016830
Jeff Johnsond377dce2017-10-04 10:32:42 -070016831 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016832
Jeff Johnsonf31df632019-03-23 11:53:28 -070016833 qdf_mem_copy(sta_macaddr.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016834
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016835 if ((adapter->device_mode == QDF_SAP_MODE) ||
16836 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016837 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
Vignesh Viswanathan597d9012018-07-06 15:26:08 +053016838 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
16839 /*
16840 * For Encrypted SAP session, this will be done as
16841 * part of eSAP_STA_SET_KEY_EVENT
16842 */
16843 if (ap_ctx->encryption_type !=
16844 eCSR_ENCRYPT_TYPE_NONE) {
16845 hdd_debug("Encrypt type %d, not setting peer authorized now",
16846 ap_ctx->encryption_type);
16847 return 0;
16848 }
16849
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016850 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016851 hdd_softap_change_sta_state(adapter,
Jeff Johnsonf31df632019-03-23 11:53:28 -070016852 &sta_macaddr,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080016853 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016854
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016855 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016856 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016857 return -EINVAL;
16858 }
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053016859 status = wlan_hdd_send_sta_authorized_event(
16860 adapter,
16861 hdd_ctx,
Jeff Johnsonf31df632019-03-23 11:53:28 -070016862 &sta_macaddr);
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053016863 if (status != QDF_STATUS_SUCCESS) {
16864 return -EINVAL;
16865 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016866 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016867 } else if ((adapter->device_mode == QDF_STA_MODE) ||
16868 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016869 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud1a28462017-09-06 22:55:48 +080016870#if defined(FEATURE_WLAN_TDLS)
Min Liu8c5d99e2018-09-10 17:18:44 +080016871 struct wlan_objmgr_vdev *vdev;
16872
16873 vdev = hdd_objmgr_get_vdev(adapter);
16874 if (!vdev)
16875 return -EINVAL;
16876 ret = wlan_cfg80211_tdls_update_peer(vdev, mac, params);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053016877 hdd_objmgr_put_vdev(vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016878#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080016879 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016880 }
Dustin Browne74003f2018-03-14 12:51:58 -070016881 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016882 return ret;
16883}
16884
16885/**
16886 * wlan_hdd_change_station() - cfg80211 change station handler function
16887 * @wiphy: Pointer to the wiphy structure
16888 * @dev: Pointer to the net device.
16889 * @mac: bssid
16890 * @params: Pointer to station parameters
16891 *
16892 * This is the cfg80211 change station handler function which invokes
16893 * the internal function @__wlan_hdd_change_station with
16894 * SSR protection.
16895 *
16896 * Return: 0 for success, error number on failure.
16897 */
16898#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
16899static int wlan_hdd_change_station(struct wiphy *wiphy,
16900 struct net_device *dev,
16901 const u8 *mac,
16902 struct station_parameters *params)
16903#else
16904static int wlan_hdd_change_station(struct wiphy *wiphy,
16905 struct net_device *dev,
16906 u8 *mac,
16907 struct station_parameters *params)
16908#endif
16909{
Dustin Brown1d31b082018-11-22 14:41:20 +053016910 int errno;
16911 struct osif_vdev_sync *vdev_sync;
16912
16913 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
16914 if (errno)
16915 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016916
Dustin Brown1d31b082018-11-22 14:41:20 +053016917 errno = __wlan_hdd_change_station(wiphy, dev, mac, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016918
Dustin Brown1d31b082018-11-22 14:41:20 +053016919 osif_vdev_sync_op_stop(vdev_sync);
16920
16921 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016922}
16923
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016924#ifdef FEATURE_WLAN_ESE
16925static bool hdd_is_krk_enc_type(uint32_t cipher_type)
16926{
16927 if (cipher_type == WLAN_CIPHER_SUITE_KRK)
16928 return true;
16929
16930 return false;
16931}
16932#else
16933static bool hdd_is_krk_enc_type(uint32_t cipher_type)
16934{
16935 return false;
16936}
16937#endif
16938
16939#if defined(FEATURE_WLAN_ESE) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
16940static bool hdd_is_btk_enc_type(uint32_t cipher_type)
16941{
16942 if (cipher_type == WLAN_CIPHER_SUITE_BTK)
16943 return true;
16944
16945 return false;
16946}
16947#else
16948static bool hdd_is_btk_enc_type(uint32_t cipher_type)
16949{
16950 return false;
16951}
16952#endif
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016953
Abhishek Ambure68677462019-09-13 12:44:26 +053016954#ifdef QCA_IBSS_SUPPORT
16955/**
16956 * wlan_hdd_add_key_ibss() - API to add IBSS key
16957 * @adapter: Pointer to adapter
16958 * @pairwise: need to add key pairwise
16959 * @key_index: key index
16960 * @mac_addr: Pointer to mac_addr
16961 * @params: Pointer to key params
16962 * @key_already_installed: pointer to key already installed state
16963 *
16964 * This API will add IBSS key for given mac address.
16965 *
16966 * Return: 0 for success, error number on failure.
16967 */
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016968static int wlan_hdd_add_key_ibss(struct hdd_adapter *adapter,
16969 bool pairwise, u8 key_index,
16970 const u8 *mac_addr, struct key_params *params,
16971 bool *key_already_installed)
16972{
16973 struct wlan_objmgr_vdev *vdev;
16974 int errno;
16975
16976 if (pairwise)
16977 return 0;
16978 /* if a key is already installed, block all subsequent ones */
16979 if (adapter->session.station.ibss_enc_key_installed) {
16980 hdd_debug("IBSS key installed already");
16981 *key_already_installed = true;
16982 return 0;
16983 }
16984 /*Set the group key */
16985 vdev = hdd_objmgr_get_vdev(adapter);
16986 if (!vdev)
16987 return -EINVAL;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016988 errno = wlan_cfg80211_crypto_add_key(vdev, WLAN_CRYPTO_KEY_TYPE_GROUP,
16989 key_index);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016990 if (errno) {
16991 hdd_err("add_ibss_key failed, errno: %d", errno);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053016992 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016993 return errno;
16994 }
16995 /* Save the keys here and call set_key for setting
16996 * the PTK after peer joins the IBSS network
16997 */
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016998 wlan_cfg80211_store_key(vdev, key_index, WLAN_CRYPTO_KEY_TYPE_UNICAST,
16999 mac_addr, params);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053017000 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017001 adapter->session.station.ibss_enc_key_installed = 1;
17002
17003 return 0;
17004}
Abhishek Ambure68677462019-09-13 12:44:26 +053017005#else
17006/**
17007 * wlan_hdd_add_key_ibss() - API to add IBSS key
17008 * @adapter: Pointer to adapter
17009 * @pairwise: need to add key pairwise
17010 * @key_index: key index
17011 * @mac_addr: Pointer to mac_addr
17012 * @params: Pointer to key params
17013 * @key_already_installed: pointer to key already installed state
17014 *
17015 * This function is dummy
17016 *
17017 * Return: 0
17018 */
17019static inline int
17020wlan_hdd_add_key_ibss(struct hdd_adapter *adapter,
17021 bool pairwise, u8 key_index,
17022 const u8 *mac_addr, struct key_params *params,
17023 bool *key_already_installed)
17024{
17025 return 0;
17026}
17027#endif
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017028
17029static int wlan_hdd_add_key_sap(struct hdd_adapter *adapter,
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017030 bool pairwise, u8 key_index,
17031 enum wlan_crypto_cipher_type cipher)
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017032{
17033 struct wlan_objmgr_vdev *vdev;
17034 int errno = 0;
17035 struct hdd_hostapd_state *hostapd_state =
17036 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
17037
17038 vdev = hdd_objmgr_get_vdev(adapter);
17039 if (!vdev)
17040 return -EINVAL;
sheenam mongaf1655e12020-05-21 18:33:30 +053017041
17042 /* Do not send install key when sap restart is in progress. If there is
17043 * critical channel request handling going on, fw will stop that request
17044 * and will not send restart resposne
17045 */
17046 if (wlan_vdev_is_restart_progress(vdev) == QDF_STATUS_SUCCESS) {
17047 hdd_err("vdev: %d restart in progress", wlan_vdev_get_id(vdev));
17048 hdd_objmgr_put_vdev(vdev);
17049 return -EINVAL;
17050 }
17051
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017052 if (hostapd_state->bss_state == BSS_START) {
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080017053 errno =
17054 wlan_cfg80211_crypto_add_key(vdev, (pairwise ?
17055 WLAN_CRYPTO_KEY_TYPE_UNICAST :
17056 WLAN_CRYPTO_KEY_TYPE_GROUP),
17057 key_index);
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017058 if (!errno)
17059 wma_update_set_key(adapter->vdev_id, pairwise,
17060 key_index, cipher);
17061 }
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053017062 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017063
17064 return errno;
17065}
17066
17067static int wlan_hdd_add_key_sta(struct hdd_adapter *adapter,
17068 bool pairwise, u8 key_index,
17069 mac_handle_t mac_handle, bool *ft_mode)
17070{
17071 struct wlan_objmgr_vdev *vdev;
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017072 int errno;
17073 QDF_STATUS status;
17074
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017075 /* The supplicant may attempt to set the PTK once
17076 * pre-authentication is done. Save the key in the
17077 * UMAC and include it in the ADD BSS request
17078 */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017079 status = sme_check_ft_status(mac_handle, adapter->vdev_id);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017080 if (status == QDF_STATUS_SUCCESS) {
17081 *ft_mode = true;
17082 return 0;
17083 }
17084 vdev = hdd_objmgr_get_vdev(adapter);
17085 if (!vdev)
17086 return -EINVAL;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080017087 errno = wlan_cfg80211_crypto_add_key(vdev, (pairwise ?
17088 WLAN_CRYPTO_KEY_TYPE_UNICAST :
17089 WLAN_CRYPTO_KEY_TYPE_GROUP),
17090 key_index);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053017091 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017092 if (!errno && adapter->send_mode_change) {
17093 wlan_hdd_send_mode_change_event();
17094 adapter->send_mode_change = false;
17095 }
17096
17097 return errno;
17098}
17099
17100static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
17101 struct net_device *ndev,
17102 u8 key_index, bool pairwise,
17103 const u8 *mac_addr,
17104 struct key_params *params)
17105{
17106 struct hdd_context *hdd_ctx;
17107 mac_handle_t mac_handle;
17108 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
17109 struct wlan_objmgr_vdev *vdev;
17110 bool key_already_installed = false, ft_mode = false;
17111 enum wlan_crypto_cipher_type cipher;
17112 int errno;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080017113 struct qdf_mac_addr mac_address;
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017114
17115 hdd_enter();
17116
17117 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17118 hdd_err("Command not allowed in FTM mode");
17119 return -EINVAL;
17120 }
17121
Jeff Johnson48363022019-02-24 16:26:51 -080017122 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017123 return -EINVAL;
17124
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053017125 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
17126 TRACE_CODE_HDD_CFG80211_ADD_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017127 adapter->vdev_id, params->key_len);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053017128
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017129 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17130 errno = wlan_hdd_validate_context(hdd_ctx);
17131 if (errno)
17132 return errno;
17133
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017134 hdd_debug("converged Device_mode %s(%d) index %d, pairwise %d",
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017135 qdf_opmode_str(adapter->device_mode),
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017136 adapter->device_mode, key_index, pairwise);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017137 mac_handle = hdd_ctx->mac_handle;
17138
17139 if (hdd_is_btk_enc_type(params->cipher))
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017140 return sme_add_key_btk(mac_handle, adapter->vdev_id,
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017141 params->key, params->key_len);
17142 if (hdd_is_krk_enc_type(params->cipher))
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017143 return sme_add_key_krk(mac_handle, adapter->vdev_id,
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017144 params->key, params->key_len);
17145
17146 vdev = hdd_objmgr_get_vdev(adapter);
17147 if (!vdev)
17148 return -EINVAL;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080017149 if (!pairwise && ((adapter->device_mode == QDF_STA_MODE) ||
17150 (adapter->device_mode == QDF_P2P_CLIENT_MODE))) {
17151 qdf_mem_copy(mac_address.bytes,
Jeff Johnsone04b6992019-02-27 14:06:55 -080017152 adapter->session.station.conn_info.bssid.bytes,
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080017153 QDF_MAC_ADDR_SIZE);
17154 } else {
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017155 if (mac_addr)
17156 qdf_mem_copy(mac_address.bytes, mac_addr,
17157 QDF_MAC_ADDR_SIZE);
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080017158 }
17159 errno = wlan_cfg80211_store_key(vdev, key_index,
17160 (pairwise ?
17161 WLAN_CRYPTO_KEY_TYPE_UNICAST :
17162 WLAN_CRYPTO_KEY_TYPE_GROUP),
17163 mac_address.bytes, params);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053017164 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017165 if (errno)
17166 return errno;
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017167 cipher = osif_nl_to_crypto_cipher_type(params->cipher);
Abhishek Singhf880a7d2019-04-29 14:51:11 +053017168 if (pairwise)
17169 wma_set_peer_ucast_cipher(mac_address.bytes, cipher);
17170
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017171 switch (adapter->device_mode) {
17172 case QDF_IBSS_MODE:
17173 errno = wlan_hdd_add_key_ibss(adapter, pairwise, key_index,
17174 mac_addr, params,
17175 &key_already_installed);
17176 if (key_already_installed)
17177 return 0;
17178 break;
17179 case QDF_SAP_MODE:
17180 case QDF_P2P_GO_MODE:
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017181 errno = wlan_hdd_add_key_sap(adapter, pairwise,
17182 key_index, cipher);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017183 break;
17184 case QDF_STA_MODE:
17185 case QDF_P2P_CLIENT_MODE:
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017186 errno = wlan_hdd_add_key_sta(adapter, pairwise, key_index,
17187 mac_handle, &ft_mode);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017188 if (ft_mode)
17189 return 0;
17190 break;
17191 default:
17192 break;
17193 }
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017194 if (!errno && (adapter->device_mode != QDF_SAP_MODE))
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017195 wma_update_set_key(adapter->vdev_id, pairwise, key_index,
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017196 cipher);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017197 hdd_exit();
17198
17199 return errno;
17200}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017201
17202static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
17203 struct net_device *ndev,
17204 u8 key_index, bool pairwise,
17205 const u8 *mac_addr,
17206 struct key_params *params)
17207{
Dustin Brown1d31b082018-11-22 14:41:20 +053017208 int errno;
17209 struct osif_vdev_sync *vdev_sync;
17210
17211 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
17212 if (errno)
17213 return errno;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070017214
Dustin Brown1d31b082018-11-22 14:41:20 +053017215 errno = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
17216 mac_addr, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017217
Dustin Brown1d31b082018-11-22 14:41:20 +053017218 osif_vdev_sync_op_stop(vdev_sync);
17219
17220 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017221}
17222
17223/*
17224 * FUNCTION: __wlan_hdd_cfg80211_get_key
17225 * This function is used to get the key information
17226 */
17227static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
17228 struct net_device *ndev,
17229 u8 key_index, bool pairwise,
17230 const u8 *mac_addr, void *cookie,
17231 void (*callback)(void *cookie,
17232 struct key_params *)
17233 )
17234{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017235 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070017236 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017237 struct key_params params;
17238
Dustin Brown491d54b2018-03-14 12:39:11 -070017239 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017240
Anurag Chouhan6d760662016-02-20 16:05:43 +053017241 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017242 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017243 return -EINVAL;
17244 }
17245
Jeff Johnson48363022019-02-24 16:26:51 -080017246 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Jiachao Wud58cfc92017-12-27 14:15:23 +080017247 return -EINVAL;
Jiachao Wud58cfc92017-12-27 14:15:23 +080017248
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017249 hdd_debug("Device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070017250 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017251
17252 memset(&params, 0, sizeof(params));
17253
17254 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017255 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017256 return -EINVAL;
17257 }
17258
Nachiket Kukaded9152832017-10-16 16:18:22 +053017259 if ((adapter->device_mode == QDF_SAP_MODE) ||
17260 (adapter->device_mode == QDF_P2P_GO_MODE)) {
17261 struct hdd_ap_ctx *ap_ctx =
17262 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070017263
Nachiket Kukaded9152832017-10-16 16:18:22 +053017264 roam_profile =
17265 wlan_sap_get_roam_profile(ap_ctx->sap_context);
17266 } else {
Jeff Johnson20227a92018-03-13 09:41:05 -070017267 roam_profile = hdd_roam_profile(adapter);
Nachiket Kukaded9152832017-10-16 16:18:22 +053017268 }
17269
Jeff Johnsond36fa332019-03-18 13:42:25 -070017270 if (!roam_profile) {
Jiachao Wud58cfc92017-12-27 14:15:23 +080017271 hdd_err("Get roam profile failed!");
17272 return -EINVAL;
17273 }
17274
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017275 switch (roam_profile->EncryptionType.encryptionType[0]) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017276 case eCSR_ENCRYPT_TYPE_NONE:
17277 params.cipher = IW_AUTH_CIPHER_NONE;
17278 break;
17279
17280 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
17281 case eCSR_ENCRYPT_TYPE_WEP40:
17282 params.cipher = WLAN_CIPHER_SUITE_WEP40;
17283 break;
17284
17285 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
17286 case eCSR_ENCRYPT_TYPE_WEP104:
17287 params.cipher = WLAN_CIPHER_SUITE_WEP104;
17288 break;
17289
17290 case eCSR_ENCRYPT_TYPE_TKIP:
17291 params.cipher = WLAN_CIPHER_SUITE_TKIP;
17292 break;
17293
17294 case eCSR_ENCRYPT_TYPE_AES:
17295 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
17296 break;
Mukul Sharma05504ac2017-06-08 12:35:53 +053017297 case eCSR_ENCRYPT_TYPE_AES_GCMP:
17298 params.cipher = WLAN_CIPHER_SUITE_GCMP;
17299 break;
17300 case eCSR_ENCRYPT_TYPE_AES_GCMP_256:
17301 params.cipher = WLAN_CIPHER_SUITE_GCMP_256;
17302 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017303 default:
17304 params.cipher = IW_AUTH_CIPHER_NONE;
17305 break;
17306 }
17307
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053017308 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
17309 TRACE_CODE_HDD_CFG80211_GET_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017310 adapter->vdev_id, params.cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017311
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017312 params.key_len = roam_profile->Keys.KeyLength[key_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017313 params.seq_len = 0;
17314 params.seq = NULL;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017315 params.key = &roam_profile->Keys.KeyMaterial[key_index][0];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017316 callback(cookie, &params);
17317
Dustin Browne74003f2018-03-14 12:51:58 -070017318 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017319 return 0;
17320}
17321
17322static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
17323 struct net_device *ndev,
17324 u8 key_index, bool pairwise,
17325 const u8 *mac_addr, void *cookie,
17326 void (*callback)(void *cookie,
17327 struct key_params *)
17328 )
17329{
Dustin Brown1d31b082018-11-22 14:41:20 +053017330 int errno;
17331 struct osif_vdev_sync *vdev_sync;
17332
17333 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
17334 if (errno)
17335 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017336
Dustin Brown1d31b082018-11-22 14:41:20 +053017337 errno = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
17338 mac_addr, cookie, callback);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017339
Dustin Brown1d31b082018-11-22 14:41:20 +053017340 osif_vdev_sync_op_stop(vdev_sync);
17341
17342 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017343}
17344
17345/**
17346 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
17347 * @wiphy: wiphy interface context
17348 * @ndev: pointer to net device
17349 * @key_index: Key index used in 802.11 frames
17350 * @unicast: true if it is unicast key
17351 * @multicast: true if it is multicast key
17352 *
17353 * This function is required for cfg80211_ops API.
17354 * It is used to delete the key information
17355 * Underlying hardware implementation does not have API to delete the
17356 * encryption key. It is automatically deleted when the peer is
17357 * removed. Hence this function currently does nothing.
17358 * Future implementation may interprete delete key operation to
17359 * replacing the key with a random junk value, effectively making it
17360 * useless.
17361 *
17362 * Return: status code, always 0.
17363 */
17364
17365static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
17366 struct net_device *ndev,
17367 u8 key_index,
17368 bool pairwise, const u8 *mac_addr)
17369{
Dustin Browne74003f2018-03-14 12:51:58 -070017370 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017371 return 0;
17372}
17373
17374/**
17375 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
17376 * @wiphy: Pointer to wiphy structure.
17377 * @dev: Pointer to net_device structure.
17378 * @key_index: key index
17379 * @pairwise: pairwise
17380 * @mac_addr: mac address
17381 *
17382 * This is the cfg80211 delete key handler function which invokes
17383 * the internal function @__wlan_hdd_cfg80211_del_key with
17384 * SSR protection.
17385 *
17386 * Return: 0 for success, error number on failure.
17387 */
17388static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
17389 struct net_device *dev,
17390 u8 key_index,
17391 bool pairwise, const u8 *mac_addr)
17392{
Dustin Brown1d31b082018-11-22 14:41:20 +053017393 int errno;
17394 struct osif_vdev_sync *vdev_sync;
17395
17396 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
17397 if (errno)
17398 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017399
Dustin Brown1d31b082018-11-22 14:41:20 +053017400 errno = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
17401 pairwise, mac_addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017402
Dustin Brown1d31b082018-11-22 14:41:20 +053017403 osif_vdev_sync_op_stop(vdev_sync);
17404
17405 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017406}
17407
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017408static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
17409 struct net_device *ndev,
17410 u8 key_index,
17411 bool unicast, bool multicast)
17412{
17413 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
17414 struct hdd_context *hdd_ctx;
17415 struct qdf_mac_addr bssid = QDF_MAC_ADDR_BCAST_INIT;
17416 struct hdd_station_ctx *sta_ctx;
17417 struct wlan_crypto_key *crypto_key;
17418 int ret;
17419 QDF_STATUS status;
17420
17421 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17422 hdd_err("Command not allowed in FTM mode");
17423 return -EINVAL;
17424 }
17425
Jeff Johnson48363022019-02-24 16:26:51 -080017426 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017427 return -EINVAL;
17428
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053017429 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
17430 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017431 adapter->vdev_id, key_index);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017432
17433 hdd_debug("Device_mode %s(%d) key_index = %d",
17434 qdf_opmode_str(adapter->device_mode),
17435 adapter->device_mode, key_index);
17436
17437 if (CSR_MAX_NUM_KEY <= key_index) {
17438 hdd_err("Invalid key index: %d", key_index);
17439 return -EINVAL;
17440 }
17441
17442 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17443 ret = wlan_hdd_validate_context(hdd_ctx);
17444
17445 if (0 != ret)
17446 return ret;
17447 crypto_key = wlan_crypto_get_key(adapter->vdev, key_index);
Qun Zhang9cbecfa2020-03-18 21:14:24 +080017448 if (!crypto_key) {
17449 hdd_err("Invalid NULL key info");
17450 return -EINVAL;
17451 }
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017452 hdd_debug("unicast %d, cipher %d", unicast, crypto_key->cipher_type);
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017453 if (!IS_WEP_CIPHER(crypto_key->cipher_type))
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017454 return 0;
17455 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17456 if (unicast)
17457 status =
17458 wlan_cfg80211_set_default_key(adapter->vdev, key_index,
Jeff Johnsone04b6992019-02-27 14:06:55 -080017459 &sta_ctx->conn_info.bssid);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017460 else
17461 status = wlan_cfg80211_set_default_key(adapter->vdev, key_index,
17462 &bssid);
17463 if (QDF_STATUS_SUCCESS != status) {
17464 hdd_err("ret fail status %d", ret);
17465 return -EINVAL;
17466 }
17467 if ((adapter->device_mode == QDF_STA_MODE) ||
17468 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080017469 ret =
17470 wlan_cfg80211_crypto_add_key(adapter->vdev, (unicast ?
17471 WLAN_CRYPTO_KEY_TYPE_UNICAST :
17472 WLAN_CRYPTO_KEY_TYPE_GROUP),
17473 key_index);
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017474 wma_update_set_key(adapter->vdev_id, unicast, key_index,
17475 crypto_key->cipher_type);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017476 }
17477
17478 return ret;
17479}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017480
17481static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
17482 struct net_device *ndev,
17483 u8 key_index,
17484 bool unicast, bool multicast)
17485{
Dustin Brown1d31b082018-11-22 14:41:20 +053017486 int errno;
17487 struct osif_vdev_sync *vdev_sync;
17488
17489 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
17490 if (errno)
17491 return errno;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -070017492
Dustin Brown1d31b082018-11-22 14:41:20 +053017493 errno = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index,
17494 unicast, multicast);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017495
Dustin Brown1d31b082018-11-22 14:41:20 +053017496 osif_vdev_sync_op_stop(vdev_sync);
17497
17498 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017499}
17500
Abhishek Singh85283ae2019-03-08 12:00:51 +053017501void wlan_hdd_cfg80211_unlink_bss(struct hdd_adapter *adapter,
Ashish Kumar Dhanotiya3d8b0ae2019-07-10 20:55:56 +053017502 tSirMacAddr bssid, uint8_t *ssid,
17503 uint8_t ssid_len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017504{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017505 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017506 struct wireless_dev *wdev = dev->ieee80211_ptr;
17507 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017508
Ashish Kumar Dhanotiya3d8b0ae2019-07-10 20:55:56 +053017509 __wlan_cfg80211_unlink_bss_list(wiphy, bssid, ssid, ssid_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017510}
17511
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017512#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017513static inline int
17514wlan_hdd_get_frame_len(struct bss_description *bss_desc)
17515{
17516 return GET_IE_LEN_IN_BSS(bss_desc->length) + sizeof(qcom_ie_age);
17517}
17518
17519static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053017520 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017521{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017522 qcom_ie_age *qie_age = NULL;
Nachiket Kukade348ede72017-04-28 16:34:24 +053017523
17524 /*
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017525 * GPS Requirement: need age ie per entry. Using vendor specific.
17526 * Assuming this is the last IE, copy at the end
Nachiket Kukade348ede72017-04-28 16:34:24 +053017527 */
Abhishek Singhf1c16762018-03-07 10:48:46 +053017528 *ie_length -= sizeof(qcom_ie_age);
17529 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + *ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017530 qie_age->element_id = QCOM_VENDOR_IE_ID;
17531 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
17532 qie_age->oui_1 = QCOM_OUI1;
17533 qie_age->oui_2 = QCOM_OUI2;
17534 qie_age->oui_3 = QCOM_OUI3;
17535 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053017536 /*
17537 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
17538 * all bss related timestamp is in units of ms. Due to this when scan
17539 * results are sent to lowi the scan age is high.To address this,
17540 * send age in units of 1/10 ms.
17541 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017542 qie_age->age = (uint32_t)(qdf_mc_timer_get_system_time() -
17543 bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017544 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070017545 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
17546 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070017547 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
17548 sizeof(qie_age->seq_ctrl));
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017549}
17550#else
17551static inline int
17552wlan_hdd_get_frame_len(struct bss_description *bss_desc)
17553{
17554 return GET_IE_LEN_IN_BSS(bss_desc->length);
17555}
17556static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053017557 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017558{
17559}
17560#endif /* WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017561
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017562
17563struct cfg80211_bss *
17564wlan_hdd_inform_bss_frame(struct hdd_adapter *adapter,
17565 struct bss_description *bss_desc)
17566{
17567 struct wireless_dev *wdev = adapter->dev->ieee80211_ptr;
17568 struct wiphy *wiphy = wdev->wiphy;
Abhishek Singhf1c16762018-03-07 10:48:46 +053017569 uint32_t ie_length = wlan_hdd_get_frame_len(bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017570 const char *ie =
17571 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
Will Huang65d64252019-07-16 17:57:42 +080017572 uint32_t i;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017573 struct cfg80211_bss *bss_status = NULL;
17574 struct hdd_context *hdd_ctx;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017575 struct hdd_config *cfg_param;
17576 struct wlan_cfg80211_inform_bss bss_data = {0};
17577
17578 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17579 /*
17580 * wlan_hdd_validate_context should not be used here, In validate ctx
17581 * start_modules_in_progress or stop_modules_in_progress is validated,
17582 * If the start_modules_in_progress is set to true means the interface
17583 * is not UP yet if the stop_modules_in_progress means that interface
17584 * is already down. So in both the two scenario's driver should not be
17585 * informing bss to kernel. Hence removing the validate context.
17586 */
17587
17588 if (!hdd_ctx || !hdd_ctx->config) {
17589 hdd_debug("HDD context is Null");
17590 return NULL;
17591 }
17592
17593 if (cds_is_driver_recovering() ||
17594 cds_is_load_or_unload_in_progress()) {
17595 hdd_debug("Recovery or load/unload in progress. State: 0x%x",
17596 cds_get_driver_state());
17597 return NULL;
17598 }
17599
17600 cfg_param = hdd_ctx->config;
17601 bss_data.frame_len = ie_length + offsetof(struct ieee80211_mgmt,
17602 u.probe_resp.variable);
17603 bss_data.mgmt = qdf_mem_malloc(bss_data.frame_len);
Min Liu74a1a502018-10-10 19:59:07 +080017604 if (!bss_data.mgmt)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017605 return NULL;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017606
17607 memcpy(bss_data.mgmt->bssid, bss_desc->bssId, ETH_ALEN);
17608
17609 /* Android does not want the timestamp from the frame.
17610 * Instead it wants a monotonic increasing value
17611 */
Alan Chenf1096fd2019-11-11 09:39:06 -080017612 bss_data.mgmt->u.probe_resp.timestamp = qdf_get_monotonic_boottime();
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017613
17614 bss_data.mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
17615 bss_data.mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
17616
Abhishek Singhf1c16762018-03-07 10:48:46 +053017617 wlan_hdd_add_age_ie(bss_data.mgmt, &ie_length, bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017618
17619 memcpy(bss_data.mgmt->u.probe_resp.variable, ie, ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017620 if (bss_desc->fProbeRsp) {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017621 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017622 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
17623 } else {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017624 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017625 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
17626 }
17627
Will Huang65d64252019-07-16 17:57:42 +080017628 bss_data.chan = ieee80211_get_channel(wiphy, bss_desc->chan_freq);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017629 if (!bss_data.chan) {
Will Huang65d64252019-07-16 17:57:42 +080017630 hdd_err("chan pointer is NULL, chan freq: %d",
17631 bss_desc->chan_freq);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017632 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017633 return NULL;
17634 }
17635
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017636 /*
17637 * Based on .ini configuration, raw rssi can be reported for bss.
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070017638 * Raw rssi is typically used for estimating power.
17639 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017640 bss_data.rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070017641 bss_desc->rssi;
17642
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017643 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017644 bss_data.rssi = QDF_MIN(bss_data.rssi, 0) * 100;
17645
17646 bss_data.boottime_ns = bss_desc->scansystimensec;
17647
17648 /* Set all per chain rssi as invalid */
17649 for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++)
Yeshwanth Sriram Guntuka14ab04c2018-09-21 15:06:49 +053017650 bss_data.per_chain_rssi[i] = WLAN_INVALID_PER_CHAIN_RSSI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017651
Ashish Kumar Dhanotiya3d8b0ae2019-07-10 20:55:56 +053017652 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 -070017653 QDF_MAC_ADDR_ARRAY(bss_data.mgmt->bssid),
Abhishek Singhef6f38c2018-12-20 13:51:29 +053017654 bss_data.chan->center_freq, (int)(bss_data.rssi / 100),
17655 bss_desc->timeStamp[0], ((bss_desc->seq_ctrl.seqNumHi <<
Ashish Kumar Dhanotiya3d8b0ae2019-07-10 20:55:56 +053017656 HIGH_SEQ_NUM_OFFSET) | bss_desc->seq_ctrl.seqNumLo),
17657 bss_desc->fProbeRsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017658
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017659 bss_status = wlan_cfg80211_inform_bss_frame_data(wiphy, &bss_data);
Jeff Johnsonb8944722017-09-03 09:03:19 -070017660 hdd_ctx->beacon_probe_rsp_cnt_per_scan++;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017661 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017662 return bss_status;
17663}
17664
17665/**
17666 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017667 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017668 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017669 *
17670 * This function is used to update the BSS data base of CFG8011
17671 *
17672 * Return: struct cfg80211_bss pointer
17673 */
Jeff Johnson172237b2017-11-07 15:32:59 -080017674struct cfg80211_bss *
17675wlan_hdd_cfg80211_update_bss_db(struct hdd_adapter *adapter,
17676 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017677{
17678 tCsrRoamConnectedProfile roamProfile;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017679 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017680 struct cfg80211_bss *bss = NULL;
17681
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017682 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017683 sme_roam_get_connect_profile(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017684 &roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017685
Pragaspathi Thilagaraj96742ae2019-05-29 00:49:33 +053017686 if (roamProfile.bss_desc) {
17687 bss = wlan_hdd_inform_bss_frame(adapter, roamProfile.bss_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017688
Jeff Johnsond36fa332019-03-18 13:42:25 -070017689 if (!bss)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017690 hdd_debug("wlan_hdd_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017691
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080017692 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017693 } else {
Pragaspathi Thilagaraj96742ae2019-05-29 00:49:33 +053017694 hdd_err("roamProfile.bss_desc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017695 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017696 return bss;
17697}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017698
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017699/**
17700 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017701 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017702 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017703 * @index: Index
17704 * @preauth: Preauth flag
17705 *
17706 * This function is used to notify the supplicant of a new PMKSA candidate.
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017707 * PMK value is notified to supplicant whether PMK caching or OKC is enabled
17708 * in firmware or not. Supplicant needs this value becaue it uses PMK caching
17709 * by default.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017710 *
17711 * Return: 0 for success, non-zero for failure
17712 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017713int wlan_hdd_cfg80211_pmksa_candidate_notify(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080017714 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017715 int index, bool preauth)
17716{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017717 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017718
Dustin Brown491d54b2018-03-14 12:39:11 -070017719 hdd_enter();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017720 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017721
Jeff Johnsond36fa332019-03-18 13:42:25 -070017722 if (!roam_info) {
Jeff Johnsonfd060852017-10-04 10:50:51 -070017723 hdd_err("roam_info is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017724 return -EINVAL;
17725 }
17726
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070017727 hdd_info(QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017728 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnsonfd060852017-10-04 10:50:51 -070017729 roam_info->bssid.bytes,
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017730 preauth, GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017731 return 0;
17732}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017733
17734#ifdef FEATURE_WLAN_LFR_METRICS
17735/**
17736 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017737 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017738 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017739 *
17740 * 802.11r/LFR metrics reporting function to report preauth initiation
17741 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017742 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017743 */
17744#define MAX_LFR_METRICS_EVENT_LENGTH 100
Jeff Johnson172237b2017-11-07 15:32:59 -080017745QDF_STATUS
17746wlan_hdd_cfg80211_roam_metrics_preauth(struct hdd_adapter *adapter,
17747 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017748{
17749 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17750 union iwreq_data wrqu;
17751
Dustin Brown491d54b2018-03-14 12:39:11 -070017752 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017753
Jeff Johnsond36fa332019-03-18 13:42:25 -070017754 if (!adapter) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017755 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017756 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017757 }
17758
17759 /* create the event */
17760 memset(&wrqu, 0, sizeof(wrqu));
17761 memset(metrics_notification, 0, sizeof(metrics_notification));
17762
17763 wrqu.data.pointer = metrics_notification;
17764 wrqu.data.length = scnprintf(metrics_notification,
17765 sizeof(metrics_notification),
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070017766 "QCOM: LFR_PREAUTH_INIT " QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070017767 QDF_MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017768
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017769 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017770 metrics_notification);
17771
Dustin Browne74003f2018-03-14 12:51:58 -070017772 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017773
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017774 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017775}
17776
17777/**
17778 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017779 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017780 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017781 * @preauth_status: Preauth status
17782 *
17783 * 802.11r/LFR metrics reporting function to report handover initiation
17784 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017785 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017786 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017787QDF_STATUS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017788wlan_hdd_cfg80211_roam_metrics_preauth_status(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080017789 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017790 bool preauth_status)
17791{
17792 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17793 union iwreq_data wrqu;
17794
Dustin Brown491d54b2018-03-14 12:39:11 -070017795 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017796
Jeff Johnsond36fa332019-03-18 13:42:25 -070017797 if (!adapter) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017798 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017799 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017800 }
17801
17802 /* create the event */
17803 memset(&wrqu, 0, sizeof(wrqu));
17804 memset(metrics_notification, 0, sizeof(metrics_notification));
17805
17806 scnprintf(metrics_notification, sizeof(metrics_notification),
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070017807 "QCOM: LFR_PREAUTH_STATUS " QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070017808 QDF_MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017809
17810 if (1 == preauth_status)
17811 strlcat(metrics_notification, " true",
17812 sizeof(metrics_notification));
17813 else
17814 strlcat(metrics_notification, " false",
17815 sizeof(metrics_notification));
17816
17817 wrqu.data.pointer = metrics_notification;
17818 wrqu.data.length = strlen(metrics_notification);
17819
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017820 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017821 metrics_notification);
17822
Dustin Browne74003f2018-03-14 12:51:58 -070017823 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017824
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017825 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017826}
17827
17828/**
17829 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017830 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017831 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017832 *
17833 * 802.11r/LFR metrics reporting function to report handover initiation
17834 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017835 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017836 */
Jeff Johnson172237b2017-11-07 15:32:59 -080017837QDF_STATUS
17838wlan_hdd_cfg80211_roam_metrics_handover(struct hdd_adapter *adapter,
17839 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017840{
17841 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17842 union iwreq_data wrqu;
17843
Dustin Brown491d54b2018-03-14 12:39:11 -070017844 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017845
Jeff Johnsond36fa332019-03-18 13:42:25 -070017846 if (!adapter) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017847 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017848 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017849 }
17850
17851 /* create the event */
17852 memset(&wrqu, 0, sizeof(wrqu));
17853 memset(metrics_notification, 0, sizeof(metrics_notification));
17854
17855 wrqu.data.pointer = metrics_notification;
17856 wrqu.data.length = scnprintf(metrics_notification,
17857 sizeof(metrics_notification),
17858 "QCOM: LFR_PREAUTH_HANDOVER "
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070017859 QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070017860 QDF_MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017861
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017862 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017863 metrics_notification);
17864
Dustin Browne74003f2018-03-14 12:51:58 -070017865 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017866
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017867 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017868}
17869#endif
17870
Nirav Shah73713f72018-05-17 14:50:41 +053017871#ifdef FEATURE_MONITOR_MODE_SUPPORT
17872static
17873void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
wadesongc48ea292019-08-07 16:40:02 +080017874 uint32_t op_freq,
Nirav Shah73713f72018-05-17 14:50:41 +053017875 struct ch_params *ch_params)
17876{
17877 struct hdd_station_ctx *station_ctx =
17878 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17879 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
17880 enum hdd_dot11_mode hdd_dot11_mode;
17881 uint8_t ini_dot11_mode =
17882 (WLAN_HDD_GET_CTX(adapter))->config->dot11Mode;
17883
17884 hdd_debug("Dot11Mode is %u", ini_dot11_mode);
17885 switch (ini_dot11_mode) {
17886 case eHDD_DOT11_MODE_AUTO:
17887 case eHDD_DOT11_MODE_11ax:
17888 case eHDD_DOT11_MODE_11ax_ONLY:
17889 if (sme_is_feature_supported_by_fw(DOT11AX))
17890 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
17891 else if (sme_is_feature_supported_by_fw(DOT11AC))
17892 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
17893 else
17894 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17895 break;
17896 case eHDD_DOT11_MODE_11ac:
17897 case eHDD_DOT11_MODE_11ac_ONLY:
17898 if (sme_is_feature_supported_by_fw(DOT11AC))
17899 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
17900 else
17901 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17902 break;
17903 case eHDD_DOT11_MODE_11n:
17904 case eHDD_DOT11_MODE_11n_ONLY:
17905 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17906 break;
17907 default:
17908 hdd_dot11_mode = ini_dot11_mode;
17909 break;
17910 }
17911 ch_info->channel_width = ch_params->ch_width;
17912 ch_info->phy_mode =
17913 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
wadesongc48ea292019-08-07 16:40:02 +080017914 ch_info->freq = op_freq;
Nirav Shah73713f72018-05-17 14:50:41 +053017915 ch_info->cb_mode = ch_params->ch_width;
wadesong59e727c2019-07-25 13:52:06 +080017916 hdd_debug("ch_info width %d, phymode %d channel freq %d",
Nirav Shah73713f72018-05-17 14:50:41 +053017917 ch_info->channel_width, ch_info->phy_mode,
wadesong59e727c2019-07-25 13:52:06 +080017918 ch_info->freq);
Nirav Shah73713f72018-05-17 14:50:41 +053017919}
17920#else
17921static
17922void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
wadesongc48ea292019-08-07 16:40:02 +080017923 uint32_t op_freq,
Nirav Shah73713f72018-05-17 14:50:41 +053017924 struct ch_params *ch_params)
17925{
17926}
17927#endif
17928
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017929/**
17930 * hdd_select_cbmode() - select channel bonding mode
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017931 * @adapter: Pointer to adapter
Saket Jhad5c0e022019-11-18 16:53:47 -080017932 * @oper_freq: Operating frequency (MHz)
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017933 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017934 *
17935 * Return: none
17936 */
Saket Jhad5c0e022019-11-18 16:53:47 -080017937void hdd_select_cbmode(struct hdd_adapter *adapter, qdf_freq_t oper_freq,
wadesongc48ea292019-08-07 16:40:02 +080017938 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017939{
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070017940 uint32_t sec_ch_freq = 0;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017941 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017942
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017943 /*
17944 * CDS api expects secondary channel for calculating
17945 * the channel params
17946 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017947 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070017948 (WLAN_REG_IS_24GHZ_CH_FREQ(oper_freq))) {
17949 if (oper_freq >= 2412 && oper_freq <= 2432)
17950 sec_ch_freq = oper_freq + 20;
17951 else if (oper_freq >= 2437 && oper_freq <= 2472)
17952 sec_ch_freq = oper_freq - 20;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017953 }
17954
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017955 /* This call decides required channel bonding mode */
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070017956 wlan_reg_set_channel_params_for_freq(hdd_ctx->pdev, oper_freq,
17957 sec_ch_freq, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017958
Abhishek Singh9fee5182019-11-01 11:39:38 +053017959 if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070017960 hdd_mon_select_cbmode(adapter, oper_freq, ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017961}
17962
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017963/**
17964 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
17965 * @adapter: STA adapter
17966 * @roam_profile: STA roam profile
17967 *
17968 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
17969 *
17970 * Return: false if sta-sap conc is not allowed, else return true
17971 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070017972static
17973bool wlan_hdd_handle_sap_sta_dfs_conc(struct hdd_adapter *adapter,
17974 struct csr_roam_profile *roam_profile)
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017975{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070017976 struct hdd_context *hdd_ctx;
Jeff Johnsone5006672017-08-29 14:39:02 -070017977 struct hdd_adapter *ap_adapter;
Jeff Johnson87251032017-08-29 13:31:11 -070017978 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070017979 struct hdd_hostapd_state *hostapd_state;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017980 QDF_STATUS status;
Tushnim Bhattacharyyafaa9c012019-10-28 15:18:36 -070017981 uint32_t ch_freq = 0;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017982
17983 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17984 if (!hdd_ctx) {
17985 hdd_err("HDD context is NULL");
17986 return true;
17987 }
17988
17989 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
17990 /* probably no sap running, no handling required */
Jeff Johnsond36fa332019-03-18 13:42:25 -070017991 if (!ap_adapter)
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017992 return true;
17993
17994 /*
17995 * sap is not in started state, so it is fine to go ahead with sta.
17996 * if sap is currently doing CAC then don't allow sta to go further.
17997 */
17998 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
17999 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
18000 return true;
18001
18002 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
18003 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
18004 return false;
18005 }
18006
18007 /*
18008 * log and return error, if we allow STA to go through, we don't
18009 * know what is going to happen better stop sta connection
18010 */
18011 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
Jeff Johnsond36fa332019-03-18 13:42:25 -070018012 if (!hdd_ap_ctx) {
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018013 hdd_err("AP context not found");
18014 return false;
18015 }
18016
18017 /* sap is on non-dfs channel, nothing to handle */
Will Huang4b097f52019-08-29 10:51:56 -070018018 if (!wlan_reg_is_dfs_for_freq(hdd_ctx->pdev,
18019 hdd_ap_ctx->operating_chan_freq)) {
Arun Kumar Khandavalliafcb0552020-01-20 11:46:36 +053018020 hdd_debug("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018021 return true;
18022 }
18023 /*
18024 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053018025 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018026 */
Manikandan Mohan282c4b62019-08-14 17:42:22 -070018027 status = policy_mgr_get_channel_from_scan_result(
18028 hdd_ctx->psoc, roam_profile, &ch_freq);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018029
Nitesh Shah59774522016-09-16 15:14:21 +053018030 /*
18031 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
18032 * channels for roaming case.
18033 */
Tushnim Bhattacharyyafaa9c012019-10-28 15:18:36 -070018034 if (WLAN_REG_IS_24GHZ_CH_FREQ(ch_freq)) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070018035 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053018036 return true;
18037 }
18038
18039 /*
Jeff Johnsondcf84ce2017-10-05 09:26:24 -070018040 * If channel is 0 or DFS or LTE unsafe then better to call pcl and
Tushnim Bhattacharyya9a929992017-06-18 00:59:09 -070018041 * find out the best channel. If channel is non-dfs 5 GHz then
18042 * better move SAP to STA's channel to make scc, so we have room
18043 * for 3port MCC scenario.
Nitesh Shah59774522016-09-16 15:14:21 +053018044 */
Tushnim Bhattacharyyafaa9c012019-10-28 15:18:36 -070018045 if (!ch_freq || wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, ch_freq) ||
18046 !policy_mgr_is_safe_channel(hdd_ctx->psoc, ch_freq))
18047 ch_freq = policy_mgr_get_nondfs_preferred_channel(
18048 hdd_ctx->psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018049
18050 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
18051 qdf_event_reset(&hostapd_state->qdf_event);
Bala Venkatesh8b9bbde2019-07-03 16:25:16 +053018052 wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, ap_adapter->vdev_id,
18053 CSA_REASON_STA_CONNECT_DFS_TO_NON_DFS);
18054
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018055 status = wlansap_set_channel_change_with_csa(
Tushnim Bhattacharyyafaa9c012019-10-28 15:18:36 -070018056 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), ch_freq,
Jeff Johnson91df29d2017-10-27 19:29:50 -070018057 hdd_ap_ctx->sap_config.ch_width_orig, false);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018058
18059 if (QDF_STATUS_SUCCESS != status) {
18060 hdd_err("Set channel with CSA IE failed, can't allow STA");
18061 return false;
18062 }
18063
18064 /*
18065 * wait here for SAP to finish the channel switch. When channel
18066 * switch happens, SAP sends few beacons with CSA_IE. After
18067 * successfully Transmission of those beacons, it will move its
18068 * state from started to disconnected and move to new channel.
18069 * once it moves to new channel, sap again moves its state
18070 * machine from disconnected to started and set this event.
18071 * wait for 10 secs to finish this.
18072 */
Nachiket Kukade0396b732017-11-14 16:35:16 +053018073 status = qdf_wait_for_event_completion(&hostapd_state->qdf_event, 10000);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018074 if (!QDF_IS_STATUS_SUCCESS(status)) {
18075 hdd_err("wait for qdf_event failed, STA not allowed!!");
18076 return false;
18077 }
18078
18079 return true;
18080}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018081
Abhishek Singhcfb44482017-03-10 12:42:37 +053018082#ifdef WLAN_FEATURE_11W
18083/**
18084 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
18085 * @roam_profile: pointer to roam profile
18086 *
18087 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
18088 * or pmf=2 is an explicit configuration in the supplicant
18089 * configuration, drop the connection request.
18090 *
18091 * Return: 0 if check result is valid, otherwise return error code
18092 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070018093static
18094int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053018095{
18096 if (roam_profile->MFPEnabled &&
Jeff Johnson20227a92018-03-13 09:41:05 -070018097 !(roam_profile->MFPRequired || roam_profile->MFPCapable)) {
Abhishek Singhcfb44482017-03-10 12:42:37 +053018098 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
18099 roam_profile->MFPEnabled,
18100 roam_profile->MFPRequired,
18101 roam_profile->MFPCapable);
18102 return -EINVAL;
18103 }
18104 return 0;
18105}
18106#else
18107static inline
Jeff Johnson61b5e982018-03-15 11:33:31 -070018108int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053018109{
18110 return 0;
18111}
18112#endif
18113
Krunal Soni31949422016-07-29 17:17:53 -070018114/**
18115 * wlan_hdd_cfg80211_connect_start() - to start the association process
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018116 * @adapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070018117 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018118 * @ssid_len: Length of ssid
18119 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070018120 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018121 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070018122 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018123 *
18124 * This function is used to start the association process
18125 *
18126 * Return: 0 for success, non-zero for failure
18127 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018128static int wlan_hdd_cfg80211_connect_start(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018129 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070018130 const u8 *bssid, const u8 *bssid_hint,
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070018131 uint32_t oper_freq,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070018132 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018133{
18134 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080018135 QDF_STATUS qdf_status;
Jeff Johnsonb8944722017-09-03 09:03:19 -070018136 struct hdd_context *hdd_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070018137 struct hdd_station_ctx *hdd_sta_ctx;
Jeff Johnson29c78672019-02-26 21:05:53 -080018138 uint32_t roam_id = INVALID_ROAM_ID;
Jeff Johnson61b5e982018-03-15 11:33:31 -070018139 struct csr_roam_profile *roam_profile;
Pragaspathi Thilagaraj7a1a08e2019-05-29 01:20:29 +053018140 enum csr_akm_type rsn_auth_type;
Jeff Johnson46b4f0e2019-03-08 10:48:35 -080018141 struct sme_config_params *sme_config;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018142 mac_handle_t mac_handle;
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +053018143 uint8_t wmm_mode = 0;
18144 uint8_t value = 0;
Min Liu8c5d99e2018-09-10 17:18:44 +080018145 struct wlan_objmgr_vdev *vdev;
Wu Gaoed616a12019-01-16 15:19:21 +080018146 uint32_t channel_bonding_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018147
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018148 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
18149 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018150
Jeff Johnsonb8944722017-09-03 09:03:19 -070018151 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018152 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018153 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018154
Srinivas Girigowdab8fdc642019-03-19 15:33:03 -070018155 if (WLAN_SSID_MAX_LEN < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018156 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018157 status = -EINVAL;
18158 goto ret_status;
18159 }
18160
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018161 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018162 hdd_err("Connection refused: conn in progress");
18163 status = -EINVAL;
18164 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018165 }
18166
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053018167 /* Disable roaming on all other adapters before connect start */
Abhinav Kumar523ca372019-08-30 16:28:19 +053018168 wlan_hdd_disable_roaming(adapter, RSO_CONNECT_START);
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053018169
Bala Venkatesh9bb9c052019-05-27 14:16:40 +053018170 hdd_notify_teardown_tdls_links(hdd_ctx->psoc);
Nitesh Shah273e4e52017-04-03 12:53:36 +053018171
Anurag Chouhand939d3d2016-07-20 17:45:48 +053018172 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
18173 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018174
Srinivas Dasariff782fb2019-10-10 18:37:24 +053018175 /*
18176 * Reset the ptk, gtk status flags to avoid using old/previous
18177 * connection status.
18178 */
18179 hdd_sta_ctx->conn_info.gtk_installed = false;
18180 hdd_sta_ctx->conn_info.ptk_installed = false;
Srinivas Dasari3b661522020-02-15 18:34:57 +053018181 adapter->last_disconnect_reason = 0;
Srinivas Dasariff782fb2019-10-10 18:37:24 +053018182
Jeff Johnson20227a92018-03-13 09:41:05 -070018183 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018184 if (roam_profile) {
Jeff Johnsond377dce2017-10-04 10:32:42 -070018185 struct hdd_station_ctx *sta_ctx;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070018186
Jeff Johnsond377dce2017-10-04 10:32:42 -070018187 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018188
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018189 /* Restart the opportunistic timer
18190 *
18191 * If hw_mode_change_in_progress is true, then wait
18192 * till firmware sends the callback for hw_mode change.
18193 *
18194 * Else set connect_in_progress as true and proceed.
18195 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018196 policy_mgr_restart_opportunistic_timer(
Dustin Brown76cd2932018-09-11 16:03:05 -070018197 hdd_ctx->psoc, false);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018198 if (policy_mgr_is_hw_mode_change_in_progress(
Dustin Brown76cd2932018-09-11 16:03:05 -070018199 hdd_ctx->psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053018200 qdf_status = policy_mgr_wait_for_connection_update(
Dustin Brown76cd2932018-09-11 16:03:05 -070018201 hdd_ctx->psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053018202 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018203 hdd_err("qdf wait for event failed!!");
18204 status = -EINVAL;
18205 goto ret_status;
18206 }
18207 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018208 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018209
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +053018210 status = ucfg_mlme_get_wmm_mode(hdd_ctx->psoc, &wmm_mode);
18211 if (!QDF_IS_STATUS_SUCCESS(status)) {
18212 hdd_err("Get wmm_mode failed");
18213 status = -EINVAL;
18214 goto ret_status;
18215 }
18216 if (HDD_WMM_USER_MODE_NO_QOS == wmm_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018217 /*QoS not enabled in cfg file */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018218 roam_profile->uapsd_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018219 } else {
18220 /*QoS enabled, update uapsd mask from cfg file */
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +053018221 status = ucfg_mlme_get_wmm_uapsd_mask(hdd_ctx->psoc,
18222 &value);
18223 if (!QDF_IS_STATUS_SUCCESS(status)) {
18224 hdd_err("Get uapsd_mask failed");
18225 status = -EINVAL;
18226 goto ret_status;
18227 }
18228 roam_profile->uapsd_mask = value;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018229 }
18230
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018231 roam_profile->SSIDs.numOfSSIDs = 1;
18232 roam_profile->SSIDs.SSIDList->SSID.length = ssid_len;
18233 qdf_mem_zero(roam_profile->SSIDs.SSIDList->SSID.ssId,
18234 sizeof(roam_profile->SSIDs.SSIDList->SSID.ssId));
18235 qdf_mem_copy((void *)(roam_profile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018236 ssid, ssid_len);
18237
Abhishek Singh3c9910e2017-01-06 17:56:47 +053018238 /* cleanup bssid hint */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018239 qdf_mem_zero(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053018240 QDF_MAC_ADDR_SIZE);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018241 qdf_mem_zero((void *)(roam_profile->BSSIDs.bssid),
Abhishek Singh3c9910e2017-01-06 17:56:47 +053018242 QDF_MAC_ADDR_SIZE);
18243
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018244 if (bssid) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018245 roam_profile->BSSIDs.numOfBSSIDs = 1;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018246 qdf_mem_copy((void *)(roam_profile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053018247 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070018248 /*
Jeff Johnsonfa7d9602018-05-06 11:25:31 -070018249 * Save BSSID in separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018250 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070018251 * association process. In case of join failure
18252 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018253 */
Jeff Johnson731bc322017-10-14 19:53:44 -070018254 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
18255 bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018256 } else if (bssid_hint) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018257 qdf_mem_copy(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053018258 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070018259 /*
18260 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018261 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070018262 * association process. In case of join failure
18263 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018264 */
Jeff Johnson731bc322017-10-14 19:53:44 -070018265 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053018266 bssid_hint, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018267 }
18268
Jeff Johnsonce4a8342017-10-14 13:12:22 -070018269 if (hdd_sta_ctx->wpa_versions) {
Jeff Johnson784efe22019-03-09 18:31:13 -080018270 hdd_set_genie_to_csr(adapter, &rsn_auth_type);
18271 hdd_set_csr_auth_type(adapter, rsn_auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018272 }
18273#ifdef FEATURE_WLAN_WAPI
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018274 if (adapter->wapi_info.wapi_mode) {
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018275 switch (adapter->wapi_info.wapi_auth_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018276 case WAPI_AUTH_MODE_PSK:
18277 {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018278 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018279 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
18280 break;
18281 }
18282 case WAPI_AUTH_MODE_CERT:
18283 {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018284 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018285 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
18286 break;
18287 }
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018288 default:
18289 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018290 } /* End of switch */
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018291 if (adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018292 WAPI_AUTH_MODE_PSK
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018293 || adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018294 WAPI_AUTH_MODE_CERT) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018295 roam_profile->AuthType.numEntries = 1;
18296 roam_profile->EncryptionType.numEntries = 1;
18297 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018298 eCSR_ENCRYPT_TYPE_WPI;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018299 roam_profile->mcEncryptionType.numEntries = 1;
18300 roam_profile->mcEncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018301 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
18302 }
18303 }
Krunal Soni31949422016-07-29 17:17:53 -070018304#endif
Min Liu8c5d99e2018-09-10 17:18:44 +080018305 vdev = hdd_objmgr_get_vdev(adapter);
18306 if (!vdev) {
18307 status = -EINVAL;
18308 goto conn_failure;
18309 }
18310 ucfg_pmo_flush_gtk_offload_req(vdev);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053018311 hdd_objmgr_put_vdev(vdev);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018312 roam_profile->csrPersona = adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018313
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070018314 if (oper_freq) {
wadesong24c869a2019-07-19 17:38:59 +080018315 roam_profile->ChannelInfo.freq_list = &oper_freq;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018316 roam_profile->ChannelInfo.numOfChannels = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018317 } else {
wadesong24c869a2019-07-19 17:38:59 +080018318 roam_profile->ChannelInfo.freq_list = NULL;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018319 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018320 }
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070018321 if (QDF_IBSS_MODE == adapter->device_mode && oper_freq) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018322 /*
18323 * Need to post the IBSS power save parameters
18324 * to WMA. WMA will configure this parameters
18325 * to firmware if power save is enabled by the
18326 * firmware.
18327 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018328 qdf_status = hdd_set_ibss_power_save_params(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018329
Abhishek Singh471652b2017-04-14 12:28:32 +053018330 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018331 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018332 status = -EINVAL;
18333 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018334 }
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018335 roam_profile->ch_params.ch_width =
Naveen Rawatc77e6e72016-08-05 15:19:03 -070018336 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053018337 /*
18338 * In IBSS mode while operating in 2.4 GHz,
18339 * the device supports only 20 MHz.
18340 */
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070018341 if (WLAN_REG_IS_24GHZ_CH_FREQ(oper_freq))
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018342 roam_profile->ch_params.ch_width =
Nitesh Shah87335a52016-09-05 15:47:32 +053018343 CH_WIDTH_20MHZ;
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070018344 hdd_select_cbmode(adapter, oper_freq,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018345 &roam_profile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018346 }
18347
Jeff Johnson20227a92018-03-13 09:41:05 -070018348 if (wlan_hdd_cfg80211_check_pmf_valid(roam_profile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018349 status = -EINVAL;
18350 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018351 }
18352
Krunal Soni31949422016-07-29 17:17:53 -070018353 /*
18354 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018355 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070018356 * enhancements, the supplicant is not issuing the scan command
18357 * now. So the unicast frames which are sent from the host are
18358 * not having the additional IEs. If it is P2P CLIENT and there
18359 * is no additional IE present in roamProfile, then use the
18360 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018361 */
18362
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018363 if ((adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018364 (!roam_profile->pAddIEScan)) {
18365 roam_profile->pAddIEScan =
Jeff Johnson37fa0402017-10-28 12:42:29 -070018366 &adapter->scan_info.scan_add_ie.addIEdata[0];
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018367 roam_profile->nAddIEScanLength =
Jeff Johnson37fa0402017-10-28 12:42:29 -070018368 adapter->scan_info.scan_add_ie.length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018369 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018370
Pragaspathi Thilagarajea0a7e12020-02-21 17:38:38 +053018371 /*
18372 * When connecting between two profiles there could be scenario
18373 * when the vdev create and vdev destroy clears the additional
18374 * scan IEs in roam profile and when the supplicant doesn't
18375 * issue scan request. So the unicast frames that are sent from
18376 * the STA doesn't have the additional MBO IE.
18377 */
18378 if (adapter->device_mode == QDF_STA_MODE &&
18379 (adapter->scan_info.default_scan_ies ||
18380 adapter->scan_info.scan_add_ie.length) &&
18381 !roam_profile->nAddIEScanLength) {
18382 if (adapter->scan_info.default_scan_ies) {
18383 roam_profile->pAddIEScan =
18384 adapter->scan_info.default_scan_ies;
18385 roam_profile->nAddIEScanLength =
18386 adapter->scan_info.default_scan_ies_len;
18387 } else if (adapter->scan_info.scan_add_ie.length) {
18388 roam_profile->pAddIEScan =
18389 adapter->scan_info.scan_add_ie.addIEdata;
18390 roam_profile->nAddIEScanLength =
18391 adapter->scan_info.scan_add_ie.length;
18392 }
18393 }
18394
Dustin Brown76cd2932018-09-11 16:03:05 -070018395 if ((policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) == true)
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018396 && (false == wlan_hdd_handle_sap_sta_dfs_conc(adapter,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018397 roam_profile))) {
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018398 hdd_err("sap-sta conc will fail, can't allow sta");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018399 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018400 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018401 status = -ENOMEM;
18402 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018403 }
18404
Anurag Chouhan600c3a02016-03-01 10:33:54 +053018405 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018406 if (!sme_config) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018407 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018408 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018409 status = -ENOMEM;
18410 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018411 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018412
18413 mac_handle = hdd_ctx->mac_handle;
18414 sme_get_config_param(mac_handle, sme_config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018415 /* These values are not sessionized. So, any change in these SME
18416 * configs on an older or parallel interface will affect the
18417 * cb mode. So, restoring the default INI params before starting
18418 * interfaces such as sta, cli etc.,
18419 */
Wu Gaoed616a12019-01-16 15:19:21 +080018420 ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc,
18421 &channel_bonding_mode);
Jeff Johnsone94ccd02019-04-02 15:02:56 -070018422 sme_config->csr_config.channelBondingMode5GHz =
Wu Gaoed616a12019-01-16 15:19:21 +080018423 channel_bonding_mode;
18424 ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
18425 &channel_bonding_mode);
Jeff Johnsone94ccd02019-04-02 15:02:56 -070018426 sme_config->csr_config.channelBondingMode24GHz =
Wu Gaoed616a12019-01-16 15:19:21 +080018427 channel_bonding_mode;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018428 sme_update_config(mac_handle, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053018429 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053018430 /*
18431 * Change conn_state to connecting before sme_roam_connect(),
18432 * because sme_roam_connect() has a direct path to call
18433 * hdd_sme_roam_callback(), which will change the conn_state
18434 * If direct path, conn_state will be accordingly changed to
18435 * NotConnected or Associated by either
18436 * hdd_association_completion_handler() or
18437 * hdd_dis_connect_handler() in sme_RoamCallback()if
18438 * sme_RomConnect is to be queued,
18439 * Connecting state will remain until it is completed.
18440 *
18441 * If connection state is not changed, connection state will
18442 * remain in eConnectionState_NotConnected state.
18443 * In hdd_association_completion_handler, "hddDisconInProgress"
18444 * is set to true if conn state is
18445 * eConnectionState_NotConnected.
18446 * If "hddDisconInProgress" is set to true then cfg80211 layer
18447 * is not informed of connect result indication which
18448 * is an issue.
18449 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018450 if (QDF_STA_MODE == adapter->device_mode ||
18451 QDF_P2P_CLIENT_MODE == adapter->device_mode)
18452 hdd_conn_set_connection_state(adapter,
Agrawal Ashish6b015762016-05-05 11:22:18 +053018453 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018454
Alok Kumarb64650c2018-03-23 17:05:11 +053018455 hdd_set_disconnect_status(adapter, false);
18456
Jingxiang Geb49aa302018-01-17 20:54:15 +080018457 qdf_runtime_pm_prevent_suspend(
18458 &hdd_ctx->runtime_context.connect);
Padma, Santhosh Kumarc88de482018-04-09 16:17:04 +053018459 hdd_prevent_suspend_timeout(HDD_WAKELOCK_CONNECT_COMPLETE,
Dustin Brownceed67e2017-05-26 11:57:31 -070018460 WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018461 qdf_status = sme_roam_connect(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018462 adapter->vdev_id, roam_profile,
Jeff Johnson29c78672019-02-26 21:05:53 -080018463 &roam_id);
Abhishek Singh471652b2017-04-14 12:28:32 +053018464 if (QDF_IS_STATUS_ERROR(qdf_status))
18465 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018466
Rajeev Kumard31e1542017-01-13 14:37:42 -080018467 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018468 (QDF_STA_MODE == adapter->device_mode ||
18469 QDF_P2P_CLIENT_MODE == adapter->device_mode)) {
Abhishek Singh4ec44a72020-02-03 15:07:34 +053018470 hdd_err("Vdev %d connect failed with status %d",
18471 adapter->vdev_id, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018472 /* change back to NotAssociated */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018473 hdd_conn_set_connection_state(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018474 eConnectionState_NotConnected);
Jingxiang Geb49aa302018-01-17 20:54:15 +080018475 qdf_runtime_pm_allow_suspend(
18476 &hdd_ctx->runtime_context.connect);
Dustin Brownceed67e2017-05-26 11:57:31 -070018477 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018478 }
18479
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018480 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018481 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018482
wadesong24c869a2019-07-19 17:38:59 +080018483 roam_profile->ChannelInfo.freq_list = NULL;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018484 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018485 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018486 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018487 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018488 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018489 goto ret_status;
18490
18491conn_failure:
18492 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018493 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018494
18495ret_status:
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053018496 /*
18497 * Enable roaming on other STA adapter for failure case.
18498 * For success case, it is enabled in assoc completion handler
18499 */
18500 if (status)
Abhinav Kumar523ca372019-08-30 16:28:19 +053018501 wlan_hdd_enable_roaming(adapter, RSO_CONNECT_START);
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053018502
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018503 return status;
18504}
18505
18506/**
18507 * wlan_hdd_cfg80211_set_auth_type() - set auth type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018508 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018509 * @auth_type: Auth type
18510 *
18511 * This function is used to set the authentication type (OPEN/SHARED).
18512 *
18513 * Return: 0 for success, non-zero for failure
18514 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018515static int wlan_hdd_cfg80211_set_auth_type(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018516 enum nl80211_auth_type auth_type)
18517{
Jeff Johnsond377dce2017-10-04 10:32:42 -070018518 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018519 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070018520 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018521
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018522 /*set authentication type */
18523 switch (auth_type) {
18524 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnson96e33512019-02-27 15:10:21 -080018525 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_AUTOSWITCH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018526 break;
18527
18528 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018529 case NL80211_AUTHTYPE_FT:
Jeff Johnson96e33512019-02-27 15:10:21 -080018530 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018531 break;
18532
18533 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnson96e33512019-02-27 15:10:21 -080018534 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_SHARED_KEY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018535 break;
18536#ifdef FEATURE_WLAN_ESE
18537 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnson96e33512019-02-27 15:10:21 -080018538 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_CCKM_WPA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018539 break;
18540#endif
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053018541#if defined(WLAN_FEATURE_FILS_SK) && \
18542 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
18543 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018544 case NL80211_AUTHTYPE_FILS_SK:
Jeff Johnson96e33512019-02-27 15:10:21 -080018545 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018546 break;
18547#endif
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018548 case NL80211_AUTHTYPE_SAE:
Jeff Johnson96e33512019-02-27 15:10:21 -080018549 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_SAE;
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018550 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018551 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018552 hdd_err("Unsupported authentication type: %d", auth_type);
Jeff Johnson96e33512019-02-27 15:10:21 -080018553 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_UNKNOWN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018554 return -EINVAL;
18555 }
18556
Jeff Johnson20227a92018-03-13 09:41:05 -070018557 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson96e33512019-02-27 15:10:21 -080018558 roam_profile->AuthType.authType[0] = sta_ctx->conn_info.auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018559 return 0;
18560}
18561
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053018562#if defined(WLAN_FEATURE_FILS_SK) && \
18563 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
18564 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Jeff Johnson20227a92018-03-13 09:41:05 -070018565static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018566{
18567 struct cds_fils_connection_info *fils_con_info;
18568
Jeff Johnson20227a92018-03-13 09:41:05 -070018569 fils_con_info = roam_profile->fils_con_info;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018570 if (!fils_con_info) {
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018571 hdd_err("No valid Roam profile");
18572 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018573 }
18574
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018575 return true;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018576}
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018577
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018578static enum eAniAuthType wlan_hdd_get_fils_auth_type(
18579 enum nl80211_auth_type auth)
18580{
18581 switch (auth) {
18582 case NL80211_AUTHTYPE_FILS_SK:
18583 return SIR_FILS_SK_WITHOUT_PFS;
18584 case NL80211_AUTHTYPE_FILS_SK_PFS:
18585 return SIR_FILS_SK_WITH_PFS;
18586 case NL80211_AUTHTYPE_FILS_PK:
18587 return SIR_FILS_PK_AUTH;
18588 default:
18589 return eSIR_DONOT_USE_AUTH_TYPE;
18590 }
18591}
18592
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018593static bool wlan_hdd_fils_data_in_limits(struct cfg80211_connect_params *req)
18594{
18595 hdd_debug("seq=%d auth=%d lengths: user=%zu rrk=%zu realm=%zu",
18596 req->fils_erp_next_seq_num, req->auth_type,
18597 req->fils_erp_username_len, req->fils_erp_rrk_len,
18598 req->fils_erp_realm_len);
18599 if (!req->fils_erp_rrk_len || !req->fils_erp_realm_len ||
18600 !req->fils_erp_username_len ||
18601 req->fils_erp_rrk_len > FILS_MAX_RRK_LENGTH ||
18602 req->fils_erp_realm_len > FILS_MAX_REALM_LEN ||
18603 req->fils_erp_username_len > FILS_MAX_KEYNAME_NAI_LENGTH) {
18604 hdd_err("length incorrect, user=%zu rrk=%zu realm=%zu",
18605 req->fils_erp_username_len, req->fils_erp_rrk_len,
18606 req->fils_erp_realm_len);
18607 return false;
18608 }
18609
bings77a35ac2018-06-01 15:10:44 +080018610 if (!req->fils_erp_rrk || !req->fils_erp_realm ||
18611 !req->fils_erp_username) {
18612 hdd_err("buffer incorrect, user=%pK rrk=%pK realm=%pK",
18613 req->fils_erp_username, req->fils_erp_rrk,
18614 req->fils_erp_realm);
18615 return false;
18616 }
18617
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018618 return true;
18619}
18620
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018621/**
18622 * wlan_hdd_cfg80211_set_fils_config() - set fils config params during connect
18623 * @adapter: Pointer to adapter
18624 * @req: Pointer to fils parameters
18625 *
18626 * Return: 0 for success, non-zero for failure
18627 */
18628static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
18629 struct cfg80211_connect_params *req)
18630{
Jeff Johnson61b5e982018-03-15 11:33:31 -070018631 struct csr_roam_profile *roam_profile;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018632 enum eAniAuthType auth_type;
18633 uint8_t *buf;
Karthik Kantamneni2231a232018-09-11 15:45:55 +053018634 bool value;
18635 QDF_STATUS status;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018636 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
18637
Jeff Johnson20227a92018-03-13 09:41:05 -070018638 roam_profile = hdd_roam_profile(adapter);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018639
Karthik Kantamneni2231a232018-09-11 15:45:55 +053018640 value = 0;
Dustin Brown05d81302018-09-11 16:49:22 -070018641 status = ucfg_mlme_get_fils_enabled_info(hdd_ctx->psoc, &value);
Karthik Kantamneni2231a232018-09-11 15:45:55 +053018642 if (QDF_IS_STATUS_ERROR(status) || !value) {
18643 hdd_err("get_fils_enabled status: %d fils_enabled: %d",
18644 status, value);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018645 return -EINVAL;
18646 }
Karthik Kantamneni2231a232018-09-11 15:45:55 +053018647
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018648 hdd_clear_fils_connection_info(adapter);
18649 roam_profile->fils_con_info =
18650 qdf_mem_malloc(sizeof(*roam_profile->fils_con_info));
18651
Min Liu74a1a502018-10-10 19:59:07 +080018652 if (!roam_profile->fils_con_info)
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018653 return -EINVAL;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018654 /*
18655 * The initial connection for FILS may happen with an OPEN
18656 * auth type. Hence we need to allow the connection to go
18657 * through in that case as well. Below is_fils_connection
18658 * flag is propagated down to CSR and PE sessions through
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018659 * the JOIN request. As the flag is used, do not free the
18660 * memory allocated to fils_con_info and return success.
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018661 */
18662 if (req->auth_type != NL80211_AUTHTYPE_FILS_SK) {
18663 roam_profile->fils_con_info->is_fils_connection = false;
18664 return 0;
18665 }
18666
18667 /*
18668 * Once above check is done, then we can check for valid FILS
18669 * auth types. Currently only NL80211_AUTHTYPE_FILS_SK is
18670 * supported. Once all auth types are supported, then we can
18671 * merge these 2 conditions into one.
18672 */
18673 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
18674 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
18675 hdd_err("invalid auth type for fils %d", req->auth_type);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018676 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018677 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018678 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080018679 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018680
18681 roam_profile->fils_con_info->is_fils_connection = true;
18682 roam_profile->fils_con_info->sequence_number =
Pragaspathi Thilagaraj87a60af2019-02-20 20:42:47 +053018683 (req->fils_erp_next_seq_num + 1);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018684 roam_profile->fils_con_info->auth_type = auth_type;
18685
18686 roam_profile->fils_con_info->r_rk_length =
18687 req->fils_erp_rrk_len;
18688 if (req->fils_erp_rrk_len)
18689 qdf_mem_copy(roam_profile->fils_con_info->r_rk,
18690 req->fils_erp_rrk,
18691 roam_profile->fils_con_info->r_rk_length);
18692
18693 roam_profile->fils_con_info->realm_len = req->fils_erp_realm_len;
18694 if (req->fils_erp_realm_len)
18695 qdf_mem_copy(roam_profile->fils_con_info->realm,
18696 req->fils_erp_realm,
18697 roam_profile->fils_con_info->realm_len);
18698
18699 roam_profile->fils_con_info->key_nai_length =
18700 req->fils_erp_username_len + sizeof(char) +
18701 req->fils_erp_realm_len;
18702 hdd_debug("key_nai_length = %d",
18703 roam_profile->fils_con_info->key_nai_length);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018704 if (roam_profile->fils_con_info->key_nai_length >
18705 FILS_MAX_KEYNAME_NAI_LENGTH) {
18706 hdd_err("Do not allow FILS conn due to excess NAI Length %d",
18707 roam_profile->fils_con_info->key_nai_length);
18708 goto fils_conn_fail;
18709 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018710 buf = roam_profile->fils_con_info->keyname_nai;
18711 qdf_mem_copy(buf, req->fils_erp_username, req->fils_erp_username_len);
18712 buf += req->fils_erp_username_len;
18713 *buf++ = '@';
18714 qdf_mem_copy(buf, req->fils_erp_realm, req->fils_erp_realm_len);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018715
18716 return 0;
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018717
18718fils_conn_fail:
18719 if (roam_profile->fils_con_info) {
18720 qdf_mem_free(roam_profile->fils_con_info);
18721 roam_profile->fils_con_info = NULL;
18722 }
18723 return -EINVAL;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018724}
18725
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018726static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
18727{
18728 switch (key_mgmt) {
18729 case WLAN_AKM_SUITE_FILS_SHA256:
18730 case WLAN_AKM_SUITE_FILS_SHA384:
18731 case WLAN_AKM_SUITE_FT_FILS_SHA256:
18732 case WLAN_AKM_SUITE_FT_FILS_SHA384:
18733 return true;
18734 default:
18735 return false;
18736 }
18737}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018738
18739static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
18740{
18741 enum nl80211_auth_type auth_type = req->auth_type;
18742 /*
18743 * Below n_akm_suites is defined as int in the kernel, even though it
18744 * is supposed to be unsigned.
18745 */
18746 int num_akm_suites = req->crypto.n_akm_suites;
18747 uint32_t key_mgmt = req->crypto.akm_suites[0];
18748 enum eAniAuthType fils_auth_type =
18749 wlan_hdd_get_fils_auth_type(req->auth_type);
18750
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018751 if (num_akm_suites <= 0)
18752 return false;
18753
18754 /*
18755 * Auth type will be either be OPEN or FILS type for a FILS connection
18756 */
18757 if ((auth_type != NL80211_AUTHTYPE_OPEN_SYSTEM) &&
Abhishek Singh4ec44a72020-02-03 15:07:34 +053018758 (fils_auth_type == eSIR_DONOT_USE_AUTH_TYPE))
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018759 return false;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018760
Abhishek Singh4ec44a72020-02-03 15:07:34 +053018761 if (!wlan_hdd_is_akm_suite_fils(key_mgmt))
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018762 return false;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053018763
18764 hdd_debug("Fils Auth %d AKM %d", fils_auth_type, key_mgmt);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018765
18766 return true;
18767}
18768
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018769#else
Jeff Johnson20227a92018-03-13 09:41:05 -070018770static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018771{
18772 return true;
18773}
18774
18775static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
18776 struct cfg80211_connect_params *req)
18777{
18778 return 0;
18779}
18780
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018781static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
18782{
18783 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018784}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018785
18786static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
18787{
18788 return false;
18789}
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018790#endif
18791
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018792/**
18793 * wlan_hdd_set_akm_suite() - set key management type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018794 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018795 * @key_mgmt: Key management type
18796 *
18797 * This function is used to set the key mgmt type(PSK/8021x).
18798 *
18799 * Return: 0 for success, non-zero for failure
18800 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018801static int wlan_hdd_set_akm_suite(struct hdd_adapter *adapter, u32 key_mgmt)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018802{
Jeff Johnson37ecea42018-03-18 17:54:40 -070018803 struct hdd_station_ctx *sta_ctx;
Jeff Johnson61b5e982018-03-15 11:33:31 -070018804 struct csr_roam_profile *roam_profile;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018805
Jeff Johnson20227a92018-03-13 09:41:05 -070018806 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018807
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018808 if (wlan_hdd_is_akm_suite_fils(key_mgmt) &&
Jeff Johnson20227a92018-03-13 09:41:05 -070018809 !hdd_validate_fils_info_ptr(roam_profile))
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018810 return -EINVAL;
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018811#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018812#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018813#endif
18814#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018815#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018816#endif
Jeff Johnson37ecea42018-03-18 17:54:40 -070018817
18818 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
18819
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018820 /*set key mgmt type */
18821 switch (key_mgmt) {
18822 case WLAN_AKM_SUITE_PSK:
18823 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018824 case WLAN_AKM_SUITE_FT_PSK:
Abhishek Singh02cb9e02017-08-30 17:39:50 +053018825 case WLAN_AKM_SUITE_DPP_RSN:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018826 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_PSK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018827 break;
18828
18829 case WLAN_AKM_SUITE_8021X_SHA256:
18830 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018831 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018832 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018833 break;
18834#ifdef FEATURE_WLAN_ESE
18835#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018836 case WLAN_AKM_SUITE_CCKM:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018837 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_CCKM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018838 break;
18839#endif
18840#ifndef WLAN_AKM_SUITE_OSEN
18841#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
18842#endif
18843 case WLAN_AKM_SUITE_OSEN:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018844 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018845 break;
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053018846#if defined(WLAN_FEATURE_FILS_SK) && \
18847 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
18848 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053018849 case WLAN_AKM_SUITE_FILS_SHA256:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018850 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018851 roam_profile->fils_con_info->akm_type =
18852 eCSR_AUTH_TYPE_FILS_SHA256;
18853 break;
18854
18855 case WLAN_AKM_SUITE_FILS_SHA384:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018856 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018857 roam_profile->fils_con_info->akm_type =
18858 eCSR_AUTH_TYPE_FILS_SHA384;
18859 break;
18860
18861 case WLAN_AKM_SUITE_FT_FILS_SHA256:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018862 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018863 roam_profile->fils_con_info->akm_type =
18864 eCSR_AUTH_TYPE_FT_FILS_SHA256;
18865 break;
18866
18867 case WLAN_AKM_SUITE_FT_FILS_SHA384:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018868 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018869 roam_profile->fils_con_info->akm_type =
18870 eCSR_AUTH_TYPE_FT_FILS_SHA384;
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053018871 break;
18872#endif
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053018873
18874 case WLAN_AKM_SUITE_OWE:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018875 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053018876 break;
18877
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018878 case WLAN_AKM_SUITE_EAP_SHA256:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018879 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018880 break;
18881 case WLAN_AKM_SUITE_EAP_SHA384:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018882 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018883 break;
18884
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018885 case WLAN_AKM_SUITE_SAE:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018886 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018887 break;
18888
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +053018889 case WLAN_AKM_SUITE_FT_SAE:
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +053018890 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
18891 break;
18892
18893 case WLAN_AKM_SUITE_FT_EAP_SHA_384:
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +053018894 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
18895 break;
18896
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018897 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018898 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018899 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018900 }
18901 return 0;
18902}
18903
18904/**
18905 * wlan_hdd_cfg80211_set_cipher() - set encryption type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018906 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018907 * @cipher: Cipher type
18908 * @ucast: Unicast flag
18909 *
18910 * This function is used to set the encryption type
18911 * (NONE/WEP40/WEP104/TKIP/CCMP).
18912 *
18913 * Return: 0 for success, non-zero for failure
18914 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018915static int wlan_hdd_cfg80211_set_cipher(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018916 u32 cipher, bool ucast)
18917{
18918 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Jeff Johnsond377dce2017-10-04 10:32:42 -070018919 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018920 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070018921 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018922
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018923 if (!cipher) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018924 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
18925 } else {
18926
18927 /*set encryption method */
18928 switch (cipher) {
18929 case IW_AUTH_CIPHER_NONE:
18930 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
18931 break;
18932
18933 case WLAN_CIPHER_SUITE_WEP40:
18934 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
18935 break;
18936
18937 case WLAN_CIPHER_SUITE_WEP104:
18938 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
18939 break;
18940
18941 case WLAN_CIPHER_SUITE_TKIP:
18942 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
18943 break;
18944
18945 case WLAN_CIPHER_SUITE_CCMP:
18946 encryptionType = eCSR_ENCRYPT_TYPE_AES;
18947 break;
18948#ifdef FEATURE_WLAN_WAPI
18949 case WLAN_CIPHER_SUITE_SMS4:
18950 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
18951 break;
18952#endif
18953
18954#ifdef FEATURE_WLAN_ESE
18955 case WLAN_CIPHER_SUITE_KRK:
18956 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
18957 break;
18958#ifdef WLAN_FEATURE_ROAM_OFFLOAD
18959 case WLAN_CIPHER_SUITE_BTK:
18960 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
18961 break;
18962#endif
18963#endif
Mukul Sharma05504ac2017-06-08 12:35:53 +053018964 case WLAN_CIPHER_SUITE_GCMP:
18965 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP;
18966 break;
18967 case WLAN_CIPHER_SUITE_GCMP_256:
18968 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP_256;
18969 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018970 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018971 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018972 return -EOPNOTSUPP;
18973 }
18974 }
18975
Jeff Johnson20227a92018-03-13 09:41:05 -070018976 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018977 if (ucast) {
Jeff Johnsonb1959842019-02-27 13:04:04 -080018978 sta_ctx->conn_info.uc_encrypt_type = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070018979 roam_profile->EncryptionType.numEntries = 1;
18980 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018981 encryptionType;
18982 } else {
Jeff Johnsonb1959842019-02-27 13:04:04 -080018983 sta_ctx->conn_info.mc_encrypt_type = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070018984 roam_profile->mcEncryptionType.numEntries = 1;
18985 roam_profile->mcEncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018986 encryptionType;
18987 }
18988
18989 return 0;
18990}
18991
18992/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018993 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
Jeff Johnson20227a92018-03-13 09:41:05 -070018994 * @adapter: Pointer to adapter
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018995 * @gen_ie: Pointer to IE data
18996 * @len: length of IE data
18997 *
18998 * Return: 0 for success, non-zero for failure
18999 */
Jeff Johnson20227a92018-03-13 09:41:05 -070019000static int wlan_hdd_add_assoc_ie(struct hdd_adapter *adapter,
19001 const uint8_t *gen_ie, uint16_t len)
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019002{
Jeff Johnson20227a92018-03-13 09:41:05 -070019003 struct csr_roam_profile *roam_profile;
19004 tSirAddie *assoc_add_ie;
19005 uint16_t cur_add_ie_len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019006
Jeff Johnson20227a92018-03-13 09:41:05 -070019007 assoc_add_ie = hdd_assoc_additional_ie(adapter);
19008 cur_add_ie_len = assoc_add_ie->length;
19009 if (SIR_MAC_MAX_ADD_IE_LENGTH < (cur_add_ie_len + len)) {
19010 hdd_err("current len %u, new ie of len %u will overflow",
19011 cur_add_ie_len, len);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019012 return -ENOMEM;
19013 }
Jeff Johnson20227a92018-03-13 09:41:05 -070019014 memcpy(assoc_add_ie->addIEdata + cur_add_ie_len, gen_ie, len);
19015 assoc_add_ie->length += len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019016
Jeff Johnson20227a92018-03-13 09:41:05 -070019017 roam_profile = hdd_roam_profile(adapter);
19018 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
19019 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
19020
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019021 return 0;
19022}
19023
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019024#ifdef WLAN_FEATURE_FILS_SK
19025/**
19026 * wlan_hdd_save_hlp_ie - API to save HLP IE
19027 * @roam_profile: Pointer to roam profile
19028 * @gen_ie: IE buffer to store
19029 * @len: length of the IE buffer @gen_ie
19030 * @flush: Flush the older saved HLP if any
19031 *
19032 * Return: None
19033 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070019034static void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070019035 const uint8_t *gen_ie, uint16_t len,
19036 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019037{
19038 uint8_t *hlp_ie = roam_profile->hlp_ie;
19039
19040 if (flush) {
19041 roam_profile->hlp_ie_len = 0;
19042 if (hlp_ie) {
19043 qdf_mem_free(hlp_ie);
19044 roam_profile->hlp_ie = NULL;
19045 }
19046 }
19047
19048 if ((roam_profile->hlp_ie_len +
19049 len) > FILS_MAX_HLP_DATA_LEN) {
19050 hdd_err("HLP len exceeds: hlp_ie_len %d len %d",
19051 roam_profile->hlp_ie_len, len);
19052 return;
19053 }
19054
19055 if (!roam_profile->hlp_ie) {
19056 roam_profile->hlp_ie =
19057 qdf_mem_malloc(FILS_MAX_HLP_DATA_LEN);
19058 hlp_ie = roam_profile->hlp_ie;
Min Liu74a1a502018-10-10 19:59:07 +080019059 if (!hlp_ie)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019060 return;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019061 }
19062
19063 qdf_mem_copy(hlp_ie + roam_profile->hlp_ie_len, gen_ie, len);
19064 roam_profile->hlp_ie_len += len;
19065}
19066#else
Jeff Johnson61b5e982018-03-15 11:33:31 -070019067static inline void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070019068 const uint8_t *gen_ie, uint16_t len,
19069 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019070{}
19071#endif
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080019072
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080019073/**
19074 * hdd_populate_crypto_auth_type() - populate auth type for crypto
19075 * @vdev: pointed to vdev obmgr
19076 * @auth_type: legacy auth_type
19077 *
19078 * set the crypto auth type for corresponding auth type received
19079 * from NL
19080 *
19081 * Return: None
19082 */
19083static void hdd_populate_crypto_auth_type(struct wlan_objmgr_vdev *vdev,
19084 enum nl80211_auth_type auth_type)
19085{
19086 QDF_STATUS status;
19087 uint32_t set_val = 0;
19088 wlan_crypto_auth_mode crypto_auth_type =
19089 osif_nl_to_crypto_auth_type(auth_type);
19090
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080019091 HDD_SET_BIT(set_val, crypto_auth_type);
19092 status = wlan_crypto_set_vdev_param(vdev,
19093 WLAN_CRYPTO_PARAM_AUTH_MODE,
19094 set_val);
19095 if (QDF_IS_STATUS_ERROR(status))
19096 hdd_err("Failed to set auth type %0X to crypto component",
19097 set_val);
19098}
19099
19100/**
19101 * hdd_populate_crypto_akm_type() - populate akm type for crypto
19102 * @vdev: pointed to vdev obmgr
19103 * @akm_type: legacy akm_type
19104 *
19105 * set the crypto akm type for corresponding akm type received
19106 * from NL
19107 *
19108 * Return: None
19109 */
19110static void hdd_populate_crypto_akm_type(struct wlan_objmgr_vdev *vdev,
19111 u32 key_mgmt)
19112{
19113 QDF_STATUS status;
19114 uint32_t set_val = 0;
19115 wlan_crypto_key_mgmt crypto_akm_type =
19116 osif_nl_to_crypto_akm_type(key_mgmt);
19117
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080019118 HDD_SET_BIT(set_val, crypto_akm_type);
19119
19120 status = wlan_crypto_set_vdev_param(vdev,
19121 WLAN_CRYPTO_PARAM_KEY_MGMT,
19122 set_val);
19123 if (QDF_IS_STATUS_ERROR(status))
19124 hdd_err("Failed to set akm type %0x to crypto component",
19125 set_val);
19126}
19127
19128/**
19129 * hdd_populate_crypto_cipher_type() - populate cipher type for crypto
19130 * @cipher: legacy cipher type
19131 * @vdev: pointed to vdev obmgr
19132 * @cipher_param_type: param type, UCST/MCAST
19133 *
19134 * set the crypto cipher type for corresponding cipher type received
19135 * from NL
19136 *
19137 * Return: None
19138 */
19139static void hdd_populate_crypto_cipher_type(u32 cipher,
19140 struct wlan_objmgr_vdev *vdev,
19141 wlan_crypto_param_type
19142 cipher_param_type)
19143{
19144 QDF_STATUS status;
19145 uint32_t set_val = 0;
19146 wlan_crypto_cipher_type crypto_cipher_type =
19147 osif_nl_to_crypto_cipher_type(cipher);
19148
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080019149 HDD_SET_BIT(set_val, crypto_cipher_type);
19150 status = wlan_crypto_set_vdev_param(vdev, cipher_param_type, set_val);
19151 if (QDF_IS_STATUS_ERROR(status))
Arun Kumar Khandavalliafcb0552020-01-20 11:46:36 +053019152 hdd_debug("Failed to set cipher params %d type %0x to crypto",
19153 cipher_param_type, set_val);
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080019154}
19155
19156/**
19157 * hdd_populate_crypto_params() - set crypto params
19158 * @vdev: Pointer to vdev obh mgr
19159 * @req: Pointer to security parameters
19160 *
19161 * Set Auth, Akm and Cipher type for crypto
19162 *
19163 * Return: None
19164 */
19165static void hdd_populate_crypto_params(struct wlan_objmgr_vdev *vdev,
19166 struct cfg80211_connect_params *req)
19167{
19168 hdd_populate_crypto_auth_type(vdev, req->auth_type);
19169
19170 if (req->crypto.n_akm_suites)
19171 hdd_populate_crypto_akm_type(vdev, req->crypto.akm_suites[0]);
19172
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019173 if (req->crypto.n_ciphers_pairwise)
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080019174 hdd_populate_crypto_cipher_type(req->crypto.ciphers_pairwise[0],
19175 vdev,
19176 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080019177
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019178 if (req->crypto.cipher_group)
19179 hdd_populate_crypto_cipher_type(req->crypto.cipher_group,
19180 vdev,
19181 WLAN_CRYPTO_PARAM_MCAST_CIPHER);
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080019182}
19183
19184/**
19185 * hdd_set_crypto_key_mgmt_param() - Set key mgmt param.
19186 * @adapter: Pointer to adapter.
19187 *
19188 * Return: None
19189 */
19190static void hdd_set_crypto_key_mgmt_param(struct hdd_adapter *adapter)
19191{
19192 uint32_t key_mgmt = 0;
19193 struct wlan_objmgr_vdev *vdev;
19194
19195 if (!adapter) {
19196 hdd_err("adapter is null");
19197 return;
19198 }
19199
19200 vdev = hdd_objmgr_get_vdev(adapter);
19201 if (!vdev)
19202 return;
19203
19204 if (adapter->wapi_info.wapi_auth_mode == WAPI_AUTH_MODE_PSK)
19205 HDD_SET_BIT(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK);
19206 if (adapter->wapi_info.wapi_auth_mode == WAPI_AUTH_MODE_CERT)
19207 HDD_SET_BIT(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT);
19208
19209 wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT, key_mgmt);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053019210 hdd_objmgr_put_vdev(vdev);
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080019211}
19212
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019213/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019214 * wlan_hdd_cfg80211_set_ie() - set IEs
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019215 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019216 * @ie: Pointer ot ie
19217 * @ie: IE length
19218 *
19219 * Return: 0 for success, non-zero for failure
19220 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019221static int wlan_hdd_cfg80211_set_ie(struct hdd_adapter *adapter,
Jeff Johnson2a722002017-09-30 20:02:35 -070019222 const uint8_t *ie,
19223 size_t ie_len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019224{
Jeff Johnson20227a92018-03-13 09:41:05 -070019225 struct csr_roam_profile *roam_profile;
19226 tSirAddie *assoc_add_ie;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019227 const uint8_t *genie = ie;
19228 uint16_t remLen = ie_len;
19229#ifdef FEATURE_WLAN_WAPI
19230 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
tinlin8a44b642018-04-25 13:56:06 +080019231 uint8_t *tmp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019232 uint16_t akmsuiteCount;
tinlin8a44b642018-04-25 13:56:06 +080019233 uint32_t *akmlist;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019234#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019235 int status;
Jeff Johnson20227a92018-03-13 09:41:05 -070019236 uint8_t *security_ie;
19237
19238 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019239
19240 /* clear previous assocAddIE */
Jeff Johnson20227a92018-03-13 09:41:05 -070019241 assoc_add_ie = hdd_assoc_additional_ie(adapter);
19242 assoc_add_ie->length = 0;
19243 roam_profile->bWPSAssociation = false;
19244 roam_profile->bOSENAssociation = false;
19245 security_ie = hdd_security_ie(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019246
19247 while (remLen >= 2) {
19248 uint16_t eLen = 0;
19249 uint8_t elementId;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019250
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019251 elementId = *genie++;
19252 eLen = *genie++;
19253 remLen -= 2;
19254
Nachiket Kukade4bea8b42017-06-13 11:53:19 +053019255 /* Sanity check on eLen */
19256 if (eLen > remLen) {
19257 hdd_err("%s: Invalid IE length[%d] for IE[0x%X]",
19258 __func__, eLen, elementId);
19259 QDF_ASSERT(0);
19260 return -EINVAL;
19261 }
19262
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019263 switch (elementId) {
19264 case DOT11F_EID_WPA:
19265 if (4 > eLen) { /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019266 hdd_err("Invalid vendor ie");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019267 return -EINVAL;
19268 } else if (0 ==
19269 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
Jeff Johnson20227a92018-03-13 09:41:05 -070019270 uint16_t curAddIELen = assoc_add_ie->length;
19271
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019272 hdd_debug("WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019273
19274 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019275 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070019276 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019277 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019278 return -ENOMEM;
19279 }
19280 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070019281 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019282 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019283 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019284
Jeff Johnson20227a92018-03-13 09:41:05 -070019285 roam_profile->bWPSAssociation = true;
19286 roam_profile->pAddIEAssoc =
19287 assoc_add_ie->addIEdata;
19288 roam_profile->nAddIEAssocLength =
19289 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019290 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowdacf161402019-03-14 11:37:33 -070019291 if (eLen > (WLAN_MAX_IE_LEN - 2)) {
Nachiket Kukade2f6509f2017-06-13 17:45:46 +053019292 hdd_err("%s: Invalid WPA IE length[%d]",
19293 __func__, eLen);
19294 QDF_ASSERT(0);
19295 return -EINVAL;
19296 }
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019297 hdd_debug("WPA IE (len %d)", eLen + 2);
Srinivas Girigowdacf161402019-03-14 11:37:33 -070019298 memset(security_ie, 0, WLAN_MAX_IE_LEN);
Jeff Johnson20227a92018-03-13 09:41:05 -070019299 memcpy(security_ie, genie - 2, (eLen + 2));
19300 roam_profile->pWPAReqIE = security_ie;
19301 roam_profile->nWPAReqIELength = eLen + 2; /* ie_len; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019302 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
19303 P2P_OUI_TYPE_SIZE))) {
19304 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070019305 assoc_add_ie->length;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019306 hdd_debug("P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019307
19308 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019309 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070019310 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019311 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019312 return -ENOMEM;
19313 }
19314 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070019315 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019316 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019317 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019318
Jeff Johnson20227a92018-03-13 09:41:05 -070019319 roam_profile->pAddIEAssoc =
19320 assoc_add_ie->addIEdata;
19321 roam_profile->nAddIEAssocLength =
19322 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019323 }
19324#ifdef WLAN_FEATURE_WFD
19325 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
19326 WFD_OUI_TYPE_SIZE)) &&
19327 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080019328 (QDF_P2P_CLIENT_MODE ==
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019329 adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019330 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070019331 assoc_add_ie->length;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019332 hdd_debug("WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019333
19334 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019335 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070019336 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019337 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019338 return -ENOMEM;
19339 }
19340 /* WFD IE is saved to Additional IE ; it should
19341 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080019342 * WFD IE
19343 */
Jeff Johnson20227a92018-03-13 09:41:05 -070019344 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019345 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019346 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019347
Jeff Johnson20227a92018-03-13 09:41:05 -070019348 roam_profile->pAddIEAssoc =
19349 assoc_add_ie->addIEdata;
19350 roam_profile->nAddIEAssocLength =
19351 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019352 }
19353#endif
19354 /* Appending HS 2.0 Indication Element in Assiciation Request */
19355 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
19356 HS20_OUI_TYPE_SIZE))) {
19357 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070019358 assoc_add_ie->length;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019359 hdd_debug("HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019360
19361 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019362 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070019363 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019364 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019365 return -ENOMEM;
19366 }
Jeff Johnson20227a92018-03-13 09:41:05 -070019367 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019368 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019369 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019370
Jeff Johnson20227a92018-03-13 09:41:05 -070019371 roam_profile->pAddIEAssoc =
19372 assoc_add_ie->addIEdata;
19373 roam_profile->nAddIEAssocLength =
19374 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019375 }
19376 /* Appending OSEN Information Element in Assiciation Request */
19377 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
19378 OSEN_OUI_TYPE_SIZE))) {
19379 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070019380 assoc_add_ie->length;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019381 hdd_debug("OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019382
19383 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019384 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070019385 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019386 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019387 return -ENOMEM;
19388 }
Jeff Johnson20227a92018-03-13 09:41:05 -070019389 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019390 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019391 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019392
Jeff Johnson20227a92018-03-13 09:41:05 -070019393 roam_profile->bOSENAssociation = true;
19394 roam_profile->pAddIEAssoc =
19395 assoc_add_ie->addIEdata;
19396 roam_profile->nAddIEAssocLength =
19397 assoc_add_ie->length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019398 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
19399 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019400 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019401 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019402 genie - 2, eLen + 2);
19403 if (status)
19404 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019405 } else {
19406 uint16_t add_ie_len =
Jeff Johnson20227a92018-03-13 09:41:05 -070019407 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019408
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019409 hdd_debug("Additional IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019410
19411 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019412 (assoc_add_ie->length + eLen)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019413 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019414 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019415 return -ENOMEM;
19416 }
19417
Jeff Johnson20227a92018-03-13 09:41:05 -070019418 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019419 add_ie_len, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019420 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019421
Jeff Johnson20227a92018-03-13 09:41:05 -070019422 roam_profile->pAddIEAssoc =
19423 assoc_add_ie->addIEdata;
19424 roam_profile->nAddIEAssocLength =
19425 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019426 }
19427 break;
19428 case DOT11F_EID_RSN:
tinlin8a44b642018-04-25 13:56:06 +080019429 if (eLen > DOT11F_IE_RSN_MAX_LEN) {
Vignesh Viswanathan96e0e702017-12-05 19:42:46 +053019430 hdd_err("%s: Invalid WPA RSN IE length[%d]",
tinlin8a44b642018-04-25 13:56:06 +080019431 __func__, eLen);
Vignesh Viswanathan96e0e702017-12-05 19:42:46 +053019432 return -EINVAL;
19433 }
Srinivas Girigowdacf161402019-03-14 11:37:33 -070019434 memset(security_ie, 0, WLAN_MAX_IE_LEN);
Jeff Johnson20227a92018-03-13 09:41:05 -070019435 memcpy(security_ie, genie - 2, (eLen + 2));
19436 roam_profile->pRSNReqIE = security_ie;
19437 roam_profile->nRSNReqIELength = eLen + 2; /* ie_len; */
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019438 hdd_debug("RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019439 break;
19440 /*
19441 * Appending Extended Capabilities with Interworking bit set
19442 * in Assoc Req.
19443 *
19444 * In assoc req this EXT Cap will only be taken into account if
19445 * interworkingService bit is set to 1. Currently
19446 * driver is only interested in interworkingService capability
19447 * from supplicant. If in future any other EXT Cap info is
19448 * required from supplicat, it needs to be handled while
19449 * sending Assoc Req in LIM.
19450 */
19451 case DOT11F_EID_EXTCAP:
19452 {
19453 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070019454 assoc_add_ie->length;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019455 hdd_debug("Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019456
19457 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019458 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070019459 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019460 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019461 return -ENOMEM;
19462 }
Jeff Johnson20227a92018-03-13 09:41:05 -070019463 memcpy(assoc_add_ie->addIEdata + curAddIELen, genie - 2, eLen + 2);
19464 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019465
Jeff Johnson20227a92018-03-13 09:41:05 -070019466 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
19467 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019468 break;
19469 }
19470#ifdef FEATURE_WLAN_WAPI
Srinivas Girigowda61771262019-04-01 11:55:19 -070019471 case WLAN_ELEMID_WAPI:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019472 /* Setting WAPI Mode to ON=1 */
tinlin8a44b642018-04-25 13:56:06 +080019473 adapter->wapi_info.wapi_mode = 1;
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070019474 hdd_debug("WAPI MODE IS %u", adapter->wapi_info.wapi_mode);
Abhinav Kumarf56c81f2018-06-06 16:07:01 +053019475 /* genie is pointing to data field of WAPI IE's buffer */
19476 tmp = (uint8_t *)genie;
19477 /* Validate length for Version(2 bytes) and Number
19478 * of AKM suite (2 bytes) in WAPI IE buffer, coming from
19479 * supplicant*/
19480 if (eLen < 4) {
19481 hdd_err("Invalid IE Len: %u", eLen);
19482 return -EINVAL;
19483 }
19484 tmp = tmp + 2; /* Skip Version */
tinlin8a44b642018-04-25 13:56:06 +080019485 /* Get the number of AKM suite */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019486 akmsuiteCount = WPA_GET_LE16(tmp);
tinlin8a44b642018-04-25 13:56:06 +080019487 /* Skip the number of AKM suite */
19488 tmp = tmp + 2;
Abhinav Kumarf56c81f2018-06-06 16:07:01 +053019489 /* Validate total length for WAPI IE's buffer */
19490 if (eLen < (4 + (akmsuiteCount * sizeof(uint32_t)))) {
19491 hdd_err("Invalid IE Len: %u", eLen);
19492 return -EINVAL;
19493 }
tinlin8a44b642018-04-25 13:56:06 +080019494 /* AKM suite list, each OUI contains 4 bytes */
19495 akmlist = (uint32_t *)(tmp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019496 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
Vignesh Viswanathan845bd472018-06-11 18:45:45 +053019497 qdf_mem_copy(akmsuite, akmlist,
19498 sizeof(uint32_t) * akmsuiteCount);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019499 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019500 hdd_err("Invalid akmSuite count: %u",
19501 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019502 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019503 return -EINVAL;
19504 }
19505
19506 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019507 hdd_debug("WAPI AUTH MODE SET TO PSK");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070019508 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019509 WAPI_AUTH_MODE_PSK;
19510 }
19511 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019512 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070019513 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019514 WAPI_AUTH_MODE_CERT;
19515 }
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080019516
19517 hdd_set_crypto_key_mgmt_param(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019518 break;
19519#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019520 case DOT11F_EID_SUPPOPERATINGCLASSES:
19521 {
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019522 hdd_debug("Supported Operating Classes IE(len %d)",
19523 eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019524 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019525 genie - 2, eLen + 2);
19526 if (status)
19527 return status;
19528 break;
19529 }
Srinivas Girigowda61771262019-04-01 11:55:19 -070019530 case WLAN_REQUEST_IE_MAX_LEN:
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019531 {
19532 if (genie[0] == SIR_FILS_HLP_EXT_EID) {
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019533 hdd_debug("HLP EXT IE(len %d)",
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019534 eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019535 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019536 genie - 2, eLen + 2,
19537 true);
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019538 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070019539 adapter, genie - 2,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019540 eLen + 2);
19541 if (status)
19542 return status;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053019543 } else if (genie[0] ==
19544 SIR_DH_PARAMETER_ELEMENT_EXT_EID) {
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019545 hdd_debug("DH EXT IE(len %d)",
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053019546 eLen + 2);
19547 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070019548 adapter, genie - 2,
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053019549 eLen + 2);
19550 if (status)
19551 return status;
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019552 } else {
19553 hdd_err("UNKNOWN EID: %X", genie[0]);
19554 }
19555 break;
19556 }
19557 case DOT11F_EID_FRAGMENT_IE:
19558 {
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019559 hdd_debug("Fragment IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019560 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019561 genie - 2, eLen + 2,
19562 false);
Jeff Johnson20227a92018-03-13 09:41:05 -070019563 status = wlan_hdd_add_assoc_ie(adapter,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019564 genie - 2, eLen + 2);
19565 if (status)
19566 return status;
19567 break;
19568 }
Pragaspathi Thilagarajc0515882019-10-24 02:59:11 +053019569 case WLAN_ELEMID_RSNXE:
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019570 hdd_debug("RSNXE(len %d)", eLen + 2);
Pragaspathi Thilagarajc0515882019-10-24 02:59:11 +053019571 status = wlan_hdd_add_assoc_ie(adapter, genie - 2,
19572 eLen + 2);
19573 if (status)
19574 return status;
19575 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019576 default:
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019577 hdd_err("UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080019578 /* when Unknown IE is received we break
19579 * and continue to the next IE in the buffer
19580 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019581 break;
19582 }
19583 genie += eLen;
19584 remLen -= eLen;
19585 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019586 return 0;
19587}
19588
Abhishek Ambure68677462019-09-13 12:44:26 +053019589#ifdef QCA_IBSS_SUPPORT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019590/**
19591 * hdd_is_wpaie_present() - check for WPA ie
19592 * @ie: Pointer to ie
19593 * @ie_len: Ie length
19594 *
19595 * Parse the received IE to find the WPA IE
19596 *
19597 * Return: true if wpa ie is found else false
19598 */
19599static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
19600{
19601 uint8_t eLen = 0;
19602 uint16_t remLen = ie_len;
19603 uint8_t elementId = 0;
19604
19605 while (remLen >= 2) {
19606 elementId = *ie++;
19607 eLen = *ie++;
19608 remLen -= 2;
19609 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019610 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019611 return false;
19612 }
19613 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
19614 /* OUI - 0x00 0X50 0XF2
19615 * WPA Information Element - 0x01
19616 * WPA version - 0x01
19617 */
19618 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
19619 return true;
19620 }
19621 ie += eLen;
19622 remLen -= eLen;
19623 }
19624 return false;
19625}
19626
Abhishek Ambure68677462019-09-13 12:44:26 +053019627/**
19628 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
19629 * @adapter: Pointer to adapter
19630 * @param: Pointer to IBSS parameters
19631 *
19632 * This function is used to initialize the security settings in IBSS mode
19633 *
19634 * Return: 0 for success, non-zero for failure
19635 */
19636static int wlan_hdd_cfg80211_set_privacy_ibss(struct hdd_adapter *adapter,
19637 struct cfg80211_ibss_params
19638 *params)
19639{
19640 uint32_t ret;
19641 int status = 0;
19642 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
19643 struct hdd_station_ctx *sta_ctx =
19644 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19645 struct csr_roam_profile *roam_profile;
19646
19647 hdd_enter();
19648
19649 sta_ctx->wpa_versions = 0;
19650 qdf_mem_zero(&sta_ctx->ibss_enc_key, sizeof(tCsrRoamSetKey));
19651 sta_ctx->ibss_enc_key_installed = 0;
19652
19653 if (params->ie_len && (params->ie)) {
19654 if (wlan_get_ie_ptr_from_eid(WLAN_EID_RSN, params->ie,
19655 params->ie_len)) {
19656 sta_ctx->wpa_versions = NL80211_WPA_VERSION_2;
19657 encryptionType = eCSR_ENCRYPT_TYPE_AES;
19658 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
19659 tDot11fIEWPA dot11_wpa_ie;
19660 mac_handle_t mac_handle =
19661 hdd_adapter_get_mac_handle(adapter);
19662 const u8 *ie;
19663
19664 memset(&dot11_wpa_ie, 0, sizeof(dot11_wpa_ie));
19665 ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_WPA,
19666 params->ie, params->ie_len);
19667 if (ie) {
19668 sta_ctx->wpa_versions = NL80211_WPA_VERSION_1;
19669 /* Unpack the WPA IE
19670 * Skip past the EID byte and length byte
19671 * and four byte WiFi OUI
19672 */
19673 if (ie[1] < DOT11F_IE_WPA_MIN_LEN ||
19674 ie[1] > DOT11F_IE_WPA_MAX_LEN) {
19675 hdd_err("invalid ie len:%d", ie[1]);
19676 return -EINVAL;
19677 }
19678 ret = dot11f_unpack_ie_wpa(
19679 MAC_CONTEXT(mac_handle),
19680 (uint8_t *)&ie[2 + 4],
19681 ie[1] - 4, &dot11_wpa_ie, false);
19682 if (DOT11F_FAILED(ret)) {
19683 hdd_err("unpack failed ret: 0x%x", ret);
19684 return -EINVAL;
19685 }
19686 /*
19687 * Extract the multicast cipher, the
19688 * encType for unicast cipher for
19689 * wpa-none is none
19690 */
19691 encryptionType =
19692 hdd_translate_wpa_to_csr_encryption_type
19693 (dot11_wpa_ie.multicast_cipher);
19694 }
19695 }
19696
19697 status =
19698 wlan_hdd_cfg80211_set_ie(adapter, params->ie,
19699 params->ie_len);
19700
19701 if (0 > status) {
19702 hdd_err("Failed to parse WPA/RSN IE");
19703 return status;
19704 }
19705 }
19706
19707 roam_profile = hdd_roam_profile(adapter);
19708 roam_profile->AuthType.authType[0] =
19709 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM;
19710
19711 if (params->privacy) {
19712 /* Security enabled IBSS, At this time there is no information
19713 * available about the security parameters, so initialise the
19714 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
19715 * The correct security parameters will be updated later in
19716 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
19717 * set inorder enable privacy bit in beacons
19718 */
19719
19720 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
19721 }
19722 hdd_debug("encryptionType=%d", encryptionType);
19723 sta_ctx->conn_info.uc_encrypt_type = encryptionType;
19724 roam_profile->EncryptionType.numEntries = 1;
19725 roam_profile->EncryptionType.encryptionType[0] =
19726 encryptionType;
19727 return status;
19728}
19729
19730/**
19731 * __wlan_hdd_cfg80211_join_ibss() - join ibss
19732 * @wiphy: Pointer to wiphy
19733 * @dev: Pointer to network device
19734 * @param: Pointer to IBSS join parameters
19735 *
19736 * This function is used to create/join an IBSS network
19737 *
19738 * Return: 0 for success, non-zero for failure
19739 */
19740static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
19741 struct net_device *dev,
19742 struct cfg80211_ibss_params *params)
19743{
19744 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19745 struct csr_roam_profile *roam_profile;
19746 int status;
19747 struct hdd_station_ctx *sta_ctx =
19748 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19749 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
19750 struct qdf_mac_addr bssid;
19751 uint8_t channelNum = 0;
19752 mac_handle_t mac_handle;
19753 struct wlan_mlme_ibss_cfg ibss_cfg = {0};
19754 uint8_t conn_info_channel;
19755
19756 hdd_enter();
19757
19758 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19759 hdd_err("Command not allowed in FTM mode");
19760 return -EINVAL;
19761 }
19762
19763 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
19764 return -EINVAL;
19765
19766 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
19767 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
19768 adapter->vdev_id, adapter->device_mode);
19769
19770 hdd_debug("Device_mode %s(%d)",
19771 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
19772
19773 status = wlan_hdd_validate_context(hdd_ctx);
19774
19775 if (0 != status)
19776 return status;
19777
19778 if (QDF_IS_STATUS_ERROR(ucfg_mlme_get_ibss_cfg(hdd_ctx->psoc,
19779 &ibss_cfg))) {
19780 return -EINVAL;
19781 }
19782
19783 mac_handle = hdd_ctx->mac_handle;
19784 if (NULL !=
19785 params->chandef.chan) {
19786 uint32_t numChans = CFG_VALID_CHANNEL_LIST_LEN;
19787 uint32_t validChan[CFG_VALID_CHANNEL_LIST_LEN];
19788 int indx;
19789
19790 /* Get channel number */
19791 channelNum = ieee80211_frequency_to_channel(
19792 params->
19793 chandef.
19794 chan->
19795 center_freq);
19796 ucfg_mlme_get_valid_channel_freq_list(hdd_ctx->psoc, validChan,
19797 &numChans);
19798
19799 for (indx = 0; indx < numChans; indx++) {
19800 if (channelNum ==
19801 wlan_reg_freq_to_chan(hdd_ctx->pdev, validChan[indx]))
19802 break;
19803 }
19804 if (indx >= numChans) {
19805 hdd_err("Not valid Channel: %d", channelNum);
19806 return -EINVAL;
19807 }
19808 }
19809
19810 /* Disable NAN Discovery if enabled */
19811 ucfg_nan_disable_concurrency(hdd_ctx->psoc);
19812
Manikandan Mohan282c4b62019-08-14 17:42:22 -070019813 if (!policy_mgr_allow_concurrency(
19814 hdd_ctx->psoc, PM_IBSS_MODE,
19815 wlan_reg_chan_to_freq(hdd_ctx->pdev, channelNum),
19816 HW_MODE_20_MHZ)) {
Abhishek Ambure68677462019-09-13 12:44:26 +053019817 hdd_err("This concurrency combination is not allowed");
19818 return -ECONNREFUSED;
19819 }
19820
19821 status = policy_mgr_reset_connection_update(hdd_ctx->psoc);
19822 if (!QDF_IS_STATUS_SUCCESS(status))
19823 hdd_err("qdf_reset_connection_update failed status: %d", status);
19824
Manikandan Mohan282c4b62019-08-14 17:42:22 -070019825 status = policy_mgr_current_connections_update(
19826 hdd_ctx->psoc, adapter->vdev_id,
19827 wlan_reg_chan_to_freq(hdd_ctx->pdev, channelNum),
19828 POLICY_MGR_UPDATE_REASON_JOIN_IBSS);
Abhishek Ambure68677462019-09-13 12:44:26 +053019829 if (QDF_STATUS_E_FAILURE == status) {
19830 hdd_err("connections update failed!!");
19831 return -EINVAL;
19832 }
19833
19834 if (QDF_STATUS_SUCCESS == status) {
19835 status = policy_mgr_wait_for_connection_update(
19836 hdd_ctx->psoc);
19837 if (!QDF_IS_STATUS_SUCCESS(status)) {
19838 hdd_err("qdf wait for event failed!!");
19839 return -EINVAL;
19840 }
19841 }
19842
19843 /*Try disconnecting if already in connected state */
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053019844 status = wlan_hdd_try_disconnect(adapter,
19845 eSIR_MAC_UNSPEC_FAILURE_REASON);
Abhishek Ambure68677462019-09-13 12:44:26 +053019846 if (0 > status) {
19847 hdd_err("Failed to disconnect the existing IBSS connection");
19848 return -EALREADY;
19849 }
19850
19851 roam_profile = hdd_roam_profile(adapter);
19852
19853 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
19854 hdd_err("Interface type is not set to IBSS");
19855 return -EINVAL;
19856 }
19857
19858 /* enable selected protection checks in IBSS mode */
19859 roam_profile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
19860
19861 /* BSSID is provided by upper layers hence no need to AUTO generate */
19862 if (params->bssid) {
19863 if (ucfg_mlme_set_ibss_auto_bssid(hdd_ctx->psoc, 0)
19864 == QDF_STATUS_E_FAILURE) {
19865 hdd_err("Unable to update MLME IBSS Auto BSSID config");
19866 return -EIO;
19867 }
19868 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
19869 } else if (ibss_cfg.coalesing_enable == 0) {
19870 if (ucfg_mlme_set_ibss_auto_bssid(hdd_ctx->psoc, 0)
19871 == QDF_STATUS_E_FAILURE) {
19872 hdd_err("Unable to update MLME IBSS Auto BSSID config");
19873 return -EIO;
19874 }
19875 qdf_copy_macaddr(&bssid, &ibss_cfg.bssid);
19876 }
19877
19878 if (cfg_in_range(CFG_BEACON_INTERVAL, params->beacon_interval))
19879 roam_profile->beaconInterval = params->beacon_interval;
19880 else
19881 roam_profile->beaconInterval = cfg_get(hdd_ctx->psoc,
19882 CFG_BEACON_INTERVAL);
19883
19884 /* Set Channel */
19885 if (channelNum) {
19886 /* Set the Operational Channel */
19887 hdd_debug("set channel %d", channelNum);
19888 roam_profile->ChannelInfo.numOfChannels = 1;
19889 sta_ctx->conn_info.chan_freq =
19890 wlan_reg_chan_to_freq(hdd_ctx->pdev,
19891 channelNum);
19892 roam_profile->ChannelInfo.freq_list =
19893 &sta_ctx->conn_info.chan_freq;
19894 }
19895
19896 /* Initialize security parameters */
19897 status = wlan_hdd_cfg80211_set_privacy_ibss(adapter, params);
19898 if (status < 0) {
19899 hdd_err("failed to set security parameters");
19900 return status;
19901 }
19902
19903 conn_info_channel =
19904 wlan_reg_freq_to_chan(
19905 hdd_ctx->pdev,
19906 sta_ctx->conn_info.chan_freq);
19907 /* Issue connect start */
19908 status = wlan_hdd_cfg80211_connect_start(adapter, params->ssid,
19909 params->ssid_len,
19910 bssid.bytes, NULL,
19911 conn_info_channel,
19912 params->chandef.width);
19913
19914 if (0 > status) {
19915 hdd_err("connect failed");
19916 return status;
19917 }
19918 hdd_exit();
19919 return 0;
19920}
19921
19922/**
19923 * wlan_hdd_cfg80211_join_ibss() - join ibss
19924 * @wiphy: Pointer to wiphy
19925 * @dev: Pointer to network device
19926 * @param: Pointer to IBSS join parameters
19927 *
19928 * This function is used to create/join an IBSS network
19929 *
19930 * Return: 0 for success, non-zero for failure
19931 */
19932static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
19933 struct net_device *dev,
19934 struct cfg80211_ibss_params *params)
19935{
19936 int errno;
19937 struct osif_vdev_sync *vdev_sync;
19938
19939 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
19940 if (errno)
19941 return errno;
19942
19943 errno = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
19944
19945 osif_vdev_sync_op_stop(vdev_sync);
19946
19947 return errno;
19948}
19949
19950/**
19951 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
19952 * @wiphy: Pointer to wiphy
19953 * @dev: Pointer to network device
19954 *
19955 * This function is used to leave an IBSS network
19956 *
19957 * Return: 0 for success, non-zero for failure
19958 */
19959static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
19960 struct net_device *dev)
19961{
19962 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19963 struct csr_roam_profile *roam_profile;
19964 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
19965 int status;
19966 mac_handle_t mac_handle;
19967 unsigned long rc;
19968 tSirUpdateIE update_ie;
19969
19970 hdd_enter();
19971
19972 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19973 hdd_err("Command not allowed in FTM mode");
19974 return -EINVAL;
19975 }
19976
19977 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
19978 return -EINVAL;
19979
19980 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
19981 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
19982 adapter->vdev_id, eCSR_DISCONNECT_REASON_IBSS_LEAVE);
19983
19984 status = wlan_hdd_validate_context(hdd_ctx);
19985 if (0 != status)
19986 return status;
19987
19988 hdd_debug("Device_mode %s(%d)",
19989 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
19990
19991 roam_profile = hdd_roam_profile(adapter);
19992
19993 /* Issue disconnect only if interface type is set to IBSS */
19994 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
19995 hdd_err("BSS Type is not set to IBSS");
19996 return -EINVAL;
19997 }
19998 /* Clearing add IE of beacon */
19999 qdf_mem_copy(update_ie.bssid.bytes, adapter->mac_addr.bytes,
20000 sizeof(tSirMacAddr));
Abhishek Singh5a2c42f2019-11-19 11:39:23 +053020001 update_ie.vdev_id = adapter->vdev_id;
Abhishek Ambure68677462019-09-13 12:44:26 +053020002 update_ie.ieBufferlength = 0;
20003 update_ie.pAdditionIEBuffer = NULL;
20004 update_ie.append = true;
20005 update_ie.notify = true;
20006 mac_handle = hdd_ctx->mac_handle;
20007 if (sme_update_add_ie(mac_handle,
20008 &update_ie,
20009 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
20010 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
20011 }
20012
20013 /* Reset WNI_CFG_PROBE_RSP Flags */
20014 wlan_hdd_reset_prob_rspies(adapter);
20015
20016 /* Issue Disconnect request */
20017 INIT_COMPLETION(adapter->disconnect_comp_var);
20018 status = sme_roam_disconnect(mac_handle,
20019 adapter->vdev_id,
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020020 eCSR_DISCONNECT_REASON_IBSS_LEAVE,
20021 eSIR_MAC_UNSPEC_FAILURE_REASON);
Abhishek Ambure68677462019-09-13 12:44:26 +053020022 if (!QDF_IS_STATUS_SUCCESS(status)) {
20023 hdd_err("sme_roam_disconnect failed status: %d",
20024 status);
20025 return -EAGAIN;
20026 }
20027
20028 /* wait for mc thread to cleanup and then return to upper stack
20029 * so by the time upper layer calls the change interface, we are
20030 * all set to proceed further
20031 */
20032 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
20033 msecs_to_jiffies(SME_DISCONNECT_TIMEOUT));
20034 if (!rc) {
20035 hdd_err("Failed to disconnect, timed out");
20036 return -ETIMEDOUT;
20037 }
20038
20039 hdd_exit();
20040 return 0;
20041}
20042
20043/**
20044 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
20045 * @wiphy: Pointer to wiphy
20046 * @dev: Pointer to network device
20047 *
20048 * This function is used to leave an IBSS network
20049 *
20050 * Return: 0 for success, non-zero for failure
20051 */
20052static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
20053 struct net_device *dev)
20054{
20055 int errno;
20056 struct osif_vdev_sync *vdev_sync;
20057
20058 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
20059 if (errno)
20060 return errno;
20061
20062 errno = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
20063
20064 osif_vdev_sync_op_stop(vdev_sync);
20065
20066 return errno;
20067}
20068#else
20069/**
20070 * wlan_hdd_cfg80211_join_ibss() - join ibss
20071 * @wiphy: Pointer to wiphy
20072 * @dev: Pointer to network device
20073 * @param: Pointer to IBSS join parameters
20074 *
20075 * This function is dummy
20076 *
20077 * Return: 0
20078 */
20079static inline int
20080wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
20081 struct net_device *dev,
20082 struct cfg80211_ibss_params *params)
20083{
20084 return 0;
20085}
20086
20087/**
20088 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
20089 * @wiphy: Pointer to wiphy
20090 * @dev: Pointer to network device
20091 *
20092 * This function is dummy
20093 *
20094 * Return: 0
20095 */
20096static inline int
20097wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
20098 struct net_device *dev)
20099{
20100 return 0;
20101}
20102#endif
20103
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080020104static void wlan_hdd_cfg80211_store_wep_key(struct hdd_adapter *adapter,
20105 struct wlan_objmgr_vdev *vdev,
20106 struct cfg80211_connect_params *req)
20107{
20108 struct key_params params;
20109
20110 qdf_mem_zero(&params, sizeof(params));
20111 params.cipher = req->crypto.ciphers_pairwise[0];
20112 params.key_len = req->key_len;
20113 params.key = req->key;
20114 wlan_cfg80211_store_key(vdev, req->key_idx,
20115 WLAN_CRYPTO_KEY_TYPE_UNICAST,
20116 NULL, &params);
20117}
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080020118
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070020119/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020120 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020121 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020122 * @req: Pointer to security parameters
20123 *
20124 * Return: 0 for success, non-zero for failure
20125 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020126static int wlan_hdd_cfg80211_set_privacy(struct hdd_adapter *adapter,
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070020127 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020128{
20129 int status = 0;
Jeff Johnsonce4a8342017-10-14 13:12:22 -070020130 struct hdd_station_ctx *sta_ctx;
Jeff Johnson20227a92018-03-13 09:41:05 -070020131 struct csr_roam_profile *roam_profile;
Min Liu8c5d99e2018-09-10 17:18:44 +080020132 struct wlan_objmgr_vdev *vdev;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020133
Jeff Johnsonce4a8342017-10-14 13:12:22 -070020134 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
20135 sta_ctx->wpa_versions = req->crypto.wpa_versions;
Jeff Johnson20227a92018-03-13 09:41:05 -070020136 roam_profile = hdd_roam_profile(adapter);
20137
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070020138 /* populate auth,akm and cipher params for crypto */
Min Liu8c5d99e2018-09-10 17:18:44 +080020139 vdev = hdd_objmgr_get_vdev(adapter);
20140 if (!vdev)
20141 return -EINVAL;
20142 hdd_populate_crypto_params(vdev, req);
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070020143
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020144 /*set authentication type */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020145 status = wlan_hdd_cfg80211_set_auth_type(adapter, req->auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020146
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070020147 if (wlan_hdd_is_conn_type_fils(req)) {
20148 status = wlan_hdd_cfg80211_set_fils_config(adapter, req);
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053020149
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070020150 if (0 > status) {
20151 hdd_err("Failed to set fils config");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080020152 goto release_vdev_ref;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070020153 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020154 }
20155
20156 /*set key mgmt type */
20157 if (req->crypto.n_akm_suites) {
20158 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020159 wlan_hdd_set_akm_suite(adapter, req->crypto.akm_suites[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020160 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020161 hdd_err("Failed to set akm suite");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080020162 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020163 }
20164 }
20165
20166 /*set pairwise cipher type */
20167 if (req->crypto.n_ciphers_pairwise) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020168 status = wlan_hdd_cfg80211_set_cipher(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020169 req->crypto.
20170 ciphers_pairwise[0],
20171 true);
20172 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020173 hdd_err("Failed to set unicast cipher type");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080020174 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020175 }
20176 } else {
20177 /*Reset previous cipher suite to none */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020178 status = wlan_hdd_cfg80211_set_cipher(adapter, 0, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020179 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020180 hdd_err("Failed to set unicast cipher type");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080020181 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020182 }
20183 }
20184
20185 /*set group cipher type */
20186 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020187 wlan_hdd_cfg80211_set_cipher(adapter, req->crypto.cipher_group,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020188 false);
20189
20190 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020191 hdd_err("Failed to set mcast cipher type");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080020192 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020193 }
20194#ifdef WLAN_FEATURE_11W
Jeff Johnson20227a92018-03-13 09:41:05 -070020195 roam_profile->MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020196#endif
20197
20198 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
20199 if (req->ie_len) {
20200 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020201 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020202 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020203 hdd_err("Failed to parse the WPA/RSN IE");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080020204 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020205 }
20206 }
20207
20208 /*incase of WEP set default key information */
20209 if (req->key && req->key_len) {
Jeff Johnson37ecea42018-03-18 17:54:40 -070020210 u32 cipher = req->crypto.ciphers_pairwise[0];
Jeff Johnson68755312017-02-10 11:46:55 -080020211
Jeff Johnson37ecea42018-03-18 17:54:40 -070020212 if ((WLAN_CIPHER_SUITE_WEP40 == cipher) ||
20213 (WLAN_CIPHER_SUITE_WEP104 == cipher)) {
20214 enum hdd_auth_key_mgmt key_mgmt =
20215 sta_ctx->auth_key_mgmt;
20216
20217 if (key_mgmt & HDD_AUTH_KEY_MGMT_802_1X) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020218 hdd_err("Dynamic WEP not supported");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080020219 status = -EOPNOTSUPP;
20220 goto release_vdev_ref;
Jeff Johnson68755312017-02-10 11:46:55 -080020221 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020222
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080020223 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
20224 req->key_len) && (CSR_MAX_NUM_KEY > req->key_idx))
20225 wlan_hdd_cfg80211_store_wep_key(adapter,
20226 vdev, req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020227 }
20228 }
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080020229release_vdev_ref:
20230 hdd_objmgr_put_vdev(vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020231
20232 return status;
20233}
20234
wadesongcaad7c72018-08-06 13:26:27 +080020235/**
20236 * wlan_hdd_clear_wapi_privacy() - reset WAPI settings in HDD layer
20237 * @adapter: pointer to HDD adapter object
20238 *
20239 * This function resets all WAPI related parameters imposed before STA
20240 * connection starts. It's invoked when privacy checking against concurrency
20241 * fails, to make sure no improper WAPI settings are still populated before
20242 * returning an error to the upper layer requester.
20243 *
20244 * Return: none
20245 */
20246#ifdef FEATURE_WLAN_WAPI
20247static inline void wlan_hdd_clear_wapi_privacy(struct hdd_adapter *adapter)
20248{
20249 adapter->wapi_info.wapi_mode = 0;
20250 adapter->wapi_info.wapi_auth_mode = WAPI_AUTH_MODE_OPEN;
20251}
20252#else
20253static inline void wlan_hdd_clear_wapi_privacy(struct hdd_adapter *adapter)
20254{
20255}
20256#endif
20257
20258/**
20259 * wlan_hdd_cfg80211_clear_privacy() - reset STA security parameters
20260 * @adapter: pointer to HDD adapter object
20261 *
20262 * This function resets all privacy related parameters imposed
20263 * before STA connection starts. It's invoked when privacy checking
20264 * against concurrency fails, to make sure no improper settings are
20265 * still populated before returning an error to the upper layer requester.
20266 *
20267 * Return: none
20268 */
20269static void wlan_hdd_cfg80211_clear_privacy(struct hdd_adapter *adapter)
20270{
20271 struct hdd_station_ctx *hdd_sta_ctx =
20272 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
20273
20274 hdd_debug("resetting all privacy configurations");
20275
20276 hdd_sta_ctx->wpa_versions = 0;
20277
Jeff Johnson96e33512019-02-27 15:10:21 -080020278 hdd_sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_NONE;
wadesongcaad7c72018-08-06 13:26:27 +080020279 hdd_sta_ctx->roam_profile.AuthType.authType[0] = eCSR_AUTH_TYPE_NONE;
20280
Jeff Johnsonb1959842019-02-27 13:04:04 -080020281 hdd_sta_ctx->conn_info.uc_encrypt_type = eCSR_ENCRYPT_TYPE_NONE;
wadesongcaad7c72018-08-06 13:26:27 +080020282 hdd_sta_ctx->roam_profile.EncryptionType.numEntries = 0;
Jeff Johnsonb1959842019-02-27 13:04:04 -080020283 hdd_sta_ctx->conn_info.mc_encrypt_type = eCSR_ENCRYPT_TYPE_NONE;
wadesongcaad7c72018-08-06 13:26:27 +080020284 hdd_sta_ctx->roam_profile.mcEncryptionType.numEntries = 0;
20285
20286 wlan_hdd_clear_wapi_privacy(adapter);
20287}
20288
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020289static int wlan_hdd_wait_for_disconnect(mac_handle_t mac_handle,
20290 struct hdd_adapter *adapter,
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020291 uint16_t reason,
20292 tSirMacReasonCodes mac_reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020293{
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020294 eConnectionState prev_conn_state;
20295 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
20296 QDF_STATUS status = QDF_STATUS_SUCCESS;
20297 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020298 unsigned long rc;
Abhishek Singhd1f21c72019-01-21 15:16:34 +053020299 uint32_t wait_time = SME_DISCONNECT_TIMEOUT;
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020300
Abhishek Singh30769a32020-01-24 09:59:11 +053020301 /* Return if already disconnected */
20302 if (sta_ctx->conn_info.conn_state == eConnectionState_NotConnected ||
20303 sta_ctx->conn_info.conn_state == eConnectionState_IbssDisconnected)
20304 return 0;
20305
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020306 /* If already in disconnecting state just wait for its completion */
20307 if (sta_ctx->conn_info.conn_state == eConnectionState_Disconnecting)
20308 goto wait_for_disconnect;
20309
20310 INIT_COMPLETION(adapter->disconnect_comp_var);
20311 prev_conn_state = sta_ctx->conn_info.conn_state;
20312 hdd_conn_set_connection_state(adapter, eConnectionState_Disconnecting);
20313
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020314 status = sme_roam_disconnect(mac_handle, adapter->vdev_id, reason,
20315 mac_reason);
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020316 if (status == QDF_STATUS_CMD_NOT_QUEUED &&
20317 prev_conn_state == eConnectionState_Connecting) {
20318 /*
20319 * Wait here instead of returning directly, this will block the
20320 * next connect command and allow processing of the scan for
20321 * ssid and the previous connect command in CSR.
20322 */
20323 hdd_debug("CSR not connected but scan for SSID is in progress, wait for scan to be aborted or completed.");
20324 } else if (QDF_IS_STATUS_ERROR(status)) {
20325 hdd_debug("SB Disconnect in progress/SME is disconencted/Connect removed from pending queue: status = %d",
20326 status);
20327 /*
20328 * Wait here instead of returning directly. This will block the
20329 * next connect command and allow processing of the disconnect
20330 * in SME. As disconnect is already in progress, wait here for
20331 * WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS instead of
20332 * SME_DISCONNECT_TIMEOUT.
20333 */
20334 wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS;
20335 }
20336
20337wait_for_disconnect:
20338 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
20339 msecs_to_jiffies(wait_time));
20340
20341 if (!rc && QDF_IS_STATUS_SUCCESS(status)) {
20342 hdd_err("Disconnect timed out!!!");
20343 ret = -ETIMEDOUT;
20344 }
20345
20346 hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
20347
20348 return ret;
20349}
20350
20351static void wlan_hdd_wait_for_roaming(mac_handle_t mac_handle,
20352 struct hdd_adapter *adapter)
20353{
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053020354 struct hdd_context *hdd_ctx;
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020355 unsigned long rc;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020356 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020357
Abhishek Singh30769a32020-01-24 09:59:11 +053020358 if (adapter->device_mode != QDF_STA_MODE)
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020359 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020360
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053020361 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020362
20363 /* Return if not in connected state */
20364 if (sta_ctx->conn_info.conn_state != eConnectionState_Associated)
20365 return;
20366
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020367 sme_stop_roaming(mac_handle, adapter->vdev_id,
20368 REASON_DRIVER_DISABLED,
20369 RSO_INVALID_REQUESTOR);
20370 /*
20371 * If firmware has already started roaming process, driver
20372 * needs to wait for processing of this disconnect request.
20373 *
20374 */
20375 INIT_COMPLETION(adapter->roaming_comp_var);
20376 if (hdd_is_roaming_in_progress(hdd_ctx) ||
20377 sme_neighbor_middle_of_roaming(mac_handle,
20378 adapter->vdev_id)) {
20379 rc = wait_for_completion_timeout(&adapter->roaming_comp_var,
Abhishek Singh533c9da2017-05-04 10:23:34 +053020380 msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020381 if (!rc) {
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020382 hdd_err("roaming_comp_var time out vdev id: %d",
20383 adapter->vdev_id);
20384 /* Clear roaming in progress flag */
20385 hdd_set_roaming_in_progress(false);
20386 }
20387 if (adapter->roam_ho_fail) {
20388 INIT_COMPLETION(adapter->disconnect_comp_var);
20389 hdd_conn_set_connection_state(adapter,
20390 eConnectionState_Disconnecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020391 }
20392 }
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020393}
20394
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020395int wlan_hdd_try_disconnect(struct hdd_adapter *adapter,
20396 enum eSirMacReasonCodes reason)
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020397{
20398 mac_handle_t mac_handle;
20399
20400 mac_handle = hdd_adapter_get_mac_handle(adapter);
20401 wlan_hdd_wait_for_roaming(mac_handle, adapter);
20402
20403 return wlan_hdd_wait_for_disconnect(mac_handle, adapter,
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020404 eCSR_DISCONNECT_REASON_UNSPECIFIED,
20405 reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020406}
20407
20408/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020409 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
20410 * @adapter: Pointer to the HDD adapter
20411 * @req: Pointer to the structure cfg_connect_params receieved from user space
20412 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053020413 * This function will start reassociation if prev_bssid is set and bssid/
20414 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020415 *
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020416 * Return: 0 if connect was for ReAssociation, non-zero error code otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020417 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053020418#if defined(CFG80211_CONNECT_PREV_BSSID) || \
20419 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020420static int wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
20421 struct cfg80211_connect_params *req)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020422{
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020423 int status = -EINVAL;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053020424 const uint8_t *bssid = NULL;
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020425 uint32_t ch_freq = 0;
Jeff Johnson731bc322017-10-14 19:53:44 -070020426 struct hdd_station_ctx *sta_ctx;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053020427
20428 if (req->bssid)
20429 bssid = req->bssid;
20430 else if (req->bssid_hint)
20431 bssid = req->bssid_hint;
20432
20433 if (req->channel)
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020434 ch_freq = req->channel->center_freq;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053020435 else if (req->channel_hint)
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020436 ch_freq = req->channel_hint->center_freq;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053020437
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020438 if (bssid && ch_freq && req->prev_bssid) {
20439 hdd_debug("REASSOC Attempt on ch freq %d to " QDF_MAC_ADDR_STR,
20440 ch_freq, QDF_MAC_ADDR_ARRAY(bssid));
Arif Hussain43354e62017-05-24 11:24:25 -070020441 /*
20442 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020443 * roam_profile's BSSID is getting zeroed out in the
Arif Hussain43354e62017-05-24 11:24:25 -070020444 * association process. In case of join failure
20445 * we should send valid BSSID to supplicant
20446 */
Jeff Johnson731bc322017-10-14 19:53:44 -070020447 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
20448 qdf_mem_copy(sta_ctx->requested_bssid.bytes, bssid,
Arif Hussain43354e62017-05-24 11:24:25 -070020449 QDF_MAC_ADDR_SIZE);
20450
Abhinav Kumarc0716d42020-01-23 18:19:36 +053020451 hdd_set_roaming_in_progress(true);
20452
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020453 status = hdd_reassoc(adapter, bssid, ch_freq,
20454 CONNECT_CMD_USERSPACE);
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020455 if (QDF_IS_STATUS_ERROR(status)) {
Abhinav Kumarc0716d42020-01-23 18:19:36 +053020456 hdd_set_roaming_in_progress(false);
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020457 hdd_debug("Failed with status: %d", status);
20458 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020459 }
Abhinav Kumarc0716d42020-01-23 18:19:36 +053020460
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020461 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020462}
20463#else
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020464static int wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
20465 struct cfg80211_connect_params *req)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020466{
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020467 return -ENOTSUPP;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020468}
20469#endif
20470
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020471
20472/**
20473 * wlan_hdd_check_ht20_ht40_ind() - check if Supplicant has indicated to
20474 * connect in HT20 mode
20475 * @hdd_ctx: hdd context
20476 * @adapter: Pointer to the HDD adapter
20477 * @req: Pointer to the structure cfg_connect_params receieved from user space
20478 *
20479 * This function will check if supplicant has indicated to to connect in HT20
20480 * mode. this is currently applicable only for 2.4Ghz mode only.
20481 * if feature is enabled and supplicant indicate HT20 set
20482 * force_24ghz_in_ht20 to true to force 2.4Ghz in HT20 else set it to false.
20483 *
20484 * Return: void
20485 */
20486#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
Jeff Johnson20227a92018-03-13 09:41:05 -070020487static void
20488wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
20489 struct hdd_adapter *adapter,
20490 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020491{
Jeff Johnson61b5e982018-03-15 11:33:31 -070020492 struct csr_roam_profile *roam_profile;
Wu Gaofc81ecf2018-11-22 11:38:41 +080020493 bool is_override_ht20_40_24g;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020494
Jeff Johnson20227a92018-03-13 09:41:05 -070020495 roam_profile = hdd_roam_profile(adapter);
20496
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020497 roam_profile->force_24ghz_in_ht20 = false;
20498
Wu Gaofc81ecf2018-11-22 11:38:41 +080020499 ucfg_mlme_is_override_ht20_40_24g(hdd_ctx->psoc,
20500 &is_override_ht20_40_24g);
20501 if (is_override_ht20_40_24g &&
Jeff Johnson20227a92018-03-13 09:41:05 -070020502 !(req->ht_capa.cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020503 roam_profile->force_24ghz_in_ht20 = true;
20504
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020505 if (is_override_ht20_40_24g)
20506 hdd_nofl_debug("HT cap %x", req->ht_capa.cap_info);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020507}
20508#else
Jeff Johnson20227a92018-03-13 09:41:05 -070020509static inline void
20510wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
20511 struct hdd_adapter *adapter,
20512 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020513{
Jeff Johnson61b5e982018-03-15 11:33:31 -070020514 struct csr_roam_profile *roam_profile;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020515
Jeff Johnson20227a92018-03-13 09:41:05 -070020516 roam_profile = hdd_roam_profile(adapter);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020517
20518 roam_profile->force_24ghz_in_ht20 = false;
20519}
20520#endif
20521
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020522static inline void hdd_dump_connect_req(struct hdd_adapter *adapter,
20523 struct net_device *ndev,
20524 struct cfg80211_connect_params *req)
20525{
20526 uint32_t i;
20527
20528 hdd_nofl_debug("cfg80211_connect req for %s(vdevid-%d): mode %d freq %d SSID %.*s auth type %d WPA ver %d n_akm %d n_cipher %d grp_cipher %x mfp %d freq hint %d",
20529 ndev->name, adapter->vdev_id, adapter->device_mode,
20530 req->channel ? req->channel->center_freq : 0,
20531 (int)req->ssid_len, req->ssid, req->auth_type,
20532 req->crypto.wpa_versions,
20533 req->crypto.n_akm_suites, req->crypto.n_ciphers_pairwise,
20534 req->crypto.cipher_group, req->mfp,
20535 req->channel_hint ? req->channel_hint->center_freq : 0);
20536 if (req->bssid)
20537 hdd_nofl_debug("BSSID %pM", req->bssid);
20538 if (req->bssid_hint)
20539 hdd_nofl_debug("BSSID hint %pM", req->bssid_hint);
20540 if (req->prev_bssid)
20541 hdd_nofl_debug("prev BSSID %pM", req->prev_bssid);
20542
20543 for (i = 0; i < req->crypto.n_akm_suites; i++)
20544 hdd_nofl_debug("akm[%d] = %x", i, req->crypto.akm_suites[i]);
20545
20546 for (i = 0; i < req->crypto.n_ciphers_pairwise; i++)
20547 hdd_nofl_debug("cipher_pairwise[%d] = %x", i,
20548 req->crypto.ciphers_pairwise[i]);
20549}
20550
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020551/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020552 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
20553 * @wiphy: Pointer to wiphy
20554 * @dev: Pointer to network device
20555 * @req: Pointer to cfg80211 connect request
20556 *
20557 * This function is used to start the association process
20558 *
20559 * Return: 0 for success, non-zero for failure
20560 */
20561static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
20562 struct net_device *ndev,
20563 struct cfg80211_connect_params *req)
20564{
20565 int status;
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020566 uint32_t ch_freq, sap_cnt, sta_cnt;
Arif Hussainee677012017-01-26 17:50:13 -080020567 const u8 *bssid = NULL;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053020568#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
20569 const u8 *bssid_hint = req->bssid_hint;
20570#else
20571 const u8 *bssid_hint = NULL;
20572#endif
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020573 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020574 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020575
Dustin Brown491d54b2018-03-14 12:39:11 -070020576 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020577
Anurag Chouhan6d760662016-02-20 16:05:43 +053020578 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020579 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020580 return -EINVAL;
20581 }
20582
Jeff Johnson48363022019-02-24 16:26:51 -080020583 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020584 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020585
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020586 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
20587 TRACE_CODE_HDD_CFG80211_CONNECT,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020588 adapter->vdev_id, adapter->device_mode);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020589
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020590 if (adapter->device_mode != QDF_STA_MODE &&
Dustin Brown458027c2018-10-19 12:26:27 -070020591 adapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020592 hdd_err("Device_mode %s(%d) is not supported",
Dustin Brown458027c2018-10-19 12:26:27 -070020593 qdf_opmode_str(adapter->device_mode),
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020594 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020595 return -EINVAL;
20596 }
20597
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020598 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020599 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020600 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020601 return -EINVAL;
20602 }
20603
Jeff Johnsonb8944722017-09-03 09:03:19 -070020604 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020605 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020606 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020607
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020608 if (req->bssid)
20609 bssid = req->bssid;
20610 else if (bssid_hint)
20611 bssid = bssid_hint;
20612
20613 if (bssid && hdd_get_adapter_by_macaddr(hdd_ctx, (uint8_t *)bssid)) {
20614 hdd_err("adapter exist with same mac address " QDF_MAC_ADDR_STR,
20615 QDF_MAC_ADDR_ARRAY(bssid));
20616 return -EINVAL;
20617 }
20618
20619 hdd_dump_connect_req(adapter, ndev, req);
20620
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020621 /*
20622 * Disable NAN Discovery if incoming connection is P2P or if a STA
Manikandan Mohan956b69e2019-02-14 13:08:14 -080020623 * connection already exists and if this is a case of STA+STA
20624 * or SAP+STA concurrency
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020625 */
Manikandan Mohan956b69e2019-02-14 13:08:14 -080020626 sta_cnt = policy_mgr_mode_specific_connection_count(hdd_ctx->psoc,
20627 PM_STA_MODE, NULL);
20628 sap_cnt = policy_mgr_mode_specific_connection_count(hdd_ctx->psoc,
20629 PM_SAP_MODE, NULL);
Nachiket Kukade089b9832018-12-12 16:38:17 +053020630
Manikandan Mohan956b69e2019-02-14 13:08:14 -080020631 if (adapter->device_mode == QDF_P2P_CLIENT_MODE || sap_cnt || sta_cnt) {
20632 hdd_debug("Invalid NAN concurrency. SAP: %d STA: %d P2P: %d",
20633 sap_cnt, sta_cnt,
20634 (adapter->device_mode == QDF_P2P_CLIENT_MODE));
20635 ucfg_nan_disable_concurrency(hdd_ctx->psoc);
20636 }
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020637 /*
20638 * STA+NDI concurrency gets preference over NDI+NDI. Disable
gaurank kathpalia7fd92d92020-02-27 00:02:54 +053020639 * first NDI in case an NDI+NDI concurrency exists if FW does
20640 * not support 4 port concurrency of two NDI + NAN with STA.
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020641 */
gaurank kathpalia7fd92d92020-02-27 00:02:54 +053020642 if (!ucfg_nan_is_sta_nan_ndi_4_port_allowed(hdd_ctx->psoc))
20643 ucfg_nan_check_and_disable_unsupported_ndi(hdd_ctx->psoc,
20644 false);
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020645
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020646 /*
Pragaspathi Thilagaraj76d0e252019-10-01 15:45:21 +053020647 * In STA + STA roaming scenario, connection to same ssid but different
20648 * bssid is allowed on both vdevs. So there could be a race where the
20649 * STA1 connectes to a bssid when roaming is in progress on STA2 for
20650 * the same bssid. Here the firwmare would have already created peer for
20651 * the roam candidate and host would have created peer on the other
20652 * vdev. When roam synch indication is received, then peer create fails
20653 * at host for the roaming vdev due to duplicate peer detection logic.
20654 * Still roam synch confirm is sent to the firmware.
20655 * When disconnection is received for STA1, then del bss is sent for
20656 * this vdev and firmware asserts as the peer was not created for this
20657 * vdev.
20658 */
20659 if (hdd_is_roaming_in_progress(hdd_ctx) ||
20660 sme_is_any_session_in_middle_of_roaming(hdd_ctx->mac_handle)) {
20661 hdd_err("Roaming in progress. Defer connect");
20662 return -EBUSY;
20663 }
20664
20665 /*
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020666 * Check if this is reassoc to same bssid, if reassoc is success, return
20667 */
20668 status = wlan_hdd_reassoc_bssid_hint(adapter, req);
Abhinav Kumarc0716d42020-01-23 18:19:36 +053020669 if (!status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020670 return status;
20671
Agrawal Ashishf156e942016-08-04 14:54:47 +053020672 /* Try disconnecting if already in connected state */
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020673 status = wlan_hdd_try_disconnect(adapter,
20674 eSIR_MAC_UNSPEC_FAILURE_REASON);
Agrawal Ashishf156e942016-08-04 14:54:47 +053020675 if (0 > status) {
20676 hdd_err("Failed to disconnect the existing connection");
20677 return -EALREADY;
20678 }
20679
Liangwei Dong3fa5cba2018-07-16 06:41:55 -040020680 /*initialise security parameters */
20681 status = wlan_hdd_cfg80211_set_privacy(adapter, req);
Liangwei Dong3fa5cba2018-07-16 06:41:55 -040020682 if (status < 0) {
20683 hdd_err("Failed to set security params");
20684 return status;
20685 }
20686
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053020687 if (req->channel)
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020688 ch_freq = req->channel->center_freq;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053020689 else
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020690 ch_freq = 0;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020691
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020692 wlan_hdd_check_ht20_ht40_ind(hdd_ctx, adapter, req);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020693
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020694 status = wlan_hdd_cfg80211_connect_start(adapter, req->ssid,
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053020695 req->ssid_len, req->bssid,
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020696 bssid_hint, ch_freq, 0);
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020697 if (status) {
20698 wlan_hdd_cfg80211_clear_privacy(adapter);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020699 hdd_err("connect failed");
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020700 }
Srinivas Girigowdad2412882018-09-07 15:42:04 -070020701
Dustin Browne74003f2018-03-14 12:51:58 -070020702 hdd_exit();
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020703
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020704 return status;
20705}
20706
20707/**
20708 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
20709 * @wiphy: Pointer to wiphy
20710 * @dev: Pointer to network device
20711 * @req: Pointer to cfg80211 connect request
20712 *
20713 * Return: 0 for success, non-zero for failure
20714 */
20715static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
20716 struct net_device *ndev,
20717 struct cfg80211_connect_params *req)
20718{
Dustin Brown1d31b082018-11-22 14:41:20 +053020719 int errno;
20720 struct osif_vdev_sync *vdev_sync;
20721
20722 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
20723 if (errno)
20724 return errno;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020725
Dustin Brown1d31b082018-11-22 14:41:20 +053020726 errno = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020727
Dustin Brown1d31b082018-11-22 14:41:20 +053020728 osif_vdev_sync_op_stop(vdev_sync);
20729
20730 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020731}
20732
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020733/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080020734 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
20735 * @reason: ieee80211 reason code.
20736 *
20737 * This utility function helps log string conversion of reason code.
20738 *
20739 * Return: string conversion of reason code, if match found;
20740 * "Unknown" otherwise.
20741 */
20742static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
20743{
20744 switch (reason) {
20745 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
20746 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
20747 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
20748 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
20749 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
20750 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
20751 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
20752 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
20753 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
20754 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
20755 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
20756 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
20757 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
20758 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
20759 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
20760 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
20761 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
20762 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
20763 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
20764 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
20765 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
20766 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
20767 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
20768 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
20769 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
20770 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
20771 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
20772 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
20773 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
20774 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
20775 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
20776 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
20777 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
20778 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
20779 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
20780 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
20781 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
20782 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
20783 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
20784 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
20785 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
20786 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
20787 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
20788 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
20789 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
20790 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
20791 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
20792 default:
20793 return "Unknown";
20794 }
20795}
20796
20797/**
Srinivas Dasariaa1b8c22020-02-26 14:33:27 +053020798 * hdd_qca_reason_to_str() - return string conversion of qca reason code
20799 * @reason: enum qca_disconnect_reason_codes
20800 *
20801 * This utility function helps log string conversion of qca reason code.
20802 *
20803 * Return: string conversion of reason code, if match found;
20804 * "Unknown" otherwise.
20805 */
20806static const char *
20807hdd_qca_reason_to_str(enum qca_disconnect_reason_codes reason)
20808{
20809 switch (reason) {
20810 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_INTERNAL_ROAM_FAILURE);
20811 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_EXTERNAL_ROAM_FAILURE);
20812 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_GATEWAY_REACHABILITY_FAILURE);
20813 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_UNSUPPORTED_CHANNEL_CSA);
20814 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_OPER_CHANNEL_DISABLED_INDOOR);
20815 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_OPER_CHANNEL_USER_DISABLED);
20816 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_DEVICE_RECOVERY);
20817 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_KEY_TIMEOUT);
20818 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_OPER_CHANNEL_BAND_CHANGE);
20819 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_IFACE_DOWN);
20820 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_PEER_XRETRY_FAIL);
20821 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_PEER_INACTIVITY);
20822 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_SA_QUERY_TIMEOUT);
20823 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_BEACON_MISS_FAILURE);
20824 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_CHANNEL_SWITCH_FAILURE);
20825 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_USER_TRIGGERED);
20826 case QCA_DISCONNECT_REASON_UNSPECIFIED:
20827 return "";
20828 default:
20829 return "Unknown";
20830 }
20831}
20832
20833/**
20834 * wlan_hdd_sir_mac_to_qca_reason() - Convert to qca internal disconnect reason
20835 * @internal_reason: Mac reason code of type @enum eSirMacReasonCodes
20836 *
20837 * Check if it is internal reason code and convert it to the
20838 * enum qca_disconnect_reason_codes.
20839 *
20840 * Return: Reason code of type enum qca_disconnect_reason_codes
20841 */
20842static enum qca_disconnect_reason_codes
20843wlan_hdd_sir_mac_to_qca_reason(enum eSirMacReasonCodes internal_reason)
20844{
20845 enum qca_disconnect_reason_codes reason =
20846 QCA_DISCONNECT_REASON_UNSPECIFIED;
20847 switch (internal_reason) {
20848 case eSIR_MAC_HOST_TRIGGERED_ROAM_FAILURE:
20849 reason = QCA_DISCONNECT_REASON_INTERNAL_ROAM_FAILURE;
20850 break;
20851 case eSIR_MAC_FW_TRIGGERED_ROAM_FAILURE:
20852 reason = QCA_DISCONNECT_REASON_EXTERNAL_ROAM_FAILURE;
20853 break;
20854 case eSIR_MAC_GATEWAY_REACHABILITY_FAILURE:
20855 reason =
20856 QCA_DISCONNECT_REASON_GATEWAY_REACHABILITY_FAILURE;
20857 break;
20858 case eSIR_MAC_UNSUPPORTED_CHANNEL_CSA:
20859 reason = QCA_DISCONNECT_REASON_UNSUPPORTED_CHANNEL_CSA;
20860 break;
20861 case eSIR_MAC_OPER_CHANNEL_DISABLED_INDOOR:
20862 reason =
20863 QCA_DISCONNECT_REASON_OPER_CHANNEL_DISABLED_INDOOR;
20864 break;
20865 case eSIR_MAC_OPER_CHANNEL_USER_DISABLED:
20866 reason =
20867 QCA_DISCONNECT_REASON_OPER_CHANNEL_USER_DISABLED;
20868 break;
20869 case eSIR_MAC_DEVICE_RECOVERY:
20870 reason = QCA_DISCONNECT_REASON_DEVICE_RECOVERY;
20871 break;
20872 case eSIR_MAC_KEY_TIMEOUT:
20873 reason = QCA_DISCONNECT_REASON_KEY_TIMEOUT;
20874 break;
20875 case eSIR_MAC_OPER_CHANNEL_BAND_CHANGE:
20876 reason = QCA_DISCONNECT_REASON_OPER_CHANNEL_BAND_CHANGE;
20877 break;
20878 case eSIR_MAC_IFACE_DOWN:
20879 reason = QCA_DISCONNECT_REASON_IFACE_DOWN;
20880 break;
20881 case eSIR_MAC_PEER_XRETRY_FAIL:
20882 reason = QCA_DISCONNECT_REASON_PEER_XRETRY_FAIL;
20883 break;
20884 case eSIR_MAC_PEER_INACTIVITY:
20885 reason = QCA_DISCONNECT_REASON_PEER_INACTIVITY;
20886 break;
20887 case eSIR_MAC_SA_QUERY_TIMEOUT:
20888 reason = QCA_DISCONNECT_REASON_SA_QUERY_TIMEOUT;
20889 break;
20890 case eSIR_MAC_CHANNEL_SWITCH_FAILED:
20891 reason = QCA_DISCONNECT_REASON_CHANNEL_SWITCH_FAILURE;
20892 break;
20893 case eSIR_MAC_BEACON_MISSED:
20894 reason = QCA_DISCONNECT_REASON_BEACON_MISS_FAILURE;
20895 break;
20896 case eSIR_MAC_USER_TRIGGERED_ROAM_FAILURE:
20897 reason = QCA_DISCONNECT_REASON_USER_TRIGGERED;
20898 break;
20899 default:
20900 hdd_debug("No QCA reason code for mac reason: %u",
20901 internal_reason);
20902 /* Unspecified reason by default */
20903 }
20904
20905 return reason;
20906}
20907
20908/**
20909 * wlan_hdd_get_ieee80211_disconnect_reason() - Get ieee80211 disconnect reason
20910 * @adapter: pointer to adapter structure
20911 * @reason: Mac Disconnect reason code as per @enum eSirMacReasonCodes
20912 *
20913 * Reason codes that are greater than eSIR_MAC_REASON_PROP_START are internal
20914 * reason codes. Convert them to qca reason code format and cache in adapter
20915 * and return UNSPECIFIED.
20916 * Rest of the reason codes are valid ieee80211 reason codes.
20917 *
20918 * Return: Reason code of type ieee80211_reasoncode.
20919 */
20920static enum ieee80211_reasoncode
20921wlan_hdd_get_cfg80211_disconnect_reason(struct hdd_adapter *adapter,
20922 enum eSirMacReasonCodes reason)
20923{
20924 enum ieee80211_reasoncode ieee80211_reason = WLAN_REASON_UNSPECIFIED;
20925
20926 /*
20927 * Convert and cache internal reason code in adapter. This can be
20928 * sent to userspace with a vendor event.
20929 */
20930 if (reason >= eSIR_MAC_REASON_PROP_START) {
20931 adapter->last_disconnect_reason =
20932 wlan_hdd_sir_mac_to_qca_reason(reason);
Srinivas Dasarid80f9c82020-05-19 01:20:53 +053020933 /*
20934 * Applications expect reason code as 0 for beacon miss failure
20935 * due to backward compatibility. So send ieee80211_reason as 0.
20936 */
20937 if (reason == eSIR_MAC_BEACON_MISSED)
20938 ieee80211_reason = 0;
Srinivas Dasariaa1b8c22020-02-26 14:33:27 +053020939 } else {
20940 ieee80211_reason = (enum ieee80211_reasoncode)reason;
20941 adapter->last_disconnect_reason =
20942 QCA_DISCONNECT_REASON_UNSPECIFIED;
20943 }
20944
20945 return ieee80211_reason;
20946}
20947
20948#if defined(CFG80211_DISCONNECTED_V2) || \
20949(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
20950void
20951wlan_hdd_cfg80211_indicate_disconnect(struct hdd_adapter *adapter,
20952 bool locally_generated,
20953 enum eSirMacReasonCodes reason,
20954 uint8_t *disconnect_ies,
20955 uint16_t disconnect_ies_len)
20956{
20957 enum ieee80211_reasoncode ieee80211_reason;
20958
20959 ieee80211_reason = wlan_hdd_get_cfg80211_disconnect_reason(adapter,
20960 reason);
20961 hdd_nofl_info("Disconnect reason: %u %s vendor: %u %s LG: %u",
20962 ieee80211_reason,
20963 hdd_ieee80211_reason_code_to_str(ieee80211_reason),
20964 adapter->last_disconnect_reason,
20965 hdd_qca_reason_to_str(adapter->last_disconnect_reason),
20966 locally_generated);
20967 cfg80211_disconnected(adapter->dev, ieee80211_reason, disconnect_ies,
20968 disconnect_ies_len, locally_generated,
20969 GFP_KERNEL);
20970}
20971#else
20972void
20973wlan_hdd_cfg80211_indicate_disconnect(struct hdd_adapter *adapter,
20974 bool locally_generated,
20975 enum eSirMacReasonCodes reason,
20976 uint8_t *disconnect_ies,
20977 uint16_t disconnect_ies_len)
20978{
20979 enum ieee80211_reasoncode ieee80211_reason;
20980
20981 ieee80211_reason = wlan_hdd_get_cfg80211_disconnect_reason(adapter,
20982 reason);
20983 hdd_nofl_info("Disconnect reason: %u %s vendor: %u %s LG: %u",
20984 ieee80211_reason,
20985 hdd_ieee80211_reason_code_to_str(ieee80211_reason),
20986 adapter->last_disconnect_reason,
20987 hdd_qca_reason_to_str(adapter->last_disconnect_reason),
20988 locally_generated);
20989 cfg80211_disconnected(adapter->dev, ieee80211_reason, disconnect_ies,
20990 disconnect_ies_len, GFP_KERNEL);
20991}
20992#endif
20993
20994int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason,
20995 tSirMacReasonCodes mac_reason)
20996{
20997 int ret;
20998 mac_handle_t mac_handle;
20999
21000 mac_handle = hdd_adapter_get_mac_handle(adapter);
21001 wlan_hdd_wait_for_roaming(mac_handle, adapter);
21002
21003 /*stop tx queues */
21004 hdd_debug("Disabling queues");
21005 wlan_hdd_netif_queue_control(adapter,
21006 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
21007
21008 ret = wlan_hdd_wait_for_disconnect(mac_handle, adapter, reason,
21009 mac_reason);
21010
21011#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
21012 /* Sending disconnect event to userspace for kernel version < 3.11
21013 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
21014 */
21015 wlan_hdd_cfg80211_indicate_disconnect(adapter, true,
21016 mac_reason, NULL, 0);
21017#endif
21018
21019 return ret;
21020}
21021
21022/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021023 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
21024 * @wiphy: Pointer to wiphy
21025 * @dev: Pointer to network device
21026 * @reason: Disconnect reason code
21027 *
21028 * This function is used to issue a disconnect request to SME
21029 *
21030 * Return: 0 for success, non-zero for failure
21031 */
21032static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
21033 struct net_device *dev, u16 reason)
21034{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021035 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021036 int status;
Jeff Johnsond377dce2017-10-04 10:32:42 -070021037 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021038 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
21039 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Min Liu8c5d99e2018-09-10 17:18:44 +080021040 struct wlan_objmgr_vdev *vdev;
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053021041 bool enable_deauth_to_disassoc_map;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021042
Anurag Chouhan6d760662016-02-20 16:05:43 +053021043 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021044 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021045 return -EINVAL;
21046 }
21047
Jeff Johnson48363022019-02-24 16:26:51 -080021048 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021049 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021050
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021051 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21052 TRACE_CODE_HDD_CFG80211_DISCONNECT,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021053 adapter->vdev_id, reason);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021054
Srinivas Girigowda44cff5c2018-04-16 15:49:30 -070021055 hdd_print_netdev_txq_status(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021056 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021057
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021058 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021059 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021060
Alok Kumarb64650c2018-03-23 17:05:11 +053021061 qdf_mutex_acquire(&adapter->disconnection_status_lock);
21062 if (adapter->disconnection_in_progress) {
21063 qdf_mutex_release(&adapter->disconnection_status_lock);
21064 hdd_debug("Disconnect is already in progress");
21065 return 0;
21066 }
21067 adapter->disconnection_in_progress = true;
21068 qdf_mutex_release(&adapter->disconnection_status_lock);
21069
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021070 /* Issue disconnect request to SME, if station is in connected state */
Jeff Johnsone7951512019-02-27 10:02:51 -080021071 if ((sta_ctx->conn_info.conn_state == eConnectionState_Associated) ||
21072 (sta_ctx->conn_info.conn_state == eConnectionState_Connecting)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021073 eCsrRoamDisconnectReason reasonCode =
21074 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021075
21076 switch (reason) {
21077 case WLAN_REASON_MIC_FAILURE:
21078 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
21079 break;
21080
21081 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
21082 case WLAN_REASON_DISASSOC_AP_BUSY:
21083 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
21084 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
21085 break;
21086
21087 case WLAN_REASON_PREV_AUTH_NOT_VALID:
21088 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
21089 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
21090 break;
21091
21092 case WLAN_REASON_DEAUTH_LEAVING:
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053021093 status = ucfg_mlme_get_enable_deauth_to_disassoc_map(
21094 hdd_ctx->psoc,
21095 &enable_deauth_to_disassoc_map);
21096 if (QDF_IS_STATUS_ERROR(status))
21097 return -EINVAL;
21098
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021099 reasonCode =
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053021100 enable_deauth_to_disassoc_map ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021101 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
21102 eCSR_DISCONNECT_REASON_DEAUTH;
Mohit Khannaceb97782017-04-05 16:27:08 -070021103 qdf_dp_trace_dump_all(
21104 WLAN_DEAUTH_DPTRACE_DUMP_COUNT,
21105 QDF_TRACE_DEFAULT_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021106 break;
21107 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
21108 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
21109 break;
21110 default:
21111 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
21112 break;
21113 }
Min Liu8c5d99e2018-09-10 17:18:44 +080021114
21115 vdev = hdd_objmgr_get_vdev(adapter);
21116 if (!vdev)
21117 return -EINVAL;
Abhishek Singh29405dc2020-02-17 13:08:32 +053021118 if (ucfg_scan_get_vdev_status(vdev) != SCAN_NOT_IN_PROGRESS)
Dustin Brown07901ec2018-09-07 11:02:41 -070021119 wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021120 adapter->vdev_id, INVALID_SCAN_ID,
Dustin Brown07901ec2018-09-07 11:02:41 -070021121 false);
Abhishek Singh29405dc2020-02-17 13:08:32 +053021122
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021123 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021124 /* First clean up the tdls peers if any */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021125 hdd_notify_sta_disconnect(adapter->vdev_id,
Min Liu8c5d99e2018-09-10 17:18:44 +080021126 false, true, vdev);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053021127 hdd_objmgr_put_vdev(vdev);
Kabilan Kannanb6153b12017-07-13 17:54:02 -070021128
Srinivas Dasariaa1b8c22020-02-26 14:33:27 +053021129 hdd_nofl_info("%s(vdevid-%d): Received Disconnect reason:%d %s",
21130 dev->name, adapter->vdev_id, reason,
21131 hdd_ieee80211_reason_code_to_str(reason));
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053021132 status = wlan_hdd_disconnect(adapter, reasonCode, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021133 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021134 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Alok Kumarb64650c2018-03-23 17:05:11 +053021135 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021136 return -EINVAL;
21137 }
21138 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021139 hdd_err("Unexpected cfg disconnect called while in state: %d",
Jeff Johnsone7951512019-02-27 10:02:51 -080021140 sta_ctx->conn_info.conn_state);
Alok Kumarb64650c2018-03-23 17:05:11 +053021141 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021142 }
21143
21144 return status;
21145}
21146
21147/**
21148 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
21149 * @wiphy: Pointer to wiphy
21150 * @dev: Pointer to network device
21151 * @reason: Disconnect reason code
21152 *
21153 * Return: 0 for success, non-zero for failure
21154 */
21155static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
21156 struct net_device *dev, u16 reason)
21157{
Dustin Brown1d31b082018-11-22 14:41:20 +053021158 int errno;
21159 struct osif_vdev_sync *vdev_sync;
21160
21161 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21162 if (errno)
21163 return errno;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070021164
Dustin Brown1d31b082018-11-22 14:41:20 +053021165 errno = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021166
Dustin Brown1d31b082018-11-22 14:41:20 +053021167 osif_vdev_sync_op_stop(vdev_sync);
21168
21169 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021170}
21171
21172/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021173 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
21174 * @wiphy: Pointer to wiphy
21175 * @changed: Parameters changed
21176 *
21177 * This function is used to set the phy parameters. RTS Threshold/FRAG
21178 * Threshold/Retry Count etc.
21179 *
21180 * Return: 0 for success, non-zero for failure
21181 */
21182static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
21183 u32 changed)
21184{
Jeff Johnsonb8944722017-09-03 09:03:19 -070021185 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021186 int status;
21187
Dustin Brown491d54b2018-03-14 12:39:11 -070021188 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021189
Anurag Chouhan6d760662016-02-20 16:05:43 +053021190 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021191 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021192 return -EINVAL;
21193 }
21194
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021195 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21196 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
21197 NO_SESSION, wiphy->rts_threshold);
21198
Jeff Johnsonb8944722017-09-03 09:03:19 -070021199 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021200
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021201 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021202 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021203
21204 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
21205 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
Harprit Chhabadabec6de42018-09-10 10:21:15 -070021206 cfg_max(CFG_RTS_THRESHOLD) :
21207 wiphy->rts_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021208
Harprit Chhabadabec6de42018-09-10 10:21:15 -070021209 if ((cfg_min(CFG_RTS_THRESHOLD) > rts_threshold) ||
21210 (cfg_max(CFG_RTS_THRESHOLD) < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021211 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021212 rts_threshold);
21213 return -EINVAL;
21214 }
21215
Harprit Chhabadabec6de42018-09-10 10:21:15 -070021216 if (0 != ucfg_mlme_set_rts_threshold(hdd_ctx->psoc,
21217 rts_threshold)) {
21218 hdd_err("mlme_set_rts_threshold failed for val %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021219 rts_threshold);
21220 return -EIO;
21221 }
21222
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021223 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021224 }
21225
21226 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
21227 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
Harprit Chhabadabec6de42018-09-10 10:21:15 -070021228 cfg_max(CFG_FRAG_THRESHOLD) :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021229 wiphy->frag_threshold;
21230
Harprit Chhabadabec6de42018-09-10 10:21:15 -070021231 if ((cfg_min(CFG_FRAG_THRESHOLD) > frag_threshold) ||
21232 (cfg_max(CFG_FRAG_THRESHOLD) < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021233 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021234 frag_threshold);
21235 return -EINVAL;
21236 }
21237
Harprit Chhabadabec6de42018-09-10 10:21:15 -070021238 if (0 != ucfg_mlme_set_frag_threshold(hdd_ctx->psoc,
21239 frag_threshold)) {
21240 hdd_err("mlme_set_frag_threshold failed for val %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021241 frag_threshold);
21242 return -EIO;
21243 }
21244
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021245 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021246 }
21247
Dustin Browne74003f2018-03-14 12:51:58 -070021248 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021249 return 0;
21250}
21251
21252/**
21253 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
21254 * @wiphy: Pointer to wiphy
21255 * @changed: Parameters changed
21256 *
21257 * Return: 0 for success, non-zero for failure
21258 */
21259static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
21260{
Dustin Brown363b4792019-02-05 16:11:55 -080021261 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080021262 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +053021263
Dustin Brown363b4792019-02-05 16:11:55 -080021264 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080021265 if (errno)
21266 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021267
Dustin Brownf0f00612019-01-31 16:02:24 -080021268 errno = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021269
Dustin Brown363b4792019-02-05 16:11:55 -080021270 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080021271
21272 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021273}
21274
21275/**
21276 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
21277 * key
21278 * @wiphy: Pointer to wiphy
21279 * @dev: Pointer to network device
21280 * @key_index: Key index
21281 *
21282 * Return: 0
21283 */
21284static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
21285 struct net_device *netdev,
21286 u8 key_index)
21287{
Dustin Brown491d54b2018-03-14 12:39:11 -070021288 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021289 return 0;
21290}
21291
21292/**
21293 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
21294 * wlan_hdd_set_default_mgmt_key
21295 * @wiphy: pointer to wiphy
21296 * @netdev: pointer to net_device structure
21297 * @key_index: key index
21298 *
21299 * Return: 0 on success, error number on failure
21300 */
21301static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
21302 struct net_device *netdev,
21303 u8 key_index)
21304{
Dustin Brown1d31b082018-11-22 14:41:20 +053021305 int errno;
21306 struct osif_vdev_sync *vdev_sync;
21307
21308 errno = osif_vdev_sync_op_start(netdev, &vdev_sync);
21309 if (errno)
21310 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021311
Dustin Brown1d31b082018-11-22 14:41:20 +053021312 errno = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021313
Dustin Brown1d31b082018-11-22 14:41:20 +053021314 osif_vdev_sync_op_stop(vdev_sync);
21315
21316 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021317}
21318
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021319/**
Subrat Dashe1f1da82019-10-21 15:54:15 +053021320 * Default val of cwmin, this value is used to overide the
21321 * incorrect user set value
21322 */
21323#define DEFAULT_CWMIN 15
21324
21325/**
21326 * Default val of cwmax, this value is used to overide the
21327 * incorrect user set value
21328 */
21329#define DEFAULT_CWMAX 1023
21330
21331/**
21332 * __wlan_hdd_set_txq_params() - implementation of set tx queue params
21333 * to configure internal EDCA parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021334 * @wiphy: Pointer to wiphy
21335 * @dev: Pointer to network device
21336 * @params: Pointer to tx queue parameters
21337 *
21338 * Return: 0
21339 */
21340static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
21341 struct net_device *dev,
21342 struct ieee80211_txq_params *params)
21343{
Subrat Dashe1f1da82019-10-21 15:54:15 +053021344 QDF_STATUS status;
21345 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21346 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21347 mac_handle_t mac_handle;
21348 tSirMacEdcaParamRecord txq_edca_params;
21349 static const uint8_t ieee_ac_to_qca_ac[] = {
21350 [IEEE80211_AC_VO] = QCA_WLAN_AC_VO,
21351 [IEEE80211_AC_VI] = QCA_WLAN_AC_VI,
21352 [IEEE80211_AC_BE] = QCA_WLAN_AC_BE,
21353 [IEEE80211_AC_BK] = QCA_WLAN_AC_BK,
21354 };
21355
Dustin Brown491d54b2018-03-14 12:39:11 -070021356 hdd_enter();
Subrat Dashe1f1da82019-10-21 15:54:15 +053021357
21358 if (wlan_hdd_validate_context(hdd_ctx))
21359 return -EINVAL;
21360
21361 mac_handle = hdd_ctx->mac_handle;
21362 if (params->cwmin == 0 || params->cwmin > DEFAULT_CWMAX)
21363 params->cwmin = DEFAULT_CWMIN;
21364
21365 if (params->cwmax < params->cwmin || params->cwmax > DEFAULT_CWMAX)
21366 params->cwmax = DEFAULT_CWMAX;
21367
21368 txq_edca_params.cw.min = convert_cw(params->cwmin);
21369 txq_edca_params.cw.max = convert_cw(params->cwmax);
21370 txq_edca_params.aci.aifsn = params->aifs;
21371 /* The txop is multiple of 32us units */
21372 txq_edca_params.txoplimit = params->txop;
21373 txq_edca_params.aci.aci =
21374 ieee_ac_to_qca_ac[params->ac];
21375
21376 status = sme_update_session_txq_edca_params(mac_handle,
21377 adapter->vdev_id,
21378 &txq_edca_params);
21379
21380 hdd_exit();
21381 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021382}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021383
21384/**
21385 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
21386 * @wiphy: pointer to wiphy
21387 * @netdev: pointer to net_device structure
21388 * @params: pointer to ieee80211_txq_params
21389 *
21390 * Return: 0 on success, error number on failure
21391 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021392static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
21393 struct net_device *dev,
21394 struct ieee80211_txq_params *params)
21395{
Dustin Brown1d31b082018-11-22 14:41:20 +053021396 int errno;
21397 struct osif_vdev_sync *vdev_sync;
21398
21399 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21400 if (errno)
21401 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021402
Dustin Brown1d31b082018-11-22 14:41:20 +053021403 errno = __wlan_hdd_set_txq_params(wiphy, dev, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021404
Dustin Brown1d31b082018-11-22 14:41:20 +053021405 osif_vdev_sync_op_stop(vdev_sync);
21406
21407 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021408}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021409
21410/**
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021411 * hdd_softap_deauth_current_sta() - Deauth current sta
21412 * @sta_info: pointer to the current station info structure
21413 * @adapter: pointer to adapter structure
21414 * @hdd_ctx: pointer to hdd context
21415 * @hapd_state: pointer to hostapd state structure
21416 * @param: pointer to del sta params
21417 *
21418 * Return: QDF_STATUS on success, corresponding QDF failure status on failure
21419 */
21420static
21421QDF_STATUS hdd_softap_deauth_current_sta(struct hdd_adapter *adapter,
21422 struct hdd_station_info *sta_info,
21423 struct hdd_hostapd_state *hapd_state,
21424 struct csr_del_sta_params *param)
21425{
21426 qdf_event_t *disassoc_event = &hapd_state->qdf_sta_disassoc_event;
21427 struct hdd_context *hdd_ctx;
21428 QDF_STATUS qdf_status;
21429
21430 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21431 if (!hdd_ctx) {
21432 hdd_err("hdd_ctx is NULL");
21433 return QDF_STATUS_E_INVAL;
21434 }
21435
21436 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
21437 return QDF_STATUS_E_INVAL;
21438
21439 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
21440
21441 if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac))
21442 sme_send_disassoc_req_frame(hdd_ctx->mac_handle,
21443 adapter->vdev_id,
Sandeep Puligillae6e43342020-07-08 05:27:59 -070021444 (uint8_t *)&sta_info->sta_mac,
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021445 param->reason_code, 0);
21446
21447 qdf_status = hdd_softap_sta_deauth(adapter, param);
21448
21449 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
21450 sta_info->is_deauth_in_progress = true;
21451 qdf_status = qdf_wait_for_event_completion(
21452 disassoc_event,
21453 SME_PEER_DISCONNECT_TIMEOUT);
21454 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
21455 hdd_warn("Deauth time expired");
21456 } else {
21457 sta_info->is_deauth_in_progress = false;
21458 hdd_debug("STA removal failed for ::" QDF_MAC_ADDR_STR,
21459 QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
21460 return QDF_STATUS_E_NOENT;
21461 }
21462 return QDF_STATUS_SUCCESS;
21463}
21464
21465/**
21466 * hdd_softap_deauth_all_sta() - Deauth all sta in the sta list
21467 * @hdd_ctx: pointer to hdd context
21468 * @adapter: pointer to adapter structure
21469 * @hapd_state: pointer to hostapd state structure
21470 * @param: pointer to del sta params
21471 *
21472 * Return: QDF_STATUS on success, corresponding QDF failure status on failure
21473 */
21474static
21475QDF_STATUS hdd_softap_deauth_all_sta(struct hdd_adapter *adapter,
21476 struct hdd_hostapd_state *hapd_state,
21477 struct csr_del_sta_params *param)
21478{
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021479 QDF_STATUS status;
21480 bool is_sap_bcast_deauth_enabled = false;
21481 struct hdd_context *hdd_ctx;
21482 struct hdd_station_info *sta_info;
21483
21484 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21485 if (!hdd_ctx) {
21486 hdd_err("hdd_ctx is NULL");
21487 return QDF_STATUS_E_INVAL;
21488 }
21489
21490 ucfg_mlme_get_sap_bcast_deauth_enabled(hdd_ctx->psoc,
21491 &is_sap_bcast_deauth_enabled);
21492
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021493 if (is_sap_bcast_deauth_enabled)
21494 return QDF_STATUS_E_INVAL;
21495
Sourav Mohapatra11be3492020-04-22 10:09:32 +053021496 hdd_for_each_sta_ref(adapter->sta_info_list, sta_info) {
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021497 if (!sta_info->is_deauth_in_progress) {
21498 hdd_debug("Delete STA with MAC:" QDF_MAC_ADDR_STR,
21499 QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
21500 status =
21501 hdd_softap_deauth_current_sta(adapter, sta_info,
21502 hapd_state, param);
Sourav Mohapatra11be3492020-04-22 10:09:32 +053021503 if (QDF_IS_STATUS_ERROR(status)) {
21504 hdd_put_sta_info_ref(&adapter->sta_info_list,
21505 &sta_info, true);
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021506 return status;
Sourav Mohapatra11be3492020-04-22 10:09:32 +053021507 }
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021508 }
Sourav Mohapatra11be3492020-04-22 10:09:32 +053021509 hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true);
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021510 }
21511
21512 return QDF_STATUS_SUCCESS;
21513}
21514
21515/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021516 * __wlan_hdd_cfg80211_del_station() - delete station v2
21517 * @wiphy: Pointer to wiphy
Jeff Johnson50e37e92019-03-08 11:32:25 -080021518 * @dev: Underlying net device
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021519 * @param: Pointer to delete station parameter
21520 *
21521 * Return: 0 for success, non-zero for failure
21522 */
21523static
21524int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
21525 struct net_device *dev,
Jeff Johnson50e37e92019-03-08 11:32:25 -080021526 struct csr_del_sta_params *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021527{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021528 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021529 struct hdd_context *hdd_ctx;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070021530 struct hdd_hostapd_state *hapd_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021531 uint8_t *mac;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021532 mac_handle_t mac_handle;
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021533 struct hdd_station_info *sta_info;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021534
Dustin Brown491d54b2018-03-14 12:39:11 -070021535 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021536
Anurag Chouhan6d760662016-02-20 16:05:43 +053021537 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021538 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021539 return -EINVAL;
21540 }
21541
Jeff Johnson48363022019-02-24 16:26:51 -080021542 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021543 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021544
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021545 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21546 TRACE_CODE_HDD_CFG80211_DEL_STA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021547 adapter->vdev_id, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021548
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021549 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Abhishek Singh97e8a712019-03-29 12:14:04 +053021550 if (!hdd_ctx) {
21551 hdd_err("hdd_ctx is NULL");
21552 return -EINVAL;
21553 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021554
Jeff Johnson50e37e92019-03-08 11:32:25 -080021555 mac = (uint8_t *) param->peerMacAddr.bytes;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021556 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021557
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021558 if (QDF_SAP_MODE != adapter->device_mode &&
21559 QDF_P2P_GO_MODE != adapter->device_mode)
21560 goto fn_end;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021561
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021562 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
21563 if (!hapd_state) {
21564 hdd_err("Hostapd State is Null");
21565 return 0;
21566 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021567
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021568 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac)) {
21569 if (!QDF_IS_STATUS_SUCCESS(hdd_softap_deauth_all_sta(adapter,
21570 hapd_state,
21571 param)))
21572 goto fn_end;
21573 } else {
Liangwei Dong102edf42020-03-27 16:31:03 +080021574 if (param->reason_code == eSIR_MAC_1X_AUTH_FAILURE_REASON)
21575 hdd_softap_check_wait_for_tx_eap_pkt(
21576 adapter, (struct qdf_mac_addr *)mac);
21577
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021578 sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
21579 mac);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070021580
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021581 if (!sta_info) {
21582 hdd_debug("Skip DEL STA as this is not used::"
21583 QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021584 QDF_MAC_ADDR_ARRAY(mac));
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021585 return -ENOENT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021586 }
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021587
21588 if (sta_info->is_deauth_in_progress) {
21589 hdd_debug("Skip DEL STA as deauth is in progress::"
21590 QDF_MAC_ADDR_STR,
21591 QDF_MAC_ADDR_ARRAY(mac));
Sourav Mohapatra11be3492020-04-22 10:09:32 +053021592 hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info,
21593 true);
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021594 return -ENOENT;
21595 }
21596
21597 hdd_debug("ucast, Delete STA with MAC:" QDF_MAC_ADDR_STR,
21598 QDF_MAC_ADDR_ARRAY(mac));
21599 hdd_softap_deauth_current_sta(adapter, sta_info, hapd_state,
21600 param);
Sourav Mohapatra11be3492020-04-22 10:09:32 +053021601 hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021602 }
21603
21604fn_end:
Dustin Browne74003f2018-03-14 12:51:58 -070021605 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021606 return 0;
21607}
21608
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080021609#if defined(USE_CFG80211_DEL_STA_V2)
21610/**
21611 * wlan_hdd_del_station() - delete station wrapper
21612 * @adapter: pointer to the hdd adapter
21613 *
Sravan Goud2aaf2042020-03-30 17:30:13 +053021614 * Return: Errno
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080021615 */
Sravan Goud2aaf2042020-03-30 17:30:13 +053021616int wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080021617{
21618 struct station_del_parameters del_sta;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070021619
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080021620 del_sta.mac = NULL;
Jia Dingeaefcc32020-05-08 19:53:59 +080021621 del_sta.subtype = IEEE80211_STYPE_DEAUTH >> 4;
21622 del_sta.reason_code = WLAN_REASON_DEAUTH_LEAVING;
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080021623
Sravan Goud2aaf2042020-03-30 17:30:13 +053021624 return wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy,
21625 adapter->dev, &del_sta);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080021626}
21627#else
Sravan Goud2aaf2042020-03-30 17:30:13 +053021628int wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080021629{
Sravan Goud2aaf2042020-03-30 17:30:13 +053021630 return wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy,
21631 adapter->dev, NULL);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080021632}
21633#endif
21634
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021635/**
Dustin Brown1d31b082018-11-22 14:41:20 +053021636 * wlan_hdd_cfg80211_del_station() - delete station entry handler
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021637 * @wiphy: Pointer to wiphy
Dustin Brown1d31b082018-11-22 14:41:20 +053021638 * @dev: net_device to operate against
21639 * @mac: binary mac address
21640 * @reason_code: reason for the deauthorization/disassociation
21641 * @subtype: management frame subtype to indicate removal
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021642 *
Dustin Brown1d31b082018-11-22 14:41:20 +053021643 * Return: Errno
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021644 */
Dustin Brown1d31b082018-11-22 14:41:20 +053021645static int _wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
21646 struct net_device *dev,
21647 const uint8_t *mac,
21648 uint16_t reason_code,
21649 uint8_t subtype)
21650{
21651 int errno;
21652 struct csr_del_sta_params delStaParams;
21653 struct osif_vdev_sync *vdev_sync;
21654
21655 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21656 if (errno)
21657 return errno;
21658
Dustin Brown1d31b082018-11-22 14:41:20 +053021659 wlansap_populate_del_sta_params(mac, reason_code, subtype,
21660 &delStaParams);
21661 errno = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
Dustin Brown1d31b082018-11-22 14:41:20 +053021662
21663 osif_vdev_sync_op_stop(vdev_sync);
21664
21665 return errno;
21666}
21667
21668#ifdef USE_CFG80211_DEL_STA_V2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021669int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
21670 struct net_device *dev,
21671 struct station_del_parameters *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021672{
Dustin Brown1d31b082018-11-22 14:41:20 +053021673 if (!param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021674 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021675
Dustin Brown1d31b082018-11-22 14:41:20 +053021676 return _wlan_hdd_cfg80211_del_station(wiphy, dev, param->mac,
21677 param->reason_code,
21678 param->subtype);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021679}
Dustin Brown1d31b082018-11-22 14:41:20 +053021680#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
21681int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
21682 const uint8_t *mac)
21683{
21684 uint16_t reason = eSIR_MAC_DEAUTH_LEAVING_BSS_REASON;
21685 uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
21686
21687 return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
21688}
21689#else
21690int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
21691 uint8_t *mac)
21692{
21693 uint16_t reason = eSIR_MAC_DEAUTH_LEAVING_BSS_REASON;
21694 uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
21695
21696 return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
21697}
21698#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021699
21700/**
21701 * __wlan_hdd_cfg80211_add_station() - add station
21702 * @wiphy: Pointer to wiphy
21703 * @mac: Pointer to station mac address
21704 * @pmksa: Pointer to add station parameter
21705 *
21706 * Return: 0 for success, non-zero for failure
21707 */
21708static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
21709 struct net_device *dev,
21710 const uint8_t *mac,
21711 struct station_parameters *params)
21712{
21713 int status = -EPERM;
21714#ifdef FEATURE_WLAN_TDLS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021715 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021716 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021717 u32 mask, set;
21718
Dustin Brown491d54b2018-03-14 12:39:11 -070021719 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021720
Anurag Chouhan6d760662016-02-20 16:05:43 +053021721 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021722 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021723 return -EINVAL;
21724 }
21725
Jeff Johnson48363022019-02-24 16:26:51 -080021726 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021727 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021728
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021729 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21730 TRACE_CODE_HDD_CFG80211_ADD_STA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021731 adapter->vdev_id, params->listen_interval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021732
Jeff Johnsonb8944722017-09-03 09:03:19 -070021733 if (0 != wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021734 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021735
21736 mask = params->sta_flags_mask;
21737
21738 set = params->sta_flags_set;
21739
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070021740 hdd_debug("mask 0x%x set 0x%x " QDF_MAC_ADDR_STR, mask, set,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021741 QDF_MAC_ADDR_ARRAY(mac));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021742
21743 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Min Liu8c5d99e2018-09-10 17:18:44 +080021744 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
21745 struct wlan_objmgr_vdev *vdev;
21746
21747 vdev = hdd_objmgr_get_vdev(adapter);
21748 if (vdev) {
21749 status = wlan_cfg80211_tdls_add_peer(vdev,
21750 mac);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053021751 hdd_objmgr_put_vdev(vdev);
Min Liu8c5d99e2018-09-10 17:18:44 +080021752 }
21753 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021754 }
21755#endif
Dustin Browne74003f2018-03-14 12:51:58 -070021756 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021757 return status;
21758}
21759
21760/**
21761 * wlan_hdd_cfg80211_add_station() - add station
21762 * @wiphy: Pointer to wiphy
21763 * @mac: Pointer to station mac address
21764 * @pmksa: Pointer to add station parameter
21765 *
21766 * Return: 0 for success, non-zero for failure
21767 */
21768#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
21769static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
21770 struct net_device *dev,
21771 const uint8_t *mac,
21772 struct station_parameters *params)
21773#else
21774static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
21775 struct net_device *dev, uint8_t *mac,
21776 struct station_parameters *params)
21777#endif
21778{
Dustin Brown1d31b082018-11-22 14:41:20 +053021779 int errno;
21780 struct osif_vdev_sync *vdev_sync;
21781
21782 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21783 if (errno)
21784 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021785
Dustin Brown1d31b082018-11-22 14:41:20 +053021786 errno = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021787
Dustin Brown1d31b082018-11-22 14:41:20 +053021788 osif_vdev_sync_op_stop(vdev_sync);
21789
21790 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021791}
21792
Liangwei Donga44d55b2019-03-20 03:22:08 -040021793static QDF_STATUS wlan_hdd_set_pmksa_cache(struct hdd_adapter *adapter,
21794 tPmkidCacheInfo *pmk_cache)
21795{
21796 QDF_STATUS result;
21797 struct wlan_crypto_pmksa *pmksa;
21798 struct wlan_objmgr_vdev *vdev;
Liangwei Dongd4ea8ea2020-02-05 14:10:36 +080021799 mac_handle_t mac_handle;
21800 struct hdd_context *hdd_ctx;
21801
21802 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21803 if (!hdd_ctx) {
21804 hdd_err("HDD context is null");
21805 return QDF_STATUS_E_INVAL;
21806 }
21807
21808 if (wlan_hdd_validate_context(hdd_ctx))
21809 return QDF_STATUS_E_INVAL;
21810 mac_handle = hdd_ctx->mac_handle;
Liangwei Donga44d55b2019-03-20 03:22:08 -040021811
21812 vdev = hdd_objmgr_get_vdev(adapter);
21813 if (!vdev)
21814 return QDF_STATUS_E_FAILURE;
21815
21816 pmksa = qdf_mem_malloc(sizeof(*pmksa));
21817 if (!pmksa) {
21818 hdd_objmgr_put_vdev(vdev);
21819 return QDF_STATUS_E_NOMEM;
21820 }
Liangwei Dongd4ea8ea2020-02-05 14:10:36 +080021821
21822 if (!pmk_cache->ssid_len) {
21823 qdf_copy_macaddr(&pmksa->bssid, &pmk_cache->BSSID);
21824 } else {
21825 qdf_mem_copy(pmksa->ssid, pmk_cache->ssid, pmk_cache->ssid_len);
21826 qdf_mem_copy(pmksa->cache_id, pmk_cache->cache_id,
21827 WLAN_CACHE_ID_LEN);
21828 pmksa->ssid_len = pmk_cache->ssid_len;
21829 }
Liangwei Donga44d55b2019-03-20 03:22:08 -040021830 qdf_mem_copy(pmksa->pmkid, pmk_cache->PMKID, PMKID_LEN);
21831 qdf_mem_copy(pmksa->pmk, pmk_cache->pmk, pmk_cache->pmk_len);
21832 pmksa->pmk_len = pmk_cache->pmk_len;
21833
21834 result = wlan_crypto_set_del_pmksa(vdev, pmksa, true);
21835 if (result != QDF_STATUS_SUCCESS) {
21836 qdf_mem_zero(pmksa, sizeof(*pmksa));
21837 qdf_mem_free(pmksa);
21838 }
Liangwei Dongd4ea8ea2020-02-05 14:10:36 +080021839
21840 if (result == QDF_STATUS_SUCCESS && pmk_cache->pmk_len)
21841 sme_roam_set_psk_pmk(mac_handle, adapter->vdev_id,
Pragaspathi Thilagaraj400a7832020-04-09 01:05:32 +053021842 pmk_cache->pmk, pmk_cache->pmk_len,
21843 false);
Liangwei Donga44d55b2019-03-20 03:22:08 -040021844 hdd_objmgr_put_vdev(vdev);
21845
21846 return result;
21847}
21848
21849static QDF_STATUS wlan_hdd_del_pmksa_cache(struct hdd_adapter *adapter,
21850 tPmkidCacheInfo *pmk_cache)
21851{
21852 QDF_STATUS result;
21853 struct wlan_crypto_pmksa pmksa;
21854 struct wlan_objmgr_vdev *vdev;
21855
21856 vdev = hdd_objmgr_get_vdev(adapter);
21857 if (!vdev)
21858 return QDF_STATUS_E_FAILURE;
21859
21860 qdf_copy_macaddr(&pmksa.bssid, &pmk_cache->BSSID);
21861 result = wlan_crypto_set_del_pmksa(adapter->vdev, &pmksa, false);
21862 hdd_objmgr_put_vdev(vdev);
21863
21864 return result;
21865}
21866
21867QDF_STATUS wlan_hdd_flush_pmksa_cache(struct hdd_adapter *adapter)
21868{
21869 QDF_STATUS result;
21870 struct wlan_objmgr_vdev *vdev;
21871
21872 vdev = hdd_objmgr_get_vdev(adapter);
21873 if (!vdev)
21874 return QDF_STATUS_E_FAILURE;
21875
21876 result = wlan_crypto_set_del_pmksa(adapter->vdev, NULL, false);
21877 hdd_objmgr_put_vdev(vdev);
21878
21879 return result;
21880}
Liangwei Donga44d55b2019-03-20 03:22:08 -040021881
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053021882#if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
21883 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021884/*
21885 * wlan_hdd_is_pmksa_valid: API to validate pmksa
21886 * @pmksa: pointer to cfg80211_pmksa structure
21887 *
21888 * Return: True if valid else false
21889 */
21890static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
21891{
21892 if (!pmksa->bssid) {
Liangwei Dongd4ea8ea2020-02-05 14:10:36 +080021893 hdd_warn("bssid is NULL");
Vignesh Viswanathanfa90d622017-12-22 13:13:26 +053021894 if (!pmksa->ssid || !pmksa->cache_id) {
Liangwei Dongd4ea8ea2020-02-05 14:10:36 +080021895 hdd_err("either ssid or cache_id are NULL");
Vignesh Viswanathanfa90d622017-12-22 13:13:26 +053021896 return false;
21897 }
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021898 }
21899 return true;
21900}
21901
21902/*
21903 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021904 * @adapter: Pointer to hdd adapter
21905 * @pmk_cache: pmk that needs to be udated
21906 * @pmksa: pmk from supplicant
21907 * @is_delete: Bool to decide set or delete PMK
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021908 * Return: None
21909 */
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021910static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
21911 tPmkidCacheInfo *pmk_cache,
21912 struct cfg80211_pmksa *pmksa, bool is_delete)
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021913{
21914 if (pmksa->bssid) {
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070021915 hdd_debug("%s PMKSA for " QDF_MAC_ADDR_STR,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021916 is_delete ? "Delete" : "Set",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021917 QDF_MAC_ADDR_ARRAY(pmksa->bssid));
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021918 qdf_mem_copy(pmk_cache->BSSID.bytes,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021919 pmksa->bssid, QDF_MAC_ADDR_SIZE);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021920 } else {
Jeff Johnson9c749db2018-05-07 12:50:46 -070021921 qdf_mem_copy(pmk_cache->ssid, pmksa->ssid, pmksa->ssid_len);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021922 qdf_mem_copy(pmk_cache->cache_id, pmksa->cache_id,
21923 CACHE_ID_LEN);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021924 pmk_cache->ssid_len = pmksa->ssid_len;
21925 hdd_debug("%s PMKSA for ssid %*.*s cache_id %x %x",
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021926 is_delete ? "Delete" : "Set",
21927 pmk_cache->ssid_len, pmk_cache->ssid_len,
21928 pmk_cache->ssid, pmk_cache->cache_id[0],
21929 pmk_cache->cache_id[1]);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021930 }
21931
21932 if (is_delete)
21933 return;
21934
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -070021935 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, PMKID_LEN);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021936 if (pmksa->pmk_len && (pmksa->pmk_len <= CSR_RSN_MAX_PMK_LEN)) {
21937 qdf_mem_copy(pmk_cache->pmk, pmksa->pmk, pmksa->pmk_len);
21938 pmk_cache->pmk_len = pmksa->pmk_len;
21939 } else
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053021940 hdd_debug("pmk len is %zu", pmksa->pmk_len);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021941}
21942#else
21943/*
21944 * wlan_hdd_is_pmksa_valid: API to validate pmksa
21945 * @pmksa: pointer to cfg80211_pmksa structure
21946 *
21947 * Return: True if valid else false
21948 */
21949static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
21950{
21951 if (!pmksa->bssid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070021952 hdd_err("both bssid is NULL %pK", pmksa->bssid);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021953 return false;
21954 }
21955 return true;
21956}
21957
21958/*
21959 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021960 * @adapter: Pointer to hdd adapter
21961 * @pmk_cache: pmk which needs to be updated
21962 * @pmksa: pmk from supplicant
21963 * @is_delete: Bool to decide whether to set or delete PMK
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021964 *
21965 * Return: None
21966 */
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021967static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
21968 tPmkidCacheInfo *pmk_cache,
21969 struct cfg80211_pmksa *pmksa, bool is_delete)
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021970{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021971 mac_handle_t mac_handle;
Srinivas Girigowda50335342018-09-07 15:21:01 -070021972
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070021973 hdd_debug("%s PMKSA for " QDF_MAC_ADDR_STR, is_delete ? "Delete" : "Set",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021974 QDF_MAC_ADDR_ARRAY(pmksa->bssid));
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021975 qdf_mem_copy(pmk_cache->BSSID.bytes,
21976 pmksa->bssid, QDF_MAC_ADDR_SIZE);
21977
21978 if (is_delete)
21979 return;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021980 mac_handle = hdd_adapter_get_mac_handle(adapter);
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021981 sme_get_pmk_info(mac_handle, adapter->vdev_id, pmk_cache);
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -070021982 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, PMKID_LEN);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021983}
21984#endif
21985
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021986/**
21987 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
21988 * @wiphy: Pointer to wiphy
21989 * @dev: Pointer to network device
21990 * @pmksa: Pointer to set pmksa parameter
21991 *
21992 * Return: 0 for success, non-zero for failure
21993 */
21994static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
21995 struct net_device *dev,
21996 struct cfg80211_pmksa *pmksa)
21997{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021998 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21999 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022000 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022001 int status;
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053022002 tPmkidCacheInfo *pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022003
Dustin Brown491d54b2018-03-14 12:39:11 -070022004 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022005
Anurag Chouhan6d760662016-02-20 16:05:43 +053022006 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022007 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022008 return -EINVAL;
22009 }
22010
Jeff Johnson48363022019-02-24 16:26:51 -080022011 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022012 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022013
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022014 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022015 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022016 return -EINVAL;
22017 }
22018
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053022019 if (!pmksa->pmkid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070022020 hdd_err("pmksa->pmkid(%pK) is NULL",
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053022021 pmksa->pmkid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022022 return -EINVAL;
22023 }
22024
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053022025 if (!wlan_hdd_is_pmksa_valid(pmksa))
22026 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022027
Jeff Johnsonb8944722017-09-03 09:03:19 -070022028 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022029
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022030 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022031 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022032
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053022033 pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
22034 if (!pmk_cache)
22035 return -ENOMEM;
22036
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053022037 hdd_fill_pmksa_info(adapter, pmk_cache, pmksa, false);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053022038
22039 /*
22040 * Add to the PMKSA Cache in CSR
22041 * PMKSA cache will be having following
22042 * 1. pmkid id
22043 * 2. pmk
22044 * 3. bssid or cache identifier
22045 */
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053022046 result = wlan_hdd_set_pmksa_cache(adapter, pmk_cache);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022047
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022048 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22049 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080022050 adapter->vdev_id, result);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022051
Abhinav Kumard9edfba2020-02-24 22:11:15 +053022052 sme_set_del_pmkid_cache(hdd_ctx->psoc, adapter->vdev_id,
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053022053 pmk_cache, true);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022054
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053022055 qdf_mem_zero(pmk_cache, sizeof(pmk_cache));
22056
22057 qdf_mem_free(pmk_cache);
Dustin Browne74003f2018-03-14 12:51:58 -070022058 hdd_exit();
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +053022059
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022060 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022061}
22062
22063/**
22064 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
22065 * @wiphy: Pointer to wiphy
22066 * @dev: Pointer to network device
22067 * @pmksa: Pointer to set pmksa parameter
22068 *
22069 * Return: 0 for success, non-zero for failure
22070 */
22071static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
22072 struct net_device *dev,
22073 struct cfg80211_pmksa *pmksa)
22074{
Dustin Brown1d31b082018-11-22 14:41:20 +053022075 int errno;
22076 struct osif_vdev_sync *vdev_sync;
22077
22078 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22079 if (errno)
22080 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022081
Dustin Brown1d31b082018-11-22 14:41:20 +053022082 errno = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022083
Dustin Brown1d31b082018-11-22 14:41:20 +053022084 osif_vdev_sync_op_stop(vdev_sync);
22085
22086 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022087}
22088
22089/**
22090 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
22091 * @wiphy: Pointer to wiphy
22092 * @dev: Pointer to network device
22093 * @pmksa: Pointer to pmksa parameter
22094 *
22095 * Return: 0 for success, non-zero for failure
22096 */
22097static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
22098 struct net_device *dev,
22099 struct cfg80211_pmksa *pmksa)
22100{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022101 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
22102 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022103 int status = 0;
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053022104 tPmkidCacheInfo *pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022105
Dustin Brown491d54b2018-03-14 12:39:11 -070022106 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022107
Anurag Chouhan6d760662016-02-20 16:05:43 +053022108 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022109 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022110 return -EINVAL;
22111 }
22112
Jeff Johnson48363022019-02-24 16:26:51 -080022113 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022114 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022115
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022116 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022117 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022118 return -EINVAL;
22119 }
22120
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053022121 if (!wlan_hdd_is_pmksa_valid(pmksa))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022122 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022123
Jeff Johnsonb8944722017-09-03 09:03:19 -070022124 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022125
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022126 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022127 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022128
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053022129 pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
22130 if (!pmk_cache)
22131 return -ENOMEM;
22132
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022133 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22134 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080022135 adapter->vdev_id, 0);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053022136
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053022137 hdd_fill_pmksa_info(adapter, pmk_cache, pmksa, true);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053022138
Abhinav Kumard9edfba2020-02-24 22:11:15 +053022139 /* clear single_pmk_info information */
22140 sme_clear_sae_single_pmk_info(hdd_ctx->psoc, adapter->vdev_id,
22141 pmk_cache);
22142
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022143 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022144 if (QDF_STATUS_SUCCESS !=
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053022145 wlan_hdd_del_pmksa_cache(adapter, pmk_cache)) {
Alan Chen159cd452020-02-13 11:09:23 -080022146 if (!pmksa->bssid)
22147 hdd_err("Failed to delete PMKSA for null bssid");
22148 else
22149 hdd_err("Failed to delete PMKSA for " QDF_MAC_ADDR_STR,
22150 QDF_MAC_ADDR_ARRAY(pmksa->bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022151 status = -EINVAL;
22152 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022153
Abhinav Kumard9edfba2020-02-24 22:11:15 +053022154 sme_set_del_pmkid_cache(hdd_ctx->psoc, adapter->vdev_id, pmk_cache,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022155 false);
Abhinav Kumard9edfba2020-02-24 22:11:15 +053022156
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053022157 qdf_mem_zero(pmk_cache, sizeof(*pmk_cache));
22158 qdf_mem_free(pmk_cache);
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +053022159
Dustin Browne74003f2018-03-14 12:51:58 -070022160 hdd_exit();
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053022161
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022162 return status;
22163}
22164
22165/**
22166 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
22167 * @wiphy: Pointer to wiphy
22168 * @dev: Pointer to network device
22169 * @pmksa: Pointer to pmksa parameter
22170 *
22171 * Return: 0 for success, non-zero for failure
22172 */
22173static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
22174 struct net_device *dev,
22175 struct cfg80211_pmksa *pmksa)
22176{
Dustin Brown1d31b082018-11-22 14:41:20 +053022177 int errno;
22178 struct osif_vdev_sync *vdev_sync;
22179
22180 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22181 if (errno)
22182 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022183
Dustin Brown1d31b082018-11-22 14:41:20 +053022184 errno = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022185
Dustin Brown1d31b082018-11-22 14:41:20 +053022186 osif_vdev_sync_op_stop(vdev_sync);
22187
22188 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022189
22190}
22191
22192/**
22193 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
22194 * @wiphy: Pointer to wiphy
22195 * @dev: Pointer to network device
22196 *
22197 * Return: 0 for success, non-zero for failure
22198 */
22199static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
22200 struct net_device *dev)
22201{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022202 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
22203 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022204 int errno;
22205 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022206
Dustin Brown491d54b2018-03-14 12:39:11 -070022207 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022208
Anurag Chouhan6d760662016-02-20 16:05:43 +053022209 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022210 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022211 return -EINVAL;
22212 }
22213
Jeff Johnson48363022019-02-24 16:26:51 -080022214 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022215 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022216
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022217 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022218
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022219 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022220 errno = wlan_hdd_validate_context(hdd_ctx);
22221 if (errno)
22222 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022223
Liangwei Donga44d55b2019-03-20 03:22:08 -040022224 status = wlan_hdd_flush_pmksa_cache(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022225 if (QDF_IS_STATUS_ERROR(status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022226 hdd_err("Cannot flush PMKIDCache");
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022227 errno = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022228 }
Vignesh Viswanathane8a26b22017-10-11 20:38:47 +053022229
Abhinav Kumard9edfba2020-02-24 22:11:15 +053022230 sme_set_del_pmkid_cache(hdd_ctx->psoc, adapter->vdev_id, NULL, false);
Dustin Browne74003f2018-03-14 12:51:58 -070022231 hdd_exit();
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022232 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022233}
22234
22235/**
22236 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
22237 * @wiphy: Pointer to wiphy
22238 * @dev: Pointer to network device
22239 *
22240 * Return: 0 for success, non-zero for failure
22241 */
22242static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
22243 struct net_device *dev)
22244{
Dustin Brown1d31b082018-11-22 14:41:20 +053022245 int errno;
22246 struct osif_vdev_sync *vdev_sync;
22247
22248 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22249 if (errno)
22250 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022251
Dustin Brown1d31b082018-11-22 14:41:20 +053022252 errno = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022253
Dustin Brown1d31b082018-11-22 14:41:20 +053022254 osif_vdev_sync_op_stop(vdev_sync);
22255
22256 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022257}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022258
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080022259#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022260/**
22261 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
22262 * @wiphy: Pointer to wiphy
22263 * @dev: Pointer to network device
22264 * @ftie: Pointer to fast transition ie parameter
22265 *
22266 * Return: 0 for success, non-zero for failure
22267 */
22268static int
22269__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
22270 struct net_device *dev,
22271 struct cfg80211_update_ft_ies_params *ftie)
22272{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022273 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022274 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsond377dce2017-10-04 10:32:42 -070022275 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022276 int status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022277 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022278
Dustin Brown491d54b2018-03-14 12:39:11 -070022279 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022280
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022281 status = wlan_hdd_validate_context(hdd_ctx);
22282 if (status)
22283 return status;
22284
Anurag Chouhan6d760662016-02-20 16:05:43 +053022285 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022286 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022287 return -EINVAL;
22288 }
22289
Jeff Johnson48363022019-02-24 16:26:51 -080022290 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022291 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022292
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022293 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22294 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
Jeff Johnsone7951512019-02-27 10:02:51 -080022295 adapter->vdev_id, sta_ctx->conn_info.conn_state);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022296
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022297 /* Added for debug on reception of Re-assoc Req. */
Jeff Johnsone7951512019-02-27 10:02:51 -080022298 if (eConnectionState_Associated != sta_ctx->conn_info.conn_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022299 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022300 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022301 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022302 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022303 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022304 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022305
22306 /* Pass the received FT IEs to SME */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022307 mac_handle = hdd_ctx->mac_handle;
Jeff Johnsoncf07c312019-02-04 13:53:29 -080022308 sme_set_ft_ies(mac_handle, adapter->vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022309 (const u8 *)ftie->ie, ftie->ie_len);
Dustin Browne74003f2018-03-14 12:51:58 -070022310 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022311 return 0;
22312}
22313
22314/**
22315 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
22316 * @wiphy: Pointer to wiphy
22317 * @dev: Pointer to network device
22318 * @ftie: Pointer to fast transition ie parameter
22319 *
22320 * Return: 0 for success, non-zero for failure
22321 */
22322static int
22323wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
22324 struct net_device *dev,
22325 struct cfg80211_update_ft_ies_params *ftie)
22326{
Dustin Brown1d31b082018-11-22 14:41:20 +053022327 int errno;
22328 struct osif_vdev_sync *vdev_sync;
22329
22330 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22331 if (errno)
22332 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022333
Dustin Brown1d31b082018-11-22 14:41:20 +053022334 errno = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022335
Dustin Brown1d31b082018-11-22 14:41:20 +053022336 osif_vdev_sync_op_stop(vdev_sync);
22337
22338 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022339}
22340#endif
22341
Min Liu0daa0982019-02-01 17:50:44 +080022342#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
22343/**
22344 * __wlan_hdd_cfg80211_update_owe_info() - update OWE info
22345 * @wiphy: Pointer to wiphy
22346 * @dev: Pointer to network device
22347 * @owe_info: Pointer to OWE info
22348 *
22349 * Return: 0 for success, non-zero for failure
22350 */
22351static int
22352__wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
22353 struct net_device *dev,
22354 struct cfg80211_update_owe_info *owe_info)
22355{
22356 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
22357 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
22358 QDF_STATUS status;
Dustin Brown96b98dd2019-03-06 12:39:37 -080022359 int errno;
Min Liu0daa0982019-02-01 17:50:44 +080022360
22361 hdd_enter_dev(dev);
22362
22363 errno = wlan_hdd_validate_context(hdd_ctx);
22364 if (errno)
22365 return errno;
22366
22367 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
22368 hdd_err("Command not allowed in FTM mode");
22369 return -EINVAL;
22370 }
22371
Jeff Johnsona6b398d2019-02-24 16:26:51 -080022372 if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) {
22373 hdd_err("invalid vdev id: %d", adapter->vdev_id);
Min Liu0daa0982019-02-01 17:50:44 +080022374 return -EINVAL;
22375 }
22376
22377 hdd_debug("owe_status %d", owe_info->status);
22378
22379 status = wlansap_update_owe_info(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Min Liue2b469f2019-04-10 19:13:42 +080022380 owe_info->peer, owe_info->ie,
Min Liu0daa0982019-02-01 17:50:44 +080022381 owe_info->ie_len, owe_info->status);
22382 if (QDF_IS_STATUS_ERROR(status)) {
22383 hdd_err("Failed to update OWE info");
22384 errno = qdf_status_to_os_return(status);
22385 }
22386
22387 hdd_exit();
22388 return errno;
22389}
22390
22391/**
22392 * wlan_hdd_cfg80211_update_owe_info() - update OWE info
22393 * @wiphy: Pointer to wiphy
22394 * @dev: Pointer to network device
22395 * @owe_info: Pointer to OWE info
22396 *
22397 * Return: 0 for success, non-zero for failure
22398 */
22399static int
22400wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
Dustin Brown96b98dd2019-03-06 12:39:37 -080022401 struct net_device *net_dev,
Min Liu0daa0982019-02-01 17:50:44 +080022402 struct cfg80211_update_owe_info *owe_info)
22403{
Dustin Brown96b98dd2019-03-06 12:39:37 -080022404 struct osif_vdev_sync *vdev_sync;
22405 int errno;
Min Liu0daa0982019-02-01 17:50:44 +080022406
Dustin Brown96b98dd2019-03-06 12:39:37 -080022407 errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
22408 if (errno)
22409 return errno;
Min Liu0daa0982019-02-01 17:50:44 +080022410
Dustin Brown96b98dd2019-03-06 12:39:37 -080022411 errno = __wlan_hdd_cfg80211_update_owe_info(wiphy, net_dev, owe_info);
22412
22413 osif_vdev_sync_op_stop(vdev_sync);
22414
22415 return errno;
Min Liu0daa0982019-02-01 17:50:44 +080022416}
22417#endif
22418
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +053022419void wlan_hdd_cfg80211_update_replay_counter_cb(
Mukul Sharma3d36c392017-01-18 18:39:12 +053022420 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
22421
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022422{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022423 struct hdd_adapter *adapter = (struct hdd_adapter *)cb_ctx;
Mukul Sharma3d36c392017-01-18 18:39:12 +053022424 uint8_t temp_replay_counter[8];
22425 int i;
22426 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022427
Dustin Brown491d54b2018-03-14 12:39:11 -070022428 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022429
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022430 if (!adapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022431 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053022432 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022433 }
22434
Mukul Sharma3d36c392017-01-18 18:39:12 +053022435 if (!gtk_rsp_param) {
22436 hdd_err("gtk_rsp_param is Null");
22437 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022438 }
22439
Mukul Sharma3d36c392017-01-18 18:39:12 +053022440 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022441 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053022442 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022443 }
22444
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022445 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053022446 gtk_rsp_param->replay_counter);
22447 /* convert little to big endian since supplicant works on big endian */
22448 p = (uint8_t *)&gtk_rsp_param->replay_counter;
22449 for (i = 0; i < 8; i++)
22450 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022451
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022452 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022453 /* Update replay counter to NL */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022454 cfg80211_gtk_rekey_notify(adapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053022455 gtk_rsp_param->bssid.bytes,
22456 temp_replay_counter, GFP_KERNEL);
22457out:
Dustin Browne74003f2018-03-14 12:51:58 -070022458 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053022459
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022460}
22461
Wu Gaoa9d336b2018-05-30 14:48:04 +080022462#ifdef WLAN_FEATURE_GTK_OFFLOAD
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022463/**
22464 * wlan_hdd_copy_gtk_kek - Copy the KEK from GTK rekey data to GTK request
22465 * @gtk_req: Pointer to GTK request
22466 * @data: Pointer to rekey data
22467 *
22468 * Return: none
22469 */
22470#ifdef CFG80211_REKEY_DATA_KEK_LEN
22471static
22472void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
22473 struct cfg80211_gtk_rekey_data *data)
22474{
22475 qdf_mem_copy(gtk_req->kek, data->kek, data->kek_len);
22476 gtk_req->kek_len = data->kek_len;
22477}
22478#else
22479static
22480void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
22481 struct cfg80211_gtk_rekey_data *data)
22482{
22483 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
22484 gtk_req->kek_len = NL80211_KEK_LEN;
22485}
22486#endif
22487
22488/**
22489 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
22490 * @wiphy: Pointer to wiphy
22491 * @dev: Pointer to network device
22492 * @data: Pointer to rekey data
22493 *
22494 * This function is used to offload GTK rekeying job to the firmware.
22495 *
22496 * Return: 0 for success, non-zero for failure
22497 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070022498static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022499int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053022500 struct net_device *dev,
22501 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022502{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022503 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053022504 int result, i;
22505 struct pmo_gtk_req *gtk_req = NULL;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022506 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharma3d36c392017-01-18 18:39:12 +053022507 uint8_t *buf;
Min Liu8c5d99e2018-09-10 17:18:44 +080022508 struct wlan_objmgr_vdev *vdev;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022509 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022510
Dustin Brown491d54b2018-03-14 12:39:11 -070022511 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022512
Anurag Chouhan6d760662016-02-20 16:05:43 +053022513 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022514 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053022515 result = -EINVAL;
22516 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022517 }
22518
Jeff Johnson48363022019-02-24 16:26:51 -080022519 if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) {
Mukul Sharma3d36c392017-01-18 18:39:12 +053022520 result = -EINVAL;
22521 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022522 }
22523
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022524 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22525 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080022526 adapter->vdev_id, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022527
Mukul Sharma3d36c392017-01-18 18:39:12 +053022528 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022529 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053022530 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022531
Mukul Sharma3d36c392017-01-18 18:39:12 +053022532 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
22533 if (!gtk_req) {
Mukul Sharma3d36c392017-01-18 18:39:12 +053022534 result = -ENOMEM;
22535 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022536 }
22537
Mukul Sharma3d36c392017-01-18 18:39:12 +053022538 /* convert big to little endian since driver work on little endian */
22539 buf = (uint8_t *)&gtk_req->replay_counter;
22540 for (i = 0; i < 8; i++)
22541 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022542
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022543 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053022544 gtk_req->replay_counter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022545
22546 wlan_hdd_copy_gtk_kek(gtk_req, data);
Yeshwanth Sriram Guntukae6313412019-08-06 14:18:33 +053022547 if (data->kck) {
nakul kachhwahaa580cc32019-03-15 17:45:17 +053022548 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
Yeshwanth Sriram Guntukae6313412019-08-06 14:18:33 +053022549 gtk_req->kck_len = NL80211_KCK_LEN;
22550 }
gaurank kathpalia82a1b2b2018-07-10 16:49:10 +053022551 gtk_req->is_fils_connection = hdd_is_fils_connection(adapter);
Min Liu8c5d99e2018-09-10 17:18:44 +080022552 vdev = hdd_objmgr_get_vdev(adapter);
22553 if (!vdev) {
22554 result = -EINVAL;
22555 goto out;
22556 }
22557 status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053022558 hdd_objmgr_put_vdev(vdev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053022559 if (status != QDF_STATUS_SUCCESS) {
22560 hdd_err("Failed to cache GTK Offload");
22561 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022562 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053022563out:
22564 if (gtk_req)
22565 qdf_mem_free(gtk_req);
Dustin Browne74003f2018-03-14 12:51:58 -070022566 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053022567
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022568 return result;
22569}
22570
22571/**
22572 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
22573 * @wiphy: Pointer to wiphy
22574 * @dev: Pointer to network device
22575 * @data: Pointer to rekey data
22576 *
22577 * This function is used to offload GTK rekeying job to the firmware.
22578 *
22579 * Return: 0 for success, non-zero for failure
22580 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070022581static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022582int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
22583 struct net_device *dev,
22584 struct cfg80211_gtk_rekey_data *data)
22585{
Dustin Brown1d31b082018-11-22 14:41:20 +053022586 int errno;
22587 struct osif_vdev_sync *vdev_sync;
22588
22589 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22590 if (errno)
22591 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022592
Dustin Brown1d31b082018-11-22 14:41:20 +053022593 errno = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022594
Dustin Brown1d31b082018-11-22 14:41:20 +053022595 osif_vdev_sync_op_stop(vdev_sync);
22596
22597 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022598}
Wu Gaoa9d336b2018-05-30 14:48:04 +080022599#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022600
22601/**
22602 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
22603 * @wiphy: Pointer to wiphy
22604 * @dev: Pointer to network device
22605 * @param: Pointer to access control parameter
22606 *
22607 * Return: 0 for success, non-zero for failure
22608 */
22609static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
22610 struct net_device *dev,
22611 const struct cfg80211_acl_data *params)
22612{
22613 int i;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022614 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson5c19ade2017-10-04 09:52:12 -070022615 struct hdd_hostapd_state *hostapd_state;
Jeff Johnson8f8ceb92019-03-24 08:16:55 -070022616 struct sap_config *config;
Jeff Johnsonb8944722017-09-03 09:03:19 -070022617 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022618 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022619 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022620
Dustin Brown491d54b2018-03-14 12:39:11 -070022621 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022622
Anurag Chouhan6d760662016-02-20 16:05:43 +053022623 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022624 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022625 return -EINVAL;
22626 }
22627
Jeff Johnsond36fa332019-03-18 13:42:25 -070022628 if (!params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022629 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022630 return -EINVAL;
22631 }
22632
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022633 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070022634 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022635
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022636 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022637 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022638
Jeff Johnson5c19ade2017-10-04 09:52:12 -070022639 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022640
Jeff Johnsond36fa332019-03-18 13:42:25 -070022641 if (!hostapd_state) {
Jeff Johnson5c19ade2017-10-04 09:52:12 -070022642 hdd_err("hostapd_state is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022643 return -EINVAL;
22644 }
22645
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022646 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022647 params->n_acl_entries);
22648
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022649 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22650 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080022651 adapter->vdev_id, adapter->device_mode);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022652
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022653 if (QDF_SAP_MODE == adapter->device_mode) {
Jeff Johnson954903d2019-03-07 20:41:27 -080022654 config = &adapter->session.ap.sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022655
22656 /* default value */
Jeff Johnson954903d2019-03-07 20:41:27 -080022657 config->num_accept_mac = 0;
22658 config->num_deny_mac = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022659
22660 /**
22661 * access control policy
22662 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
22663 * listed in hostapd.deny file.
22664 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
22665 * listed in hostapd.accept file.
22666 */
22667 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
Jeff Johnson954903d2019-03-07 20:41:27 -080022668 config->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022669 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
22670 params->acl_policy) {
Jeff Johnson954903d2019-03-07 20:41:27 -080022671 config->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022672 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022673 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022674 params->acl_policy);
22675 return -ENOTSUPP;
22676 }
22677
Jeff Johnson954903d2019-03-07 20:41:27 -080022678 if (eSAP_DENY_UNLESS_ACCEPTED == config->SapMacaddr_acl) {
22679 config->num_accept_mac = params->n_acl_entries;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022680 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022681 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070022682 QDF_MAC_ADDR_STR, i,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070022683 QDF_MAC_ADDR_ARRAY(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022684 params->mac_addrs[i].addr));
22685
Jeff Johnson954903d2019-03-07 20:41:27 -080022686 qdf_mem_copy(&config->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022687 params->mac_addrs[i].addr,
Srinivas Girigowdaa47b45f2019-02-27 12:29:02 -080022688 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022689 }
Jeff Johnson954903d2019-03-07 20:41:27 -080022690 } else if (eSAP_ACCEPT_UNLESS_DENIED == config->SapMacaddr_acl) {
22691 config->num_deny_mac = params->n_acl_entries;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022692 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022693 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070022694 QDF_MAC_ADDR_STR, i,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070022695 QDF_MAC_ADDR_ARRAY(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022696 params->mac_addrs[i].addr));
22697
Jeff Johnson954903d2019-03-07 20:41:27 -080022698 qdf_mem_copy(&config->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022699 params->mac_addrs[i].addr,
Srinivas Girigowdaa47b45f2019-02-27 12:29:02 -080022700 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022701 }
22702 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070022703 qdf_status = wlansap_set_mac_acl(
Jeff Johnson954903d2019-03-07 20:41:27 -080022704 WLAN_HDD_GET_SAP_CTX_PTR(adapter), config);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022705 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022706 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022707 return -EINVAL;
22708 }
22709 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022710 hdd_debug("Invalid device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070022711 qdf_opmode_str(adapter->device_mode),
22712 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022713 return -EINVAL;
22714 }
Dustin Browne74003f2018-03-14 12:51:58 -070022715 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022716 return 0;
22717}
22718
22719/**
22720 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
22721 * __wlan_hdd_cfg80211_set_mac_acl
22722 * @wiphy: pointer to wiphy structure
22723 * @dev: pointer to net_device
22724 * @params: pointer to cfg80211_acl_data
22725 *
22726 * Return; 0 on success, error number otherwise
22727 */
22728static int
22729wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
22730 struct net_device *dev,
22731 const struct cfg80211_acl_data *params)
22732{
Dustin Brown1d31b082018-11-22 14:41:20 +053022733 int errno;
22734 struct osif_vdev_sync *vdev_sync;
22735
22736 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22737 if (errno)
22738 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022739
Dustin Brown1d31b082018-11-22 14:41:20 +053022740 errno = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022741
Dustin Brown1d31b082018-11-22 14:41:20 +053022742 osif_vdev_sync_op_stop(vdev_sync);
22743
22744 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022745}
22746
22747#ifdef WLAN_NL80211_TESTMODE
22748#ifdef FEATURE_WLAN_LPHB
22749/**
22750 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
Jeff Johnsonb8944722017-09-03 09:03:19 -070022751 * @hdd_ctx: Pointer to hdd context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022752 * @lphbInd: Pointer to low power heart beat indication parameter
22753 *
22754 * Return: none
22755 */
Jeff Johnsonb8944722017-09-03 09:03:19 -070022756static void wlan_hdd_cfg80211_lphb_ind_handler(void *hdd_ctx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022757 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022758{
22759 struct sk_buff *skb;
22760
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022761 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022762
Jeff Johnsonb8944722017-09-03 09:03:19 -070022763 if (0 != wlan_hdd_validate_context((struct hdd_context *) hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022764 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022765
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022766 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022767 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022768 return;
22769 }
22770
Jeff Johnsonb8944722017-09-03 09:03:19 -070022771 skb = cfg80211_testmode_alloc_event_skb(((struct hdd_context *) hdd_ctx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022772 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022773 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022774 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022775 return;
22776 }
22777
22778 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022779 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022780 goto nla_put_failure;
22781 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022782 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022783 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022784 goto nla_put_failure;
22785 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022786 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
22787 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022788 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022789 goto nla_put_failure;
22790 }
22791 cfg80211_testmode_event(skb, GFP_ATOMIC);
22792 return;
22793
22794nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022795 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022796 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022797}
22798#endif /* FEATURE_WLAN_LPHB */
22799
22800/**
22801 * __wlan_hdd_cfg80211_testmode() - test mode
22802 * @wiphy: Pointer to wiphy
22803 * @data: Data pointer
22804 * @len: Data length
22805 *
22806 * Return: 0 for success, non-zero for failure
22807 */
22808static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
22809 void *data, int len)
22810{
22811 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
22812 int err;
Jeff Johnsonb8944722017-09-03 09:03:19 -070022813 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022814
Dustin Brown491d54b2018-03-14 12:39:11 -070022815 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022816
Jeff Johnsonb8944722017-09-03 09:03:19 -070022817 err = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022818 if (err)
22819 return err;
22820
Ryan Hsu4df41382018-06-15 15:45:22 -070022821 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
22822 hdd_err("Driver Modules are closed");
22823 return -EINVAL;
22824 }
22825
Dustin Brown4ea21db2018-01-05 14:13:17 -080022826 err = wlan_cfg80211_nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
22827 len, wlan_hdd_tm_policy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022828 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022829 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022830 return err;
22831 }
22832
22833 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022834 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022835 return -EINVAL;
22836 }
22837
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022838 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22839 TRACE_CODE_HDD_CFG80211_TESTMODE,
22840 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
22841
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022842 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
22843#ifdef FEATURE_WLAN_LPHB
22844 /* Low Power Heartbeat configuration request */
22845 case WLAN_HDD_TM_CMD_WLAN_HB:
22846 {
22847 int buf_len;
22848 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022849 struct pmo_lphb_req *hb_params = NULL;
22850 struct pmo_lphb_req *hb_params_temp = NULL;
22851 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022852
22853 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022854 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022855 return -EINVAL;
22856 }
22857
22858 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
22859 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
Rajeev Kumar Sirasanagandla012e7b72019-03-14 21:54:43 +053022860 if (buf_len < sizeof(*hb_params_temp)) {
22861 hdd_err("Invalid buffer length for TM_ATTR_DATA");
22862 return -EINVAL;
22863 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022864
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022865 hb_params_temp = (struct pmo_lphb_req *) buf;
22866 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
22867 && (hb_params_temp->params.lphb_tcp_params.
22868 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022869 return -EINVAL;
22870
Manjeet Singh00b2a562017-01-03 12:08:10 +053022871 if (buf_len > sizeof(*hb_params)) {
22872 hdd_err("buf_len=%d exceeded hb_params size limit",
22873 buf_len);
22874 return -ERANGE;
22875 }
22876
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022877 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
22878 sizeof(*hb_params));
Min Liu74a1a502018-10-10 19:59:07 +080022879 if (!hb_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022880 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022881
Ashish Kumar Dhanotiya0fa8ee02017-07-13 14:04:31 +053022882 qdf_mem_zero(hb_params, sizeof(*hb_params));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053022883 qdf_mem_copy(hb_params, buf, buf_len);
Wu Gaod7dd6e42018-10-16 17:22:56 +080022884 status = ucfg_pmo_lphb_config_req(
22885 hdd_ctx->psoc,
Jeff Johnsonb8944722017-09-03 09:03:19 -070022886 hb_params, (void *)hdd_ctx,
Wu Gaod7dd6e42018-10-16 17:22:56 +080022887 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022888 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022889 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022890
22891 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022892 return 0;
22893 }
22894#endif /* FEATURE_WLAN_LPHB */
22895
22896#if defined(QCA_WIFI_FTM)
22897 case WLAN_HDD_TM_CMD_WLAN_FTM:
22898 {
Ryan Hsu4df41382018-06-15 15:45:22 -070022899 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam()) {
22900 hdd_err("Command not allowed in FTM mode, mode %d",
22901 hdd_get_conparam());
22902 return -EINVAL;
22903 }
22904
Dustin Brown07901ec2018-09-07 11:02:41 -070022905 err = wlan_cfg80211_ftm_testmode_cmd(hdd_ctx->pdev,
Ryan Hsuc8b27a42018-01-02 13:57:56 -080022906 data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022907 break;
22908 }
22909#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022910 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022911 hdd_err("command: %d not supported",
Ryan Hsuc8b27a42018-01-02 13:57:56 -080022912 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022913 return -EOPNOTSUPP;
22914 }
Ryan Hsuc8b27a42018-01-02 13:57:56 -080022915
Dustin Browne74003f2018-03-14 12:51:58 -070022916 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022917 return err;
22918}
22919
22920/**
22921 * wlan_hdd_cfg80211_testmode() - test mode
22922 * @wiphy: Pointer to wiphy
22923 * @dev: Pointer to network device
22924 * @data: Data pointer
22925 * @len: Data length
22926 *
22927 * Return: 0 for success, non-zero for failure
22928 */
22929static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
22930#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
22931 struct wireless_dev *wdev,
22932#endif
22933 void *data, int len)
22934{
Dustin Brown363b4792019-02-05 16:11:55 -080022935 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080022936 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +053022937
Dustin Brown363b4792019-02-05 16:11:55 -080022938 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080022939 if (errno)
22940 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022941
Dustin Brownf0f00612019-01-31 16:02:24 -080022942 errno = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022943
Dustin Brown363b4792019-02-05 16:11:55 -080022944 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080022945
22946 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022947}
22948
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022949#endif /* CONFIG_NL80211_TESTMODE */
22950
22951#ifdef QCA_HT_2040_COEX
22952/**
22953 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
22954 * @wiphy: Pointer to wiphy
22955 * @dev: Pointer to network device
22956 * @chandef: Pointer to channel definition parameter
22957 *
22958 * Return: 0 for success, non-zero for failure
22959 */
22960static int
22961__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
22962 struct net_device *dev,
22963 struct cfg80211_chan_def *chandef)
22964{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022965 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070022966 struct hdd_context *hdd_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022967 QDF_STATUS status;
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053022968 int retval = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022969
Anurag Chouhan6d760662016-02-20 16:05:43 +053022970 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022971 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022972 return -EINVAL;
22973 }
22974
Jeff Johnson48363022019-02-24 16:26:51 -080022975 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022976 return -EINVAL;
Dustin Brown63500612018-08-07 11:36:09 -070022977
Abhishek Singh9d5f4582017-10-11 17:59:48 +053022978 if (!(adapter->device_mode == QDF_SAP_MODE ||
22979 adapter->device_mode == QDF_P2P_GO_MODE))
22980 return -EOPNOTSUPP;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022981
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022982 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070022983 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053022984 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022985 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022986
Abhishek Singh9d5f4582017-10-11 17:59:48 +053022987 hdd_debug("Channel width changed to %d ",
22988 cfg80211_get_chandef_type(chandef));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022989
22990 /* Change SAP ht2040 mode */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022991 status = hdd_set_sap_ht2040_mode(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022992 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022993 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022994 hdd_err("Cannot set SAP HT20/40 mode!");
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053022995 retval = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022996 }
22997
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053022998 return retval;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022999}
23000
23001/**
23002 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
23003 * @wiphy: Pointer to wiphy
23004 * @dev: Pointer to network device
23005 * @chandef: Pointer to channel definition parameter
23006 *
23007 * Return: 0 for success, non-zero for failure
23008 */
23009static int
23010wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
23011 struct net_device *dev,
23012 struct cfg80211_chan_def *chandef)
23013{
Dustin Brown1d31b082018-11-22 14:41:20 +053023014 int errno;
23015 struct osif_vdev_sync *vdev_sync;
23016
23017 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
23018 if (errno)
23019 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023020
Dustin Brown1d31b082018-11-22 14:41:20 +053023021 errno = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023022
Dustin Brown1d31b082018-11-22 14:41:20 +053023023 osif_vdev_sync_op_stop(vdev_sync);
23024
23025 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023026}
23027#endif
23028
Abhishek Singh1bdb1572015-10-16 16:24:19 +053023029#ifdef CHANNEL_SWITCH_SUPPORTED
23030/**
23031 * __wlan_hdd_cfg80211_channel_switch()- function to switch
23032 * channel in SAP/GO
23033 * @wiphy: wiphy pointer
23034 * @dev: dev pointer.
23035 * @csa_params: Change channel params
23036 *
23037 * This function is called to switch channel in SAP/GO
23038 *
23039 * Return: 0 if success else return non zero
23040 */
23041static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
23042 struct net_device *dev,
23043 struct cfg80211_csa_settings *csa_params)
23044{
Jeff Johnsone5006672017-08-29 14:39:02 -070023045 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070023046 struct hdd_context *hdd_ctx;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053023047 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080023048 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053023049
Srinivas Girigowda13d39252017-03-06 16:12:15 -080023050 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053023051 csa_params->chandef.chan->center_freq);
23052
Jeff Johnson48363022019-02-24 16:26:51 -080023053 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053023054 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053023055
Abhishek Singh1bdb1572015-10-16 16:24:19 +053023056 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23057 ret = wlan_hdd_validate_context(hdd_ctx);
23058
23059 if (0 != ret)
23060 return ret;
23061
Krunal Sonib4326f22016-03-10 13:05:51 -080023062 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
23063 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053023064 return -ENOTSUPP;
Bala Venkatesh8b9bbde2019-07-03 16:25:16 +053023065 wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->vdev_id,
23066 CSA_REASON_USER_INITIATED);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053023067
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053023068 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
23069
Tushnim Bhattacharyya6c40b112019-10-30 11:39:25 -070023070 ret =
23071 hdd_softap_set_channel_change(dev,
23072 csa_params->chandef.chan->center_freq,
23073 ch_width, false);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053023074 return ret;
23075}
23076
Rakesh Pillai20fde902020-06-08 20:02:55 +053023077enum qca_wlan_802_11_mode
23078hdd_convert_cfgdot11mode_to_80211mode(enum csr_cfgdot11mode mode)
23079{
23080 switch (mode) {
23081 case eCSR_CFG_DOT11_MODE_11A:
23082 return QCA_WLAN_802_11_MODE_11A;
23083 case eCSR_CFG_DOT11_MODE_11B:
23084 return QCA_WLAN_802_11_MODE_11B;
23085 case eCSR_CFG_DOT11_MODE_11G:
23086 return QCA_WLAN_802_11_MODE_11G;
23087 case eCSR_CFG_DOT11_MODE_11N:
23088 return QCA_WLAN_802_11_MODE_11N;
23089 case eCSR_CFG_DOT11_MODE_11AC:
23090 return QCA_WLAN_802_11_MODE_11AC;
23091 case eCSR_CFG_DOT11_MODE_11G_ONLY:
23092 return QCA_WLAN_802_11_MODE_11G;
23093 case eCSR_CFG_DOT11_MODE_11N_ONLY:
23094 return QCA_WLAN_802_11_MODE_11N;
23095 case eCSR_CFG_DOT11_MODE_11AC_ONLY:
23096 return QCA_WLAN_802_11_MODE_11AC;
23097 case eCSR_CFG_DOT11_MODE_11AX:
23098 return QCA_WLAN_802_11_MODE_11AX;
23099 case eCSR_CFG_DOT11_MODE_11AX_ONLY:
23100 return QCA_WLAN_802_11_MODE_11AX;
23101 case eCSR_CFG_DOT11_MODE_ABG:
23102 case eCSR_CFG_DOT11_MODE_AUTO:
23103 default:
23104 return QCA_WLAN_802_11_MODE_INVALID;
23105 }
23106}
23107
Abhishek Singh1bdb1572015-10-16 16:24:19 +053023108/**
23109 * wlan_hdd_cfg80211_channel_switch()- function to switch
23110 * channel in SAP/GO
23111 * @wiphy: wiphy pointer
23112 * @dev: dev pointer.
23113 * @csa_params: Change channel params
23114 *
23115 * This function is called to switch channel in SAP/GO
23116 *
23117 * Return: 0 if success else return non zero
23118 */
23119static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
23120 struct net_device *dev,
23121 struct cfg80211_csa_settings *csa_params)
23122{
Dustin Brown1d31b082018-11-22 14:41:20 +053023123 int errno;
23124 struct osif_vdev_sync *vdev_sync;
23125
23126 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
23127 if (errno)
23128 return errno;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053023129
Dustin Brown1d31b082018-11-22 14:41:20 +053023130 errno = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
Dustin Brown1d31b082018-11-22 14:41:20 +053023131
23132 osif_vdev_sync_op_stop(vdev_sync);
23133
23134 return errno;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053023135}
23136#endif
23137
Krunal Sonied3bc8e2018-01-26 12:13:34 -080023138int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter,
Tushnim Bhattacharyyac682bfb2019-12-11 17:11:10 -080023139 uint32_t chan_freq,
23140 enum policy_mgr_conn_update_reason reason)
Krunal Sonied3bc8e2018-01-26 12:13:34 -080023141{
23142 QDF_STATUS status;
23143 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23144
Dustin Brown491d54b2018-03-14 12:39:11 -070023145 hdd_enter();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080023146
Dustin Brown76cd2932018-09-11 16:03:05 -070023147 status = policy_mgr_reset_connection_update(hdd_ctx->psoc);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080023148 if (!QDF_IS_STATUS_SUCCESS(status))
23149 hdd_err("clearing event failed");
23150
Manikandan Mohan282c4b62019-08-14 17:42:22 -070023151 status = policy_mgr_current_connections_update(
23152 hdd_ctx->psoc, adapter->vdev_id,
Tushnim Bhattacharyyac682bfb2019-12-11 17:11:10 -080023153 chan_freq, reason);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080023154 switch (status) {
23155 case QDF_STATUS_E_FAILURE:
23156 /*
Jeff Johnson11d7c9d2018-05-06 15:44:09 -070023157 * QDF_STATUS_E_FAILURE indicates that some error has occurred
Krunal Sonied3bc8e2018-01-26 12:13:34 -080023158 * while changing the hw mode
23159 */
23160 hdd_err("ERROR: connections update failed!!");
23161 return -EINVAL;
23162
23163 case QDF_STATUS_SUCCESS:
23164 /*
23165 * QDF_STATUS_SUCCESS indicates that HW mode change has been
23166 * triggered and wait for it to finish.
23167 */
23168 status = policy_mgr_wait_for_connection_update(
Dustin Brown76cd2932018-09-11 16:03:05 -070023169 hdd_ctx->psoc);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080023170 if (!QDF_IS_STATUS_SUCCESS(status)) {
23171 hdd_err("ERROR: qdf wait for event failed!!");
23172 return -EINVAL;
23173 }
23174 if (QDF_MONITOR_MODE == adapter->device_mode)
Tushnim Bhattacharyyac682bfb2019-12-11 17:11:10 -080023175 hdd_info("Monitor mode:channel freq:%d (SMM->DBS)", chan_freq);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080023176 break;
23177
23178 default:
23179 /*
23180 * QDF_STATUS_E_NOSUPPORT indicates that no HW mode change is
23181 * required, so caller can proceed further.
23182 */
23183 break;
23184
23185 }
Dustin Browne74003f2018-03-14 12:51:58 -070023186 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080023187
23188 return 0;
23189}
23190
Nirav Shah73713f72018-05-17 14:50:41 +053023191#ifdef FEATURE_MONITOR_MODE_SUPPORT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023192/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023193 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
23194 * @wiphy: Handle to struct wiphy to get handle to module context.
23195 * @chandef: Contains information about the capture channel to be set.
23196 *
23197 * This interface is called if and only if monitor mode interface alone is
23198 * active.
23199 *
23200 * Return: 0 success or error code on failure.
23201 */
23202static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
23203 struct cfg80211_chan_def *chandef)
23204{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070023205 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsone5006672017-08-29 14:39:02 -070023206 struct hdd_adapter *adapter;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070023207 struct hdd_station_ctx *sta_ctx;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023208 struct hdd_mon_set_ch_info *ch_info;
23209 QDF_STATUS status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023210 mac_handle_t mac_handle;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023211 struct qdf_mac_addr bssid;
Jeff Johnson61b5e982018-03-15 11:33:31 -070023212 struct csr_roam_profile roam_profile;
Saket Jhad5c0e022019-11-18 16:53:47 -080023213 struct ch_params ch_params;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023214 int ret;
gaurank kathpalia31800672019-11-22 13:50:11 +053023215 enum channel_state chan_freq_state;
23216 uint8_t max_fw_bw;
23217 enum phy_ch_width ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023218
Dustin Brown491d54b2018-03-14 12:39:11 -070023219 hdd_enter();
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023220
23221 ret = wlan_hdd_validate_context(hdd_ctx);
23222 if (ret)
23223 return ret;
23224
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023225 mac_handle = hdd_ctx->mac_handle;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023226
23227 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
23228 if (!adapter)
23229 return -EIO;
23230
Saket Jhad5c0e022019-11-18 16:53:47 -080023231 hdd_debug("%s: set monitor mode freq %d",
23232 adapter->dev->name, chandef->chan->center_freq);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023233
gaurank kathpalia31800672019-11-22 13:50:11 +053023234 /* Verify channel state before accepting this request */
23235 chan_freq_state =
23236 wlan_reg_get_channel_state_for_freq(hdd_ctx->pdev,
23237 chandef->chan->center_freq);
23238 if (chan_freq_state == CHANNEL_STATE_DISABLE ||
23239 chan_freq_state == CHANNEL_STATE_INVALID) {
23240 hdd_err("Invalid chan freq received for monitor mode aborting");
23241 return -EINVAL;
23242 }
23243
23244 /* Verify the BW before accepting this request */
23245 ch_width = hdd_map_nl_chan_width(chandef->width);
23246
gaurank kathpaliab3b21942020-01-10 15:09:33 +053023247 if (ch_width > CH_WIDTH_10MHZ ||
23248 (!cds_is_sub_20_mhz_enabled() && ch_width > CH_WIDTH_160MHZ)) {
23249 hdd_err("invalid BW received %d", ch_width);
23250 return -EINVAL;
23251 }
23252
gaurank kathpalia31800672019-11-22 13:50:11 +053023253 max_fw_bw = sme_get_vht_ch_width();
23254
23255 if ((ch_width == CH_WIDTH_160MHZ &&
23256 max_fw_bw <= WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) ||
23257 (ch_width == CH_WIDTH_80P80MHZ &&
23258 max_fw_bw <= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)) {
23259 hdd_err("FW does not support this BW %d max BW supported %d",
23260 ch_width, max_fw_bw);
23261 return -EINVAL;
23262 }
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023263 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
23264 ch_info = &sta_ctx->ch_info;
wadesong24c869a2019-07-19 17:38:59 +080023265 roam_profile.ChannelInfo.freq_list = &ch_info->freq;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023266 roam_profile.ChannelInfo.numOfChannels = 1;
23267 roam_profile.phyMode = ch_info->phy_mode;
gaurank kathpalia31800672019-11-22 13:50:11 +053023268 roam_profile.ch_params.ch_width = ch_width;
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070023269 hdd_select_cbmode(adapter, chandef->chan->center_freq,
23270 &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023271
Jeff Johnson1e851a12017-10-28 14:36:12 -070023272 qdf_mem_copy(bssid.bytes, adapter->mac_addr.bytes,
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023273 QDF_MAC_ADDR_SIZE);
23274
Saket Jhad5c0e022019-11-18 16:53:47 -080023275 ch_params.ch_width = ch_width;
23276 wlan_reg_set_channel_params_for_freq(hdd_ctx->pdev,
23277 chandef->chan->center_freq,
23278 0, &ch_params);
23279
23280 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter,
23281 chandef->chan->center_freq,
23282 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
Krunal Sonied3bc8e2018-01-26 12:13:34 -080023283 hdd_err("Failed to change hw mode");
23284 return -EINVAL;
23285 }
Pankaj Singhcb4da122020-03-27 00:44:47 +053023286
23287 if (adapter->monitor_mode_vdev_up_in_progress) {
23288 hdd_err_rl("monitor mode vdev up in progress");
23289 return -EBUSY;
23290 }
23291
23292 status = qdf_event_reset(&adapter->qdf_monitor_mode_vdev_up_event);
23293 if (QDF_IS_STATUS_ERROR(status)) {
23294 hdd_err_rl("failed to reinit monitor mode vdev up event");
23295 return qdf_status_to_os_return(status);
23296 }
23297 adapter->monitor_mode_vdev_up_in_progress = true;
23298
gaurank kathpaliab3b21942020-01-10 15:09:33 +053023299 status = sme_roam_channel_change_req(mac_handle, bssid,
23300 &roam_profile.ch_params,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023301 &roam_profile);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023302 if (status) {
Pankaj Singhcb4da122020-03-27 00:44:47 +053023303 hdd_err_rl("Failed to set sme_RoamChannel for monitor mode status: %d",
23304 status);
23305 adapter->monitor_mode_vdev_up_in_progress = false;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023306 ret = qdf_status_to_os_return(status);
23307 return ret;
23308 }
Pankaj Singhcb4da122020-03-27 00:44:47 +053023309
23310 /* block on a completion variable until vdev up success*/
23311 status = qdf_wait_for_event_completion(
23312 &adapter->qdf_monitor_mode_vdev_up_event,
23313 WLAN_MONITOR_MODE_VDEV_UP_EVT);
23314 if (QDF_IS_STATUS_ERROR(status)) {
23315 hdd_err_rl("monitor vdev up event time out vdev id: %d",
23316 adapter->vdev_id);
23317 if (adapter->qdf_monitor_mode_vdev_up_event.force_set)
23318 /*
23319 * SSR/PDR has caused shutdown, which has
23320 * forcefully set the event.
23321 */
23322 hdd_err_rl("monitor mode vdev up event forcefully set");
23323 else if (status == QDF_STATUS_E_TIMEOUT)
23324 hdd_err_rl("monitor mode vdev up timed out");
23325 else
23326 hdd_err_rl("Failed monitor mode vdev up(status-%d)",
23327 status);
23328
23329 adapter->monitor_mode_vdev_up_in_progress = false;
23330 return qdf_status_to_os_return(status);
23331 }
23332
Dustin Browne74003f2018-03-14 12:51:58 -070023333 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080023334
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023335 return 0;
23336}
23337
23338/**
23339 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
23340 * @wiphy: Handle to struct wiphy to get handle to module context.
23341 * @chandef: Contains information about the capture channel to be set.
23342 *
23343 * This interface is called if and only if monitor mode interface alone is
23344 * active.
23345 *
23346 * Return: 0 success or error code on failure.
23347 */
23348static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
23349 struct cfg80211_chan_def *chandef)
23350{
Dustin Brown363b4792019-02-05 16:11:55 -080023351 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080023352 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +053023353
Dustin Brown363b4792019-02-05 16:11:55 -080023354 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080023355 if (errno)
23356 return errno;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023357
Dustin Brownf0f00612019-01-31 16:02:24 -080023358 errno = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
Arunk Khandavalli447837f2018-11-08 14:32:53 +053023359
Dustin Brown363b4792019-02-05 16:11:55 -080023360 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080023361
23362 return errno;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023363}
Nirav Shah73713f72018-05-17 14:50:41 +053023364#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023365
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023366#define CNT_DIFF(cur, prev) \
23367 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
23368#define MAX_COUNT 0xffffffff
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070023369static void hdd_update_chan_info(struct hdd_context *hdd_ctx,
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023370 struct scan_chan_info *chan,
23371 struct scan_chan_info *info, uint32_t cmd_flag)
23372{
23373 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
23374 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
23375 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
23376
23377 mutex_lock(&hdd_ctx->chan_info_lock);
23378
23379 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
23380 qdf_mem_zero(chan, sizeof(*chan));
23381
23382 chan->freq = info->freq;
23383 chan->noise_floor = info->noise_floor;
23384 chan->clock_freq = info->clock_freq;
23385 chan->cmd_flag = info->cmd_flag;
23386 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
23387
23388 chan->rx_clear_count =
23389 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
23390
23391 chan->tx_frame_count =
23392 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
23393
23394 mutex_unlock(&hdd_ctx->chan_info_lock);
23395
23396}
23397#undef CNT_DIFF
23398#undef MAX_COUNT
23399
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023400#ifndef UPDATE_ASSOC_IE
23401#define UPDATE_ASSOC_IE BIT(0)
23402#endif
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023403
23404#ifndef UPDATE_FILS_ERP_INFO
23405#define UPDATE_FILS_ERP_INFO BIT(1)
23406#endif
23407
23408#ifndef UPDATE_FILS_AUTH_TYPE
23409#define UPDATE_FILS_AUTH_TYPE BIT(2)
23410#endif
23411
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023412#if defined(WLAN_FEATURE_FILS_SK) &&\
23413 defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) &&\
23414 (defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
23415 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
23416
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023417/**
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023418 * hdd_update_connect_params_fils_info() - Update fils parameters based on
23419 * the update_connect_params received from userspace
23420 * @adapter: Pointer to hdd_adapter
23421 * @hdd_ctx: Pointer to hdd_context
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023422 * @req: Pointer to connect params
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023423 * @changed: bitmap indicating which parameters have changed
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023424 *
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023425 * Return 0 on SUCCESS or error code on FAILURE
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023426 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023427static int
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023428hdd_update_connect_params_fils_info(struct hdd_adapter *adapter,
23429 struct hdd_context *hdd_ctx,
23430 struct cfg80211_connect_params *req,
23431 uint32_t changed)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023432{
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023433 uint8_t *buf;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023434 QDF_STATUS status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023435 mac_handle_t mac_handle;
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023436 struct csr_roam_profile *roam_profile;
23437 struct cds_fils_connection_info *fils_info;
23438 enum eAniAuthType auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023439
Jeff Johnson20227a92018-03-13 09:41:05 -070023440 roam_profile = hdd_roam_profile(adapter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023441 fils_info = roam_profile->fils_con_info;
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023442 mac_handle = hdd_ctx->mac_handle;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023443 if (!fils_info) {
23444 hdd_err("No valid FILS conn info");
23445 return -EINVAL;
23446 }
23447
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023448 fils_info->is_fils_connection = true;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023449 if (changed & UPDATE_FILS_ERP_INFO) {
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080023450 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080023451 return -EINVAL;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023452 fils_info->key_nai_length = req->fils_erp_username_len +
23453 sizeof(char) +
23454 req->fils_erp_realm_len;
Dundi Raviteja170d2872018-03-23 15:49:54 +053023455 if (fils_info->key_nai_length >
23456 FILS_MAX_KEYNAME_NAI_LENGTH) {
23457 hdd_err("Key NAI Length %d",
23458 fils_info->key_nai_length);
23459 return -EINVAL;
23460 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023461 if (req->fils_erp_username_len && req->fils_erp_username) {
23462 buf = fils_info->keyname_nai;
23463 qdf_mem_copy(buf, req->fils_erp_username,
23464 req->fils_erp_username_len);
23465 buf += req->fils_erp_username_len;
23466 *buf++ = '@';
23467 qdf_mem_copy(buf, req->fils_erp_realm,
23468 req->fils_erp_realm_len);
23469 }
23470
Pragaspathi Thilagaraj87a60af2019-02-20 20:42:47 +053023471 fils_info->sequence_number = req->fils_erp_next_seq_num + 1;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023472 fils_info->r_rk_length = req->fils_erp_rrk_len;
23473
Alan Chendc26e042019-12-10 16:44:56 -080023474 if (fils_info->r_rk_length > FILS_MAX_RRK_LENGTH) {
23475 hdd_err("r_rk_length is invalid");
23476 return -EINVAL;
23477 }
23478
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023479 if (req->fils_erp_rrk_len && req->fils_erp_rrk)
23480 qdf_mem_copy(fils_info->r_rk, req->fils_erp_rrk,
23481 fils_info->r_rk_length);
23482
23483 fils_info->realm_len = req->fils_erp_realm_len;
23484 if (req->fils_erp_realm_len && req->fils_erp_realm)
23485 qdf_mem_copy(fils_info->realm, req->fils_erp_realm,
23486 fils_info->realm_len);
23487 }
23488
23489 if (changed & UPDATE_FILS_AUTH_TYPE) {
23490 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070023491 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023492 hdd_err("invalid auth type for fils %d",
23493 req->auth_type);
23494 return -EINVAL;
23495 }
23496
23497 roam_profile->fils_con_info->auth_type = auth_type;
23498 }
23499
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080023500 hdd_debug("fils conn update: changed %x is_fils %d keyname nai len %d",
23501 changed, roam_profile->fils_con_info->is_fils_connection,
23502 roam_profile->fils_con_info->key_nai_length);
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023503 /*
23504 * Update the FILS config from adapter->roam_profile to
23505 * csr_session
23506 */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080023507 status = sme_update_fils_config(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023508 roam_profile);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023509 if (QDF_IS_STATUS_ERROR(status))
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023510 hdd_err("Update FILS connect params to csr failed %d", status);
23511
23512 return 0;
23513}
23514#else
23515
Lin Bai9dc616c2019-04-10 10:08:49 +080023516static inline int
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023517hdd_update_connect_params_fils_info(struct hdd_adapter *adapter,
23518 struct hdd_context *hdd_ctx,
23519 struct cfg80211_connect_params *req,
23520 uint32_t changed)
23521{
23522 return -EINVAL;
23523}
23524
23525#endif
23526
23527#if defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
23528 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
23529
23530/**
23531 * __wlan_hdd_cfg80211_update_connect_params - update connect params
23532 * @wiphy: Handle to struct wiphy to get handle to module context.
23533 * @dev: Pointer to network device
23534 * @req: Pointer to connect params
23535 * @changed: Bitmap used to indicate the changed params
23536 *
23537 * Update the connect parameters while connected to a BSS. The updated
23538 * parameters can be used by driver/firmware for subsequent BSS selection
23539 * (roaming) decisions and to form the Authentication/(Re)Association
23540 * Request frames. This call does not request an immediate disassociation
23541 * or reassociation with the current BSS, i.e., this impacts only
23542 * subsequent (re)associations. The bits in changed are defined in enum
23543 * cfg80211_connect_params_changed
23544 *
23545 * Return: zero for success, non-zero for failure
23546 */
23547static int
23548__wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
23549 struct net_device *dev,
23550 struct cfg80211_connect_params *req,
23551 uint32_t changed)
23552{
23553 struct csr_roam_profile *roam_profile;
23554 int ret;
23555 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
23556 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
23557 QDF_STATUS status;
23558 mac_handle_t mac_handle;
23559
23560 hdd_enter_dev(dev);
23561
23562 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
23563 return -EINVAL;
23564
23565 ret = wlan_hdd_validate_context(hdd_ctx);
23566 if (ret)
23567 return -EINVAL;
23568
23569 mac_handle = hdd_ctx->mac_handle;
23570 roam_profile = hdd_roam_profile(adapter);
23571
23572 if (changed & UPDATE_ASSOC_IE) {
23573 /*
23574 * Validate the elements of the IE and copy it to
23575 * roam_profile in adapter
23576 */
23577 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
23578
23579 /*
23580 * Update this assoc IE received from user space to
23581 * csr_session. RSO command will pick up the assoc
23582 * IEs to be sent to firmware from the csr_session.
23583 */
23584 sme_update_session_assoc_ie(mac_handle, adapter->vdev_id,
23585 roam_profile);
23586 }
23587
23588 if ((changed & UPDATE_FILS_ERP_INFO) ||
23589 (changed & UPDATE_FILS_AUTH_TYPE)) {
23590 ret = hdd_update_connect_params_fils_info(adapter, hdd_ctx,
23591 req, changed);
23592 if (ret)
23593 return -EINVAL;
23594
23595 if (!hdd_ctx->is_fils_roaming_supported) {
23596 hdd_debug("FILS roaming support %d",
23597 hdd_ctx->is_fils_roaming_supported);
23598 return 0;
23599 }
23600 }
23601
23602 if (changed) {
23603 status = sme_send_rso_connect_params(mac_handle,
23604 adapter->vdev_id,
23605 roam_profile);
23606 if (QDF_IS_STATUS_ERROR(status))
23607 hdd_err("Update connect params to fw failed %d",
23608 status);
23609 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023610
23611 return 0;
23612}
23613
23614/**
23615 * wlan_hdd_cfg80211_update_connect_params - SSR wrapper for
23616 * __wlan_hdd_cfg80211_update_connect_params
23617 * @wiphy: Pointer to wiphy structure
23618 * @dev: Pointer to net_device
23619 * @req: Pointer to connect params
23620 * @changed: flags used to indicate the changed params
23621 *
23622 * Return: zero for success, non-zero for failure
23623 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023624static int
23625wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
23626 struct net_device *dev,
23627 struct cfg80211_connect_params *req,
23628 uint32_t changed)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023629{
Dustin Brown1d31b082018-11-22 14:41:20 +053023630 int errno;
23631 struct osif_vdev_sync *vdev_sync;
23632
23633 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
23634 if (errno)
23635 return errno;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023636
Dustin Brown1d31b082018-11-22 14:41:20 +053023637 errno = __wlan_hdd_cfg80211_update_connect_params(wiphy, dev,
23638 req, changed);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023639
Dustin Brown1d31b082018-11-22 14:41:20 +053023640 osif_vdev_sync_op_stop(vdev_sync);
23641
23642 return errno;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023643}
23644#endif
23645
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023646#if defined(WLAN_FEATURE_SAE) && \
23647 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023648#if defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT)
23649/**
23650 * wlan_hdd_extauth_cache_pmkid() - Extract and cache pmkid
23651 * @adapter: hdd vdev/net_device context
23652 * @mac_handle: Handle to the MAC
23653 * @params: Pointer to external auth params.
23654 *
23655 * Extract the PMKID and BSS from external auth params and add to the
23656 * PMKSA Cache in CSR.
23657 */
23658static void
23659wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
23660 mac_handle_t mac_handle,
23661 struct cfg80211_external_auth_params *params)
23662{
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023663 tPmkidCacheInfo *pmk_cache;
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023664 QDF_STATUS result;
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023665
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023666 if (params->pmkid) {
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023667 pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
23668 if (!pmk_cache)
23669 return;
23670
23671 qdf_mem_copy(pmk_cache->BSSID.bytes, params->bssid,
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023672 QDF_MAC_ADDR_SIZE);
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023673 qdf_mem_copy(pmk_cache->PMKID, params->pmkid,
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -070023674 PMKID_LEN);
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023675 result = wlan_hdd_set_pmksa_cache(adapter, pmk_cache);
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023676 if (!QDF_IS_STATUS_SUCCESS(result))
23677 hdd_debug("external_auth: Failed to cache PMKID");
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023678
23679 qdf_mem_free(pmk_cache);
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023680 }
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023681
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023682}
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053023683
23684/**
23685 * wlan_hdd_extauth_copy_pmkid() - Copy the pmkid received from the
23686 * external authentication command received from the userspace.
23687 * @params: pointer to auth params
23688 * @pmkid: Pointer to destination pmkid buffer to be filled
23689 *
23690 * The caller should ensure that destination pmkid buffer is not NULL.
23691 *
23692 * Return: None
23693 */
23694static void
23695wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params *params,
23696 uint8_t *pmkid)
23697{
Pragaspathi Thilagarajaf840592019-08-14 11:45:32 +053023698 if (params->pmkid)
23699 qdf_mem_copy(pmkid, params->pmkid, PMKID_LEN);
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053023700}
23701
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023702#else
23703static void
23704wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
23705 mac_handle_t mac_handle,
23706 struct cfg80211_external_auth_params *params)
23707{}
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053023708
23709static void
23710wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params *params,
23711 uint8_t *pmkid)
23712{}
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023713#endif
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023714/**
23715 * __wlan_hdd_cfg80211_external_auth() - Handle external auth
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023716 *
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023717 * @wiphy: Pointer to wireless phy
23718 * @dev: net device
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023719 * @params: Pointer to external auth params.
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023720 * Return: 0 on success, negative errno on failure
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023721 *
23722 * Userspace sends status of the external authentication(e.g., SAE) with a peer.
23723 * The message carries BSSID of the peer and auth status (WLAN_STATUS_SUCCESS/
23724 * WLAN_STATUS_UNSPECIFIED_FAILURE) in params.
23725 * Userspace may send PMKID in params, which can be used for
23726 * further connections.
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023727 */
23728static int
23729__wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
23730 struct net_device *dev,
23731 struct cfg80211_external_auth_params *params)
23732{
23733 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
23734 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
23735 int ret;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023736 mac_handle_t mac_handle;
Srinivas Dasarie854ff02019-02-11 17:24:48 +053023737 struct qdf_mac_addr peer_mac_addr;
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053023738 uint8_t pmkid[PMKID_LEN] = {0};
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023739
23740 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
23741 hdd_err("Command not allowed in FTM mode");
23742 return -EPERM;
23743 }
23744
Jeff Johnson48363022019-02-24 16:26:51 -080023745 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023746 return -EINVAL;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023747
23748 ret = wlan_hdd_validate_context(hdd_ctx);
23749 if (ret)
23750 return ret;
23751
Srinivas Dasarie854ff02019-02-11 17:24:48 +053023752 hdd_debug("external_auth status: %d peer mac: " QDF_MAC_ADDR_STR,
23753 params->status, QDF_MAC_ADDR_ARRAY(params->bssid));
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023754 mac_handle = hdd_ctx->mac_handle;
Srinivas Dasarie854ff02019-02-11 17:24:48 +053023755 qdf_mem_copy(peer_mac_addr.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023756
23757 wlan_hdd_extauth_cache_pmkid(adapter, mac_handle, params);
23758
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053023759 wlan_hdd_extauth_copy_pmkid(params, pmkid);
Srinivas Dasarie854ff02019-02-11 17:24:48 +053023760 sme_handle_sae_msg(mac_handle, adapter->vdev_id, params->status,
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053023761 peer_mac_addr, pmkid);
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023762
23763 return ret;
23764}
23765
23766/**
23767 * wlan_hdd_cfg80211_external_auth() - Handle external auth
23768 * @wiphy: Pointer to wireless phy
23769 * @dev: net device
23770 * @params: Pointer to external auth params
23771 *
23772 * Return: 0 on success, negative errno on failure
23773 */
23774static int
23775wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
23776 struct net_device *dev,
23777 struct cfg80211_external_auth_params *params)
23778{
Dustin Brown1d31b082018-11-22 14:41:20 +053023779 int errno;
23780 struct osif_vdev_sync *vdev_sync;
23781
23782 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
23783 if (errno)
23784 return errno;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023785
Dustin Brown1d31b082018-11-22 14:41:20 +053023786 errno = __wlan_hdd_cfg80211_external_auth(wiphy, dev, params);
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023787
Dustin Brown1d31b082018-11-22 14:41:20 +053023788 osif_vdev_sync_op_stop(vdev_sync);
23789
23790 return errno;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023791}
23792#endif
23793
Srinivas Dasarid2ba2612019-12-11 17:27:52 +053023794#if defined(WLAN_FEATURE_NAN) && \
Srinivas Dasarief9a8ad2020-06-10 14:32:21 +053023795 (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE)
Srinivas Dasarid2ba2612019-12-11 17:27:52 +053023796static int
23797wlan_hdd_cfg80211_start_nan(struct wiphy *wiphy, struct wireless_dev *wdev,
23798 struct cfg80211_nan_conf *conf)
23799{
23800 return -EOPNOTSUPP;
23801}
23802
23803static void
23804wlan_hdd_cfg80211_stop_nan(struct wiphy *wiphy, struct wireless_dev *wdev)
23805{
23806}
23807
23808static int wlan_hdd_cfg80211_add_nan_func(struct wiphy *wiphy,
23809 struct wireless_dev *wdev,
23810 struct cfg80211_nan_func *nan_func)
23811{
23812 return -EOPNOTSUPP;
23813}
23814
23815static void wlan_hdd_cfg80211_del_nan_func(struct wiphy *wiphy,
23816 struct wireless_dev *wdev,
23817 u64 cookie)
23818{
23819}
23820
23821static int wlan_hdd_cfg80211_nan_change_conf(struct wiphy *wiphy,
23822 struct wireless_dev *wdev,
23823 struct cfg80211_nan_conf *conf,
23824 u32 changes)
23825{
23826 return -EOPNOTSUPP;
23827}
23828#endif
23829
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023830/**
23831 * wlan_hdd_chan_info_cb() - channel info callback
23832 * @chan_info: struct scan_chan_info
23833 *
23834 * Store channel info into HDD context
23835 *
23836 * Return: None.
23837 */
23838static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
23839{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070023840 struct hdd_context *hdd_ctx;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023841 struct scan_chan_info *chan;
23842 uint8_t idx;
23843
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023844 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
23845 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
23846 hdd_err("hdd_ctx is invalid");
23847 return;
23848 }
23849
23850 if (!hdd_ctx->chan_info) {
23851 hdd_err("chan_info is NULL");
23852 return;
23853 }
23854
23855 chan = hdd_ctx->chan_info;
23856 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
23857 if (chan[idx].freq == info->freq) {
23858 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
23859 info->cmd_flag);
Rajeev Kumareb6ec172018-09-26 20:45:36 -070023860 hdd_debug("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
23861 chan[idx].cmd_flag, chan[idx].freq,
23862 chan[idx].noise_floor,
23863 chan[idx].cycle_count,
23864 chan[idx].rx_clear_count,
23865 chan[idx].clock_freq, chan[idx].cmd_flag,
23866 chan[idx].tx_frame_count, idx);
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023867 if (chan[idx].freq == 0)
23868 break;
23869
23870 }
23871 }
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023872}
23873
23874/**
23875 * wlan_hdd_init_chan_info() - init chan info in hdd context
23876 * @hdd_ctx: HDD context pointer
23877 *
23878 * Return: none
23879 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070023880void wlan_hdd_init_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023881{
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053023882 uint32_t num_2g, num_5g, index = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023883 mac_handle_t mac_handle;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023884
Kapil Gupta63e75282017-05-18 20:55:10 +053023885 hdd_ctx->chan_info = NULL;
hqud109f762019-12-18 14:26:17 +080023886 if (!ucfg_scan_is_snr_monitor_enabled(hdd_ctx->psoc)) {
Dustin Brown31116772018-08-15 14:59:21 -070023887 hdd_debug("SNR monitoring is disabled");
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023888 return;
23889 }
23890
23891 hdd_ctx->chan_info =
23892 qdf_mem_malloc(sizeof(struct scan_chan_info)
Qun Zhang3a5bd1a2020-03-20 12:05:25 +080023893 * NUM_CHANNELS);
Min Liu74a1a502018-10-10 19:59:07 +080023894 if (!hdd_ctx->chan_info)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023895 return;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023896 mutex_init(&hdd_ctx->chan_info_lock);
23897
23898 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
23899 for (; index < num_2g; index++) {
23900 hdd_ctx->chan_info[index].freq =
23901 hdd_channels_2_4_ghz[index].center_freq;
23902 }
23903
23904 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
23905 for (; (index - num_2g) < num_5g; index++) {
Dustin Brown07901ec2018-09-07 11:02:41 -070023906 if (wlan_reg_is_dsrc_chan(hdd_ctx->pdev,
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070023907 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023908 continue;
23909 hdd_ctx->chan_info[index].freq =
23910 hdd_channels_5_ghz[index - num_2g].center_freq;
23911 }
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053023912
23913 index = num_2g + num_5g;
23914 index = wlan_hdd_populate_srd_chan_info(hdd_ctx, index);
23915
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023916 mac_handle = hdd_ctx->mac_handle;
23917 sme_set_chan_info_callback(mac_handle,
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023918 &wlan_hdd_chan_info_cb);
23919}
23920
23921/**
23922 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
23923 * @hdd_ctx: hdd context pointer
23924 *
23925 * Return: none
23926 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070023927void wlan_hdd_deinit_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023928{
23929 struct scan_chan_info *chan;
23930
23931 chan = hdd_ctx->chan_info;
23932 hdd_ctx->chan_info = NULL;
23933 if (chan)
23934 qdf_mem_free(chan);
23935}
23936
Dustin Brown32cb4792017-06-15 15:33:42 -070023937#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
23938static enum rate_info_bw hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
23939{
23940 switch (hdd_bw) {
23941 case HDD_RATE_BW_5:
23942 return RATE_INFO_BW_5;
23943 case HDD_RATE_BW_10:
23944 return RATE_INFO_BW_10;
23945 case HDD_RATE_BW_20:
23946 return RATE_INFO_BW_20;
23947 case HDD_RATE_BW_40:
23948 return RATE_INFO_BW_40;
23949 case HDD_RATE_BW_80:
23950 return RATE_INFO_BW_80;
23951 case HDD_RATE_BW_160:
23952 return RATE_INFO_BW_160;
23953 }
23954
23955 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
23956
23957 return RATE_INFO_BW_20;
23958}
23959
23960void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
23961{
23962 info->bw = hdd_map_hdd_bw_to_os(hdd_bw);
23963}
23964#else
23965static enum rate_info_flags hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
23966{
23967 switch (hdd_bw) {
23968 case HDD_RATE_BW_5:
23969 case HDD_RATE_BW_10:
23970 case HDD_RATE_BW_20:
23971 return (enum rate_info_flags)0;
23972 case HDD_RATE_BW_40:
23973 return RATE_INFO_FLAGS_40_MHZ_WIDTH;
23974 case HDD_RATE_BW_80:
23975 return RATE_INFO_FLAGS_80_MHZ_WIDTH;
23976 case HDD_RATE_BW_160:
23977 return RATE_INFO_FLAGS_160_MHZ_WIDTH;
23978 }
23979
23980 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
23981
23982 return (enum rate_info_flags)0;
23983}
23984
23985void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
23986{
23987 const enum rate_info_flags all_bws =
23988 RATE_INFO_FLAGS_40_MHZ_WIDTH |
23989 RATE_INFO_FLAGS_80_MHZ_WIDTH |
23990 RATE_INFO_FLAGS_80P80_MHZ_WIDTH |
23991 RATE_INFO_FLAGS_160_MHZ_WIDTH;
23992
23993 info->flags &= ~all_bws;
23994 info->flags |= hdd_map_hdd_bw_to_os(hdd_bw);
23995}
23996#endif
23997
Min Liue34708a2019-02-01 15:00:34 +080023998#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
23999void hdd_send_update_owe_info_event(struct hdd_adapter *adapter,
24000 uint8_t sta_addr[],
24001 uint8_t *owe_ie,
24002 uint32_t owe_ie_len)
24003{
24004 struct cfg80211_update_owe_info owe_info;
24005 struct net_device *dev = adapter->dev;
24006
24007 hdd_enter_dev(dev);
24008
Srikanth Marepalli140612d2020-06-24 00:42:42 +053024009 qdf_mem_zero(&owe_info, sizeof(owe_info));
Min Liue2b469f2019-04-10 19:13:42 +080024010 qdf_mem_copy(owe_info.peer, sta_addr, ETH_ALEN);
Min Liue34708a2019-02-01 15:00:34 +080024011 owe_info.ie = owe_ie;
24012 owe_info.ie_len = owe_ie_len;
24013
24014 cfg80211_update_owe_info_event(dev, &owe_info, GFP_KERNEL);
24015
24016 hdd_exit();
24017}
24018#endif
24019
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053024020/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080024021 * struct cfg80211_ops - cfg80211_ops
24022 *
24023 * @add_virtual_intf: Add virtual interface
24024 * @del_virtual_intf: Delete virtual interface
24025 * @change_virtual_intf: Change virtual interface
24026 * @change_station: Change station
24027 * @add_beacon: Add beacon in sap mode
24028 * @del_beacon: Delete beacon in sap mode
24029 * @set_beacon: Set beacon in sap mode
24030 * @start_ap: Start ap
24031 * @change_beacon: Change beacon
24032 * @stop_ap: Stop ap
24033 * @change_bss: Change bss
24034 * @add_key: Add key
24035 * @get_key: Get key
24036 * @del_key: Delete key
24037 * @set_default_key: Set default key
24038 * @set_channel: Set channel
24039 * @scan: Scan
24040 * @connect: Connect
24041 * @disconnect: Disconnect
24042 * @join_ibss = Join ibss
24043 * @leave_ibss = Leave ibss
24044 * @set_wiphy_params = Set wiphy params
24045 * @set_tx_power = Set tx power
24046 * @get_tx_power = get tx power
24047 * @remain_on_channel = Remain on channel
24048 * @cancel_remain_on_channel = Cancel remain on channel
24049 * @mgmt_tx = Tx management frame
24050 * @mgmt_tx_cancel_wait = Cancel management tx wait
24051 * @set_default_mgmt_key = Set default management key
24052 * @set_txq_params = Set tx queue parameters
24053 * @get_station = Get station
24054 * @set_power_mgmt = Set power management
24055 * @del_station = Delete station
24056 * @add_station = Add station
24057 * @set_pmksa = Set pmksa
24058 * @del_pmksa = Delete pmksa
24059 * @flush_pmksa = Flush pmksa
24060 * @update_ft_ies = Update FT IEs
24061 * @tdls_mgmt = Tdls management
24062 * @tdls_oper = Tdls operation
24063 * @set_rekey_data = Set rekey data
24064 * @sched_scan_start = Scheduled scan start
24065 * @sched_scan_stop = Scheduled scan stop
24066 * @resume = Resume wlan
24067 * @suspend = Suspend wlan
24068 * @set_mac_acl = Set mac acl
24069 * @testmode_cmd = Test mode command
24070 * @set_ap_chanwidth = Set AP channel bandwidth
24071 * @dump_survey = Dump survey
24072 * @key_mgmt_set_pmk = Set pmk key management
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053024073 * @update_connect_params = Update connect params
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080024074 */
24075static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
24076 .add_virtual_intf = wlan_hdd_add_virtual_intf,
24077 .del_virtual_intf = wlan_hdd_del_virtual_intf,
24078 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
24079 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080024080 .start_ap = wlan_hdd_cfg80211_start_ap,
24081 .change_beacon = wlan_hdd_cfg80211_change_beacon,
24082 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080024083 .change_bss = wlan_hdd_cfg80211_change_bss,
24084 .add_key = wlan_hdd_cfg80211_add_key,
24085 .get_key = wlan_hdd_cfg80211_get_key,
24086 .del_key = wlan_hdd_cfg80211_del_key,
24087 .set_default_key = wlan_hdd_cfg80211_set_default_key,
24088 .scan = wlan_hdd_cfg80211_scan,
24089 .connect = wlan_hdd_cfg80211_connect,
24090 .disconnect = wlan_hdd_cfg80211_disconnect,
24091 .join_ibss = wlan_hdd_cfg80211_join_ibss,
24092 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
24093 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
24094 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
24095 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
24096 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
24097 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
24098 .mgmt_tx = wlan_hdd_mgmt_tx,
24099 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
24100 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
24101 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053024102 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080024103 .get_station = wlan_hdd_cfg80211_get_station,
24104 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
24105 .del_station = wlan_hdd_cfg80211_del_station,
24106 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080024107 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
24108 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
24109 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080024110#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080024111 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
24112#endif
Min Liu0daa0982019-02-01 17:50:44 +080024113#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
24114 .update_owe_info = wlan_hdd_cfg80211_update_owe_info,
24115#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080024116#ifdef FEATURE_WLAN_TDLS
24117 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
24118 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
24119#endif
24120#ifdef WLAN_FEATURE_GTK_OFFLOAD
24121 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
24122#endif /* WLAN_FEATURE_GTK_OFFLOAD */
24123#ifdef FEATURE_WLAN_SCAN_PNO
24124 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
24125 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
24126#endif /*FEATURE_WLAN_SCAN_PNO */
24127 .resume = wlan_hdd_cfg80211_resume_wlan,
24128 .suspend = wlan_hdd_cfg80211_suspend_wlan,
24129 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
24130#ifdef WLAN_NL80211_TESTMODE
24131 .testmode_cmd = wlan_hdd_cfg80211_testmode,
24132#endif
24133#ifdef QCA_HT_2040_COEX
24134 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
24135#endif
24136 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053024137#ifdef CHANNEL_SWITCH_SUPPORTED
24138 .channel_switch = wlan_hdd_cfg80211_channel_switch,
24139#endif
Nirav Shah73713f72018-05-17 14:50:41 +053024140#ifdef FEATURE_MONITOR_MODE_SUPPORT
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070024141 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Nirav Shah73713f72018-05-17 14:50:41 +053024142#endif
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053024143#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
Srinivas Girigowda576b2352017-08-25 14:44:26 -070024144 defined(CFG80211_ABORT_SCAN)
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053024145 .abort_scan = wlan_hdd_cfg80211_abort_scan,
24146#endif
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053024147#if defined(CFG80211_UPDATE_CONNECT_PARAMS) || \
24148 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053024149 .update_connect_params = wlan_hdd_cfg80211_update_connect_params,
24150#endif
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053024151#if defined(WLAN_FEATURE_SAE) && \
24152 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
24153 .external_auth = wlan_hdd_cfg80211_external_auth,
24154#endif
Srinivas Dasarid2ba2612019-12-11 17:27:52 +053024155#if defined(WLAN_FEATURE_NAN) && \
Srinivas Dasarief9a8ad2020-06-10 14:32:21 +053024156 (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE)
Srinivas Dasarid2ba2612019-12-11 17:27:52 +053024157 .start_nan = wlan_hdd_cfg80211_start_nan,
24158 .stop_nan = wlan_hdd_cfg80211_stop_nan,
24159 .add_nan_func = wlan_hdd_cfg80211_add_nan_func,
24160 .del_nan_func = wlan_hdd_cfg80211_del_nan_func,
24161 .nan_change_conf = wlan_hdd_cfg80211_nan_change_conf,
24162#endif
24163
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080024164};