blob: 93a7587cddc60515e5c1191d8acabe5e2a73c39e [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>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080036#include <wlan_hdd_wowl.h>
37#include <ani_global.h>
38#include "sir_params.h"
39#include "dot11f.h"
40#include "wlan_hdd_assoc.h"
41#include "wlan_hdd_wext.h"
42#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070043#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080044#include "wlan_hdd_p2p.h"
45#include "wlan_hdd_cfg80211.h"
46#include "wlan_hdd_hostapd.h"
47#include "wlan_hdd_softap_tx_rx.h"
48#include "wlan_hdd_main.h"
49#include "wlan_hdd_power.h"
50#include "wlan_hdd_trace.h"
Dustin Brownd4241942018-02-26 12:51:37 -080051#include "qdf_str.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053052#include "qdf_trace.h"
Dustin Brownd4241942018-02-26 12:51:37 -080053#include "qdf_types.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080054#include "cds_utils.h"
55#include "cds_sched.h"
56#include "wlan_hdd_scan.h"
57#include <qc_sap_ioctl.h>
58#include "wlan_hdd_tdls.h"
59#include "wlan_hdd_wmm.h"
60#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053061#include "wma.h"
Arif Hussain1f58cbb2019-03-14 17:06:56 -070062#include "wma_twt.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080063#include "wlan_hdd_misc.h"
64#include "wlan_hdd_nan.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080065#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053066#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053067#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053068#include "pld_common.h"
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070069#include "wmi_unified_param.h"
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070070
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080071#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080072#include <wlan_cfg80211_scan.h>
Ryan Hsuc8b27a42018-01-02 13:57:56 -080073#include <wlan_cfg80211_ftm.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080074
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080075#include "wlan_hdd_ext_scan.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080076
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077#include "wlan_hdd_stats.h"
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080078#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080079#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080080#include "qwlan_version.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081
82#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070083#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080084
Ravi Joshideb5a8d2015-11-09 19:11:43 -080085#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053086#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070087#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070088#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053089#include "wlan_hdd_disa.h"
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070090#include "wlan_osif_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080091#include "wlan_hdd_he.h"
Nachiket Kukade177b5b02018-05-22 20:52:17 +053092#ifdef FEATURE_WLAN_APF
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053093#include "wlan_hdd_apf.h"
Nachiket Kukade177b5b02018-05-22 20:52:17 +053094#endif
Qun Zhangef655622019-02-25 10:48:10 +080095#include "wlan_hdd_fw_state.h"
stonez2d686482019-03-12 14:54:26 +080096#include "wlan_hdd_mpta_helper.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -080097
Leo Changfdb45c32016-10-28 11:09:23 -070098#include <cdp_txrx_cmn.h>
99#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800100#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530101#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800102#include "os_if_wifi_pos.h"
Ajit Pal Singh90a45a42017-04-18 18:53:46 +0530103#include "wlan_utility.h"
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -0700104#include "wlan_reg_ucfg_api.h"
Naveen Rawatd2657be2017-10-10 14:31:23 -0700105#include "wifi_pos_api.h"
Sandeep Puligilla063a4342018-01-10 02:50:14 -0800106#include "wlan_hdd_spectralscan.h"
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +0530107#include "wlan_ipa_ucfg_api.h"
Naveen Rawate8b1b822018-01-30 09:46:16 -0800108#include <wlan_cfg80211_mc_cp_stats.h>
Yu Wang157d1472018-03-09 16:05:01 +0800109#include <wlan_cp_stats_mc_ucfg_api.h>
Wu Gaobdb7f272018-07-05 19:33:26 +0800110#include "wlan_tdls_cfg_api.h"
Qiwei Caie689a262018-07-26 15:50:22 +0800111#include <wlan_hdd_bss_transition.h>
112#include <wlan_hdd_concurrency_matrix.h>
113#include <wlan_hdd_p2p_listen_offload.h>
114#include <wlan_hdd_rssi_monitor.h>
115#include <wlan_hdd_sap_cond_chan_switch.h>
116#include <wlan_hdd_station_info.h>
117#include <wlan_hdd_tx_power.h>
118#include <wlan_hdd_active_tos.h>
119#include <wlan_hdd_sar_limits.h>
120#include <wlan_hdd_ota_test.h>
Krunal Soni5e3f9622018-09-26 16:35:50 -0700121#include "wlan_policy_mgr_ucfg.h"
Arunk Khandavalli99716d12018-11-14 15:02:02 +0530122#include "wlan_mlme_ucfg_api.h"
123#include "wlan_mlme_public_struct.h"
Harprit Chhabadae8155d32018-08-22 16:19:34 -0700124#include "wlan_extscan_ucfg_api.h"
Wu Gao93816212018-08-31 16:49:54 +0800125#include "wlan_mlme_ucfg_api.h"
Wu Gao66454f12018-09-26 19:55:41 +0800126#include "wlan_pmo_cfg.h"
127#include "cfg_ucfg_api.h"
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +0530128
Harprit Chhabada6c641ba2018-06-28 14:45:10 -0700129#include "wlan_crypto_global_api.h"
130#include "wlan_nl_to_crypto_params.h"
131#include "wlan_crypto_global_def.h"
jitiphil377bcc12018-10-05 19:46:08 +0530132#include "cdp_txrx_cfg.h"
Min Liu8c5d99e2018-09-10 17:18:44 +0800133#include "wlan_hdd_object_manager.h"
Nachiket Kukade089b9832018-12-12 16:38:17 +0530134#include "nan_ucfg_api.h"
Manikandan Mohand350c192018-11-29 14:01:12 -0800135#include "wlan_fwol_ucfg_api.h"
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -0700136#include "wlan_cfg80211_crypto.h"
Paul Zhang37185672019-05-14 11:20:14 +0800137#include "wlan_cfg80211_interop_issues_ap.h"
gaurank kathpalia97c070b2019-01-07 17:23:06 +0530138#include "wlan_scan_ucfg_api.h"
Jiani Liua5f17222019-03-04 16:22:33 +0800139#include "wlan_hdd_coex_config.h"
Abhinav Kumardbbfd2c2019-05-07 12:22:06 +0530140#include "wlan_hdd_bcn_recv.h"
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +0530141#include "wlan_blm_ucfg_api.h"
guangde4853c402019-05-06 15:54:04 +0800142#include "wlan_hdd_hw_capability.h"
Paul Zhangda2970b2019-06-23 18:16:38 +0800143#include "wlan_hdd_oemdata.h"
Paul Zhangc9dbaee2019-06-23 22:07:31 +0800144#include "os_if_fwol.h"
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +0530145#include "wlan_hdd_sta_info.h"
Pankaj Singh50e40422020-01-09 15:29:35 +0530146#include "sme_api.h"
147#include "wlan_hdd_thermal.h"
Rakesh Pillai6a36b0a2019-09-06 16:30:05 +0530148#include <ol_defines.h>
Harprit Chhabada6c641ba2018-06-28 14:45:10 -0700149
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800150#define g_mode_rates_size (12)
151#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800152
Sourav Mohapatrafab026a2019-11-20 14:22:28 +0530153/**
154 * rtt_is_initiator - Macro to check if the bitmap has any RTT roles set
155 * @bitmap: The bitmap to be checked
156 */
157#define rtt_is_enabled(bitmap) \
158 ((bitmap) & (WMI_FW_STA_RTT_INITR | \
159 WMI_FW_STA_RTT_RESPR | \
160 WMI_FW_AP_RTT_INITR | \
161 WMI_FW_AP_RTT_RESPR))
162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163/*
164 * Android CTS verifier needs atleast this much wait time (in msec)
165 */
166#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
167
168/*
169 * Refer @tCfgProtection structure for definition of the bit map.
170 * below value is obtained by setting the following bit-fields.
171 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
172 */
173#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
174
175#define HDD2GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700176 .band = HDD_NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177 .center_freq = (freq), \
178 .hw_value = (chan), \
179 .flags = (flag), \
180 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800181 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800182}
183
184#define HDD5GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700185 .band = HDD_NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800186 .center_freq = (freq), \
187 .hw_value = (chan), \
188 .flags = (flag), \
189 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800190 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800191}
192
193#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
194 { \
195 .bitrate = rate, \
196 .hw_value = rate_id, \
197 .flags = flag, \
198 }
199
Agrawal Ashish65634612016-08-18 13:24:32 +0530200#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
201 mode <= DFS_MODE_DEPRIORITIZE))
Mohit Khannaceb97782017-04-05 16:27:08 -0700202/*
203 * Number of DPTRACE records to dump when a cfg80211 disconnect with reason
204 * WLAN_REASON_DEAUTH_LEAVING DEAUTH is received from user-space.
205 */
206#define WLAN_DEAUTH_DPTRACE_DUMP_COUNT 100
Mukul Sharma05504ac2017-06-08 12:35:53 +0530207#ifndef WLAN_CIPHER_SUITE_GCMP
208#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
209#endif
210#ifndef WLAN_CIPHER_SUITE_GCMP_256
211#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09
212#endif
Mohit Khannaceb97782017-04-05 16:27:08 -0700213
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +0530214static const u32 hdd_gcmp_cipher_suits[] = {
215 WLAN_CIPHER_SUITE_GCMP,
216 WLAN_CIPHER_SUITE_GCMP_256,
217};
218
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219static const u32 hdd_cipher_suites[] = {
220 WLAN_CIPHER_SUITE_WEP40,
221 WLAN_CIPHER_SUITE_WEP104,
222 WLAN_CIPHER_SUITE_TKIP,
223#ifdef FEATURE_WLAN_ESE
224#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
225#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
226 WLAN_CIPHER_SUITE_BTK,
227 WLAN_CIPHER_SUITE_KRK,
228 WLAN_CIPHER_SUITE_CCMP,
229#else
230 WLAN_CIPHER_SUITE_CCMP,
231#endif
232#ifdef FEATURE_WLAN_WAPI
233 WLAN_CIPHER_SUITE_SMS4,
234#endif
235#ifdef WLAN_FEATURE_11W
236 WLAN_CIPHER_SUITE_AES_CMAC,
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +0530237#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
238 WLAN_CIPHER_SUITE_BIP_GMAC_128,
239 WLAN_CIPHER_SUITE_BIP_GMAC_256,
240#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800241#endif
242};
243
Abhishek Singhf512bf32016-05-04 16:47:46 +0530244static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800245 HDD2GHZCHAN(2412, 1, 0),
246 HDD2GHZCHAN(2417, 2, 0),
247 HDD2GHZCHAN(2422, 3, 0),
248 HDD2GHZCHAN(2427, 4, 0),
249 HDD2GHZCHAN(2432, 5, 0),
250 HDD2GHZCHAN(2437, 6, 0),
251 HDD2GHZCHAN(2442, 7, 0),
252 HDD2GHZCHAN(2447, 8, 0),
253 HDD2GHZCHAN(2452, 9, 0),
254 HDD2GHZCHAN(2457, 10, 0),
255 HDD2GHZCHAN(2462, 11, 0),
256 HDD2GHZCHAN(2467, 12, 0),
257 HDD2GHZCHAN(2472, 13, 0),
258 HDD2GHZCHAN(2484, 14, 0),
259};
260
Abhishek Singhf512bf32016-05-04 16:47:46 +0530261static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800262 HDD5GHZCHAN(5180, 36, 0),
263 HDD5GHZCHAN(5200, 40, 0),
264 HDD5GHZCHAN(5220, 44, 0),
265 HDD5GHZCHAN(5240, 48, 0),
266 HDD5GHZCHAN(5260, 52, 0),
267 HDD5GHZCHAN(5280, 56, 0),
268 HDD5GHZCHAN(5300, 60, 0),
269 HDD5GHZCHAN(5320, 64, 0),
270 HDD5GHZCHAN(5500, 100, 0),
271 HDD5GHZCHAN(5520, 104, 0),
272 HDD5GHZCHAN(5540, 108, 0),
273 HDD5GHZCHAN(5560, 112, 0),
274 HDD5GHZCHAN(5580, 116, 0),
275 HDD5GHZCHAN(5600, 120, 0),
276 HDD5GHZCHAN(5620, 124, 0),
277 HDD5GHZCHAN(5640, 128, 0),
278 HDD5GHZCHAN(5660, 132, 0),
279 HDD5GHZCHAN(5680, 136, 0),
280 HDD5GHZCHAN(5700, 140, 0),
281 HDD5GHZCHAN(5720, 144, 0),
282 HDD5GHZCHAN(5745, 149, 0),
283 HDD5GHZCHAN(5765, 153, 0),
284 HDD5GHZCHAN(5785, 157, 0),
285 HDD5GHZCHAN(5805, 161, 0),
286 HDD5GHZCHAN(5825, 165, 0),
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +0530287};
288
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -0700289#ifdef WLAN_FEATURE_DSRC
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +0530290static const struct ieee80211_channel hdd_channels_dot11p[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800291 HDD5GHZCHAN(5852, 170, 0),
292 HDD5GHZCHAN(5855, 171, 0),
293 HDD5GHZCHAN(5860, 172, 0),
294 HDD5GHZCHAN(5865, 173, 0),
295 HDD5GHZCHAN(5870, 174, 0),
296 HDD5GHZCHAN(5875, 175, 0),
297 HDD5GHZCHAN(5880, 176, 0),
298 HDD5GHZCHAN(5885, 177, 0),
299 HDD5GHZCHAN(5890, 178, 0),
300 HDD5GHZCHAN(5895, 179, 0),
301 HDD5GHZCHAN(5900, 180, 0),
302 HDD5GHZCHAN(5905, 181, 0),
303 HDD5GHZCHAN(5910, 182, 0),
304 HDD5GHZCHAN(5915, 183, 0),
305 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800306};
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -0700307#else
308static const struct ieee80211_channel hdd_etsi13_srd_ch[] = {
309 HDD5GHZCHAN(5845, 169, 0),
310 HDD5GHZCHAN(5865, 173, 0),
311};
312#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800313
Qun Zhang043635a2019-02-27 15:19:29 +0800314#define band_2_ghz_channels_size sizeof(hdd_channels_2_4_ghz)
315
316#ifdef WLAN_FEATURE_DSRC
317#define band_5_ghz_chanenls_size (sizeof(hdd_channels_5_ghz) + \
318 sizeof(hdd_channels_dot11p))
319#else
320#define band_5_ghz_chanenls_size (sizeof(hdd_channels_5_ghz) + \
321 sizeof(hdd_etsi13_srd_ch))
322#endif
323
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800324static struct ieee80211_rate g_mode_rates[] = {
325 HDD_G_MODE_RATETAB(10, 0x1, 0),
326 HDD_G_MODE_RATETAB(20, 0x2, 0),
327 HDD_G_MODE_RATETAB(55, 0x4, 0),
328 HDD_G_MODE_RATETAB(110, 0x8, 0),
329 HDD_G_MODE_RATETAB(60, 0x10, 0),
330 HDD_G_MODE_RATETAB(90, 0x20, 0),
331 HDD_G_MODE_RATETAB(120, 0x40, 0),
332 HDD_G_MODE_RATETAB(180, 0x80, 0),
333 HDD_G_MODE_RATETAB(240, 0x100, 0),
334 HDD_G_MODE_RATETAB(360, 0x200, 0),
335 HDD_G_MODE_RATETAB(480, 0x400, 0),
336 HDD_G_MODE_RATETAB(540, 0x800, 0),
337};
338
339static struct ieee80211_rate a_mode_rates[] = {
340 HDD_G_MODE_RATETAB(60, 0x10, 0),
341 HDD_G_MODE_RATETAB(90, 0x20, 0),
342 HDD_G_MODE_RATETAB(120, 0x40, 0),
343 HDD_G_MODE_RATETAB(180, 0x80, 0),
344 HDD_G_MODE_RATETAB(240, 0x100, 0),
345 HDD_G_MODE_RATETAB(360, 0x200, 0),
346 HDD_G_MODE_RATETAB(480, 0x400, 0),
347 HDD_G_MODE_RATETAB(540, 0x800, 0),
348};
349
350static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530351 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800352 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700353 .band = HDD_NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800354 .bitrates = g_mode_rates,
355 .n_bitrates = g_mode_rates_size,
356 .ht_cap.ht_supported = 1,
357 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
358 | IEEE80211_HT_CAP_GRN_FLD
359 | IEEE80211_HT_CAP_DSSSCCK40
360 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
361 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
362 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
363 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
364 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
365 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
366 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
367};
368
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800369static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530370 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800371 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700372 .band = HDD_NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800373 .bitrates = a_mode_rates,
374 .n_bitrates = a_mode_rates_size,
375 .ht_cap.ht_supported = 1,
376 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
377 | IEEE80211_HT_CAP_GRN_FLD
378 | IEEE80211_HT_CAP_DSSSCCK40
379 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
380 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
381 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
382 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
383 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
384 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
385 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
386 .vht_cap.vht_supported = 1,
387};
388
Liangwei Dong692455f2019-08-09 17:59:46 +0800389#if defined(CONFIG_BAND_6GHZ) && (defined(CFG80211_6GHZ_BAND_SUPPORTED) || \
390 (KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE))
391
392static struct ieee80211_channel hdd_channels_6_ghz[NUM_6GHZ_CHANNELS];
393
394static struct ieee80211_supported_band wlan_hdd_band_6_ghz = {
395 .channels = NULL,
396 .n_channels = 0,
397 .band = HDD_NL80211_BAND_6GHZ,
398 .bitrates = a_mode_rates,
399 .n_bitrates = a_mode_rates_size,
Liangwei Dong692455f2019-08-09 17:59:46 +0800400};
401
402#define HDD_SET_6GHZCHAN(ch, freq, chan, flag) { \
403 (ch).band = HDD_NL80211_BAND_6GHZ; \
404 (ch).center_freq = (freq); \
405 (ch).hw_value = (chan); \
406 (ch).flags = (flag); \
407 (ch).max_antenna_gain = 0; \
408 (ch).max_power = 0; \
409}
410
411static void hdd_init_6ghz(struct hdd_context *hdd_ctx)
412{
413 uint32_t i;
414 struct wiphy *wiphy = hdd_ctx->wiphy;
415 struct ieee80211_channel *chlist = hdd_channels_6_ghz;
416 uint32_t num = ARRAY_SIZE(hdd_channels_6_ghz);
417
418 qdf_mem_zero(chlist, sizeof(*chlist) * num);
419 for (i = 0; i < num; i++)
420 HDD_SET_6GHZCHAN(chlist[i], 5945 + i * 20, 1 + i * 4, \
421 IEEE80211_CHAN_DISABLED);
422 wiphy->bands[HDD_NL80211_BAND_6GHZ] = &wlan_hdd_band_6_ghz;
423 wiphy->bands[HDD_NL80211_BAND_6GHZ]->channels = chlist;
424 wiphy->bands[HDD_NL80211_BAND_6GHZ]->n_channels = num;
425}
426#else
427static void hdd_init_6ghz(struct hdd_context *hdd_ctx)
428{
429}
430#endif
431
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800432/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800433 * TX/RX direction for each kind of interface
434 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800435static const struct ieee80211_txrx_stypes
436 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
437 [NL80211_IFTYPE_STATION] = {
438 .tx = 0xffff,
439 .rx = BIT(SIR_MAC_MGMT_ACTION) |
Padma, Santhosh Kumar1ccc1332017-09-13 17:39:01 +0530440 BIT(SIR_MAC_MGMT_PROBE_REQ) |
441 BIT(SIR_MAC_MGMT_AUTH),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800442 },
443 [NL80211_IFTYPE_AP] = {
444 .tx = 0xffff,
445 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
446 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
447 BIT(SIR_MAC_MGMT_PROBE_REQ) |
448 BIT(SIR_MAC_MGMT_DISASSOC) |
449 BIT(SIR_MAC_MGMT_AUTH) |
450 BIT(SIR_MAC_MGMT_DEAUTH) |
451 BIT(SIR_MAC_MGMT_ACTION),
452 },
453 [NL80211_IFTYPE_ADHOC] = {
454 .tx = 0xffff,
455 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
456 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
457 BIT(SIR_MAC_MGMT_PROBE_REQ) |
458 BIT(SIR_MAC_MGMT_DISASSOC) |
459 BIT(SIR_MAC_MGMT_AUTH) |
460 BIT(SIR_MAC_MGMT_DEAUTH) |
461 BIT(SIR_MAC_MGMT_ACTION),
462 },
463 [NL80211_IFTYPE_P2P_CLIENT] = {
464 .tx = 0xffff,
465 .rx = BIT(SIR_MAC_MGMT_ACTION) |
466 BIT(SIR_MAC_MGMT_PROBE_REQ),
467 },
468 [NL80211_IFTYPE_P2P_GO] = {
469 /* This is also same as for SoftAP */
470 .tx = 0xffff,
471 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
472 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
473 BIT(SIR_MAC_MGMT_PROBE_REQ) |
474 BIT(SIR_MAC_MGMT_DISASSOC) |
475 BIT(SIR_MAC_MGMT_AUTH) |
476 BIT(SIR_MAC_MGMT_DEAUTH) |
477 BIT(SIR_MAC_MGMT_ACTION),
478 },
479};
480
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800481/* Interface limits and combinations registered by the driver */
482
483/* STA ( + STA ) combination */
484static const struct ieee80211_iface_limit
485 wlan_hdd_sta_iface_limit[] = {
486 {
487 .max = 3, /* p2p0 is a STA as well */
488 .types = BIT(NL80211_IFTYPE_STATION),
489 },
490};
491
492/* ADHOC (IBSS) limit */
493static const struct ieee80211_iface_limit
494 wlan_hdd_adhoc_iface_limit[] = {
495 {
496 .max = 1,
497 .types = BIT(NL80211_IFTYPE_STATION),
498 },
499 {
500 .max = 1,
501 .types = BIT(NL80211_IFTYPE_ADHOC),
502 },
503};
504
505/* AP ( + AP ) combination */
506static const struct ieee80211_iface_limit
507 wlan_hdd_ap_iface_limit[] = {
508 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530509 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510 .types = BIT(NL80211_IFTYPE_AP),
511 },
512};
513
514/* P2P limit */
515static const struct ieee80211_iface_limit
516 wlan_hdd_p2p_iface_limit[] = {
517 {
518 .max = 1,
519 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
520 },
521 {
522 .max = 1,
523 .types = BIT(NL80211_IFTYPE_P2P_GO),
524 },
525};
526
527static const struct ieee80211_iface_limit
528 wlan_hdd_sta_ap_iface_limit[] = {
529 {
530 /* We need 1 extra STA interface for OBSS scan when SAP starts
531 * with HT40 in STA+SAP concurrency mode
532 */
533 .max = (1 + SAP_MAX_OBSS_STA_CNT),
534 .types = BIT(NL80211_IFTYPE_STATION),
535 },
536 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530537 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538 .types = BIT(NL80211_IFTYPE_AP),
539 },
540};
541
542/* STA + P2P combination */
543static const struct ieee80211_iface_limit
544 wlan_hdd_sta_p2p_iface_limit[] = {
545 {
546 /* One reserved for dedicated P2PDEV usage */
547 .max = 2,
548 .types = BIT(NL80211_IFTYPE_STATION)
549 },
550 {
551 /* Support for two identical (GO + GO or CLI + CLI)
552 * or dissimilar (GO + CLI) P2P interfaces
553 */
554 .max = 2,
555 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
556 },
557};
558
559/* STA + AP + P2PGO combination */
560static const struct ieee80211_iface_limit
561wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
562 /* Support for AP+P2PGO interfaces */
563 {
564 .max = 2,
565 .types = BIT(NL80211_IFTYPE_STATION)
566 },
567 {
568 .max = 1,
569 .types = BIT(NL80211_IFTYPE_P2P_GO)
570 },
571 {
572 .max = 1,
573 .types = BIT(NL80211_IFTYPE_AP)
574 }
575};
576
577/* SAP + P2P combination */
578static const struct ieee80211_iface_limit
579wlan_hdd_sap_p2p_iface_limit[] = {
580 {
581 /* 1 dedicated for p2p0 which is a STA type */
582 .max = 1,
583 .types = BIT(NL80211_IFTYPE_STATION)
584 },
585 {
586 /* The p2p interface in SAP+P2P can be GO/CLI.
587 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
588 */
589 .max = 1,
590 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
591 },
592 {
593 /* SAP+GO to support only one SAP interface */
594 .max = 1,
595 .types = BIT(NL80211_IFTYPE_AP)
596 }
597};
598
599/* P2P + P2P combination */
600static const struct ieee80211_iface_limit
601wlan_hdd_p2p_p2p_iface_limit[] = {
602 {
603 /* 1 dedicated for p2p0 which is a STA type */
604 .max = 1,
605 .types = BIT(NL80211_IFTYPE_STATION)
606 },
607 {
608 /* The p2p interface in P2P+P2P can be GO/CLI.
609 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
610 */
611 .max = 2,
612 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
613 },
614};
615
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700616static const struct ieee80211_iface_limit
617 wlan_hdd_mon_iface_limit[] = {
618 {
619 .max = 3, /* Monitor interface */
620 .types = BIT(NL80211_IFTYPE_MONITOR),
621 },
622};
623
624static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800625 wlan_hdd_iface_combination[] = {
626 /* STA */
627 {
628 .limits = wlan_hdd_sta_iface_limit,
629 .num_different_channels = 2,
630 .max_interfaces = 3,
631 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
632 },
633 /* ADHOC */
634 {
635 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700636 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800637 .max_interfaces = 2,
638 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
639 },
640 /* AP */
641 {
642 .limits = wlan_hdd_ap_iface_limit,
643 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530644 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800645 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
hqu3c4ed3d2017-09-19 11:42:35 +0800646#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
647 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
648 .beacon_int_min_gcd = 1,
649#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800650 },
651 /* P2P */
652 {
653 .limits = wlan_hdd_p2p_iface_limit,
654 .num_different_channels = 2,
655 .max_interfaces = 2,
656 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
657 },
658 /* STA + AP */
659 {
660 .limits = wlan_hdd_sta_ap_iface_limit,
661 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530662 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800663 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
664 .beacon_int_infra_match = true,
hqu3c4ed3d2017-09-19 11:42:35 +0800665#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
666 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
667 .beacon_int_min_gcd = 1,
668#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800669 },
670 /* STA + P2P */
671 {
672 .limits = wlan_hdd_sta_p2p_iface_limit,
673 .num_different_channels = 2,
674 /* one interface reserved for P2PDEV dedicated usage */
675 .max_interfaces = 4,
676 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
677 .beacon_int_infra_match = true,
678 },
679 /* STA + P2P GO + SAP */
680 {
681 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
682 /* we can allow 3 channels for three different persona
683 * but due to firmware limitation, allow max 2 concrnt channels.
684 */
685 .num_different_channels = 2,
686 /* one interface reserved for P2PDEV dedicated usage */
687 .max_interfaces = 4,
688 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
689 .beacon_int_infra_match = true,
690 },
691 /* SAP + P2P */
692 {
693 .limits = wlan_hdd_sap_p2p_iface_limit,
694 .num_different_channels = 2,
695 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
696 .max_interfaces = 3,
697 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
698 .beacon_int_infra_match = true,
699 },
700 /* P2P + P2P */
701 {
702 .limits = wlan_hdd_p2p_p2p_iface_limit,
703 .num_different_channels = 2,
704 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
705 .max_interfaces = 3,
706 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
707 .beacon_int_infra_match = true,
708 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530709 /* Monitor */
710 {
711 .limits = wlan_hdd_mon_iface_limit,
712 .max_interfaces = 3,
713 .num_different_channels = 2,
714 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
715 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800717
718static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719
720#ifdef WLAN_NL80211_TESTMODE
721enum wlan_hdd_tm_attr {
722 WLAN_HDD_TM_ATTR_INVALID = 0,
723 WLAN_HDD_TM_ATTR_CMD = 1,
724 WLAN_HDD_TM_ATTR_DATA = 2,
725 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
726 WLAN_HDD_TM_ATTR_TYPE = 4,
727 /* keep last */
728 WLAN_HDD_TM_ATTR_AFTER_LAST,
729 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
730};
731
732enum wlan_hdd_tm_cmd {
733 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
734 WLAN_HDD_TM_CMD_WLAN_HB = 1,
735};
736
737#define WLAN_HDD_TM_DATA_MAX_LEN 5000
738
739static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
740 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
741 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
742 .len = WLAN_HDD_TM_DATA_MAX_LEN},
743};
744#endif /* WLAN_NL80211_TESTMODE */
745
Lin Baia016e9a2017-08-29 19:10:42 +0800746enum wlan_hdd_vendor_ie_access_policy {
747 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
748 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
749};
750
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800751#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
752static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
753 .flags = WIPHY_WOWLAN_MAGIC_PKT,
754 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
755 .pattern_min_len = 1,
756 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
757};
758#endif
759
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800760/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530761 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
762 * @flags: Pointer to the flags to Add channel switch flag.
763 *
764 * This Function adds Channel Switch support flag, if channel switch is
765 * supported by kernel.
766 * Return: void.
767 */
768#ifdef CHANNEL_SWITCH_SUPPORTED
769static inline void hdd_add_channel_switch_support(uint32_t *flags)
770{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800771 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530772}
773#else
774static inline void hdd_add_channel_switch_support(uint32_t *flags)
775{
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530776}
777#endif
778
Manikandan Mohan22b83722015-12-15 15:03:23 -0800779#ifdef FEATURE_WLAN_TDLS
780
781/* TDLS capabilities params */
782#define PARAM_MAX_TDLS_SESSION \
783 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
784#define PARAM_TDLS_FEATURE_SUPPORT \
785 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
786
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530787/**
Jeff Johnson118a4a02018-05-06 00:14:15 -0700788 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800789 * @wiphy: WIPHY structure pointer
790 * @wdev: Wireless device structure pointer
791 * @data: Pointer to the data received
792 * @data_len: Length of the data received
793 *
794 * This function provides TDLS capabilities
795 *
796 * Return: 0 on success and errno on failure
797 */
798static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
799 struct wireless_dev *wdev,
800 const void *data,
801 int data_len)
802{
803 int status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -0700804 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800805 struct sk_buff *skb;
806 uint32_t set = 0;
Frank Liu5c63dc82017-09-07 14:49:05 +0800807 uint32_t max_num_tdls_sta = 0;
Wu Gaobdb7f272018-07-05 19:33:26 +0800808 bool tdls_support;
809 bool tdls_external_control;
810 bool tdls_sleep_sta_enable;
811 bool tdls_buffer_sta;
812 bool tdls_off_channel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813
Dustin Brownfdf17c12018-03-14 12:55:34 -0700814 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -0800815
Anurag Chouhan6d760662016-02-20 16:05:43 +0530816 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800817 hdd_err("Command not allowed in FTM mode");
818 return -EPERM;
819 }
820
821 status = wlan_hdd_validate_context(hdd_ctx);
822 if (status)
823 return status;
824
825 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
826 NLMSG_HDRLEN);
827 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700828 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800829 goto fail;
830 }
831
Dustin Brown76cd2932018-09-11 16:03:05 -0700832 if ((cfg_tdls_get_support_enable(hdd_ctx->psoc, &tdls_support) ==
Bala Venkateshdcbad342019-03-18 13:57:24 +0530833 QDF_STATUS_SUCCESS) && !tdls_support) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800834 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800835 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
836 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700837 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800838 goto fail;
839 }
840 } else {
Dustin Brown76cd2932018-09-11 16:03:05 -0700841 cfg_tdls_get_external_control(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800842 &tdls_external_control);
Dustin Brown76cd2932018-09-11 16:03:05 -0700843 cfg_tdls_get_sleep_sta_enable(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800844 &tdls_sleep_sta_enable);
Dustin Brown76cd2932018-09-11 16:03:05 -0700845 cfg_tdls_get_buffer_sta_enable(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800846 &tdls_buffer_sta);
Dustin Brown76cd2932018-09-11 16:03:05 -0700847 cfg_tdls_get_off_channel_enable(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800848 &tdls_off_channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800849 set = set | WIFI_TDLS_SUPPORT;
Wu Gaobdb7f272018-07-05 19:33:26 +0800850 set = set | (tdls_external_control ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800851 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
Wu Gaobdb7f272018-07-05 19:33:26 +0800852 set = set | (tdls_off_channel ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800853 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Wu Gaobdb7f272018-07-05 19:33:26 +0800854 if (tdls_sleep_sta_enable || tdls_buffer_sta ||
855 tdls_off_channel)
Frank Liu5c63dc82017-09-07 14:49:05 +0800856 max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA_P_UAPSD_OFFCHAN;
857 else
858 max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA;
859
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800860 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800861 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
Frank Liu5c63dc82017-09-07 14:49:05 +0800862 max_num_tdls_sta) ||
863 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700864 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800865 goto fail;
866 }
867 }
868 return cfg80211_vendor_cmd_reply(skb);
869fail:
870 if (skb)
871 kfree_skb(skb);
872 return -EINVAL;
873}
874
875/**
Jeff Johnson118a4a02018-05-06 00:14:15 -0700876 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800877 * @wiphy: WIPHY structure pointer
878 * @wdev: Wireless device structure pointer
879 * @data: Pointer to the data received
880 * @data_len: Length of the data received
881 *
882 * This function provides TDLS capabilities
883 *
884 * Return: 0 on success and errno on failure
885 */
886static int
887wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
888 struct wireless_dev *wdev,
889 const void *data,
890 int data_len)
891{
Dustin Brown363b4792019-02-05 16:11:55 -0800892 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -0800893 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +0530894
Dustin Brown363b4792019-02-05 16:11:55 -0800895 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -0800896 if (errno)
897 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800898
Dustin Brownf0f00612019-01-31 16:02:24 -0800899 errno = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
900 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800901
Dustin Brown363b4792019-02-05 16:11:55 -0800902 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -0800903
904 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800905}
jiad7b8a5e02018-11-26 16:37:57 +0800906
907static uint8_t hdd_get_bw_offset(uint32_t ch_width)
908{
909 uint8_t bw_offset = 0;
910
911 if (ch_width == CH_WIDTH_40MHZ)
912 bw_offset = 1 << BW_40_OFFSET_BIT;
913 else if (ch_width == CH_WIDTH_20MHZ)
914 bw_offset = 1 << BW_20_OFFSET_BIT;
915
916 return bw_offset;
917}
918
919#else /* !FEATURE_WLAN_TDLS */
920
921static inline uint8_t hdd_get_bw_offset(uint32_t ch_width)
922{
923 return 0;
924}
925
926#endif /* FEATURE_WLAN_TDLS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800927
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700928int wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type *destFreqList,
929 struct ch_avoid_ind_type *srcFreqList)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530930{
931 int i;
Jeff Johnson62f28992019-03-05 14:48:42 -0800932 uint32_t room;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700933 struct ch_avoid_freq_type *avoid_range =
934 &destFreqList->avoid_freq_range[destFreqList->ch_avoid_range_cnt];
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530935
Jeff Johnson62f28992019-03-05 14:48:42 -0800936 room = CH_AVOID_MAX_RANGE - destFreqList->ch_avoid_range_cnt;
937 if (srcFreqList->ch_avoid_range_cnt > room) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530938 hdd_err("avoid freq overflow");
939 return -EINVAL;
940 }
Jeff Johnson62f28992019-03-05 14:48:42 -0800941 destFreqList->ch_avoid_range_cnt += srcFreqList->ch_avoid_range_cnt;
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530942
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700943 for (i = 0; i < srcFreqList->ch_avoid_range_cnt; i++) {
944 avoid_range->start_freq =
945 srcFreqList->avoid_freq_range[i].start_freq;
946 avoid_range->end_freq =
947 srcFreqList->avoid_freq_range[i].end_freq;
948 avoid_range++;
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530949 }
950 return 0;
951}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800952/*
953 * FUNCTION: wlan_hdd_send_avoid_freq_event
954 * This is called when wlan driver needs to send vendor specific
955 * avoid frequency range event to userspace
956 */
Jeff Johnsonb8944722017-09-03 09:03:19 -0700957int wlan_hdd_send_avoid_freq_event(struct hdd_context *hdd_ctx,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700958 struct ch_avoid_ind_type *avoid_freq_list)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800959{
960 struct sk_buff *vendor_event;
961
Dustin Brown491d54b2018-03-14 12:39:11 -0700962 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963
Jeff Johnsonb8944722017-09-03 09:03:19 -0700964 if (!hdd_ctx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700965 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800966 return -EINVAL;
967 }
968
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700969 if (!avoid_freq_list) {
970 hdd_err("avoid_freq_list is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800971 return -EINVAL;
972 }
973
Jeff Johnsonb8944722017-09-03 09:03:19 -0700974 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700975 NULL, sizeof(struct ch_avoid_ind_type),
976 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
977 GFP_KERNEL);
978
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800979 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700980 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800981 return -EINVAL;
982 }
983
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700984 memcpy(skb_put(vendor_event, sizeof(struct ch_avoid_ind_type)),
985 (void *)avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800986
987 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
988
Dustin Browne74003f2018-03-14 12:51:58 -0700989 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800990 return 0;
991}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800992
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530993/*
994 * define short names for the global vendor params
995 * used by QCA_NL80211_VENDOR_SUBCMD_HANG
996 */
997#define HANG_REASON_INDEX QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX
998
999/**
1000 * hdd_convert_hang_reason() - Convert cds recovery reason to vendor specific
1001 * hang reason
1002 * @reason: cds recovery reason
1003 *
1004 * Return: Vendor specific reason code
1005 */
1006static enum qca_wlan_vendor_hang_reason
1007hdd_convert_hang_reason(enum qdf_hang_reason reason)
1008{
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -07001009 u32 ret_val;
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301010
1011 switch (reason) {
1012 case QDF_RX_HASH_NO_ENTRY_FOUND:
1013 ret_val = QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND;
1014 break;
1015 case QDF_PEER_DELETION_TIMEDOUT:
1016 ret_val = QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT;
1017 break;
1018 case QDF_PEER_UNMAP_TIMEDOUT:
1019 ret_val = QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT;
1020 break;
1021 case QDF_SCAN_REQ_EXPIRED:
1022 ret_val = QCA_WLAN_HANG_SCAN_REQ_EXPIRED;
1023 break;
1024 case QDF_SCAN_ATTEMPT_FAILURES:
1025 ret_val = QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES;
1026 break;
1027 case QDF_GET_MSG_BUFF_FAILURE:
1028 ret_val = QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE;
1029 break;
1030 case QDF_ACTIVE_LIST_TIMEOUT:
1031 ret_val = QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT;
1032 break;
1033 case QDF_SUSPEND_TIMEOUT:
1034 ret_val = QCA_WLAN_HANG_SUSPEND_TIMEOUT;
1035 break;
1036 case QDF_RESUME_TIMEOUT:
1037 ret_val = QCA_WLAN_HANG_RESUME_TIMEOUT;
1038 break;
Jingxiang Ge2a67be52019-04-10 14:47:51 +08001039 case QDF_WMI_EXCEED_MAX_PENDING_CMDS:
1040 ret_val = QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS;
1041 break;
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301042 case QDF_REASON_UNSPECIFIED:
1043 default:
1044 ret_val = QCA_WLAN_HANG_REASON_UNSPECIFIED;
1045 }
1046 return ret_val;
1047}
1048
1049/**
1050 * wlan_hdd_send_hang_reason_event() - Send hang reason to the userspace
1051 * @hdd_ctx: Pointer to hdd context
1052 * @reason: cds recovery reason
1053 *
1054 * Return: 0 on success or failure reason
1055 */
1056int wlan_hdd_send_hang_reason_event(struct hdd_context *hdd_ctx,
1057 enum qdf_hang_reason reason)
1058{
1059 struct sk_buff *vendor_event;
1060 enum qca_wlan_vendor_hang_reason hang_reason;
Abhinav Kumarcab72532019-11-22 12:19:22 +05301061 struct hdd_adapter *sta_adapter;
1062 struct wireless_dev *wdev = NULL;
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301063
Dustin Brown491d54b2018-03-14 12:39:11 -07001064 hdd_enter();
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301065
1066 if (!hdd_ctx) {
1067 hdd_err("HDD context is null");
1068 return -EINVAL;
1069 }
1070
Abhinav Kumarcab72532019-11-22 12:19:22 +05301071 sta_adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
1072 if (sta_adapter)
1073 wdev = &(sta_adapter->wdev);
1074
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301075 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Abhinav Kumarcab72532019-11-22 12:19:22 +05301076 wdev,
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301077 sizeof(uint32_t),
1078 HANG_REASON_INDEX,
1079 GFP_KERNEL);
1080 if (!vendor_event) {
1081 hdd_err("cfg80211_vendor_event_alloc failed");
1082 return -ENOMEM;
1083 }
1084
1085 hang_reason = hdd_convert_hang_reason(reason);
1086
1087 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON,
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -07001088 (uint32_t)hang_reason)) {
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301089 hdd_err("QCA_WLAN_VENDOR_ATTR_HANG_REASON put fail");
1090 kfree_skb(vendor_event);
1091 return -EINVAL;
1092 }
1093
1094 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1095
Dustin Browne74003f2018-03-14 12:51:58 -07001096 hdd_exit();
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301097 return 0;
1098}
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -07001099
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301100#undef HANG_REASON_INDEX
1101
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301102/**
1103 * wlan_hdd_get_adjacent_chan(): Gets next/previous channel
1104 * with respect to the channel passed.
1105 * @chan: Channel
1106 * @upper: If "true" then next channel is returned or else
1107 * previous channel is returned.
1108 *
1109 * This function returns the next/previous adjacent-channel to
1110 * the channel passed. If "upper = true" then next channel is
1111 * returned else previous is returned.
1112 */
1113int wlan_hdd_get_adjacent_chan(uint8_t chan, bool upper)
1114{
Ashish Kumar Dhanotiyaaa9fdbb2018-12-14 15:29:14 +05301115 enum channel_enum ch_idx = wlan_reg_get_chan_enum(chan);
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301116
1117 if (ch_idx == INVALID_CHANNEL)
1118 return -EINVAL;
1119
1120 if (upper && (ch_idx < (NUM_CHANNELS - 1)))
1121 ch_idx++;
Amar Singhal2e4cccc2019-08-06 12:47:18 -07001122 else if (!upper && (ch_idx > CHAN_ENUM_2412))
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301123 ch_idx--;
1124 else
1125 return -EINVAL;
1126
1127 return WLAN_REG_CH_NUM(ch_idx);
1128}
1129
1130/**
1131 * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
1132 * avoided when Do_Not_Break_Stream is active.
Jeff Johnsonb8944722017-09-03 09:03:19 -07001133 * @hdd_ctx: HDD Context
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301134 * @op_chan: AP/P2P-GO operating channel
1135 *
1136 * This function sends list of frequencies to be avoided when
1137 * Do_Not_Break_Stream is active.
1138 * To clear the avoid_frequency_list in the application,
1139 * op_chan = 0 can be passed.
1140 *
1141 * Return: 0 on success and errno on failure
1142 */
Jeff Johnsonb8944722017-09-03 09:03:19 -07001143int wlan_hdd_send_avoid_freq_for_dnbs(struct hdd_context *hdd_ctx, uint8_t op_chan)
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301144{
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001145 struct ch_avoid_ind_type p2p_avoid_freq_list;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301146 uint8_t min_chan, max_chan;
1147 int ret;
1148 int chan;
1149
Dustin Brown491d54b2018-03-14 12:39:11 -07001150 hdd_enter();
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301151
Jeff Johnsonb8944722017-09-03 09:03:19 -07001152 if (!hdd_ctx) {
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301153 hdd_err("invalid param");
1154 return -EINVAL;
1155 }
1156
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001157 qdf_mem_zero(&p2p_avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301158 /*
1159 * If channel passed is zero, clear the avoid_freq list in application.
1160 */
1161 if (!op_chan) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301162#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001163 mutex_lock(&hdd_ctx->avoid_freq_lock);
1164 qdf_mem_zero(&hdd_ctx->dnbs_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001165 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001166 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301167 memcpy(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001168 &hdd_ctx->coex_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001169 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001170 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301171#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001172 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx,
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301173 &p2p_avoid_freq_list);
1174 if (ret)
1175 hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
1176 ret);
1177
1178 return ret;
1179 }
1180
1181 if (WLAN_REG_IS_24GHZ_CH(op_chan)) {
Ashish Kumar Dhanotiyaaa9fdbb2018-12-14 15:29:14 +05301182 min_chan = WLAN_REG_MIN_24GHZ_CH_NUM;
1183 max_chan = WLAN_REG_MAX_24GHZ_CH_NUM;
1184 } else if (WLAN_REG_IS_5GHZ_CH(op_chan)) {
1185 min_chan = WLAN_REG_MIN_5GHZ_CH_NUM;
1186 max_chan = WLAN_REG_MAX_5GHZ_CH_NUM;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301187 } else {
1188 hdd_err("invalid channel:%d", op_chan);
1189 return -EINVAL;
1190 }
1191
1192 if ((op_chan > min_chan) && (op_chan < max_chan)) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001193 p2p_avoid_freq_list.ch_avoid_range_cnt = 2;
1194 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301195 wlan_chan_to_freq(min_chan);
1196
1197 /* Get channel before the op_chan */
1198 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1199 if (chan < 0)
1200 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001201 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301202 wlan_chan_to_freq(chan);
1203
1204 /* Get channel next to the op_chan */
1205 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1206 if (chan < 0)
1207 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001208 p2p_avoid_freq_list.avoid_freq_range[1].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301209 wlan_chan_to_freq(chan);
1210
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001211 p2p_avoid_freq_list.avoid_freq_range[1].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301212 wlan_chan_to_freq(max_chan);
1213 } else if (op_chan == min_chan) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001214 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301215
1216 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1217 if (chan < 0)
1218 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001219 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301220 wlan_chan_to_freq(chan);
1221
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001222 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301223 wlan_chan_to_freq(max_chan);
1224 } else {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001225 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
1226 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301227 wlan_chan_to_freq(min_chan);
1228
1229 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1230 if (chan < 0)
1231 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001232 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301233 wlan_chan_to_freq(chan);
1234 }
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301235#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001236 mutex_lock(&hdd_ctx->avoid_freq_lock);
1237 hdd_ctx->dnbs_avoid_freq_list = p2p_avoid_freq_list;
1238 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301239 ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001240 &hdd_ctx->coex_avoid_freq_list);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301241 if (ret) {
Jeff Johnsonb8944722017-09-03 09:03:19 -07001242 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301243 hdd_err("avoid freq merge failed");
1244 return ret;
1245 }
1246 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07001247 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301248#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001249 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx, &p2p_avoid_freq_list);
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301250 if (ret)
1251 hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
1252
1253 return ret;
1254}
1255
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001256/* vendor specific events */
1257static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
1259 .vendor_id =
1260 QCA_NL80211_VENDOR_ID,
1261 .subcmd =
1262 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
1263 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001265 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
1266 .vendor_id =
1267 QCA_NL80211_VENDOR_ID,
1268 .subcmd =
1269 QCA_NL80211_VENDOR_SUBCMD_NAN
1270 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001271
1272#ifdef WLAN_FEATURE_STATS_EXT
1273 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
1274 .vendor_id =
1275 QCA_NL80211_VENDOR_ID,
1276 .subcmd =
1277 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
1278 },
1279#endif /* WLAN_FEATURE_STATS_EXT */
1280#ifdef FEATURE_WLAN_EXTSCAN
1281 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
1282 .vendor_id =
1283 QCA_NL80211_VENDOR_ID,
1284 .subcmd =
1285 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
1286 },
1287 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
1288 .vendor_id =
1289 QCA_NL80211_VENDOR_ID,
1290 .subcmd =
1291 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
1292 },
1293 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
1294 .
1295 vendor_id
1296 =
1297 QCA_NL80211_VENDOR_ID,
1298 .subcmd =
1299 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
1300 },
1301 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
1302 .
1303 vendor_id
1304 =
1305 QCA_NL80211_VENDOR_ID,
1306 .
1307 subcmd =
1308 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
1309 },
1310 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
1311 .
1312 vendor_id
1313 =
1314 QCA_NL80211_VENDOR_ID,
1315 .
1316 subcmd
1317 =
1318 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1319 },
1320 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1321 .
1322 vendor_id
1323 =
1324 QCA_NL80211_VENDOR_ID,
1325 .subcmd =
1326 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1327 },
1328 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1329 .vendor_id =
1330 QCA_NL80211_VENDOR_ID,
1331 .subcmd =
1332 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1333 },
1334 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1335 .
1336 vendor_id
1337 =
1338 QCA_NL80211_VENDOR_ID,
1339 .subcmd =
1340 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1341 },
1342 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1343 .
1344 vendor_id
1345 =
1346 QCA_NL80211_VENDOR_ID,
1347 .subcmd =
1348 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1349 },
1350 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1351 .
1352 vendor_id
1353 =
1354 QCA_NL80211_VENDOR_ID,
1355 .
1356 subcmd
1357 =
1358 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1359 },
1360 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1361 .
1362 vendor_id
1363 =
1364 QCA_NL80211_VENDOR_ID,
1365 .
1366 subcmd =
1367 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1368 },
1369 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1370 .
1371 vendor_id
1372 =
1373 QCA_NL80211_VENDOR_ID,
1374 .
1375 subcmd
1376 =
1377 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
1378 },
1379 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
1380 .
1381 vendor_id
1382 =
1383 QCA_NL80211_VENDOR_ID,
1384 .
1385 subcmd
1386 =
1387 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
1388 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001389#endif /* FEATURE_WLAN_EXTSCAN */
1390
1391#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1392 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
1393 .vendor_id =
1394 QCA_NL80211_VENDOR_ID,
1395 .subcmd =
1396 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
1397 },
1398 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
1399 .vendor_id =
1400 QCA_NL80211_VENDOR_ID,
1401 .subcmd =
1402 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
1403 },
1404 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
1405 .vendor_id =
1406 QCA_NL80211_VENDOR_ID,
1407 .subcmd =
1408 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
1409 },
1410 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
1411 .vendor_id =
1412 QCA_NL80211_VENDOR_ID,
1413 .subcmd =
1414 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
1415 },
1416 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
1417 .vendor_id =
1418 QCA_NL80211_VENDOR_ID,
1419 .subcmd =
1420 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
1421 },
1422 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
1423 .vendor_id =
1424 QCA_NL80211_VENDOR_ID,
1425 .subcmd =
1426 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
1427 },
Zhang Qianca38fb12016-12-23 11:10:48 +08001428 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
1429 .vendor_id =
1430 QCA_NL80211_VENDOR_ID,
1431 .subcmd =
1432 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
1433 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001434#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1435 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1436 .vendor_id =
1437 QCA_NL80211_VENDOR_ID,
1438 .subcmd =
1439 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1440 },
1441 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1442 .vendor_id = QCA_NL80211_VENDOR_ID,
1443 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1444 },
1445#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1446 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1447 .vendor_id =
1448 QCA_NL80211_VENDOR_ID,
1449 .subcmd =
1450 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1451 },
1452#endif
1453 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1454 .vendor_id =
1455 QCA_NL80211_VENDOR_ID,
1456 .subcmd =
1457 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1458 },
1459 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1460 .vendor_id =
1461 QCA_NL80211_VENDOR_ID,
1462 .subcmd =
1463 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1464 },
1465 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1466 .vendor_id =
1467 QCA_NL80211_VENDOR_ID,
1468 .subcmd =
1469 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1470 },
1471 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1472 .vendor_id =
1473 QCA_NL80211_VENDOR_ID,
1474 .subcmd =
1475 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1476 },
1477 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1478 .vendor_id =
1479 QCA_NL80211_VENDOR_ID,
1480 .subcmd =
1481 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1482 },
1483#ifdef FEATURE_WLAN_EXTSCAN
1484 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1485 .vendor_id = QCA_NL80211_VENDOR_ID,
1486 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1487 },
1488 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1489 .vendor_id = QCA_NL80211_VENDOR_ID,
1490 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1491 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001492 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1493 .vendor_id = QCA_NL80211_VENDOR_ID,
1494 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1495 },
1496#endif /* FEATURE_WLAN_EXTSCAN */
Qiwei Caie689a262018-07-26 15:50:22 +08001497
1498 FEATURE_RSSI_MONITOR_VENDOR_EVENTS
1499
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001500#ifdef WLAN_FEATURE_TSF
1501 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1502 .vendor_id = QCA_NL80211_VENDOR_ID,
1503 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1504 },
1505#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001506 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1507 .vendor_id = QCA_NL80211_VENDOR_ID,
1508 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1509 },
1510 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1511 .vendor_id = QCA_NL80211_VENDOR_ID,
1512 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1513 },
1514 /* OCB events */
1515 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1516 .vendor_id = QCA_NL80211_VENDOR_ID,
1517 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1518 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001519#ifdef FEATURE_LFR_SUBNET_DETECTION
1520 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1521 .vendor_id = QCA_NL80211_VENDOR_ID,
1522 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1523 },
1524#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001525
Paul Zhang37185672019-05-14 11:20:14 +08001526 FEATURE_INTEROP_ISSUES_AP_VENDOR_COMMANDS_INDEX
1527
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001528 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1529 .vendor_id = QCA_NL80211_VENDOR_ID,
1530 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1531 },
Peng Xu8fdaa492016-06-22 10:20:47 -07001532
1533 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1534 .vendor_id = QCA_NL80211_VENDOR_ID,
1535 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1536 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301537 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1538 .vendor_id = QCA_NL80211_VENDOR_ID,
1539 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1540 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301541 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1542 .vendor_id = QCA_NL80211_VENDOR_ID,
1543 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1544 },
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05301545 [QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX] = {
1546 .vendor_id = QCA_NL80211_VENDOR_ID,
1547 .subcmd = QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE
Anurag Chouhan3920c0f2017-09-11 17:10:56 +05301548 },
1549 [QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX] = {
1550 .vendor_id = QCA_NL80211_VENDOR_ID,
1551 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
1552 },
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301553 [QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX] = {
1554 .vendor_id = QCA_NL80211_VENDOR_ID,
1555 .subcmd = QCA_NL80211_VENDOR_SUBCMD_HANG,
1556 },
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +05301557 [QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX] = {
1558 .vendor_id = QCA_NL80211_VENDOR_ID,
1559 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO,
1560 },
Alok Kumar2fad6442018-11-08 19:19:28 +05301561 [QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT_INDEX] = {
1562 .vendor_id = QCA_NL80211_VENDOR_ID,
1563 .subcmd = QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT,
1564 },
Nachiket Kukadea6a70a92018-10-09 20:07:21 +05301565 [QCA_NL80211_VENDOR_SUBCMD_NAN_EXT_INDEX] = {
1566 .vendor_id = QCA_NL80211_VENDOR_ID,
1567 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN_EXT
1568 },
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +05301569 [QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX] = {
1570 .vendor_id = QCA_NL80211_VENDOR_ID,
1571 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
1572 },
Abhinav Kumar4d1f9f42019-05-07 13:14:49 +05301573
1574 BCN_RECV_FEATURE_VENDOR_EVENTS
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05301575 [QCA_NL80211_VENDOR_SUBCMD_ROAM_INDEX] = {
1576 .vendor_id = QCA_NL80211_VENDOR_ID,
1577 .subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
1578 },
Ashish Kumar Dhanotiyad8d7dea2019-10-24 14:34:56 +05301579 [QCA_NL80211_VENDOR_SUBCMD_OEM_DATA_INDEX] = {
1580 .vendor_id = QCA_NL80211_VENDOR_ID,
1581 .subcmd = QCA_NL80211_VENDOR_SUBCMD_OEM_DATA,
1582 },
Ashish Kumar Dhanotiya3d5a7422020-01-20 14:42:02 +05301583 [QCA_NL80211_VENDOR_SUBCMD_REQUEST_SAR_LIMITS_INDEX] = {
1584 .vendor_id = QCA_NL80211_VENDOR_ID,
1585 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS_EVENT,
1586 },
Abhishek Ambure5e9b6a42020-02-12 21:32:35 +05301587 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO_INDEX] = {
1588 .vendor_id = QCA_NL80211_VENDOR_ID,
1589 .subcmd = QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO,
1590 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001591};
1592
1593/**
1594 * __is_driver_dfs_capable() - get driver DFS capability
1595 * @wiphy: pointer to wireless wiphy structure.
1596 * @wdev: pointer to wireless_dev structure.
1597 * @data: Pointer to the data to be passed via vendor interface
1598 * @data_len:Length of the data to be passed
1599 *
1600 * This function is called by userspace to indicate whether or not
1601 * the driver supports DFS offload.
1602 *
1603 * Return: 0 on success, negative errno on failure
1604 */
1605static int __is_driver_dfs_capable(struct wiphy *wiphy,
1606 struct wireless_dev *wdev,
1607 const void *data,
1608 int data_len)
1609{
1610 u32 dfs_capability = 0;
1611 struct sk_buff *temp_skbuff;
1612 int ret_val;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001613 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001614
Dustin Brownfdf17c12018-03-14 12:55:34 -07001615 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001616
1617 ret_val = wlan_hdd_validate_context(hdd_ctx);
1618 if (ret_val)
1619 return ret_val;
1620
Anurag Chouhan6d760662016-02-20 16:05:43 +05301621 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001622 hdd_err("Command not allowed in FTM mode");
1623 return -EPERM;
1624 }
1625
Peng Xu8e8b0392018-04-30 11:32:34 -07001626#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
1627 defined(CFG80211_DFS_OFFLOAD_BACKPORT)
1628 dfs_capability =
1629 wiphy_ext_feature_isset(wiphy,
1630 NL80211_EXT_FEATURE_DFS_OFFLOAD);
1631#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001632 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Peng Xu8e8b0392018-04-30 11:32:34 -07001633#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001634
1635 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1636 NLMSG_HDRLEN);
1637
Jeff Johnsond36fa332019-03-18 13:42:25 -07001638 if (temp_skbuff) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001639 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1640 dfs_capability);
1641 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001642 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001643 kfree_skb(temp_skbuff);
1644
1645 return ret_val;
1646 }
1647
1648 return cfg80211_vendor_cmd_reply(temp_skbuff);
1649 }
1650
Jeff Johnson020db452016-06-29 14:37:26 -07001651 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001652 return -ENOMEM;
1653}
1654
1655/**
1656 * is_driver_dfs_capable() - get driver DFS capability
1657 * @wiphy: pointer to wireless wiphy structure.
1658 * @wdev: pointer to wireless_dev structure.
1659 * @data: Pointer to the data to be passed via vendor interface
1660 * @data_len:Length of the data to be passed
1661 *
1662 * This function is called by userspace to indicate whether or not
1663 * the driver supports DFS offload. This is an SSR-protected
1664 * wrapper function.
1665 *
1666 * Return: 0 on success, negative errno on failure
1667 */
1668static int is_driver_dfs_capable(struct wiphy *wiphy,
1669 struct wireless_dev *wdev,
1670 const void *data,
1671 int data_len)
1672{
Dustin Brown363b4792019-02-05 16:11:55 -08001673 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08001674 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05301675
Dustin Brown363b4792019-02-05 16:11:55 -08001676 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001677 if (errno)
1678 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001679
Dustin Brownf0f00612019-01-31 16:02:24 -08001680 errno = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001681
Dustin Brown363b4792019-02-05 16:11:55 -08001682 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001683
1684 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001685}
1686
1687/**
1688 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1689 *
1690 * @adapter: SAP adapter pointer
1691 *
1692 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1693 * radio. So in case of DFS MCC scenario override current SAP given config
1694 * to follow concurrent SAP DFS config
1695 *
1696 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1697 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001698int wlan_hdd_sap_cfg_dfs_override(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001699{
Jeff Johnsone5006672017-08-29 14:39:02 -07001700 struct hdd_adapter *con_sap_adapter;
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001701 struct sap_config *sap_config, *con_sap_config;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001702 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001703 uint32_t con_ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001704
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001705 if (!hdd_ctx) {
1706 hdd_err("hdd context is NULL");
1707 return 0;
1708 }
1709
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001710 /*
1711 * Check if AP+AP case, once primary AP chooses a DFS
1712 * channel secondary AP should always follow primary APs channel
1713 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001714 if (!policy_mgr_concurrent_beaconing_sessions_running(
Dustin Brown76cd2932018-09-11 16:03:05 -07001715 hdd_ctx->psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001716 return 0;
1717
1718 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1719 if (!con_sap_adapter)
1720 return 0;
1721
Jeff Johnsonb9424862017-10-30 08:49:35 -07001722 sap_config = &adapter->session.ap.sap_config;
1723 con_sap_config = &con_sap_adapter->session.ap.sap_config;
Will Huang4b097f52019-08-29 10:51:56 -07001724 con_ch_freq = con_sap_adapter->session.ap.operating_chan_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001725
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001726 if (!wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, con_ch_freq))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001727 return 0;
1728
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001729 hdd_debug("Only SCC AP-AP DFS Permitted (ch_freq=%d, con_ch_freq=%d)",
1730 sap_config->chan_freq, con_ch_freq);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001731 hdd_debug("Overriding guest AP's channel");
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001732 sap_config->chan_freq = con_ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001733
1734 if (con_sap_config->acs_cfg.acs_mode == true) {
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05301735 if (con_ch_freq != con_sap_config->acs_cfg.pri_ch_freq &&
1736 con_ch_freq != con_sap_config->acs_cfg.ht_sec_ch_freq) {
Jeff Johnson020db452016-06-29 14:37:26 -07001737 hdd_err("Primary AP channel config error");
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05301738 hdd_err("Operating ch: %d ACS ch freq: %d Sec Freq %d",
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001739 con_ch_freq,
1740 con_sap_config->acs_cfg.pri_ch_freq,
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05301741 con_sap_config->acs_cfg.ht_sec_ch_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001742 return -EINVAL;
1743 }
1744 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1745 * MCC restriction. So free ch list allocated in do_acs
1746 * func for Sec AP and realloc for Pri AP ch list size
1747 */
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301748 if (sap_config->acs_cfg.freq_list)
1749 qdf_mem_free(sap_config->acs_cfg.freq_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001750
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301751 qdf_mem_copy(&sap_config->acs_cfg,
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301752 &con_sap_config->acs_cfg,
1753 sizeof(struct sap_acs_cfg));
1754 sap_config->acs_cfg.freq_list = qdf_mem_malloc(
1755 sizeof(uint32_t) *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001756 con_sap_config->acs_cfg.ch_list_count);
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301757 if (!sap_config->acs_cfg.freq_list) {
gaurank kathpalia6701aef2019-06-27 11:53:08 +05301758 sap_config->acs_cfg.ch_list_count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001759 return -ENOMEM;
gaurank kathpalia6701aef2019-06-27 11:53:08 +05301760 }
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301761 qdf_mem_copy(sap_config->acs_cfg.freq_list,
1762 con_sap_config->acs_cfg.freq_list,
1763 con_sap_config->acs_cfg.ch_list_count *
1764 sizeof(uint32_t));
gaurank kathpalia6701aef2019-06-27 11:53:08 +05301765 sap_config->acs_cfg.ch_list_count =
1766 con_sap_config->acs_cfg.ch_list_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001767
1768 } else {
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05301769 sap_config->acs_cfg.pri_ch_freq = con_ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001770 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05301771 sap_config->acs_cfg.ht_sec_ch_freq =
1772 con_sap_config->sec_ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001773 }
1774
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001775 return con_ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001776}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001777
1778/**
wadesong1795e142018-01-05 11:13:07 +08001779 * wlan_hdd_set_acs_ch_range : Populate ACS hw mode and channel range values
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001780 * @sap_cfg: pointer to SAP config struct
wadesong1795e142018-01-05 11:13:07 +08001781 * @hw_mode: hw mode retrieved from vendor command buffer
1782 * @ht_enabled: whether HT phy mode is enabled
1783 * @vht_enabled: whether VHT phy mode is enabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001784 *
wadesong1795e142018-01-05 11:13:07 +08001785 * This function populates the ACS hw mode based on the configuration retrieved
1786 * from the vendor command buffer; and sets ACS start and end channel for the
1787 * given band.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001788 *
wadesong1795e142018-01-05 11:13:07 +08001789 * Return: 0 if success; -EINVAL if ACS channel list is NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001790 */
wadesong1795e142018-01-05 11:13:07 +08001791static int wlan_hdd_set_acs_ch_range(
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001792 struct sap_config *sap_cfg, enum qca_wlan_vendor_acs_hw_mode hw_mode,
wadesong1795e142018-01-05 11:13:07 +08001793 bool ht_enabled, bool vht_enabled)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001794{
1795 int i;
Srinivas Girigowda576b2352017-08-25 14:44:26 -07001796
wadesong1795e142018-01-05 11:13:07 +08001797 if (hw_mode == QCA_ACS_MODE_IEEE80211B) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001798 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001799 sap_cfg->acs_cfg.start_ch_freq =
1800 wlan_reg_ch_to_freq(CHAN_ENUM_2412);
1801 sap_cfg->acs_cfg.end_ch_freq =
1802 wlan_reg_ch_to_freq(CHAN_ENUM_2484);
wadesong1795e142018-01-05 11:13:07 +08001803 } else if (hw_mode == QCA_ACS_MODE_IEEE80211G) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001804 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001805 sap_cfg->acs_cfg.start_ch_freq =
1806 wlan_reg_ch_to_freq(CHAN_ENUM_2412);
1807 sap_cfg->acs_cfg.end_ch_freq =
1808 wlan_reg_ch_to_freq(CHAN_ENUM_2472);
wadesong1795e142018-01-05 11:13:07 +08001809 } else if (hw_mode == QCA_ACS_MODE_IEEE80211A) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001810 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001811 sap_cfg->acs_cfg.start_ch_freq =
1812 wlan_reg_ch_to_freq(CHAN_ENUM_5180);
1813 sap_cfg->acs_cfg.end_ch_freq =
1814 wlan_reg_ch_to_freq(CHAN_ENUM_5865);
wadesong1795e142018-01-05 11:13:07 +08001815 } else if (hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001816 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001817 sap_cfg->acs_cfg.start_ch_freq =
1818 wlan_reg_ch_to_freq(CHAN_ENUM_2412);
1819 sap_cfg->acs_cfg.end_ch_freq =
1820 wlan_reg_ch_to_freq(CHAN_ENUM_5865);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001821 }
1822
1823 if (ht_enabled)
1824 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1825
1826 if (vht_enabled)
1827 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1828
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001829 /* Parse ACS Chan list from hostapd */
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301830 if (!sap_cfg->acs_cfg.freq_list)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301831 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001832
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001833 sap_cfg->acs_cfg.start_ch_freq = sap_cfg->acs_cfg.freq_list[0];
1834 sap_cfg->acs_cfg.end_ch_freq =
1835 sap_cfg->acs_cfg.freq_list[sap_cfg->acs_cfg.ch_list_count - 1];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001836 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301837 /* avoid channel as start channel */
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001838 if (sap_cfg->acs_cfg.start_ch_freq >
1839 sap_cfg->acs_cfg.freq_list[i] &&
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301840 sap_cfg->acs_cfg.freq_list[i] != 0)
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001841 sap_cfg->acs_cfg.start_ch_freq =
1842 sap_cfg->acs_cfg.freq_list[i];
1843 if (sap_cfg->acs_cfg.end_ch_freq <
1844 sap_cfg->acs_cfg.freq_list[i])
1845 sap_cfg->acs_cfg.end_ch_freq =
1846 sap_cfg->acs_cfg.freq_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 }
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301848
1849 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001850}
1851
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001852static void hdd_update_acs_channel_list(struct sap_config *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001853 enum band_info band)
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301854{
1855 int i, temp_count = 0;
1856 int acs_list_count = sap_config->acs_cfg.ch_list_count;
1857
1858 for (i = 0; i < acs_list_count; i++) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001859 if (BAND_2G == band) {
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301860 if (WLAN_REG_IS_24GHZ_CH_FREQ(
1861 sap_config->acs_cfg.freq_list[i])) {
1862 sap_config->acs_cfg.freq_list[temp_count] =
1863 sap_config->acs_cfg.freq_list[i];
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301864 temp_count++;
1865 }
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001866 } else if (BAND_5G == band) {
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301867 if (WLAN_REG_IS_5GHZ_CH_FREQ(
1868 sap_config->acs_cfg.freq_list[i]) ||
1869 WLAN_REG_IS_6GHZ_CHAN_FREQ(
1870 sap_config->acs_cfg.freq_list[i])) {
1871 sap_config->acs_cfg.freq_list[temp_count] =
1872 sap_config->acs_cfg.freq_list[i];
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301873 temp_count++;
1874 }
1875 }
1876 }
1877 sap_config->acs_cfg.ch_list_count = temp_count;
1878}
1879
1880
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001881/**
1882 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1883 * @adapter: pointer to SAP adapter struct
1884 *
1885 * This function starts the ACS procedure if there are no
1886 * constraints like MBSSID DFS restrictions.
1887 *
1888 * Return: Status of ACS Start procedure
1889 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001890int wlan_hdd_cfg80211_start_acs(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891{
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001892 struct hdd_context *hdd_ctx;
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07001893 struct sap_config *sap_config;
Jeff Johnson7dcac7e2019-03-23 15:10:06 -07001894 sap_event_cb acs_event_callback;
Krunal Soni5e3f9622018-09-26 16:35:50 -07001895 uint8_t mcc_to_scc_switch = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001896 int status;
gaurank kathpaliafa8b2e12019-11-20 12:30:38 +05301897 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001898
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001899 if (!adapter) {
Jeff Johnsondd2f1fc2018-05-06 11:22:52 -07001900 hdd_err("adapter is NULL");
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001901 return -EINVAL;
1902 }
1903 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Ashish Kumar Dhanotiyadc3900f2019-01-11 20:42:04 +05301904 status = wlan_hdd_validate_context(hdd_ctx);
1905 if (0 != status)
1906 return status;
1907
Jeff Johnsonb9424862017-10-30 08:49:35 -07001908 sap_config = &adapter->session.ap.sap_config;
Ashish Kumar Dhanotiyab0629622018-09-21 18:58:59 +05301909 if (!sap_config) {
1910 hdd_err("SAP config is NULL");
1911 return -EINVAL;
1912 }
Rajeev Kumar Sirasanagandlae83ac292019-09-19 16:35:26 +05301913 if (hdd_ctx->acs_policy.acs_chan_freq)
1914 sap_config->chan_freq = hdd_ctx->acs_policy.acs_chan_freq;
Agrawal Ashish65634612016-08-18 13:24:32 +05301915 else
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -07001916 sap_config->chan_freq = AUTO_CHANNEL_SELECT;
Krunal Soni5e3f9622018-09-26 16:35:50 -07001917 ucfg_policy_mgr_get_mcc_scc_switch(hdd_ctx->psoc,
1918 &mcc_to_scc_switch);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301919 /*
1920 * No DFS SCC is allowed in Auto use case. Hence not
1921 * calling DFS override
1922 */
1923 if (QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION !=
Jianmin Zhu7f212f72019-06-18 15:41:10 +08001924 mcc_to_scc_switch &&
1925 !(policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) &&
Liangwei Dong50d12dc2019-11-06 14:19:46 +08001926 WLAN_REG_IS_24GHZ_CH_FREQ(sap_config->acs_cfg.end_ch_freq))) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301927 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1928 if (status < 0)
1929 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301931 if (status > 0) {
1932 /*notify hostapd about channel override */
1933 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301934 return 0;
1935 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936 }
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301937 /* When first 2 connections are on the same frequency band,
1938 * then PCL would include only channels from the other
1939 * frequency band on which no connections are active
1940 */
Dustin Brown76cd2932018-09-11 16:03:05 -07001941 if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301942 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
1943 struct policy_mgr_conc_connection_info *conc_connection_info;
1944 uint32_t i;
Jeff Johnson68755312017-02-10 11:46:55 -08001945
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301946 conc_connection_info = policy_mgr_get_conn_info(&i);
1947 if (conc_connection_info[0].mac ==
1948 conc_connection_info[1].mac) {
gaurank kathpalia924b2a72019-10-29 17:36:45 +05301949 if (WLAN_REG_IS_5GHZ_CH_FREQ(
1950 sap_config->acs_cfg.pcl_chan_freq[0])) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301951 sap_config->acs_cfg.band =
1952 QCA_ACS_MODE_IEEE80211A;
1953 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001954 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301955 } else {
1956 sap_config->acs_cfg.band =
1957 QCA_ACS_MODE_IEEE80211G;
1958 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001959 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301960 }
1961 }
1962 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1964 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001965 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966 return -EINVAL;
1967 }
1968
1969 acs_event_callback = hdd_hostapd_sap_event_cb;
1970
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301971 qdf_mem_copy(sap_config->self_macaddr.bytes,
Jeff Johnson1e851a12017-10-28 14:36:12 -07001972 adapter->mac_addr.bytes, sizeof(struct qdf_mac_addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973
gaurank kathpaliafa8b2e12019-11-20 12:30:38 +05301974 qdf_status = wlansap_acs_chselect(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
1975 acs_event_callback,
1976 sap_config, adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001977
gaurank kathpaliafa8b2e12019-11-20 12:30:38 +05301978 if (QDF_IS_STATUS_ERROR(qdf_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001979 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001980 return -EINVAL;
1981 }
bings394afdd2017-01-09 11:22:38 +08001982 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1983 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984
1985 return 0;
1986}
1987
1988/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301989 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1990 * @hdd_ctx: hdd context
1991 * @acs_chan_params: external acs channel params
1992 * @sap_config: SAP config
1993 *
1994 * This API provides unsorted pcl list.
1995 * this list is a subset of the valid channel list given by hostapd.
1996 * if channel is not present in pcl, weightage will be given as zero
1997 *
1998 * Return: Zero on success, non-zero on failure
1999 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002000static void hdd_update_vendor_pcl_list(struct hdd_context *hdd_ctx,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302001 struct hdd_vendor_acs_chan_params *acs_chan_params,
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002002 struct sap_config *sap_config)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302003{
2004 int i, j;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05302005 /*
2006 * PCL shall contain only the preferred channels from the
2007 * application. If those channels are not present in the
2008 * driver PCL, then set the weight to zero
2009 */
2010 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
2011 acs_chan_params->vendor_pcl_list[i] =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302012 sap_config->acs_cfg.freq_list[i];
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05302013 acs_chan_params->vendor_weight_list[i] = 0;
2014 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302015 if (sap_config->acs_cfg.freq_list[i] ==
2016 sap_config->acs_cfg.pcl_chan_freq[j]) {
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05302017 acs_chan_params->vendor_weight_list[i] =
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302018 sap_config->acs_cfg.pcl_channels_weight_list[j];
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05302019 break;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302020 }
2021 }
2022 }
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05302023 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302024}
2025
2026/**
Kapil Gupta086c6202016-12-11 18:17:06 +05302027 * hdd_update_reg_chan_info : This API contructs channel info
2028 * for all the given channel
2029 * @adapter: pointer to SAP adapter struct
2030 * @channel_count: channel count
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302031 * @freq_list: channel frequency (MHz) list
Kapil Gupta086c6202016-12-11 18:17:06 +05302032 *
2033 * Return: Status of of channel information updation
2034 */
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302035static int
2036hdd_update_reg_chan_info(struct hdd_adapter *adapter,
2037 uint32_t channel_count, uint32_t *freq_list)
Kapil Gupta086c6202016-12-11 18:17:06 +05302038{
2039 int i;
2040 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08002041 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05302042 uint8_t bw_offset = 0, chan = 0;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002043 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002044 struct sap_config *sap_config = &adapter->session.ap.sap_config;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07002045 mac_handle_t mac_handle;
Vignesh Viswanathana1f3a1a2018-10-04 13:10:46 +05302046 uint8_t sub_20_chan_width = 0;
2047 QDF_STATUS status;
Kapil Gupta086c6202016-12-11 18:17:06 +05302048
Jeff Johnson34fc63a2018-06-14 10:10:02 -07002049 mac_handle = hdd_ctx->mac_handle;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302050 sap_config->channel_info_count = channel_count;
Vignesh Viswanathana1f3a1a2018-10-04 13:10:46 +05302051
2052 status = ucfg_mlme_get_sub_20_chan_width(hdd_ctx->psoc,
2053 &sub_20_chan_width);
2054 if (QDF_IS_STATUS_ERROR(status))
2055 hdd_err("Failed to get sub_20_chan_width config");
2056
Kapil Gupta086c6202016-12-11 18:17:06 +05302057 for (i = 0; i < channel_count; i++) {
2058 icv = &sap_config->channel_info[i];
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302059 chan = wlan_reg_freq_to_chan(hdd_ctx->pdev,
2060 freq_list[i]);
Kapil Gupta086c6202016-12-11 18:17:06 +05302061 if (chan == 0)
2062 continue;
2063
Dustin Brown07901ec2018-09-07 11:02:41 -07002064 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05302065 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002066 icv->max_reg_power = wlan_reg_get_channel_reg_power(
Dustin Brown07901ec2018-09-07 11:02:41 -07002067 hdd_ctx->pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05302068
2069 /* filling demo values */
2070 icv->max_radio_power = HDD_MAX_TX_POWER;
2071 icv->min_radio_power = HDD_MIN_TX_POWER;
2072 /* not supported in current driver */
2073 icv->max_antenna_gain = 0;
2074
jiad7b8a5e02018-11-26 16:37:57 +08002075 bw_offset = hdd_get_bw_offset(sap_config->acs_cfg.ch_width);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07002076 icv->reg_class_id =
2077 wlan_hdd_find_opclass(mac_handle, chan, bw_offset);
Kapil Gupta086c6202016-12-11 18:17:06 +05302078
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002079 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05302080 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Dustin Brown07901ec2018-09-07 11:02:41 -07002081 wlan_reg_set_channel_params(hdd_ctx->pdev, chan,
2082 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05302083 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
2084 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
2085 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002086
Kapil Gupta086c6202016-12-11 18:17:06 +05302087 icv->flags = 0;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302088 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->pdev,
2089 icv->ieee_chan_number,
Kapil Gupta086c6202016-12-11 18:17:06 +05302090 sap_config->acs_cfg.ch_width,
2091 sap_config->acs_cfg.is_ht_enabled,
2092 sap_config->acs_cfg.is_vht_enabled,
Vignesh Viswanathana1f3a1a2018-10-04 13:10:46 +05302093 sub_20_chan_width);
Kapil Guptac1224bf2017-06-22 21:22:40 +05302094 if (icv->flags & IEEE80211_CHAN_PASSIVE)
2095 icv->flagext |= IEEE80211_CHAN_DFS;
Kapil Gupta086c6202016-12-11 18:17:06 +05302096
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +05302097 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 +05302098 icv->freq, icv->flags,
2099 icv->flagext, icv->ieee_chan_number,
2100 icv->max_reg_power, icv->max_radio_power,
2101 icv->min_radio_power, icv->reg_class_id,
2102 icv->max_antenna_gain, icv->vht_center_freq_seg0,
2103 icv->vht_center_freq_seg1);
2104 }
2105 return 0;
2106}
2107
2108/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
2109#define CHAN_INFO_ATTR_FLAGS \
2110 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
2111#define CHAN_INFO_ATTR_FLAG_EXT \
2112 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
2113#define CHAN_INFO_ATTR_FREQ \
2114 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
2115#define CHAN_INFO_ATTR_MAX_REG_POWER \
2116 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
2117#define CHAN_INFO_ATTR_MAX_POWER \
2118 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
2119#define CHAN_INFO_ATTR_MIN_POWER \
2120 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
2121#define CHAN_INFO_ATTR_REG_CLASS_ID \
2122 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
2123#define CHAN_INFO_ATTR_ANTENNA_GAIN \
2124 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
2125#define CHAN_INFO_ATTR_VHT_SEG_0 \
2126 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
2127#define CHAN_INFO_ATTR_VHT_SEG_1 \
2128 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
2129
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302130#define CHAN_INFO_ATTR_FREQ_VHT_SEG_0 \
2131 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0
2132#define CHAN_INFO_ATTR_FREQ_VHT_SEG_1 \
2133 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1
2134
Kapil Gupta086c6202016-12-11 18:17:06 +05302135/**
2136 * hdd_cfg80211_update_channel_info() - add channel info attributes
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302137 * @hdd_ctx: pointer to hdd context
Kapil Gupta086c6202016-12-11 18:17:06 +05302138 * @skb: pointer to sk buff
2139 * @hdd_ctx: pointer to hdd station context
2140 * @idx: attribute index
2141 *
2142 * Return: Success(0) or reason code for failure
2143 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05302144static int32_t
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302145hdd_cfg80211_update_channel_info(struct hdd_context *hdd_ctx,
2146 struct sk_buff *skb,
2147 struct sap_config *sap_config, int idx)
Kapil Gupta086c6202016-12-11 18:17:06 +05302148{
2149 struct nlattr *nla_attr, *channel;
2150 struct hdd_channel_info *icv;
2151 int i;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302152 uint32_t freq_seg_0, freq_seg_1;
Kapil Gupta086c6202016-12-11 18:17:06 +05302153
2154 nla_attr = nla_nest_start(skb, idx);
2155 if (!nla_attr)
2156 goto fail;
2157
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302158 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05302159 channel = nla_nest_start(skb, i);
2160 if (!channel)
2161 goto fail;
2162
2163 icv = &sap_config->channel_info[i];
2164 if (!icv) {
2165 hdd_err("channel info not found");
2166 goto fail;
2167 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302168
2169 freq_seg_0 = wlan_reg_legacy_chan_to_freq(
2170 hdd_ctx->pdev,
2171 icv->vht_center_freq_seg0);
2172 freq_seg_1 = wlan_reg_legacy_chan_to_freq(
2173 hdd_ctx->pdev,
2174 icv->vht_center_freq_seg1);
2175
Kapil Gupta086c6202016-12-11 18:17:06 +05302176 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
2177 icv->freq) ||
2178 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
2179 icv->flags) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302180 nla_put_u32(skb, CHAN_INFO_ATTR_FLAG_EXT,
Kapil Gupta086c6202016-12-11 18:17:06 +05302181 icv->flagext) ||
2182 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
2183 icv->max_reg_power) ||
2184 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
2185 icv->max_radio_power) ||
2186 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
2187 icv->min_radio_power) ||
2188 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
2189 icv->reg_class_id) ||
2190 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
2191 icv->max_antenna_gain) ||
2192 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
2193 icv->vht_center_freq_seg0) ||
2194 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302195 icv->vht_center_freq_seg1) ||
2196 nla_put_u32(skb, CHAN_INFO_ATTR_FREQ_VHT_SEG_0,
2197 freq_seg_0) ||
2198 nla_put_u32(skb, CHAN_INFO_ATTR_FREQ_VHT_SEG_1,
2199 freq_seg_1)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05302200 hdd_err("put fail");
2201 goto fail;
2202 }
2203 nla_nest_end(skb, channel);
2204 }
2205 nla_nest_end(skb, nla_attr);
2206 return 0;
2207fail:
2208 hdd_err("nl channel update failed");
2209 return -EINVAL;
2210}
2211#undef CHAN_INFO_ATTR_FLAGS
2212#undef CHAN_INFO_ATTR_FLAG_EXT
2213#undef CHAN_INFO_ATTR_FREQ
2214#undef CHAN_INFO_ATTR_MAX_REG_POWER
2215#undef CHAN_INFO_ATTR_MAX_POWER
2216#undef CHAN_INFO_ATTR_MIN_POWER
2217#undef CHAN_INFO_ATTR_REG_CLASS_ID
2218#undef CHAN_INFO_ATTR_ANTENNA_GAIN
2219#undef CHAN_INFO_ATTR_VHT_SEG_0
2220#undef CHAN_INFO_ATTR_VHT_SEG_1
2221
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302222#undef CHAN_INFO_ATTR_FREQ_VHT_SEG_0
2223#undef CHAN_INFO_ATTR_FREQ_VHT_SEG_1
2224
Kapil Gupta086c6202016-12-11 18:17:06 +05302225/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05302226 * hdd_cfg80211_update_pcl() - add pcl info attributes
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302227 * @hdd_ctx: pointer to hdd context
Kapil Gupta8878ad92017-02-13 11:56:04 +05302228 * @skb: pointer to sk buff
2229 * @hdd_ctx: pointer to hdd station context
2230 * @idx: attribute index
2231 * @vendor_pcl_list: PCL list
2232 * @vendor_weight_list: PCL weights
2233 *
2234 * Return: Success(0) or reason code for failure
2235 */
2236static int32_t
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302237hdd_cfg80211_update_pcl(struct hdd_context *hdd_ctx,
2238 struct sk_buff *skb,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302239 uint8_t ch_list_count, int idx,
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302240 uint32_t *vendor_pcl_list, uint8_t *vendor_weight_list)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302241{
2242 struct nlattr *nla_attr, *channel;
2243 int i;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302244 uint8_t chan;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302245
2246 nla_attr = nla_nest_start(skb, idx);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302247 if (!nla_attr)
2248 goto fail;
2249
2250 for (i = 0; i < ch_list_count; i++) {
2251 channel = nla_nest_start(skb, i);
2252 if (!channel)
2253 goto fail;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302254
2255 chan = (uint8_t)wlan_reg_freq_to_chan(hdd_ctx->pdev,
2256 vendor_pcl_list[i]);
2257
2258 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL, chan) ||
2259 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_PCL_FREQ,
2260 vendor_pcl_list[i]) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302261 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302262 vendor_weight_list[i])) {
2263 hdd_err("put fail");
2264 goto fail;
2265 }
2266 nla_nest_end(skb, channel);
2267 }
2268 nla_nest_end(skb, nla_attr);
2269
2270 return 0;
2271fail:
2272 hdd_err("updating pcl list failed");
2273 return -EINVAL;
2274}
2275
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002276static void hdd_get_scan_band(struct hdd_context *hdd_ctx,
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002277 struct sap_config *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002278 enum band_info *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302279{
2280 /* Get scan band */
Kapil Guptac1224bf2017-06-22 21:22:40 +05302281 if ((sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211B) ||
2282 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211G)) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002283 *band = BAND_2G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302284 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002285 *band = BAND_5G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302286 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002287 *band = BAND_ALL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302288 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302289}
2290
Qiwei Caie689a262018-07-26 15:50:22 +08002291/**
2292 * wlan_hdd_sap_get_valid_channellist() - Get SAPs valid channel list
2293 * @ap_adapter: adapter
2294 * @channel_count: valid channel count
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302295 * @freq_list: valid channel frequency (MHz) list
Qiwei Caie689a262018-07-26 15:50:22 +08002296 * @band: frequency band
2297 *
2298 * This API returns valid channel list for SAP after removing nol and
2299 * channel which lies outside of configuration.
2300 *
2301 * Return: Zero on success, non-zero on failure
2302 */
2303static int wlan_hdd_sap_get_valid_channellist(struct hdd_adapter *adapter,
2304 uint32_t *channel_count,
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302305 uint32_t *freq_list,
Qiwei Caie689a262018-07-26 15:50:22 +08002306 enum band_info band)
2307{
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002308 struct sap_config *sap_config;
Qiwei Caie689a262018-07-26 15:50:22 +08002309 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manikandan Mohan19f36092019-08-15 15:54:02 -07002310 uint32_t pcl_freqs[QDF_MAX_NUM_CHAN] = {0};
Qiwei Caie689a262018-07-26 15:50:22 +08002311 uint32_t chan_count;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302312 uint32_t i;
Qiwei Caie689a262018-07-26 15:50:22 +08002313 QDF_STATUS status;
Dustin Brown07901ec2018-09-07 11:02:41 -07002314 struct wlan_objmgr_pdev *pdev = hdd_ctx->pdev;
Qiwei Caie689a262018-07-26 15:50:22 +08002315
2316 sap_config = &adapter->session.ap.sap_config;
2317
Manikandan Mohan19f36092019-08-15 15:54:02 -07002318 status = policy_mgr_get_valid_chans(hdd_ctx->psoc,
2319 pcl_freqs,
2320 &chan_count);
Qiwei Caie689a262018-07-26 15:50:22 +08002321 if (QDF_IS_STATUS_ERROR(status)) {
2322 hdd_err("Failed to get channel list");
2323 return -EINVAL;
2324 }
2325
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302326 *channel_count = 0;
Qiwei Caie689a262018-07-26 15:50:22 +08002327 for (i = 0; i < chan_count; i++) {
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302328 if (*channel_count >= QDF_MAX_NUM_CHAN)
Qiwei Caie689a262018-07-26 15:50:22 +08002329 break;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302330
2331 if (band == BAND_2G &&
2332 WLAN_REG_IS_24GHZ_CH_FREQ(pcl_freqs[i]) &&
2333 !wlan_reg_is_disable_for_freq(pdev, pcl_freqs[i])) {
2334 freq_list[*channel_count] = pcl_freqs[i];
2335 *channel_count += 1;
2336 } else if (band == BAND_5G &&
2337 (WLAN_REG_IS_5GHZ_CH_FREQ(pcl_freqs[i]) ||
2338 WLAN_REG_IS_6GHZ_CHAN_FREQ(pcl_freqs[i])) &&
2339 !wlan_reg_is_disable_for_freq(pdev, pcl_freqs[i])) {
2340 freq_list[*channel_count] = pcl_freqs[i];
2341 *channel_count += 1;
Qiwei Caie689a262018-07-26 15:50:22 +08002342 }
2343 }
2344
2345 if (*channel_count == 0) {
2346 hdd_err("no valid channel found");
2347 return -EINVAL;
2348 }
2349
2350 return 0;
2351}
2352
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302353/**
2354 * hdd_get_external_acs_event_len() - Get event buffer length for external ACS
2355 * @channel_count: number of channels for ACS operation
2356 *
2357 * Return: External ACS event (SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG) buffer length.
2358 */
2359static int hdd_get_external_acs_event_len(uint32_t channel_count)
2360{
2361 uint32_t len = NLMSG_HDRLEN;
2362 uint32_t i;
2363
2364 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON */
2365 len += nla_total_size(sizeof(u8));
2366
2367 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED */
2368 len += nla_total_size(sizeof(u32));
2369
2370 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT */
2371 len += nla_total_size(sizeof(u32));
2372
2373 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH */
2374 len += nla_total_size(sizeof(u8));
2375
2376 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND */
2377 len += nla_total_size(sizeof(u8));
2378
2379 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE */
2380 len += nla_total_size(sizeof(u32));
2381
2382 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST */
2383 len += nla_total_size(channel_count * sizeof(u32));
2384
2385 for (i = 0; i < channel_count; i++) {
2386 /* QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL */
2387 len += nla_total_size(sizeof(u8));
2388
2389 /* QCA_WLAN_VENDOR_ATTR_PCL_FREQ */
2390 len += nla_total_size(sizeof(u32));
2391
2392 /* QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT */
2393 len += nla_total_size(sizeof(u8));
2394 }
2395
2396 for (i = 0; i < channel_count; i++) {
2397 /* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ */
2398 len += nla_total_size(sizeof(u16));
2399
2400 /* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS */
2401 len += nla_total_size(sizeof(u32));
2402
2403 /* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT */
2404 len += nla_total_size(sizeof(u32));
2405
2406 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER */
2407 len += nla_total_size(sizeof(u8));
2408
2409 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER */
2410 len += nla_total_size(sizeof(u8));
2411
2412 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER */
2413 len += nla_total_size(sizeof(u8));
2414
2415 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID */
2416 len += nla_total_size(sizeof(u8));
2417
2418 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN */
2419 len += nla_total_size(sizeof(u8));
2420
2421 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0 */
2422 len += nla_total_size(sizeof(u8));
2423
2424 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1 */
2425 len += nla_total_size(sizeof(u8));
2426
2427 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 */
2428 len += nla_total_size(sizeof(u32));
2429
2430 /* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 */
2431 len += nla_total_size(sizeof(u32));
2432 }
2433
2434 /* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY */
2435 len += nla_total_size(sizeof(u32));
2436
2437 return len;
2438}
2439
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302440int hdd_cfg80211_update_acs_config(struct hdd_adapter *adapter,
2441 uint8_t reason)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302442{
2443 struct sk_buff *skb;
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002444 struct sap_config *sap_config;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302445 uint32_t channel_count = 0, status = -EINVAL;
Kapil Gupta63e75282017-05-18 20:55:10 +05302446 uint32_t freq_list[QDF_MAX_NUM_CHAN] = {0};
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302447 uint32_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
Kapil Gupta8878ad92017-02-13 11:56:04 +05302448 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
2449 struct hdd_vendor_acs_chan_params acs_chan_params;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002450 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002451 enum band_info band = BAND_2G;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302452 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302453 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302454 uint32_t i, id;
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002455 QDF_STATUS qdf_status;
2456 bool is_external_acs_policy = cfg_default(CFG_EXTERNAL_ACS_POLICY);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302457 uint32_t len;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302458
Kapil Gupta8878ad92017-02-13 11:56:04 +05302459 if (!hdd_ctx) {
2460 hdd_err("HDD context is NULL");
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302461 return -EINVAL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302462 }
2463
Dustin Brown491d54b2018-03-14 12:39:11 -07002464 hdd_enter();
Jeff Johnsonb9424862017-10-30 08:49:35 -07002465 sap_config = &adapter->session.ap.sap_config;
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302466 /* When first 2 connections are on the same frequency band,
2467 * then PCL would include only channels from the other
2468 * frequency band on which no connections are active
2469 */
Dustin Brown76cd2932018-09-11 16:03:05 -07002470 if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302471 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
2472 struct policy_mgr_conc_connection_info *conc_connection_info;
2473
2474 conc_connection_info = policy_mgr_get_conn_info(&i);
2475 if (conc_connection_info[0].mac ==
2476 conc_connection_info[1].mac) {
2477
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302478 if (WLAN_REG_IS_5GHZ_CH_FREQ(
2479 sap_config->acs_cfg.pcl_chan_freq[0])) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302480 sap_config->acs_cfg.band =
2481 QCA_ACS_MODE_IEEE80211A;
2482 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002483 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302484 } else {
2485 sap_config->acs_cfg.band =
2486 QCA_ACS_MODE_IEEE80211G;
2487 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002488 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302489 }
2490 }
2491 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302492
Jeff Johnsonb9424862017-10-30 08:49:35 -07002493 hdd_get_scan_band(hdd_ctx, &adapter->session.ap.sap_config, &band);
Nachiket Kukade3208c162017-08-29 17:40:59 +05302494
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302495 if (sap_config->acs_cfg.freq_list) {
Nachiket Kukade3208c162017-08-29 17:40:59 +05302496 /* Copy INI or hostapd provided ACS channel range*/
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302497 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302498 freq_list[i] = sap_config->acs_cfg.freq_list[i];
Nachiket Kukade3208c162017-08-29 17:40:59 +05302499 channel_count = sap_config->acs_cfg.ch_list_count;
2500 } else {
2501 /* No channel list provided, copy all valid channels */
2502 wlan_hdd_sap_get_valid_channellist(adapter,
2503 &channel_count,
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302504 freq_list,
Nachiket Kukade3208c162017-08-29 17:40:59 +05302505 band);
2506 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302507
Lin Baifac77972018-07-05 19:51:49 +08002508 sap_config->channel_info = qdf_mem_malloc(
2509 sizeof(struct hdd_channel_info) *
2510 channel_count);
Min Liu74a1a502018-10-10 19:59:07 +08002511 if (!sap_config->channel_info)
Lin Baifac77972018-07-05 19:51:49 +08002512 return -ENOMEM;
Lin Baifac77972018-07-05 19:51:49 +08002513
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302514 hdd_update_reg_chan_info(adapter, channel_count, freq_list);
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302515
Kapil Gupta8878ad92017-02-13 11:56:04 +05302516 /* Get phymode */
Jeff Johnsonb9424862017-10-30 08:49:35 -07002517 phy_mode = adapter->session.ap.sap_config.acs_cfg.hw_mode;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302518
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302519 len = hdd_get_external_acs_event_len(channel_count);
2520 id = QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG;
2521 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, &adapter->wdev,
2522 len, id, GFP_KERNEL);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302523 if (!skb) {
2524 hdd_err("cfg80211_vendor_event_alloc failed");
Lin Baifac77972018-07-05 19:51:49 +08002525 qdf_mem_free(sap_config->channel_info);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302526 return -ENOMEM;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302527 }
2528 /*
2529 * Application expects pcl to be a subset of channel list
2530 * Remove all channels which are not in channel list from pcl
2531 * and add weight as zero
2532 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05302533 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
2534 acs_chan_params.vendor_weight_list = vendor_weight_list;
2535
2536 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
2537 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302538
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302539 if (acs_chan_params.pcl_count) {
2540 hdd_debug("ACS PCL list: len: %d",
2541 acs_chan_params.pcl_count);
2542 for (i = 0; i < acs_chan_params.pcl_count; i++)
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302543 hdd_debug("channel_frequency: %u, weight: %u",
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302544 acs_chan_params.
2545 vendor_pcl_list[i],
2546 acs_chan_params.
2547 vendor_weight_list[i]);
2548 }
2549
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002550 qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
2551 &is_external_acs_policy);
2552 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2553 hdd_err("get_external_acs_policy failed, set default");
2554
2555 if (is_external_acs_policy) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302556 acs_policy =
2557 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
2558 } else {
2559 acs_policy =
2560 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
2561 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302562 /* Update values in NL buffer */
2563 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
2564 reason) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302565 nla_put_flag(skb,
2566 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED) ||
2567 nla_put_flag(skb,
2568 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT)
2569 ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302570 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
2571 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302572 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
2573 band) ||
2574 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
2575 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05302576 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta63e75282017-05-18 20:55:10 +05302577 channel_count * sizeof(uint32_t), freq_list)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302578 hdd_err("nla put fail");
2579 goto fail;
2580 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302581 status =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302582 hdd_cfg80211_update_pcl(hdd_ctx, skb,
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302583 acs_chan_params.pcl_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302584 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
2585 vendor_pcl_list,
2586 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302587
2588 if (status != 0)
2589 goto fail;
2590
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302591 id = QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302592
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +05302593 status = hdd_cfg80211_update_channel_info(hdd_ctx, skb, sap_config, id);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302594 if (status != 0)
2595 goto fail;
2596
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302597 status = nla_put_u32(skb,
2598 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
2599 acs_policy);
2600
2601 if (status != 0)
2602 goto fail;
2603
Kapil Gupta8878ad92017-02-13 11:56:04 +05302604 cfg80211_vendor_event(skb, GFP_KERNEL);
Lin Baifac77972018-07-05 19:51:49 +08002605 qdf_mem_free(sap_config->channel_info);
2606
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302607 return 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302608fail:
Lin Baifac77972018-07-05 19:51:49 +08002609 qdf_mem_free(sap_config->channel_info);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302610 if (skb)
2611 kfree_skb(skb);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302612 return status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302613}
2614
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302615/**
2616 * hdd_create_acs_timer(): Initialize vendor ACS timer
2617 * @adapter: pointer to SAP adapter struct
2618 *
2619 * This function initializes the vendor ACS timer.
2620 *
2621 * Return: Status of create vendor ACS timer
2622 */
Jeff Johnsone5006672017-08-29 14:39:02 -07002623static int hdd_create_acs_timer(struct hdd_adapter *adapter)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302624{
2625 struct hdd_external_acs_timer_context *timer_context;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302626 QDF_STATUS status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302627
Jeff Johnsonb9424862017-10-30 08:49:35 -07002628 if (adapter->session.ap.vendor_acs_timer_initialized)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302629 return 0;
2630
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302631 hdd_debug("Starting vendor app based ACS");
Kapil Gupta8878ad92017-02-13 11:56:04 +05302632 timer_context = qdf_mem_malloc(sizeof(*timer_context));
Min Liu74a1a502018-10-10 19:59:07 +08002633 if (!timer_context)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302634 return -ENOMEM;
Min Liu74a1a502018-10-10 19:59:07 +08002635
Kapil Gupta8878ad92017-02-13 11:56:04 +05302636 timer_context->adapter = adapter;
2637
2638 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
Jeff Johnsonb9424862017-10-30 08:49:35 -07002639 status = qdf_mc_timer_init(&adapter->session.ap.vendor_acs_timer,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302640 QDF_TIMER_TYPE_SW,
2641 hdd_acs_response_timeout_handler, timer_context);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302642 if (status != QDF_STATUS_SUCCESS) {
2643 hdd_err("Failed to initialize acs response timeout timer");
2644 return -EFAULT;
2645 }
Jeff Johnsonb9424862017-10-30 08:49:35 -07002646 adapter->session.ap.vendor_acs_timer_initialized = true;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302647 return 0;
2648}
2649
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302650static const struct nla_policy
2651wlan_hdd_cfg80211_do_acs_policy[QCA_WLAN_VENDOR_ATTR_ACS_MAX+1] = {
2652 [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
2653 [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
2654 [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
2655 [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
2656 [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
2657 [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_UNSPEC },
2658 [QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_UNSPEC },
2659};
2660
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302661int hdd_start_vendor_acs(struct hdd_adapter *adapter)
2662{
2663 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2664 int status;
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002665 QDF_STATUS qdf_status;
2666 bool is_acs_support_for_dfs_ltecoex = cfg_default(CFG_USER_ACS_DFS_LTE);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302667
2668 status = hdd_create_acs_timer(adapter);
2669 if (status != 0) {
2670 hdd_err("failed to create acs timer");
2671 return status;
2672 }
2673 status = hdd_update_acs_timer_reason(adapter,
2674 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2675 if (status != 0) {
2676 hdd_err("failed to update acs timer reason");
2677 return status;
2678 }
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002679 qdf_status = ucfg_mlme_get_acs_support_for_dfs_ltecoex(
2680 hdd_ctx->psoc,
2681 &is_acs_support_for_dfs_ltecoex);
2682 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2683 hdd_err("get_acs_support_for_dfs_ltecoex failed, set def");
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302684
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002685 if (is_acs_support_for_dfs_ltecoex)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302686 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2687 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2688 true));
2689 else
2690 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2691 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2692 false));
2693
2694 return status;
2695}
2696
Kapil Gupta8878ad92017-02-13 11:56:04 +05302697/**
Ashish Kumar Dhanotiya2168aad2019-06-12 20:51:36 +05302698 * hdd_avoid_acs_channels() - Avoid acs channels
2699 * @hdd_ctx: Pointer to the hdd context
2700 * @sap_config: Sap config structure pointer
2701 *
2702 * This function avoids channels from the acs corresponding to
2703 * the frequencies configured in the ini sap_avoid_acs_freq_list
2704 *
2705 * Return: None
2706 */
2707
2708#ifdef SAP_AVOID_ACS_FREQ_LIST
2709static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
2710 struct sap_config *sap_config)
2711{
2712 int i, j, ch_cnt = 0;
2713 uint16_t avoid_acs_freq_list[CFG_VALID_CHANNEL_LIST_LEN];
2714 uint8_t avoid_acs_freq_list_num;
2715
Ashish Kumar Dhanotiya2168aad2019-06-12 20:51:36 +05302716 ucfg_mlme_get_acs_avoid_freq_list(hdd_ctx->psoc,
2717 avoid_acs_freq_list,
2718 &avoid_acs_freq_list_num);
2719
2720 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
2721 for (j = 0; j < avoid_acs_freq_list_num; j++) {
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302722 if (sap_config->acs_cfg.freq_list[i] ==
2723 avoid_acs_freq_list[j]) {
2724 hdd_debug("skip freq %d",
2725 sap_config->acs_cfg.freq_list[i]);
Ashish Kumar Dhanotiya2168aad2019-06-12 20:51:36 +05302726 break;
2727 }
2728 }
2729 if (j == avoid_acs_freq_list_num)
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302730 sap_config->acs_cfg.freq_list[ch_cnt++] =
2731 sap_config->acs_cfg.freq_list[i];
Ashish Kumar Dhanotiya2168aad2019-06-12 20:51:36 +05302732 }
2733 sap_config->acs_cfg.ch_list_count = ch_cnt;
2734}
2735#else
2736static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
2737 struct sap_config *sap_config)
2738{
2739}
2740#endif
2741
2742/**
Manikandan Mohan932c11e2019-08-14 14:09:08 -07002743 * wlan_hdd_trim_acs_channel_list() - Trims ACS channel list with
2744 * intersection of PCL
2745 * @pcl: preferred channel list
2746 * @pcl_count: Preferred channel list count
2747 * @org_ch_list: ACS channel list from user space
2748 * @org_ch_list_count: ACS channel count from user space
2749 *
2750 * Return: None
2751 */
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302752static void wlan_hdd_trim_acs_channel_list(uint32_t *pcl, uint8_t pcl_count,
2753 uint32_t *org_freq_list,
Manikandan Mohan932c11e2019-08-14 14:09:08 -07002754 uint8_t *org_ch_list_count)
2755{
2756 uint16_t i, j, ch_list_count = 0;
2757
2758 if (*org_ch_list_count >= QDF_MAX_NUM_CHAN) {
2759 hdd_err("org_ch_list_count too big %d",
2760 *org_ch_list_count);
2761 return;
2762 }
2763
2764 if (pcl_count >= QDF_MAX_NUM_CHAN) {
2765 hdd_err("pcl_count is too big %d", pcl_count);
2766 return;
2767 }
2768
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302769 hdd_debug("Update ACS chan freq with PCL");
Manikandan Mohan932c11e2019-08-14 14:09:08 -07002770 for (j = 0; j < *org_ch_list_count; j++)
2771 for (i = 0; i < pcl_count; i++)
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302772 if (pcl[i] == org_freq_list[j]) {
2773 org_freq_list[ch_list_count++] = pcl[i];
Manikandan Mohan932c11e2019-08-14 14:09:08 -07002774 break;
2775 }
2776
2777 *org_ch_list_count = ch_list_count;
2778}
2779
2780/**
Liangwei Donge0279e32020-01-15 16:05:32 +08002781 * wlan_hdd_handle_zero_acs_list() - Handle worst case of acs channel
2782 * trimmed to zero
2783 * @hdd_ctx: struct hdd_context
2784 * @org_ch_list: ACS channel list from user space
2785 * @org_ch_list_count: ACS channel count from user space
2786 *
2787 * When all chan in ACS freq list is filtered out
2788 * by wlan_hdd_trim_acs_channel_list, the hostapd start will fail.
2789 * This happens when PCL is PM_24G_SCC_CH_SBS_CH, and SAP acs range includes
2790 * 5G channel list. One example is STA active on 6Ghz chan. Hostapd
2791 * start SAP on 5G ACS range. The intersection of PCL and ACS range is zero.
2792 * Instead of ACS failure, this API selects one channel from ACS range
2793 * and report to Hostapd. When hostapd do start_ap, the driver will
2794 * force SCC to 6G or move SAP to 2G based on SAP's configuration.
2795 *
2796 * Return: None
2797 */
2798static void wlan_hdd_handle_zero_acs_list(struct hdd_context *hdd_ctx,
2799 uint32_t *acs_freq_list,
2800 uint8_t *acs_ch_list_count,
2801 uint32_t *org_freq_list,
2802 uint8_t org_ch_list_count)
2803{
2804 uint16_t i, sta_count;
2805 uint32_t acs_chan_default = 0;
2806
2807 if (!acs_ch_list_count || *acs_ch_list_count > 0 ||
2808 !acs_freq_list) {
2809 return;
2810 }
2811 if (!org_ch_list_count || !org_freq_list)
2812 return;
2813
2814 if (!policy_mgr_is_force_scc(hdd_ctx->psoc))
2815 return;
2816 sta_count = policy_mgr_mode_specific_connection_count
2817 (hdd_ctx->psoc, PM_STA_MODE, NULL);
2818 sta_count += policy_mgr_mode_specific_connection_count
2819 (hdd_ctx->psoc, PM_P2P_CLIENT_MODE, NULL);
2820 if (!sta_count)
2821 return;
2822
2823 for (i = 0; i < org_ch_list_count; i++) {
2824 if (!wlan_reg_is_dfs_for_freq(hdd_ctx->pdev,
2825 org_freq_list[i])) {
2826 acs_chan_default = org_freq_list[i];
2827 break;
2828 }
2829 }
2830 if (!acs_chan_default)
2831 acs_chan_default = org_freq_list[0];
2832
2833 acs_freq_list[0] = acs_chan_default;
2834 *acs_ch_list_count = 1;
2835 hdd_debug("retore acs chan list to single freq %d", acs_chan_default);
2836}
2837
2838/**
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302839 * __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002840 * @wiphy: Linux wiphy struct pointer
2841 * @wdev: Linux wireless device struct pointer
2842 * @data: ACS information from hostapd
2843 * @data_len: ACS information length
2844 *
2845 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2846 * and starts ACS procedure.
2847 *
2848 * Return: ACS procedure start status
2849 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002850static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2851 struct wireless_dev *wdev,
2852 const void *data, int data_len)
2853{
2854 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07002855 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002856 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07002857 struct sap_config *sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002858 struct sk_buff *temp_skbuff;
gaurank kathpalia924b2a72019-10-29 17:36:45 +05302859 int ret, i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002860 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
2861 bool ht_enabled, ht40_enabled, vht_enabled;
wadesong1795e142018-01-05 11:13:07 +08002862 uint8_t ch_width;
2863 enum qca_wlan_vendor_acs_hw_mode hw_mode;
Rachit Kankanedef2b172019-03-07 11:34:44 +05302864 enum policy_mgr_con_mode pm_mode;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302865 QDF_STATUS qdf_status;
gaurank kathpaliafa8b2e12019-11-20 12:30:38 +05302866 bool is_vendor_acs_support = false;
2867 bool is_external_acs_policy = false;
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302868 bool sap_force_11n_for_11ac = 0;
2869 bool go_force_11n_for_11ac = 0;
Sandeep Puligilla34618782019-01-04 17:42:42 -08002870 bool go_11ac_override = 0;
2871 bool sap_11ac_override = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002872
2873 /* ***Note*** Donot set SME config related to ACS operation here because
2874 * ACS operation is not synchronouse and ACS for Second AP may come when
2875 * ACS operation for first AP is going on. So only do_acs is split to
Jeff Johnsonfa7d9602018-05-06 11:25:31 -07002876 * separate start_acs routine. Also SME-PMAC struct that is used to
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002877 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
2878 * config shall be set only from start_acs.
2879 */
2880
Anurag Chouhan6d760662016-02-20 16:05:43 +05302881 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002882 hdd_err("Command not allowed in FTM mode");
2883 return -EPERM;
2884 }
2885
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302886 ret = wlan_hdd_validate_context(hdd_ctx);
2887 if (ret)
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302888 return ret;
2889
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302890 ucfg_mlme_get_sap_force_11n_for_11ac(hdd_ctx->psoc,
2891 &sap_force_11n_for_11ac);
2892 ucfg_mlme_get_go_force_11n_for_11ac(hdd_ctx->psoc,
2893 &go_force_11n_for_11ac);
2894
Hanumanth Reddy Pothula89b0dce2018-05-18 12:49:43 +05302895 if (!((adapter->device_mode == QDF_SAP_MODE) ||
2896 (adapter->device_mode == QDF_P2P_GO_MODE))) {
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302897 hdd_err("Invalid device mode %d", adapter->device_mode);
2898 return -EINVAL;
2899 }
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302900
Naveen Rawat64e477e2016-05-20 10:34:56 -07002901 if (cds_is_sub_20_mhz_enabled()) {
2902 hdd_err("ACS not supported in sub 20 MHz ch wd.");
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302903 return -EINVAL;
Naveen Rawat64e477e2016-05-20 10:34:56 -07002904 }
2905
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302906 if (qdf_atomic_read(&adapter->session.ap.acs_in_progress) > 0) {
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302907 hdd_err("ACS rejected as previous req already in progress");
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302908 return -EINVAL;
2909 } else {
2910 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 1);
gaurank kathpalia7aed85e2019-10-10 15:12:54 +05302911 qdf_event_reset(&adapter->acs_complete_event);
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302912 }
2913
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302914 ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
Dustin Brown4ea21db2018-01-05 14:13:17 -08002915 data_len,
2916 wlan_hdd_cfg80211_do_acs_policy);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302917 if (ret) {
Jeff Johnson020db452016-06-29 14:37:26 -07002918 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919 goto out;
2920 }
2921
2922 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002923 hdd_err("Attr hw_mode failed");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302924 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002925 goto out;
2926 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302927 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002928
Arun Kumar Khandavalliafcb0552020-01-20 11:46:36 +05302929 hdd_nofl_info("ACS request vid %d hw mode %d", adapter->vdev_id,
2930 hw_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002931 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
2932 ht_enabled =
2933 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2934 else
2935 ht_enabled = 0;
2936
2937 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2938 ht40_enabled =
2939 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2940 else
2941 ht40_enabled = 0;
2942
2943 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2944 vht_enabled =
2945 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2946 else
2947 vht_enabled = 0;
2948
Bala Venkateshb9cf3362017-11-09 15:48:46 +05302949 if (((adapter->device_mode == QDF_SAP_MODE) &&
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302950 sap_force_11n_for_11ac) ||
2951 ((adapter->device_mode == QDF_P2P_GO_MODE) &&
2952 go_force_11n_for_11ac)) {
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302953 vht_enabled = 0;
Dustin Brownbacc48f2018-03-14 14:48:44 -07002954 hdd_info("VHT is Disabled in ACS");
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302955 }
2956
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2958 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2959 } else {
2960 if (ht_enabled && ht40_enabled)
2961 ch_width = 40;
2962 else
2963 ch_width = 20;
2964 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302965
Bala Venkateshb9cf3362017-11-09 15:48:46 +05302966 /* this may be possible, when sap_force_11n_for_11ac or
2967 * go_force_11n_for_11ac is set
2968 */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302969 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2970 if (ht_enabled && ht40_enabled)
2971 ch_width = 40;
2972 else
2973 ch_width = 20;
2974 }
2975
Hanumanth Reddy Pothula560d5712018-03-15 18:11:27 +05302976 sap_config = &adapter->session.ap.sap_config;
2977
2978 /* Check and free if memory is already allocated for acs channel list */
2979 wlan_hdd_undo_acs(adapter);
2980
2981 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
2982
Himanshu Agarwal75e74412018-02-01 20:51:47 +05302983 if (ch_width == 160)
2984 sap_config->acs_cfg.ch_width = CH_WIDTH_160MHZ;
2985 else if (ch_width == 80)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002986 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2987 else if (ch_width == 40)
2988 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2989 else
2990 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2991
Rajeev Kumar Sirasanagandlaa57c6702019-11-01 18:41:41 +05302992 /* Firstly try to get channel frequencies */
2993 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002994 uint32_t *freq =
2995 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2996 sap_config->acs_cfg.ch_list_count = nla_len(
2997 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2998 sizeof(uint32_t);
2999 if (sap_config->acs_cfg.ch_list_count) {
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303000 sap_config->acs_cfg.freq_list = qdf_mem_malloc(
3001 sap_config->acs_cfg.ch_list_count *
3002 sizeof(uint32_t));
gaurank kathpaliaaa252b52019-10-30 15:29:04 +05303003 sap_config->acs_cfg.master_freq_list = qdf_mem_malloc(
3004 sap_config->acs_cfg.ch_list_count *
3005 sizeof(uint32_t));
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303006 if (!sap_config->acs_cfg.freq_list ||
gaurank kathpaliaaa252b52019-10-30 15:29:04 +05303007 !sap_config->acs_cfg.master_freq_list) {
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303008 ret = -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003009 goto out;
3010 }
3011
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303012 for (i = 0; i < sap_config->acs_cfg.ch_list_count;
3013 i++) {
gaurank kathpaliaaa252b52019-10-30 15:29:04 +05303014 sap_config->acs_cfg.master_freq_list[i] =
3015 freq[i];
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303016 sap_config->acs_cfg.freq_list[i] = freq[i];
3017 }
gaurank kathpalia7ca94ae2019-08-14 11:33:52 +05303018 sap_config->acs_cfg.master_ch_list_count =
3019 sap_config->acs_cfg.ch_list_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003020 }
Rajeev Kumar Sirasanagandlaa57c6702019-11-01 18:41:41 +05303021 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
3022 uint8_t *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
3023
3024 sap_config->acs_cfg.ch_list_count = nla_len(
3025 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
3026 if (sap_config->acs_cfg.ch_list_count) {
3027 sap_config->acs_cfg.freq_list = qdf_mem_malloc(
3028 sap_config->acs_cfg.ch_list_count *
3029 sizeof(uint32_t));
3030 sap_config->acs_cfg.master_freq_list = qdf_mem_malloc(
3031 sap_config->acs_cfg.ch_list_count *
3032 sizeof(uint32_t));
3033 if (!sap_config->acs_cfg.freq_list ||
3034 !sap_config->acs_cfg.master_freq_list) {
3035 ret = -ENOMEM;
3036 goto out;
3037 }
3038
3039 /* convert channel to frequency */
3040 for (i = 0; i < sap_config->acs_cfg.ch_list_count;
3041 i++) {
3042 sap_config->acs_cfg.freq_list[i] =
3043 wlan_reg_legacy_chan_to_freq(
3044 hdd_ctx->pdev,
3045 tmp[i]);
3046 sap_config->acs_cfg.master_freq_list[i] =
3047 sap_config->acs_cfg.freq_list[i];
3048 }
3049 sap_config->acs_cfg.master_ch_list_count =
3050 sap_config->acs_cfg.ch_list_count;
3051 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003052 }
3053
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303054 if (!sap_config->acs_cfg.ch_list_count) {
Amar Singhal5f783132018-03-29 13:58:50 -07003055 hdd_err("acs config chan count 0");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303056 ret = -EINVAL;
3057 goto out;
3058 }
3059
Ashish Kumar Dhanotiya2168aad2019-06-12 20:51:36 +05303060 hdd_avoid_acs_channels(hdd_ctx, sap_config);
3061
Rachit Kankanedef2b172019-03-07 11:34:44 +05303062 pm_mode =
3063 policy_mgr_convert_device_mode_to_qdf_type(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003064 /* consult policy manager to get PCL */
Rachit Kankanedef2b172019-03-07 11:34:44 +05303065 qdf_status = policy_mgr_get_pcl(hdd_ctx->psoc, pm_mode,
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303066 sap_config->acs_cfg.pcl_chan_freq,
Rachit Kankanedef2b172019-03-07 11:34:44 +05303067 &sap_config->acs_cfg.pcl_ch_count,
3068 sap_config->acs_cfg.
3069 pcl_channels_weight_list,
3070 QDF_MAX_NUM_CHAN);
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303071
Kapil Guptac1224bf2017-06-22 21:22:40 +05303072 sap_config->acs_cfg.band = hw_mode;
Rachit Kankanedef2b172019-03-07 11:34:44 +05303073
3074 qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
3075 &is_external_acs_policy);
3076 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
3077 hdd_err("get_external_acs_policy failed");
3078
gaurank kathpaliaaf483f52019-07-19 09:04:07 +05303079 sap_config->acs_cfg.acs_mode = true;
3080
Rachit Kankanedef2b172019-03-07 11:34:44 +05303081 if (is_external_acs_policy &&
3082 policy_mgr_is_force_scc(hdd_ctx->psoc) &&
3083 policy_mgr_get_connection_count(hdd_ctx->psoc)) {
Manikandan Mohan932c11e2019-08-14 14:09:08 -07003084 wlan_hdd_trim_acs_channel_list(
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303085 sap_config->acs_cfg.pcl_chan_freq,
Rachit Kankanedef2b172019-03-07 11:34:44 +05303086 sap_config->acs_cfg.pcl_ch_count,
gaurank kathpalia924b2a72019-10-29 17:36:45 +05303087 sap_config->acs_cfg.freq_list,
Rachit Kankanedef2b172019-03-07 11:34:44 +05303088 &sap_config->acs_cfg.ch_list_count);
Liangwei Donge0279e32020-01-15 16:05:32 +08003089 if (!sap_config->acs_cfg.ch_list_count &&
3090 sap_config->acs_cfg.master_ch_list_count)
3091 wlan_hdd_handle_zero_acs_list(
3092 hdd_ctx,
3093 sap_config->acs_cfg.freq_list,
3094 &sap_config->acs_cfg.ch_list_count,
3095 sap_config->acs_cfg.master_freq_list,
3096 sap_config->acs_cfg.master_ch_list_count);
Rachit Kankanedef2b172019-03-07 11:34:44 +05303097 /* if it is only one channel, send ACS event to upper layer */
3098 if (sap_config->acs_cfg.ch_list_count == 1) {
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303099 sap_config->acs_cfg.pri_ch_freq =
3100 sap_config->acs_cfg.freq_list[0];
Rachit Kankanedef2b172019-03-07 11:34:44 +05303101 wlan_sap_set_sap_ctx_acs_cfg(
3102 WLAN_HDD_GET_SAP_CTX_PTR(adapter), sap_config);
3103 sap_config_acs_result(hdd_ctx->mac_handle,
3104 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303105 sap_config->acs_cfg.ht_sec_ch_freq);
Rachit Kankanedef2b172019-03-07 11:34:44 +05303106 sap_config->ch_params.ch_width =
3107 sap_config->acs_cfg.ch_width;
3108 sap_config->ch_params.sec_ch_offset =
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303109 wlan_reg_freq_to_chan(hdd_ctx->pdev,
3110 sap_config->acs_cfg.ht_sec_ch_freq);
Rachit Kankanedef2b172019-03-07 11:34:44 +05303111 sap_config->ch_params.center_freq_seg0 =
Liangwei Dong0e18c472019-11-08 17:59:09 +08003112 wlan_reg_freq_to_chan(
3113 hdd_ctx->pdev,
3114 sap_config->acs_cfg.vht_seg0_center_ch_freq);
Rachit Kankanedef2b172019-03-07 11:34:44 +05303115 sap_config->ch_params.center_freq_seg1 =
Liangwei Dong0e18c472019-11-08 17:59:09 +08003116 wlan_reg_freq_to_chan(
3117 hdd_ctx->pdev,
3118 sap_config->acs_cfg.vht_seg1_center_ch_freq);
3119 sap_config->ch_params.mhz_freq_seg0 =
3120 sap_config->acs_cfg.vht_seg0_center_ch_freq;
3121 sap_config->ch_params.mhz_freq_seg1 =
3122 sap_config->acs_cfg.vht_seg1_center_ch_freq;
Rachit Kankanedef2b172019-03-07 11:34:44 +05303123 /*notify hostapd about channel override */
3124 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
3125 ret = 0;
3126 goto out;
3127 }
3128 }
3129
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303130 ret = wlan_hdd_set_acs_ch_range(sap_config, hw_mode,
gaurank kathpaliaaa252b52019-10-30 15:29:04 +05303131 ht_enabled, vht_enabled);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303132 if (ret) {
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05303133 hdd_err("set acs channel range failed");
3134 goto out;
3135 }
3136
Sandeep Puligilla34618782019-01-04 17:42:42 -08003137 ucfg_mlme_is_go_11ac_override(hdd_ctx->psoc, &go_11ac_override);
3138 ucfg_mlme_is_sap_11ac_override(hdd_ctx->psoc, &sap_11ac_override);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05303139 /* ACS override for android */
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05303140 if (ht_enabled &&
Liangwei Dong50d12dc2019-11-06 14:19:46 +08003141 sap_config->acs_cfg.end_ch_freq >=
3142 WLAN_REG_CH_TO_FREQ(CHAN_ENUM_5180) &&
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05303143 ((adapter->device_mode == QDF_SAP_MODE &&
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05303144 !sap_force_11n_for_11ac &&
Sandeep Puligilla34618782019-01-04 17:42:42 -08003145 sap_11ac_override) ||
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05303146 (adapter->device_mode == QDF_P2P_GO_MODE &&
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05303147 !go_force_11n_for_11ac &&
Sandeep Puligilla34618782019-01-04 17:42:42 -08003148 go_11ac_override))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003149 vht_enabled = 1;
3150 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05303151 qdf_status =
3152 ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
3153 &ch_width);
3154 sap_config->acs_cfg.ch_width = ch_width;
Himanshu Agarwal29a9a3e2018-02-21 17:44:37 +05303155 }
3156
3157 /* No VHT80 in 2.4G so perform ACS accordingly */
Liangwei Dong50d12dc2019-11-06 14:19:46 +08003158 if (sap_config->acs_cfg.end_ch_freq <=
3159 WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484) &&
Himanshu Agarwal29a9a3e2018-02-21 17:44:37 +05303160 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
3161 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
3162 hdd_debug("resetting to 40Mhz in 2.4Ghz");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163 }
3164
gaurank kathpaliaac1feea2020-02-03 16:37:23 +05303165 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",
3166 hdd_ctx->reg.alpha2, ch_width,
3167 sap_config->acs_cfg.hw_mode, sap_config->acs_cfg.ch_width,
3168 ht_enabled, vht_enabled, sap_config->acs_cfg.start_ch_freq,
3169 sap_config->acs_cfg.end_ch_freq,
3170 sap_config->acs_cfg.band);
wadesongcb0ded22018-02-02 17:57:20 +08003171 host_log_acs_req_event(adapter->dev->name,
3172 csr_phy_mode_str(sap_config->acs_cfg.hw_mode),
3173 ch_width, ht_enabled, vht_enabled,
Liangwei Dong50d12dc2019-11-06 14:19:46 +08003174 sap_config->acs_cfg.start_ch_freq,
3175 sap_config->acs_cfg.end_ch_freq);
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07003176
Kapil Gupta8878ad92017-02-13 11:56:04 +05303177 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
3178 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
3179
gaurank kathpalia00d7c342020-02-18 11:40:51 +05303180 sap_dump_acs_channel(&sap_config->acs_cfg);
Himanshu Agarwal33163982018-05-17 18:11:10 +05303181
gaurank kathpaliafa8b2e12019-11-20 12:30:38 +05303182 qdf_status = ucfg_mlme_get_vendor_acs_support(hdd_ctx->psoc,
3183 &is_vendor_acs_support);
3184 if (QDF_IS_STATUS_ERROR(qdf_status))
3185 hdd_err("get_vendor_acs_support failed, set default");
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07003186
gaurank kathpaliafa8b2e12019-11-20 12:30:38 +05303187 /* Check if vendor specific acs is enabled */
3188 if (is_vendor_acs_support)
3189 ret = hdd_start_vendor_acs(adapter);
3190 else
3191 ret = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192
3193out:
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303194 if (ret == 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003195 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3196 NLMSG_HDRLEN);
Jeff Johnsond36fa332019-03-18 13:42:25 -07003197 if (temp_skbuff)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198 return cfg80211_vendor_cmd_reply(temp_skbuff);
3199 }
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05303200 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003201
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05303202 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203}
3204
Jeff Johnsonf3826e12017-01-12 09:49:40 -08003205/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
3207 * @wiphy: Linux wiphy struct pointer
3208 * @wdev: Linux wireless device struct pointer
3209 * @data: ACS information from hostapd
3210 * @data_len: ACS information len
3211 *
3212 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
3213 * and starts ACS procedure.
3214 *
3215 * Return: ACS procedure start status
3216 */
3217
3218static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
3219 struct wireless_dev *wdev,
3220 const void *data, int data_len)
3221{
Dustin Browna09acf42018-11-08 12:32:26 +05303222 int errno;
3223 struct osif_vdev_sync *vdev_sync;
3224
3225 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
3226 if (errno)
3227 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003228
Dustin Browna09acf42018-11-08 12:32:26 +05303229 errno = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003230
Dustin Browna09acf42018-11-08 12:32:26 +05303231 osif_vdev_sync_op_stop(vdev_sync);
3232
3233 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234}
3235
3236/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003237 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
3238 * @adapter: Pointer to adapter struct
3239 *
3240 * This function handle cleanup of what was done in DO_ACS, including free
3241 * memory.
3242 *
3243 * Return: void
3244 */
Jeff Johnsone5006672017-08-29 14:39:02 -07003245void wlan_hdd_undo_acs(struct hdd_adapter *adapter)
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003246{
gaurank kathpalia081c66c2019-09-19 14:44:35 +05303247 sap_undo_acs(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
3248 &adapter->session.ap.sap_config);
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003249}
3250
3251/**
Rajeev Kumar Sirasanagandlaa57c6702019-11-01 18:41:41 +05303252 * hdd_fill_acs_chan_freq() - Populate channel frequencies (MHz) selected in ACS
3253 * @hdd_ctx: pointer to hdd context
3254 * @sap_cfg: sap acs configuration
3255 * @vendor_event: output pointer to populate channel frequencies (MHz)
3256 *
3257 * Return: If populated successfully return 0 else negative value.
3258 */
3259static int hdd_fill_acs_chan_freq(struct hdd_context *hdd_ctx,
3260 struct sap_config *sap_cfg,
3261 struct sk_buff *vendor_event)
3262{
3263 uint32_t id;
3264 int errno;
3265
3266 id = QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY;
3267 errno = nla_put_u32(vendor_event, id, sap_cfg->acs_cfg.pri_ch_freq);
3268 if (errno) {
3269 hdd_err("VENDOR_ATTR_ACS_PRIMARY_FREQUENCY put fail");
3270 return errno;
3271 }
3272
3273 id = QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY;
3274 errno = nla_put_u32(vendor_event, id, sap_cfg->acs_cfg.ht_sec_ch_freq);
3275 if (errno) {
3276 hdd_err("VENDOR_ATTR_ACS_SECONDARY_FREQUENCY put fail");
3277 return errno;
3278 }
3279
3280 id = QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY;
3281 errno = nla_put_u32(vendor_event, id,
3282 sap_cfg->acs_cfg.vht_seg0_center_ch_freq);
3283 if (errno) {
3284 hdd_err("VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY put fail");
3285 return errno;
3286 }
3287
3288 id = QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY;
3289 errno = nla_put_u32(vendor_event, id,
3290 sap_cfg->acs_cfg.vht_seg1_center_ch_freq);
3291 if (errno) {
3292 hdd_err("VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY put fail");
3293 return errno;
3294 }
3295
3296 return 0;
3297}
3298
3299static int hdd_get_acs_evt_data_len(void)
3300{
3301 uint32_t len = NLMSG_HDRLEN;
3302
3303 /* QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL */
3304 len += nla_total_size(sizeof(u8));
3305
3306 /* QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL */
3307 len += nla_total_size(sizeof(u8));
3308
3309 /* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL */
3310 len += nla_total_size(sizeof(u8));
3311
3312 /* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL */
3313 len += nla_total_size(sizeof(u8));
3314
3315 /* QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY */
3316 len += nla_total_size(sizeof(u32));
3317
3318 /* QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY */
3319 len += nla_total_size(sizeof(u32));
3320
3321 /* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY */
3322 len += nla_total_size(sizeof(u32));
3323
3324 /* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY */
3325 len += nla_total_size(sizeof(u32));
3326
3327 /* QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH */
3328 len += nla_total_size(sizeof(u16));
3329
3330 /* QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE */
3331 len += nla_total_size(sizeof(u8));
3332
3333 return len;
3334}
3335
3336/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003337 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
3338 * @adapter: Pointer to SAP adapter struct
3339 * @pri_channel: SAP ACS procedure selected Primary channel
3340 * @sec_channel: SAP ACS procedure selected secondary channel
3341 *
3342 * This is a callback function from SAP module on ACS procedure is completed.
3343 * This function send the ACS selected channel information to hostapd
3344 *
3345 * Return: None
3346 */
Jeff Johnsone5006672017-08-29 14:39:02 -07003347void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003348{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003349 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson8f8ceb92019-03-24 08:16:55 -07003350 struct sap_config *sap_cfg =
3351 &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003352 struct sk_buff *vendor_event;
3353 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003354 uint16_t ch_width;
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303355 uint8_t pri_channel;
3356 uint8_t ht_sec_channel;
Liangwei Dong0e18c472019-11-08 17:59:09 +08003357 uint8_t vht_seg0_center_ch, vht_seg1_center_ch;
Rajeev Kumar Sirasanagandlaa57c6702019-11-01 18:41:41 +05303358 uint32_t id = QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX;
3359 uint32_t len = hdd_get_acs_evt_data_len();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003360
gaurank kathpalia11aa98c2019-12-09 17:56:08 +05303361 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 0);
3362 qdf_event_set(&adapter->acs_complete_event);
3363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003364 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Rajeev Kumar Sirasanagandlaa57c6702019-11-01 18:41:41 +05303365 &adapter->wdev, len, id,
3366 GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003367
3368 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003369 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003370 return;
3371 }
3372
Rajeev Kumar Sirasanagandlaa57c6702019-11-01 18:41:41 +05303373 ret_val = hdd_fill_acs_chan_freq(hdd_ctx, sap_cfg, vendor_event);
3374 if (ret_val) {
3375 hdd_err("failed to put frequencies");
3376 kfree_skb(vendor_event);
3377 return;
3378 }
3379
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303380 pri_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev,
3381 sap_cfg->acs_cfg.pri_ch_freq);
3382
3383 ht_sec_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev,
3384 sap_cfg->acs_cfg.ht_sec_ch_freq);
3385
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003386 ret_val = nla_put_u8(vendor_event,
3387 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303388 pri_channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003389 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003390 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003391 kfree_skb(vendor_event);
3392 return;
3393 }
3394
3395 ret_val = nla_put_u8(vendor_event,
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303396 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
3397 ht_sec_channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003398 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003399 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003400 kfree_skb(vendor_event);
3401 return;
3402 }
Liangwei Dong0e18c472019-11-08 17:59:09 +08003403 vht_seg0_center_ch = wlan_reg_freq_to_chan(
3404 hdd_ctx->pdev,
3405 sap_cfg->acs_cfg.vht_seg0_center_ch_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003406 ret_val = nla_put_u8(vendor_event,
3407 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
Liangwei Dong0e18c472019-11-08 17:59:09 +08003408 vht_seg0_center_ch);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003409 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003410 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003411 kfree_skb(vendor_event);
3412 return;
3413 }
Liangwei Dong0e18c472019-11-08 17:59:09 +08003414 vht_seg1_center_ch = wlan_reg_freq_to_chan(
3415 hdd_ctx->pdev,
3416 sap_cfg->acs_cfg.vht_seg1_center_ch_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003417 ret_val = nla_put_u8(vendor_event,
3418 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
Liangwei Dong0e18c472019-11-08 17:59:09 +08003419 vht_seg1_center_ch);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003420 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003421 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003422 kfree_skb(vendor_event);
3423 return;
3424 }
3425
Himanshu Agarwal75e74412018-02-01 20:51:47 +05303426 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_160MHZ)
3427 ch_width = 160;
3428 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003429 ch_width = 80;
3430 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
3431 ch_width = 40;
3432 else
3433 ch_width = 20;
3434
3435 ret_val = nla_put_u16(vendor_event,
3436 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
3437 ch_width);
3438 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003439 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003440 kfree_skb(vendor_event);
3441 return;
3442 }
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303443 if (WLAN_REG_IS_24GHZ_CH_FREQ(sap_cfg->acs_cfg.pri_ch_freq))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003444 ret_val = nla_put_u8(vendor_event,
3445 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
3446 QCA_ACS_MODE_IEEE80211G);
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303447 else
3448 ret_val = nla_put_u8(vendor_event,
3449 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
3450 QCA_ACS_MODE_IEEE80211A);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003451
3452 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003453 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003454 kfree_skb(vendor_event);
3455 return;
3456 }
3457
gaurank kathpalia92b81ce2019-10-30 17:21:48 +05303458 hdd_debug("ACS result for %s: PRI_CH_FREQ: %d SEC_CH_FREQ: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
3459 adapter->dev->name, sap_cfg->acs_cfg.pri_ch_freq,
3460 sap_cfg->acs_cfg.ht_sec_ch_freq,
Liangwei Dong0e18c472019-11-08 17:59:09 +08003461 sap_cfg->acs_cfg.vht_seg0_center_ch_freq,
3462 sap_cfg->acs_cfg.vht_seg1_center_ch_freq, ch_width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003463
3464 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003465}
3466
Sourav Mohapatrac457ae62018-12-06 15:19:41 +05303467/**
3468 * hdd_is_wlm_latency_manager_supported - Checks if WLM Latency manager is
3469 * supported
3470 * @hdd_ctx: The HDD context
3471 *
3472 * Return: True if supported, false otherwise
3473 */
3474static inline
3475bool hdd_is_wlm_latency_manager_supported(struct hdd_context *hdd_ctx)
3476{
3477 bool latency_enable;
3478
3479 if (QDF_IS_STATUS_ERROR(ucfg_mlme_get_latency_enable
3480 (hdd_ctx->psoc, &latency_enable)))
3481 return false;
3482
3483 if (latency_enable &&
3484 sme_is_feature_supported_by_fw(VDEV_LATENCY_CONFIG))
3485 return true;
3486 else
3487 return false;
3488}
3489
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003490static int
3491__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
3492 struct wireless_dev *wdev,
3493 const void *data,
3494 int data_len)
3495{
Jeff Johnsonb8944722017-09-03 09:03:19 -07003496 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003497 struct sk_buff *skb = NULL;
3498 uint32_t fset = 0;
3499 int ret;
Wu Gaobdb7f272018-07-05 19:33:26 +08003500#ifdef FEATURE_WLAN_TDLS
3501 bool bvalue;
3502#endif
Sourav Mohapatrafab026a2019-11-20 14:22:28 +05303503 uint32_t fine_time_meas_cap;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003504
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07003505 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303506
Anurag Chouhan6d760662016-02-20 16:05:43 +05303507 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003508 hdd_err("Command not allowed in FTM mode");
3509 return -EPERM;
3510 }
3511
Jeff Johnsonb8944722017-09-03 09:03:19 -07003512 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303513 if (ret)
3514 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003515
3516 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003517 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003518 fset |= WIFI_FEATURE_INFRA;
3519 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07003520 if (true == hdd_is_5g_supported(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003521 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003522 fset |= WIFI_FEATURE_INFRA_5G;
3523 }
3524#ifdef WLAN_FEATURE_P2P
3525 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
3526 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003527 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003528 fset |= WIFI_FEATURE_P2P;
3529 }
3530#endif
3531 fset |= WIFI_FEATURE_SOFT_AP;
3532
3533 /* HOTSPOT is a supplicant feature, enable it by default */
3534 fset |= WIFI_FEATURE_HOTSPOT;
3535
Dustin Brown76cd2932018-09-11 16:03:05 -07003536 if (ucfg_extscan_get_enable(hdd_ctx->psoc) &&
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303537 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003538 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003539 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
3540 }
Nachiket Kukade989bb352018-07-31 18:01:17 +05303541 if (wlan_hdd_nan_is_supported(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003542 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003543 fset |= WIFI_FEATURE_NAN;
3544 }
Sourav Mohapatrafab026a2019-11-20 14:22:28 +05303545
3546 ucfg_mlme_get_fine_time_meas_cap(hdd_ctx->psoc, &fine_time_meas_cap);
3547
Sourav Mohapatra9e014cf2018-12-11 09:39:33 +05303548 if (sme_is_feature_supported_by_fw(RTT) &&
Sourav Mohapatrafab026a2019-11-20 14:22:28 +05303549 rtt_is_enabled(fine_time_meas_cap)) {
3550 hdd_debug("RTT is supported by firmware and driver: %x",
3551 fine_time_meas_cap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003552 fset |= WIFI_FEATURE_D2D_RTT;
3553 fset |= WIFI_FEATURE_D2AP_RTT;
3554 }
3555#ifdef FEATURE_WLAN_SCAN_PNO
Pragaspathi Thilagaraj24789d32018-12-10 22:28:03 +05303556 if (ucfg_scan_get_pno_scan_support(hdd_ctx->psoc) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003557 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003558 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003559 fset |= WIFI_FEATURE_PNO;
3560 }
3561#endif
3562 fset |= WIFI_FEATURE_ADDITIONAL_STA;
3563#ifdef FEATURE_WLAN_TDLS
Dustin Brown76cd2932018-09-11 16:03:05 -07003564 cfg_tdls_get_support_enable(hdd_ctx->psoc, &bvalue);
Wu Gaobdb7f272018-07-05 19:33:26 +08003565 if ((bvalue) && sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003566 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003567 fset |= WIFI_FEATURE_TDLS;
3568 }
Wu Gaobdb7f272018-07-05 19:33:26 +08003569
Dustin Brown76cd2932018-09-11 16:03:05 -07003570 cfg_tdls_get_off_channel_enable(hdd_ctx->psoc, &bvalue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003571 if (sme_is_feature_supported_by_fw(TDLS) &&
Wu Gaobdb7f272018-07-05 19:33:26 +08003572 bvalue && sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003573 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003574 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
3575 }
3576#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003577 fset |= WIFI_FEATURE_AP_STA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003578 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07003579 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Srinivas Girigowda5a1da622017-07-12 17:07:44 -07003580 fset |= WIFI_FEATURE_SET_TX_POWER_LIMIT;
Sourav Mohapatra804359e2017-12-07 13:52:05 +05303581 fset |= WIFI_FEATURE_CONFIG_NDO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003582
3583 if (hdd_link_layer_stats_supported())
3584 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
3585
Jeff Johnsonb8944722017-09-03 09:03:19 -07003586 if (hdd_roaming_supported(hdd_ctx))
Srinivas Girigowda8df27ea2017-01-06 12:42:16 -08003587 fset |= WIFI_FEATURE_CONTROL_ROAMING;
3588
3589 if (hdd_scan_random_mac_addr_supported())
3590 fset |= WIFI_FEATURE_SCAN_RAND;
3591
Sourav Mohapatrac457ae62018-12-06 15:19:41 +05303592 if (hdd_is_wlm_latency_manager_supported(hdd_ctx))
3593 fset |= WIFI_FEATURE_SET_LATENCY_MODE;
3594
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003595 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
3596 NLMSG_HDRLEN);
3597 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003598 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003599 return -EINVAL;
3600 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003601 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003602 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003603 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003604 goto nla_put_failure;
3605 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303606 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303607 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003608nla_put_failure:
3609 kfree_skb(skb);
3610 return -EINVAL;
3611}
3612
3613/**
3614 * wlan_hdd_cfg80211_get_supported_features() - get supported features
3615 * @wiphy: pointer to wireless wiphy structure.
3616 * @wdev: pointer to wireless_dev structure.
3617 * @data: Pointer to the data to be passed via vendor interface
3618 * @data_len:Length of the data to be passed
3619 *
3620 * Return: Return the Success or Failure code.
3621 */
3622static int
3623wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
3624 struct wireless_dev *wdev,
3625 const void *data, int data_len)
3626{
Dustin Brown363b4792019-02-05 16:11:55 -08003627 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08003628 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303629
Dustin Brown363b4792019-02-05 16:11:55 -08003630 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08003631 if (errno)
3632 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003633
Dustin Brownf0f00612019-01-31 16:02:24 -08003634 errno = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
3635 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003636
Dustin Brown363b4792019-02-05 16:11:55 -08003637 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303638
Dustin Brownf0f00612019-01-31 16:02:24 -08003639 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003640}
3641
3642/**
3643 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3644 * @wiphy: pointer to wireless wiphy structure.
3645 * @wdev: pointer to wireless_dev structure.
3646 * @data: Pointer to the data to be passed via vendor interface
3647 * @data_len:Length of the data to be passed
3648 *
3649 * Set the MAC address that is to be used for scanning.
3650 *
3651 * Return: Return the Success or Failure code.
3652 */
3653static int
3654__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3655 struct wireless_dev *wdev,
3656 const void *data,
3657 int data_len)
3658{
Jeff Johnson9d45f332019-01-29 08:42:00 -08003659 struct scan_mac_oui scan_mac_oui = { {0} };
Jeff Johnsonb8944722017-09-03 09:03:19 -07003660 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003661 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303662 QDF_STATUS status;
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +05303663 int ret, len;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303664 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07003665 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003666 mac_handle_t mac_handle;
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +05303667 bool mac_spoofing_enabled;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003668
Dustin Brownfdf17c12018-03-14 12:55:34 -07003669 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003670
Anurag Chouhan6d760662016-02-20 16:05:43 +05303671 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003672 hdd_err("Command not allowed in FTM mode");
3673 return -EPERM;
3674 }
3675
Jeff Johnsonb8944722017-09-03 09:03:19 -07003676 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303677 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003678 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003679
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +05303680 mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
3681 if (!mac_spoofing_enabled) {
Dustin Browna7bb6ae2018-08-16 16:51:50 -07003682 hdd_debug("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003683 return -ENOTSUPP;
3684 }
3685
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003686 /*
3687 * audit note: it is ok to pass a NULL policy here since only
3688 * one attribute is parsed and it is explicitly validated
3689 */
Dustin Brown4ea21db2018-01-05 14:13:17 -08003690 if (wlan_cfg80211_nla_parse(tb,
3691 QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
3692 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003693 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003694 return -EINVAL;
3695 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003696
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003697 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003698 hdd_err("attr mac oui failed");
Jeff Johnson9d45f332019-01-29 08:42:00 -08003699 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003700 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003701
3702 len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]);
Jeff Johnson9d45f332019-01-29 08:42:00 -08003703 if (len != sizeof(scan_mac_oui.oui)) {
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003704 hdd_err("attr mac oui invalid size %d expected %zu",
Jeff Johnson9d45f332019-01-29 08:42:00 -08003705 len, sizeof(scan_mac_oui.oui));
3706 return -EINVAL;
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003707 }
3708
Jeff Johnson9d45f332019-01-29 08:42:00 -08003709 nla_memcpy(scan_mac_oui.oui,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003710 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
Jeff Johnson9d45f332019-01-29 08:42:00 -08003711 sizeof(scan_mac_oui.oui));
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303712
Jeff Johnson9d45f332019-01-29 08:42:00 -08003713 /* populate rest of scan_mac_oui for mac addr randomization */
Jeff Johnsoncf07c312019-02-04 13:53:29 -08003714 scan_mac_oui.vdev_id = adapter->vdev_id;
Jeff Johnson9d45f332019-01-29 08:42:00 -08003715 scan_mac_oui.enb_probe_req_sno_randomization = true;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303716
Jeff Johnson9d45f332019-01-29 08:42:00 -08003717 hdd_debug("Oui (%02x:%02x:%02x), vdev_id = %d",
3718 scan_mac_oui.oui[0], scan_mac_oui.oui[1],
3719 scan_mac_oui.oui[2], scan_mac_oui.vdev_id);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303720
Jeff Johnson9d45f332019-01-29 08:42:00 -08003721 hdd_update_ie_whitelist_attr(&scan_mac_oui.ie_whitelist, hdd_ctx);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303722
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003723 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson9d45f332019-01-29 08:42:00 -08003724 status = sme_set_scanning_mac_oui(mac_handle, &scan_mac_oui);
3725 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson020db452016-06-29 14:37:26 -07003726 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Jeff Johnson9d45f332019-01-29 08:42:00 -08003727
3728 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003729}
3730
3731/**
3732 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3733 * @wiphy: pointer to wireless wiphy structure.
3734 * @wdev: pointer to wireless_dev structure.
3735 * @data: Pointer to the data to be passed via vendor interface
3736 * @data_len:Length of the data to be passed
3737 *
3738 * Set the MAC address that is to be used for scanning. This is an
3739 * SSR-protecting wrapper function.
3740 *
3741 * Return: Return the Success or Failure code.
3742 */
3743static int
3744wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3745 struct wireless_dev *wdev,
3746 const void *data,
3747 int data_len)
3748{
Dustin Browna09acf42018-11-08 12:32:26 +05303749 int errno;
3750 struct osif_vdev_sync *vdev_sync;
3751
3752 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
3753 if (errno)
3754 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003755
Dustin Browna09acf42018-11-08 12:32:26 +05303756 errno = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
3757 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003758
Dustin Browna09acf42018-11-08 12:32:26 +05303759 osif_vdev_sync_op_stop(vdev_sync);
3760
3761 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003762}
3763
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303764/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003765 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
3766 * @feature_flags: pointer to the byte array of features.
3767 * @feature: Feature to be turned ON in the byte array.
3768 *
3769 * Return: None
3770 *
3771 * This is called to turn ON or SET the feature flag for the requested feature.
3772 **/
3773#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07003774static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
3775 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003776{
3777 uint32_t index;
3778 uint8_t bit_mask;
3779
3780 index = feature / NUM_BITS_IN_BYTE;
3781 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
3782 feature_flags[index] |= bit_mask;
3783}
3784
3785/**
3786 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
3787 * @wiphy: pointer to wireless wiphy structure.
3788 * @wdev: pointer to wireless_dev structure.
3789 * @data: Pointer to the data to be passed via vendor interface
3790 * @data_len:Length of the data to be passed
3791 *
3792 * This is called when wlan driver needs to send supported feature set to
3793 * supplicant upon a request/query from the supplicant.
3794 *
3795 * Return: Return the Success or Failure code.
3796 **/
3797#define MAX_CONCURRENT_CHAN_ON_24G 2
3798#define MAX_CONCURRENT_CHAN_ON_5G 2
3799static int
3800__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3801 struct wireless_dev *wdev,
3802 const void *data, int data_len)
3803{
3804 struct sk_buff *skb = NULL;
3805 uint32_t dbs_capability = 0;
3806 bool one_by_one_dbs, two_by_two_dbs;
Ashish Kumar Dhanotiya12de5332019-03-27 14:45:27 +05303807 bool value, twt_req, twt_res;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303808 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303809 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003810 int ret_val;
3811
3812 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003813 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003814
Dustin Brownfdf17c12018-03-14 12:55:34 -07003815 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08003816
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003817 ret_val = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003818 if (ret_val)
3819 return ret_val;
3820
Anurag Chouhan6d760662016-02-20 16:05:43 +05303821 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003822 hdd_err("Command not allowed in FTM mode");
3823 return -EPERM;
3824 }
3825
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003826 if (roaming_offload_enabled(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003827 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003828 wlan_hdd_cfg80211_set_feature(feature_flags,
3829 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
3830 }
3831
3832 wlan_hdd_cfg80211_set_feature(feature_flags,
3833 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Dustin Brown76cd2932018-09-11 16:03:05 -07003834 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx->psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003835 wlan_hdd_cfg80211_set_feature(feature_flags,
3836 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07003837
3838 if (wma_is_p2p_lo_capable())
3839 wlan_hdd_cfg80211_set_feature(feature_flags,
3840 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
3841
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303842 value = 0;
Dustin Brown05d81302018-09-11 16:49:22 -07003843 status = ucfg_mlme_get_oce_sta_enabled_info(hdd_ctx->psoc, &value);
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303844 if (QDF_IS_STATUS_ERROR(status))
3845 hdd_err("could not get OCE STA enable info");
3846 if (value)
yeshwanth sriram guntuka1413dfb2017-06-23 14:09:48 +05303847 wlan_hdd_cfg80211_set_feature(feature_flags,
3848 QCA_WLAN_VENDOR_FEATURE_OCE_STA);
3849
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303850 value = 0;
Dustin Brown05d81302018-09-11 16:49:22 -07003851 status = ucfg_mlme_get_oce_sap_enabled_info(hdd_ctx->psoc, &value);
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303852 if (QDF_IS_STATUS_ERROR(status))
3853 hdd_err("could not get OCE SAP enable info");
3854 if (value)
yeshwanth sriram guntuka1413dfb2017-06-23 14:09:48 +05303855 wlan_hdd_cfg80211_set_feature(feature_flags,
3856 QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON);
3857
Ashish Kumar Dhanotiya12de5332019-03-27 14:45:27 +05303858 ucfg_mlme_get_twt_requestor(hdd_ctx->psoc, &twt_req);
3859 ucfg_mlme_get_twt_responder(hdd_ctx->psoc, &twt_res);
3860
3861 if (twt_req || twt_res)
3862 wlan_hdd_cfg80211_set_feature(feature_flags,
3863 QCA_WLAN_VENDOR_FEATURE_TWT);
3864
Kiran Kumar Lokere0508af92018-04-23 18:38:32 -07003865 /* Check the kernel version for upstream commit aced43ce780dc5 that
3866 * has support for processing user cell_base hints when wiphy is
3867 * self managed or check the backport flag for the same.
3868 */
3869#if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
3870 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
3871 wlan_hdd_cfg80211_set_feature(feature_flags,
3872 QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY);
3873#endif
Pankaj Singh50e40422020-01-09 15:29:35 +05303874
3875 if (wlan_hdd_thermal_config_support())
3876 wlan_hdd_cfg80211_set_feature(feature_flags,
3877 QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG);
3878
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003879 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
3880 NLMSG_HDRLEN);
3881
3882 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003883 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003884 return -ENOMEM;
3885 }
3886
3887 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
3888 sizeof(feature_flags), feature_flags))
3889 goto nla_put_failure;
3890
Dustin Brown76cd2932018-09-11 16:03:05 -07003891 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx->psoc,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003892 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303893 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003894 if (one_by_one_dbs)
3895 dbs_capability = DRV_DBS_CAPABILITY_1X1;
3896
3897 if (two_by_two_dbs)
3898 dbs_capability = DRV_DBS_CAPABILITY_2X2;
3899
3900 if (!one_by_one_dbs && !two_by_two_dbs)
3901 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
3902 } else {
3903 hdd_err("wma_get_dbs_hw_mode failed");
3904 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
3905 }
3906
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003907 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003908
3909 if (nla_put_u32(skb,
Ganesh Kondabattinid921ed92017-06-20 16:40:48 +05303910 QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA,
3911 dbs_capability))
3912 goto nla_put_failure;
3913
3914
3915 if (nla_put_u32(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003916 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
3917 MAX_CONCURRENT_CHAN_ON_24G))
3918 goto nla_put_failure;
3919
3920 if (nla_put_u32(skb,
3921 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
3922 MAX_CONCURRENT_CHAN_ON_5G))
3923 goto nla_put_failure;
3924
3925 return cfg80211_vendor_cmd_reply(skb);
3926
3927nla_put_failure:
3928 kfree_skb(skb);
3929 return -EINVAL;
3930}
3931
3932/**
3933 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
3934 * @wiphy: pointer to wireless wiphy structure.
3935 * @wdev: pointer to wireless_dev structure.
3936 * @data: Pointer to the data to be passed via vendor interface
3937 * @data_len:Length of the data to be passed
3938 *
3939 * This is called when wlan driver needs to send supported feature set to
3940 * supplicant upon a request/query from the supplicant.
3941 *
3942 * Return: Return the Success or Failure code.
3943 */
3944static int
3945wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3946 struct wireless_dev *wdev,
3947 const void *data, int data_len)
3948{
Dustin Brown363b4792019-02-05 16:11:55 -08003949 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08003950 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303951
Dustin Brown363b4792019-02-05 16:11:55 -08003952 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08003953 if (errno)
3954 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003955
Dustin Brownf0f00612019-01-31 16:02:24 -08003956 errno = __wlan_hdd_cfg80211_get_features(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003957
Dustin Brown363b4792019-02-05 16:11:55 -08003958 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303959
Dustin Brownf0f00612019-01-31 16:02:24 -08003960 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003961}
3962
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303963#define PARAM_NUM_NW \
3964 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
3965#define PARAM_SET_BSSID \
3966 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05303967#define PARAM_SET_BSSID_HINT \
3968 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003969#define PARAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303970#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303971#define MAX_ROAMING_PARAM \
3972 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003973#define PARAM_NUM_BSSID \
3974 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID
3975#define PARAM_BSSID_PREFS \
3976 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS
3977#define PARAM_ROAM_BSSID \
3978 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID
3979#define PARAM_RSSI_MODIFIER \
3980 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER
3981#define PARAMS_NUM_BSSID \
3982 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID
3983#define PARAM_BSSID_PARAMS \
3984 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS
3985#define PARAM_A_BAND_BOOST_THLD \
3986 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD
3987#define PARAM_A_BAND_PELT_THLD \
3988 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD
3989#define PARAM_A_BAND_BOOST_FACTOR \
3990 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR
3991#define PARAM_A_BAND_PELT_FACTOR \
3992 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR
3993#define PARAM_A_BAND_MAX_BOOST \
3994 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST
3995#define PARAM_ROAM_HISTERESYS \
3996 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS
3997#define PARAM_RSSI_TRIGGER \
3998 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER
3999#define PARAM_ROAM_ENABLE \
4000 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304001#define PARAM_ROAM_CONTROL_CONFIG \
4002 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL
4003#define PARAM_FREQ_LIST_SCHEME \
4004 QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME
4005#define PARAM_FREQ_LIST_SCHEME_MAX \
4006 QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_MAX
4007#define PARAM_SCAN_FREQ_LIST \
4008 QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST
4009#define PARAM_SCAN_FREQ_LIST_TYPE \
4010 QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_TYPE
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304011#define PARAM_CAND_SEL_CRITERIA_MAX \
4012 QCA_ATTR_ROAM_CAND_SEL_CRITERIA_RATE_MAX
4013#define PARAM_CAND_SEL_SCORE_RSSI \
4014 QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_RSSI
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004015
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05304016
4017static const struct nla_policy
4018wlan_hdd_set_roam_param_policy[MAX_ROAMING_PARAM + 1] = {
4019 [QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD] = {.type = NLA_U32},
4020 [QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID] = {.type = NLA_U32},
4021 [PARAM_NUM_NW] = {.type = NLA_U32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004022 [PARAM_A_BAND_BOOST_FACTOR] = {.type = NLA_U32},
4023 [PARAM_A_BAND_PELT_FACTOR] = {.type = NLA_U32},
4024 [PARAM_A_BAND_MAX_BOOST] = {.type = NLA_U32},
4025 [PARAM_ROAM_HISTERESYS] = {.type = NLA_S32},
4026 [PARAM_A_BAND_BOOST_THLD] = {.type = NLA_S32},
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07004027 [PARAM_A_BAND_PELT_THLD] = {.type = NLA_S32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004028 [PARAM_RSSI_TRIGGER] = {.type = NLA_U32},
4029 [PARAM_ROAM_ENABLE] = { .type = NLA_S32},
4030 [PARAM_NUM_BSSID] = {.type = NLA_U32},
4031 [PARAM_RSSI_MODIFIER] = {.type = NLA_U32},
4032 [PARAMS_NUM_BSSID] = {.type = NLA_U32},
4033 [PARAM_ROAM_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
4034 [PARAM_SET_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304035 [PARAM_SET_BSSID_HINT] = {.type = NLA_FLAG},
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304036 [PARAM_ROAM_CONTROL_CONFIG] = {.type = NLA_NESTED},
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05304037};
4038
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004039/**
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004040 * hdd_set_white_list() - parse white list
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004041 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004042 * @roam_params: roam params
4043 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004044 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004045 *
4046 * Return: 0 on success; error number on failure
4047 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004048static int hdd_set_white_list(struct hdd_context *hdd_ctx,
4049 struct roam_ext_params *roam_params,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004050 struct nlattr **tb, uint8_t vdev_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004051{
4052 int rem, i;
4053 uint32_t buf_len = 0, count;
4054 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
4055 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004056 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004057
4058 i = 0;
4059 if (tb[PARAM_NUM_NW]) {
4060 count = nla_get_u32(tb[PARAM_NUM_NW]);
4061 } else {
4062 hdd_err("Number of networks is not provided");
4063 goto fail;
4064 }
4065
4066 if (count && tb[PARAM_SSID_LIST]) {
4067 nla_for_each_nested(curr_attr,
Min Liudd308892019-05-16 18:48:41 +08004068 tb[PARAM_SSID_LIST], rem) {
4069 if (i == MAX_SSID_ALLOWED_LIST) {
4070 hdd_err("Excess MAX_SSID_ALLOWED_LIST");
4071 goto fail;
4072 }
Dustin Brown4ea21db2018-01-05 14:13:17 -08004073 if (wlan_cfg80211_nla_parse(tb2,
Srinivas Dasari0cc64372019-08-13 12:04:20 +05304074 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
4075 nla_data(curr_attr),
4076 nla_len(curr_attr),
4077 wlan_hdd_set_roam_param_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08004078 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004079 goto fail;
4080 }
4081 /* Parse and Fetch allowed SSID list*/
4082 if (!tb2[PARAM_LIST_SSID]) {
4083 hdd_err("attr allowed ssid failed");
4084 goto fail;
4085 }
4086 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
4087 /*
4088 * Upper Layers include a null termination
4089 * character. Check for the actual permissible
4090 * length of SSID and also ensure not to copy
4091 * the NULL termination character to the driver
4092 * buffer.
4093 */
Min Liudd308892019-05-16 18:48:41 +08004094 if (buf_len > 1 &&
Srinivas Girigowdab8fdc642019-03-19 15:33:03 -07004095 ((buf_len - 1) <= WLAN_SSID_MAX_LEN)) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004096 nla_memcpy(roam_params->ssid_allowed_list[i].ssId,
4097 tb2[PARAM_LIST_SSID], buf_len - 1);
4098 roam_params->ssid_allowed_list[i].length = buf_len - 1;
4099 hdd_debug("SSID[%d]: %.*s,length = %d",
4100 i,
4101 roam_params->ssid_allowed_list[i].length,
4102 roam_params->ssid_allowed_list[i].ssId,
4103 roam_params->ssid_allowed_list[i].length);
4104 i++;
4105 } else {
4106 hdd_err("Invalid buffer length");
4107 }
4108 }
4109 }
4110
4111 if (i != count) {
4112 hdd_err("Invalid number of SSIDs i = %d, count = %d", i, count);
4113 goto fail;
4114 }
4115
4116 roam_params->num_ssid_allowed_list = i;
4117 hdd_debug("Num of Allowed SSID %d", roam_params->num_ssid_allowed_list);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004118 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004119 sme_update_roam_params(mac_handle, vdev_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004120 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
4121 return 0;
4122
4123fail:
4124 return -EINVAL;
4125}
4126
4127/**
4128 * hdd_set_bssid_prefs() - parse set bssid prefs
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004129 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004130 * @roam_params: roam params
4131 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004132 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004133 *
4134 * Return: 0 on success; error number on failure
4135 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004136static int hdd_set_bssid_prefs(struct hdd_context *hdd_ctx,
4137 struct roam_ext_params *roam_params,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004138 struct nlattr **tb, uint8_t vdev_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004139{
4140 int rem, i;
4141 uint32_t count;
4142 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
4143 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004144 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004145
4146 /* Parse and fetch number of preferred BSSID */
4147 if (!tb[PARAM_NUM_BSSID]) {
4148 hdd_err("attr num of preferred bssid failed");
4149 goto fail;
4150 }
4151 count = nla_get_u32(tb[PARAM_NUM_BSSID]);
4152 if (count > MAX_BSSID_FAVORED) {
4153 hdd_err("Preferred BSSID count %u exceeds max %u",
4154 count, MAX_BSSID_FAVORED);
4155 goto fail;
4156 }
4157 hdd_debug("Num of Preferred BSSID (%d)", count);
4158 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS]) {
4159 hdd_err("attr Preferred BSSID failed");
4160 goto fail;
4161 }
4162
4163 i = 0;
4164 nla_for_each_nested(curr_attr,
4165 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
4166 rem) {
4167 if (i == count) {
4168 hdd_warn("Ignoring excess Preferred BSSID");
4169 break;
4170 }
4171
Dustin Brown4ea21db2018-01-05 14:13:17 -08004172 if (wlan_cfg80211_nla_parse(tb2,
4173 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
4174 nla_data(curr_attr),
4175 nla_len(curr_attr),
4176 wlan_hdd_set_roam_param_policy)) {
4177 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004178 goto fail;
4179 }
4180 /* Parse and fetch MAC address */
4181 if (!tb2[PARAM_ROAM_BSSID]) {
4182 hdd_err("attr mac address failed");
4183 goto fail;
4184 }
4185 nla_memcpy(roam_params->bssid_favored[i].bytes,
4186 tb2[PARAM_ROAM_BSSID],
4187 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07004188 hdd_debug(QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07004189 QDF_MAC_ADDR_ARRAY(roam_params->bssid_favored[i].bytes));
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004190 /* Parse and fetch preference factor*/
4191 if (!tb2[PARAM_RSSI_MODIFIER]) {
4192 hdd_err("BSSID Preference score failed");
4193 goto fail;
4194 }
4195 roam_params->bssid_favored_factor[i] = nla_get_u32(
4196 tb2[PARAM_RSSI_MODIFIER]);
4197 hdd_debug("BSSID Preference score (%d)",
4198 roam_params->bssid_favored_factor[i]);
4199 i++;
4200 }
4201 if (i < count)
4202 hdd_warn("Num Preferred BSSID %u less than expected %u",
4203 i, count);
4204
4205 roam_params->num_bssid_favored = i;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004206 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004207 sme_update_roam_params(mac_handle, vdev_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004208 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
4209
4210 return 0;
4211
4212fail:
4213 return -EINVAL;
4214}
4215
4216/**
4217 * hdd_set_blacklist_bssid() - parse set blacklist bssid
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004218 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004219 * @roam_params: roam params
4220 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004221 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004222 *
4223 * Return: 0 on success; error number on failure
4224 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004225static int hdd_set_blacklist_bssid(struct hdd_context *hdd_ctx,
4226 struct roam_ext_params *roam_params,
4227 struct nlattr **tb,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004228 uint8_t vdev_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004229{
4230 int rem, i;
4231 uint32_t count;
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304232 uint8_t j = 0;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004233 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
4234 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004235 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004236
4237 /* Parse and fetch number of blacklist BSSID */
4238 if (!tb[PARAMS_NUM_BSSID]) {
4239 hdd_err("attr num of blacklist bssid failed");
4240 goto fail;
4241 }
4242 count = nla_get_u32(tb[PARAMS_NUM_BSSID]);
4243 if (count > MAX_BSSID_AVOID_LIST) {
4244 hdd_err("Blacklist BSSID count %u exceeds max %u",
4245 count, MAX_BSSID_AVOID_LIST);
4246 goto fail;
4247 }
4248 hdd_debug("Num of blacklist BSSID (%d)", count);
4249
4250 i = 0;
4251 if (count && tb[PARAM_BSSID_PARAMS]) {
4252 nla_for_each_nested(curr_attr,
4253 tb[PARAM_BSSID_PARAMS],
4254 rem) {
4255 if (i == count) {
4256 hdd_warn("Ignoring excess Blacklist BSSID");
4257 break;
4258 }
4259
Dustin Brown4ea21db2018-01-05 14:13:17 -08004260 if (wlan_cfg80211_nla_parse(tb2,
Dustin Brown3fb15042017-08-15 15:54:49 -07004261 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
4262 nla_data(curr_attr),
4263 nla_len(curr_attr),
4264 wlan_hdd_set_roam_param_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08004265 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004266 goto fail;
4267 }
4268 /* Parse and fetch MAC address */
4269 if (!tb2[PARAM_SET_BSSID]) {
4270 hdd_err("attr blacklist addr failed");
4271 goto fail;
4272 }
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304273 if (tb2[PARAM_SET_BSSID_HINT]) {
4274 struct reject_ap_info ap_info;
4275
4276 nla_memcpy(ap_info.bssid.bytes,
4277 tb2[PARAM_SET_BSSID],
4278 QDF_MAC_ADDR_SIZE);
4279 ap_info.reject_ap_type = USERSPACE_AVOID_TYPE;
4280 /* This BSSID is avoided and not blacklisted */
4281 ucfg_blm_add_bssid_to_reject_list(hdd_ctx->pdev,
4282 &ap_info);
4283 i++;
4284 continue;
4285 }
4286 nla_memcpy(roam_params->bssid_avoid_list[j].bytes,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004287 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07004288 hdd_debug(QDF_MAC_ADDR_STR,
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304289 QDF_MAC_ADDR_ARRAY(roam_params->
4290 bssid_avoid_list[j].bytes));
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004291 i++;
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304292 j++;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004293 }
4294 }
4295
4296 if (i < count)
4297 hdd_warn("Num Blacklist BSSID %u less than expected %u",
4298 i, count);
4299
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05304300 roam_params->num_bssid_avoid_list = j;
4301 /* Send the blacklist to the blacklist mgr component */
4302 ucfg_blm_add_userspace_black_list(hdd_ctx->pdev,
4303 roam_params->bssid_avoid_list,
4304 roam_params->num_bssid_avoid_list);
4305
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004306 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004307 sme_update_roam_params(mac_handle, vdev_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004308 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
4309
4310 return 0;
4311fail:
4312 return -EINVAL;
4313}
4314
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304315static const struct nla_policy
4316roam_scan_freq_list_scheme_policy[PARAM_FREQ_LIST_SCHEME_MAX + 1] = {
4317 [PARAM_SCAN_FREQ_LIST_TYPE] = {.type = NLA_U32},
4318 [PARAM_SCAN_FREQ_LIST] = {.type = NLA_NESTED},
4319};
4320
4321/**
4322 * hdd_send_roam_scan_channel_freq_list_to_sme() - Send control roam scan freqs
4323 * @hdd_ctx: HDD context
4324 * @vdev_id: vdev id
4325 * @tb: Nested attribute carrying frequency list scheme
4326 *
4327 * Extracts the frequency list and frequency list type from the frequency
4328 * list scheme and send the frequencies to SME.
4329 *
4330 * Return: QDF_STATUS
4331 */
4332static QDF_STATUS
4333hdd_send_roam_scan_channel_freq_list_to_sme(struct hdd_context *hdd_ctx,
4334 uint8_t vdev_id, struct nlattr *tb)
4335{
4336 QDF_STATUS status;
4337 struct nlattr *tb2[PARAM_FREQ_LIST_SCHEME_MAX + 1], *curr_attr;
4338 uint8_t num_chan = 0;
4339 uint32_t freq_list[SIR_MAX_SUPPORTED_CHANNEL_LIST] = {0};
4340 uint32_t list_type;
4341 mac_handle_t mac_handle = hdd_ctx->mac_handle;
4342 int rem;
4343
4344 if (wlan_cfg80211_nla_parse_nested(tb2, PARAM_FREQ_LIST_SCHEME_MAX,
4345 tb,
4346 roam_scan_freq_list_scheme_policy)) {
4347 hdd_err("nla_parse failed");
4348 return QDF_STATUS_E_INVAL;
4349 }
4350
4351 if (!tb2[PARAM_SCAN_FREQ_LIST] || !tb2[PARAM_SCAN_FREQ_LIST_TYPE]) {
4352 hdd_err("ROAM_CONTROL_SCAN_FREQ_LIST or type are not present");
4353 return QDF_STATUS_E_INVAL;
4354 }
4355
4356 list_type = nla_get_u32(tb2[PARAM_SCAN_FREQ_LIST_TYPE]);
4357 if (list_type != QCA_PREFERRED_SCAN_FREQ_LIST &&
4358 list_type != QCA_SPECIFIC_SCAN_FREQ_LIST) {
4359 hdd_err("Invalid freq list type received: %u", list_type);
4360 return QDF_STATUS_E_INVAL;
4361 }
4362
4363 nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem)
4364 num_chan++;
4365 if (num_chan > SIR_MAX_SUPPORTED_CHANNEL_LIST) {
4366 hdd_err("number of channels (%d) supported exceeded max (%d)",
4367 num_chan, SIR_MAX_SUPPORTED_CHANNEL_LIST);
4368 return QDF_STATUS_E_INVAL;
4369 }
4370 num_chan = 0;
4371
Srinivas Dasariac5312a2019-08-23 07:21:46 +05304372 nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem) {
4373 if (nla_len(curr_attr) != sizeof(uint32_t)) {
4374 hdd_err("len is not correct for frequency %d",
4375 num_chan);
4376 return QDF_STATUS_E_INVAL;
4377 }
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304378 freq_list[num_chan++] = nla_get_u32(curr_attr);
Srinivas Dasariac5312a2019-08-23 07:21:46 +05304379 }
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304380
4381 status = sme_update_roam_scan_freq_list(mac_handle, vdev_id, freq_list,
4382 num_chan, list_type);
4383 if (QDF_IS_STATUS_ERROR(status))
4384 hdd_err("Failed to update channel list information");
4385
4386 return status;
4387}
4388
4389static const struct nla_policy
4390roam_control_policy[QCA_ATTR_ROAM_CONTROL_MAX + 1] = {
Srinivas Dasari391692d2019-08-21 08:40:53 +05304391 [QCA_ATTR_ROAM_CONTROL_ENABLE] = {.type = NLA_U8},
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304392 [QCA_ATTR_ROAM_CONTROL_STATUS] = {.type = NLA_U8},
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304393 [PARAM_FREQ_LIST_SCHEME] = {.type = NLA_NESTED},
Srinivas Dasari0628e842019-08-22 01:17:38 +05304394 [QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD] = {.type = NLA_U32},
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05304395 [QCA_ATTR_ROAM_CONTROL_CLEAR_ALL] = {.type = NLA_FLAG},
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304396 [QCA_ATTR_ROAM_CONTROL_TRIGGERS] = {.type = NLA_U32},
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304397 [QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA] = {.type = NLA_NESTED},
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304398 [QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD] = {.type = NLA_U32},
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304399};
4400
4401/**
Srinivas Dasari0628e842019-08-22 01:17:38 +05304402 * hdd_send_roam_full_scan_period_to_sme() - Send full roam scan period to SME
4403 * @hdd_ctx: HDD context
4404 * @vdev_id: vdev id
4405 * @full_roam_scan_period: Idle period in seconds between two successive
Srinivas Dasari240d3272019-09-20 12:00:57 +05304406 * full channel roam scans
4407 * @check_and_update: If this is true/set, update the value only if the current
4408 * configured value is not same as global value read from
4409 * ini param. This is to give priority to the user configured
4410 * values and retain the value, if updated already.
4411 * If this is not set, update the value without any check.
Srinivas Dasari0628e842019-08-22 01:17:38 +05304412 *
4413 * Validate the full roam scan period and send it to firmware
4414 *
4415 * Return: QDF_STATUS
4416 */
4417static QDF_STATUS
4418hdd_send_roam_full_scan_period_to_sme(struct hdd_context *hdd_ctx,
4419 uint8_t vdev_id,
Srinivas Dasari240d3272019-09-20 12:00:57 +05304420 uint32_t full_roam_scan_period,
4421 bool check_and_update)
Srinivas Dasari0628e842019-08-22 01:17:38 +05304422{
4423 QDF_STATUS status;
Srinivas Dasari240d3272019-09-20 12:00:57 +05304424 uint32_t full_roam_scan_period_current, full_roam_scan_period_global;
Srinivas Dasari0628e842019-08-22 01:17:38 +05304425
4426 if (!ucfg_mlme_validate_full_roam_scan_period(full_roam_scan_period))
4427 return QDF_STATUS_E_INVAL;
4428
4429 hdd_debug("Received Command to Set full roam scan period = %u",
4430 full_roam_scan_period);
4431
Srinivas Dasari240d3272019-09-20 12:00:57 +05304432 status = sme_get_full_roam_scan_period(hdd_ctx->mac_handle, vdev_id,
4433 &full_roam_scan_period_current);
4434 if (QDF_IS_STATUS_ERROR(status))
4435 return status;
4436
4437 full_roam_scan_period_global =
4438 sme_get_full_roam_scan_period_global(hdd_ctx->mac_handle);
4439 if (check_and_update &&
4440 full_roam_scan_period_current != full_roam_scan_period_global) {
4441 hdd_debug("Full roam scan period is already updated, value: %u",
4442 full_roam_scan_period_current);
4443 return QDF_STATUS_SUCCESS;
4444 }
Srinivas Dasari0628e842019-08-22 01:17:38 +05304445 status = sme_update_full_roam_scan_period(hdd_ctx->mac_handle, vdev_id,
4446 full_roam_scan_period);
4447 if (QDF_IS_STATUS_ERROR(status))
4448 hdd_err("Failed to set full scan period");
4449
4450 return status;
4451}
4452
4453/**
Pragaspathi Thilagaraj47385952020-02-28 14:41:42 +05304454 * wlan_hdd_convert_control_roam_trigger_reason_bitmap - Convert the
4455 * vendor specific reason code to internal reason code.
4456 * @trigger_reason_bitmap: Vendor specific roam trigger bitmap
4457 *
4458 * Return: Internal roam trigger bitmap
4459 */
4460static uint32_t
4461wlan_hdd_convert_control_roam_trigger_bitmap(uint32_t trigger_reason_bitmap)
4462{
4463 uint32_t drv_trigger_bitmap = 0, all_bitmap;
4464
4465 /* Enable the complete trigger bitmap when all bits are set in
4466 * the control config bitmap
4467 */
4468 all_bitmap = (QCA_ROAM_TRIGGER_REASON_BSS_LOAD << 1) - 1;
4469 if (trigger_reason_bitmap == all_bitmap)
4470 return BIT(ROAM_TRIGGER_REASON_MAX) - 1;
4471
4472 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_PER)
4473 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_PER);
4474
4475 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BEACON_MISS)
4476 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BMISS);
4477
4478 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_POOR_RSSI)
4479 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_LOW_RSSI);
4480
4481 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BETTER_RSSI)
4482 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_HIGH_RSSI);
4483
4484 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_PERIODIC)
4485 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_PERIODIC);
4486
4487 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_DENSE)
4488 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_DENSE);
4489
4490 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BTM)
4491 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BTM);
4492
4493 if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BSS_LOAD)
4494 drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BSS_LOAD);
4495
4496 return drv_trigger_bitmap;
4497}
4498
4499/**
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304500 * hdd_send_roam_triggers_to_sme() - Send roam trigger bitmap to SME
4501 * @hdd_ctx: HDD context
4502 * @vdev_id: vdev id
4503 * @roam_trigger_bitmap: Vendor configured roam trigger bitmap to be configured
4504 * to firmware
4505 *
4506 * Send the roam trigger bitmap received to SME
4507 *
4508 * Return: QDF_STATUS
4509 */
4510static QDF_STATUS
4511hdd_send_roam_triggers_to_sme(struct hdd_context *hdd_ctx,
4512 uint8_t vdev_id,
4513 uint32_t roam_trigger_bitmap)
4514{
4515 QDF_STATUS status;
4516 struct roam_triggers triggers;
Abhinav Kumar523ca372019-08-30 16:28:19 +05304517 struct hdd_adapter *adapter;
4518
4519 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
4520 if (!adapter) {
4521 hdd_err("adapter NULL");
4522 return QDF_STATUS_E_FAILURE;
4523 }
4524
4525 if (adapter->device_mode != QDF_STA_MODE) {
4526 hdd_err("Roam trigger bitmap supported only in STA mode");
4527 return QDF_STATUS_E_FAILURE;
4528 }
4529
4530 /*
4531 * In standalone STA, if this vendor command is received between
4532 * ROAM_START and roam synch indication, it is better to reject
4533 * roam disable since driver would send vdev_params command to
4534 * de-initialize roaming structures in fw.
4535 * In STA+STA mode, if this vendor command to enable roaming is
4536 * received for one STA vdev and ROAM_START was received for other
4537 * STA vdev, then also driver would be send vdev_params command to
4538 * de-initialize roaming structures in fw on the roaming enabled
4539 * vdev.
4540 */
4541 if (hdd_ctx->roaming_in_progress) {
4542 hdd_err("Reject set roam trigger as roaming is in progress");
4543 return QDF_STATUS_E_FAILURE;
4544 }
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304545
4546 triggers.vdev_id = vdev_id;
Pragaspathi Thilagaraj47385952020-02-28 14:41:42 +05304547 triggers.trigger_bitmap =
4548 wlan_hdd_convert_control_roam_trigger_bitmap(roam_trigger_bitmap);
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304549
4550 status = sme_set_roam_triggers(hdd_ctx->mac_handle, &triggers);
4551 if (QDF_IS_STATUS_ERROR(status))
4552 hdd_err("Failed to set roam control trigger bitmap");
4553
4554 return status;
4555}
4556
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304557/*
4558 * Disable default scoring algorithm. This is intended to set all bits of the
4559 * disable_bitmap in struct scoring_param.
4560 */
4561#define DISABLE_SCORING 0
4562
4563/*
4564 * Enable scoring algorithm. This is intended to clear all bits of the
4565 * disable_bitmap in struct scoring_param.
4566 */
4567#define ENABLE_SCORING 1
4568
4569/*
4570 * Controlled roam candidate selection is enabled from userspace.
4571 * Driver/firmware should honor the selection criteria
4572 */
4573#define CONTROL_ROAM_CAND_SEL_ENABLE 1
4574
4575/*
4576 * Controlled roam candidate selection is disabled from userspace.
4577 * Driver/firmware can use its internal candidate selection criteria
4578 */
4579#define CONTROL_ROAM_CAND_SEL_DISABLE 0
4580
4581static const struct nla_policy
4582roam_scan_cand_sel_policy[PARAM_CAND_SEL_CRITERIA_MAX + 1] = {
4583 [PARAM_CAND_SEL_SCORE_RSSI] = {.type = NLA_U8},
4584};
4585
4586/**
4587 * hdd_send_roam_cand_sel_criteria_to_sme() - Send candidate sel criteria to SME
4588 * @hdd_ctx: HDD context
4589 * @vdev_id: vdev id
4590 * @attr: Nested attribute carrying candidate selection criteria
4591 *
4592 * Extract different candidate sel criteria mentioned and convert it to
4593 * driver/firmware understable format.
4594 *
4595 * Return: QDF_STATUS
4596 */
4597static QDF_STATUS
4598hdd_send_roam_cand_sel_criteria_to_sme(struct hdd_context *hdd_ctx,
4599 uint8_t vdev_id,
4600 struct nlattr *attr)
4601{
4602 QDF_STATUS status;
4603 struct nlattr *tb2[PARAM_CAND_SEL_CRITERIA_MAX + 1];
4604 struct nlattr *curr_attr;
4605 uint8_t sel_criteria = 0, rssi_score = 0, scoring;
4606 int rem;
4607
4608 hdd_debug("Received Command to Set candidate selection criteria ");
4609 nla_for_each_nested(curr_attr, attr, rem) {
4610 sel_criteria++;
4611 break;
4612 }
4613
4614 if (sel_criteria &&
4615 wlan_cfg80211_nla_parse_nested(tb2, PARAM_CAND_SEL_CRITERIA_MAX,
4616 attr, roam_scan_cand_sel_policy)) {
4617 hdd_err("nla_parse failed");
4618 return QDF_STATUS_E_INVAL;
4619 }
4620
4621 /*
4622 * Firmware supports the below configurations currently,
4623 * 1. Default selection criteria where all scoring params
4624 * are enabled and different weightages/scores are given to
4625 * different parameters.
4626 * When userspace doesn't specify any candidate selection criteria,
4627 * this will be enabled.
4628 * 2. Legacy candidate selection criteria where scoring
4629 * algorithm is disabled and only RSSI is considered for
4630 * roam candidate selection.
4631 * When userspace specify 100% weightage for RSSI, this will
4632 * be enabled.
4633 * Rest of the combinations are not supported for now.
4634 */
4635 if (sel_criteria == CONTROL_ROAM_CAND_SEL_ENABLE) {
4636 /* Legacy selection criteria: 100% weightage to RSSI */
4637 if (tb2[PARAM_CAND_SEL_SCORE_RSSI])
4638 rssi_score = nla_get_u8(tb2[PARAM_CAND_SEL_SCORE_RSSI]);
4639
4640 if (rssi_score != 100) {
4641 hdd_debug("Ignore the candidate selection criteria");
4642 return QDF_STATUS_E_INVAL;
4643 }
4644 scoring = DISABLE_SCORING;
4645 } else {
4646 /* Default selection criteria */
4647 scoring = ENABLE_SCORING;
4648 }
4649
4650 status = sme_modify_roam_cand_sel_criteria(hdd_ctx->mac_handle, vdev_id,
4651 !!scoring);
4652 if (QDF_IS_STATUS_ERROR(status))
4653 hdd_err("Failed to disable scoring");
4654
4655 return status;
4656}
4657
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304658/**
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304659 * hdd_send_roam_scan_period_to_sme() - Send roam scan period to SME
4660 * @hdd_ctx: HDD context
4661 * @vdev_id: vdev id
4662 * @roam_scan_period: Roam scan period in seconds
Srinivas Dasari240d3272019-09-20 12:00:57 +05304663 * @check_and_update: If this is true/set, update the value only if the current
4664 * configured value is not same as global value read from
4665 * ini param. This is to give priority to the user configured
4666 * values and retain the value, if updated already.
4667 * If this is not set, update the value without any check.
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304668 *
4669 * Validate the roam scan period and send it to firmware if valid.
4670 *
4671 * Return: QDF_STATUS
4672 */
4673static QDF_STATUS
4674hdd_send_roam_scan_period_to_sme(struct hdd_context *hdd_ctx,
4675 uint8_t vdev_id,
Srinivas Dasari240d3272019-09-20 12:00:57 +05304676 uint32_t roam_scan_period,
4677 bool check_and_update)
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304678{
4679 QDF_STATUS status;
Srinivas Dasari240d3272019-09-20 12:00:57 +05304680 uint16_t roam_scan_period_current, roam_scan_period_global;
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304681
4682 if (!ucfg_mlme_validate_scan_period(roam_scan_period * 1000))
4683 return QDF_STATUS_E_INVAL;
4684
4685 hdd_debug("Received Command to Set roam scan period (Empty Scan refresh period) = %d",
4686 roam_scan_period);
4687
Srinivas Dasari240d3272019-09-20 12:00:57 +05304688 status = sme_get_empty_scan_refresh_period(hdd_ctx->mac_handle, vdev_id,
4689 &roam_scan_period_current);
4690 if (QDF_IS_STATUS_ERROR(status))
4691 return status;
4692
4693 roam_scan_period_global =
4694 sme_get_empty_scan_refresh_period_global(hdd_ctx->mac_handle);
4695 if (check_and_update &&
4696 roam_scan_period_current != roam_scan_period_global) {
4697 hdd_debug("roam scan period is already updated, value: %u",
4698 roam_scan_period_current / 1000);
4699 return QDF_STATUS_SUCCESS;
4700 }
Srinivas Dasarib5d9f3e2019-08-22 01:43:42 +05304701 status = sme_update_empty_scan_refresh_period(hdd_ctx->mac_handle,
4702 vdev_id,
4703 roam_scan_period * 1000);
4704 if (QDF_IS_STATUS_ERROR(status))
4705 hdd_err("Failed to set scan period");
4706
4707 return status;
4708}
4709
4710/**
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304711 * hdd_set_roam_with_control_config() - Set roam control configuration
4712 * @hdd_ctx: HDD context
4713 * @tb: List of attributes carrying roam subcmd data
4714 * @vdev_id: vdev id
4715 *
4716 * Extracts the attribute PARAM_ROAM_CONTROL_CONFIG from the attributes list tb
4717 * and sends the corresponding roam control configuration to driver/firmware.
4718 *
4719 * Return: 0 on success; error number on failure
4720 */
4721static int
4722hdd_set_roam_with_control_config(struct hdd_context *hdd_ctx,
4723 struct nlattr **tb,
4724 uint8_t vdev_id)
4725{
4726 QDF_STATUS status = QDF_STATUS_SUCCESS;
4727 struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1], *attr;
Srinivas Dasari0628e842019-08-22 01:17:38 +05304728 uint32_t value;
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304729
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304730 hdd_enter();
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304731 /* The command must carry PARAM_ROAM_CONTROL_CONFIG */
4732 if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
4733 hdd_err("Attribute CONTROL_CONFIG is not present");
4734 return -EINVAL;
4735 }
4736
4737 if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
4738 tb[PARAM_ROAM_CONTROL_CONFIG],
4739 roam_control_policy)) {
4740 hdd_err("nla_parse failed");
4741 return -EINVAL;
4742 }
4743
4744 attr = tb2[PARAM_FREQ_LIST_SCHEME];
4745 if (attr) {
4746 status = hdd_send_roam_scan_channel_freq_list_to_sme(hdd_ctx,
4747 vdev_id,
4748 attr);
4749 if (QDF_IS_STATUS_ERROR(status))
4750 hdd_err("failed to config roam control");
4751 }
4752
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304753 if (tb2[QCA_ATTR_ROAM_CONTROL_TRIGGERS]) {
Srinivas Dasarif4e1b122019-08-22 03:39:48 +05304754 value = nla_get_u32(tb2[QCA_ATTR_ROAM_CONTROL_TRIGGERS]);
4755 hdd_debug("Received roam trigger bitmap: 0x%x", value);
4756 status = hdd_send_roam_triggers_to_sme(hdd_ctx,
4757 vdev_id,
4758 value);
4759 if (status)
4760 hdd_err("failed to config roam triggers");
4761 }
4762
Srinivas Dasari391692d2019-08-21 08:40:53 +05304763 attr = tb2[QCA_ATTR_ROAM_CONTROL_ENABLE];
4764 if (attr) {
Srinivas Dasari391692d2019-08-21 08:40:53 +05304765 status = sme_set_roam_config_enable(hdd_ctx->mac_handle,
4766 vdev_id,
4767 nla_get_u8(attr));
4768 if (QDF_IS_STATUS_ERROR(status))
4769 hdd_err("failed to enable/disable roam control config");
Srinivas Dasari240d3272019-09-20 12:00:57 +05304770
sheenam monga65415d12020-02-07 14:39:15 +05304771 hdd_debug("Parse and send roam control %s:",
4772 nla_get_u8(attr) ? "Enable" : "Disable");
4773
Srinivas Dasari240d3272019-09-20 12:00:57 +05304774 attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD];
4775 if (attr) {
Srinivas Dasari240d3272019-09-20 12:00:57 +05304776 /* Default value received as part of Roam control enable
4777 * Set this only if user hasn't configured any value so
4778 * far.
4779 */
4780 value = nla_get_u32(attr);
4781 status = hdd_send_roam_scan_period_to_sme(hdd_ctx,
4782 vdev_id,
4783 value, true);
4784 if (QDF_IS_STATUS_ERROR(status))
4785 hdd_err("failed to send scan period to firmware");
4786 }
4787
4788 attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD];
4789 if (attr) {
Srinivas Dasari240d3272019-09-20 12:00:57 +05304790 value = nla_get_u32(attr);
4791 /* Default value received as part of Roam control enable
4792 * Set this only if user hasn't configured any value so
4793 * far.
4794 */
4795 status = hdd_send_roam_full_scan_period_to_sme(hdd_ctx,
4796 vdev_id,
4797 value,
4798 true);
4799 if (status)
4800 hdd_err("failed to config full scan period");
4801 }
4802 } else {
4803 attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD];
4804 if (attr) {
Srinivas Dasari240d3272019-09-20 12:00:57 +05304805 /* User configured value, cache the value directly */
4806 value = nla_get_u32(attr);
4807 status = hdd_send_roam_scan_period_to_sme(hdd_ctx,
4808 vdev_id,
4809 value, false);
4810 if (QDF_IS_STATUS_ERROR(status))
4811 hdd_err("failed to send scan period to firmware");
4812 }
4813
4814 attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD];
4815 if (attr) {
Srinivas Dasari240d3272019-09-20 12:00:57 +05304816 value = nla_get_u32(attr);
4817 /* User configured value, cache the value directly */
4818 status = hdd_send_roam_full_scan_period_to_sme(hdd_ctx,
4819 vdev_id,
4820 value,
4821 false);
4822 if (status)
4823 hdd_err("failed to config full scan period");
4824 }
Srinivas Dasari391692d2019-08-21 08:40:53 +05304825 }
4826
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304827 /* Scoring and roam candidate selection criteria */
4828 attr = tb2[QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA];
4829 if (attr) {
Srinivas Dasari5fb81902019-08-22 01:39:42 +05304830 status = hdd_send_roam_cand_sel_criteria_to_sme(hdd_ctx,
4831 vdev_id, attr);
4832 if (QDF_IS_STATUS_ERROR(status))
4833 hdd_err("failed to set candidate selection criteria");
4834 }
4835
Srinivas Dasari25d77b22019-08-07 16:21:48 +05304836 return qdf_status_to_os_return(status);
4837}
4838
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05304839#define ENABLE_ROAM_TRIGGERS_ALL (QCA_ROAM_TRIGGER_REASON_PER | \
4840 QCA_ROAM_TRIGGER_REASON_BEACON_MISS | \
4841 QCA_ROAM_TRIGGER_REASON_POOR_RSSI | \
4842 QCA_ROAM_TRIGGER_REASON_BETTER_RSSI | \
4843 QCA_ROAM_TRIGGER_REASON_PERIODIC | \
4844 QCA_ROAM_TRIGGER_REASON_DENSE | \
4845 QCA_ROAM_TRIGGER_REASON_BTM | \
4846 QCA_ROAM_TRIGGER_REASON_BSS_LOAD)
4847
4848static int
4849hdd_clear_roam_control_config(struct hdd_context *hdd_ctx,
4850 struct nlattr **tb,
4851 uint8_t vdev_id)
4852{
4853 QDF_STATUS status;
4854 struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1];
4855 mac_handle_t mac_handle = hdd_ctx->mac_handle;
Srinivas Dasari05bc2c22019-08-23 17:54:53 +05304856 uint32_t value;
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05304857
4858 /* The command must carry PARAM_ROAM_CONTROL_CONFIG */
4859 if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
4860 hdd_err("Attribute CONTROL_CONFIG is not present");
4861 return -EINVAL;
4862 }
4863
4864 if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
4865 tb[PARAM_ROAM_CONTROL_CONFIG],
4866 roam_control_policy)) {
4867 hdd_err("nla_parse failed");
4868 return -EINVAL;
4869 }
4870
4871 hdd_debug("Clear the control config done through SET");
4872 if (tb2[QCA_ATTR_ROAM_CONTROL_CLEAR_ALL]) {
4873 hdd_debug("Disable roam control config done through SET");
4874 status = sme_set_roam_config_enable(hdd_ctx->mac_handle,
4875 vdev_id, 0);
4876 if (QDF_IS_STATUS_ERROR(status)) {
4877 hdd_err("failed to enable/disable roam control config");
4878 return qdf_status_to_os_return(status);
4879 }
4880
Srinivas Dasari05bc2c22019-08-23 17:54:53 +05304881 value = ENABLE_ROAM_TRIGGERS_ALL;
4882 hdd_debug("Reset roam trigger bitmap to 0x%x", value);
4883 status = hdd_send_roam_triggers_to_sme(hdd_ctx, vdev_id, value);
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05304884 if (QDF_IS_STATUS_ERROR(status)) {
4885 hdd_err("failed to restore roam trigger bitmap");
4886 return qdf_status_to_os_return(status);
4887 }
4888
4889 status = sme_roam_control_restore_default_config(mac_handle,
4890 vdev_id);
4891 if (QDF_IS_STATUS_ERROR(status)) {
4892 hdd_err("failed to config roam control");
4893 return qdf_status_to_os_return(status);
4894 }
4895 }
4896
4897 return 0;
4898}
4899
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304900/**
4901 * hdd_roam_control_config_buf_size() - Calculate the skb size to be allocated
4902 * @hdd_ctx: HDD context
4903 * @tb: List of attributes to be populated
4904 *
4905 * Calculate the buffer size to be allocated based on the attributes
4906 * mentioned in tb.
4907 *
4908 * Return: buffer size to be allocated
4909 */
4910static uint16_t
4911hdd_roam_control_config_buf_size(struct hdd_context *hdd_ctx,
4912 struct nlattr **tb)
4913{
4914 uint16_t skb_len = 0;
4915
4916 if (tb[QCA_ATTR_ROAM_CONTROL_STATUS])
4917 skb_len += NLA_HDRLEN + sizeof(uint8_t);
4918
Srinivas Dasaria33fdd82019-08-21 16:15:22 +05304919 if (tb[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD])
4920 skb_len += NLA_HDRLEN + sizeof(uint32_t);
4921
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304922 return skb_len;
4923}
4924
4925/**
4926 * hdd_roam_control_config_fill_data() - Fill the data requested by userspace
4927 * @hdd_ctx: HDD context
4928 * @vdev_id: vdev id
4929 * @skb: SK buffer
4930 * @tb: List of attributes
4931 *
4932 * Get the data corresponding to the attribute list specified in tb and
4933 * update the same to skb by populating the same attributes.
4934 *
4935 * Return: 0 on success; error number on failure
4936 */
4937static int
4938hdd_roam_control_config_fill_data(struct hdd_context *hdd_ctx, uint8_t vdev_id,
4939 struct sk_buff *skb, struct nlattr **tb)
4940{
4941 QDF_STATUS status = QDF_STATUS_SUCCESS;
4942 uint8_t roam_control;
4943 struct nlattr *config;
Srinivas Dasaria33fdd82019-08-21 16:15:22 +05304944 uint32_t full_roam_scan_period;
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304945
4946 config = nla_nest_start(skb, PARAM_ROAM_CONTROL_CONFIG);
sheenam monga65415d12020-02-07 14:39:15 +05304947 if (!config) {
4948 hdd_err("nla nest start failure");
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304949 return -EINVAL;
sheenam monga65415d12020-02-07 14:39:15 +05304950 }
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304951
4952 if (tb[QCA_ATTR_ROAM_CONTROL_STATUS]) {
4953 status = sme_get_roam_config_status(hdd_ctx->mac_handle,
4954 vdev_id,
4955 &roam_control);
4956 if (QDF_IS_STATUS_ERROR(status))
4957 goto out;
4958 hdd_debug("Roam control: %s",
4959 roam_control ? "Enabled" : "Disabled");
4960 if (nla_put_u8(skb, QCA_ATTR_ROAM_CONTROL_STATUS,
4961 roam_control)) {
4962 hdd_info("failed to put vendor_roam_control");
4963 return -ENOMEM;
4964 }
4965 }
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304966
Srinivas Dasaria33fdd82019-08-21 16:15:22 +05304967 if (tb[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD]) {
4968 status = sme_get_full_roam_scan_period(hdd_ctx->mac_handle,
4969 vdev_id,
4970 &full_roam_scan_period);
4971 if (QDF_IS_STATUS_ERROR(status))
4972 goto out;
4973 hdd_debug("full_roam_scan_period: %u", full_roam_scan_period);
4974
4975 if (nla_put_u32(skb, QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD,
4976 full_roam_scan_period)) {
4977 hdd_info("failed to put full_roam_scan_period");
4978 return -EINVAL;
4979 }
4980 }
4981
4982 nla_nest_end(skb, config);
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05304983out:
4984 return qdf_status_to_os_return(status);
4985}
4986
4987/**
4988 * hdd_send_roam_control_config() - Send the roam config as vendor cmd reply
4989 * @mac_handle: Opaque handle to the MAC context
4990 * @vdev_id: vdev id
4991 * @tb: List of attributes
4992 *
4993 * Parse the attributes list tb and get the data corresponding to the
4994 * attributes specified in tb. Send them as a vendor response.
4995 *
4996 * Return: 0 on success; error number on failure
4997 */
4998static int
4999hdd_send_roam_control_config(struct hdd_context *hdd_ctx,
5000 uint8_t vdev_id,
5001 struct nlattr **tb)
5002{
5003 struct sk_buff *skb;
5004 uint16_t skb_len;
5005 int status;
5006
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305007 skb_len = hdd_roam_control_config_buf_size(hdd_ctx, tb);
5008 if (!skb_len) {
5009 hdd_err("No data requested");
5010 return -EINVAL;
5011 }
5012
5013 skb_len += NLMSG_HDRLEN;
5014 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, skb_len);
5015 if (!skb) {
5016 hdd_info("cfg80211_vendor_cmd_alloc_reply_skb failed");
5017 return -ENOMEM;
5018 }
5019
5020 status = hdd_roam_control_config_fill_data(hdd_ctx, vdev_id, skb, tb);
5021 if (status)
5022 goto fail;
5023
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305024 return cfg80211_vendor_cmd_reply(skb);
5025
5026fail:
5027 hdd_err("nla put fail");
5028 kfree_skb(skb);
5029 return status;
5030}
5031
5032/**
5033 * hdd_get_roam_control_config() - Send requested roam config to userspace
5034 * @hdd_ctx: HDD context
5035 * @tb: list of attributes
5036 * @vdev_id: vdev id
5037 *
5038 * Return: 0 on success; error number on failure
5039 */
5040static int hdd_get_roam_control_config(struct hdd_context *hdd_ctx,
5041 struct nlattr **tb,
5042 uint8_t vdev_id)
5043{
5044 QDF_STATUS status;
5045 struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1];
5046
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305047 /* The command must carry PARAM_ROAM_CONTROL_CONFIG */
5048 if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
5049 hdd_err("Attribute CONTROL_CONFIG is not present");
5050 return -EINVAL;
5051 }
5052
5053 if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
5054 tb[PARAM_ROAM_CONTROL_CONFIG],
5055 roam_control_policy)) {
5056 hdd_err("nla_parse failed");
5057 return -EINVAL;
5058 }
5059
5060 status = hdd_send_roam_control_config(hdd_ctx, vdev_id, tb2);
5061 if (status) {
5062 hdd_err("failed to enable/disable roam control");
5063 return status;
5064 }
5065
5066 return qdf_status_to_os_return(status);
5067}
5068
Srinivas Dasari25d77b22019-08-07 16:21:48 +05305069#undef PARAM_ROAM_CONTROL_CONFIG
5070#undef PARAM_FREQ_LIST_SCHEME_MAX
5071#undef PARAM_FREQ_LIST_SCHEME
5072#undef PARAM_SCAN_FREQ_LIST
5073#undef PARAM_SCAN_FREQ_LIST_TYPE
Srinivas Dasari5fb81902019-08-22 01:39:42 +05305074#undef PARAM_CAND_SEL_CRITERIA_MAX
5075#undef PARAM_CAND_SEL_SCORE_RSSI
Srinivas Dasari25d77b22019-08-07 16:21:48 +05305076
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005077/**
5078 * hdd_set_ext_roam_params() - parse ext roam params
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005079 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005080 * @roam_params: roam params
5081 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005082 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005083 *
5084 * Return: 0 on success; error number on failure
5085 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005086static int hdd_set_ext_roam_params(struct hdd_context *hdd_ctx,
5087 const void *data, int data_len,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005088 uint8_t vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005089 struct roam_ext_params *roam_params)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005090{
5091 uint32_t cmd_type, req_id;
5092 struct nlattr *tb[MAX_ROAMING_PARAM + 1];
5093 int ret;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005094 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005095
Dustin Brown4ea21db2018-01-05 14:13:17 -08005096 if (wlan_cfg80211_nla_parse(tb, MAX_ROAMING_PARAM, data, data_len,
5097 wlan_hdd_set_roam_param_policy)) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005098 hdd_err("Invalid ATTR");
5099 return -EINVAL;
5100 }
5101 /* Parse and fetch Command Type */
5102 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
5103 hdd_err("roam cmd type failed");
5104 goto fail;
5105 }
5106
5107 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
5108 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
5109 hdd_err("attr request id failed");
5110 goto fail;
5111 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005112 mac_handle = hdd_ctx->mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005113 req_id = nla_get_u32(
5114 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
5115 hdd_debug("Req Id: %u Cmd Type: %u", req_id, cmd_type);
5116 switch (cmd_type) {
Srinivas Dasari0cc64372019-08-13 12:04:20 +05305117 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST:
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005118 ret = hdd_set_white_list(hdd_ctx, roam_params, tb, vdev_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005119 if (ret)
5120 goto fail;
5121 break;
5122
Srinivas Dasari0cc64372019-08-13 12:04:20 +05305123 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005124 /* Parse and fetch 5G Boost Threshold */
5125 if (!tb[PARAM_A_BAND_BOOST_THLD]) {
5126 hdd_err("5G boost threshold failed");
5127 goto fail;
5128 }
5129 roam_params->raise_rssi_thresh_5g = nla_get_s32(
5130 tb[PARAM_A_BAND_BOOST_THLD]);
5131 hdd_debug("5G Boost Threshold (%d)",
5132 roam_params->raise_rssi_thresh_5g);
5133 /* Parse and fetch 5G Penalty Threshold */
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07005134 if (!tb[PARAM_A_BAND_PELT_THLD]) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005135 hdd_err("5G penalty threshold failed");
5136 goto fail;
5137 }
5138 roam_params->drop_rssi_thresh_5g = nla_get_s32(
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07005139 tb[PARAM_A_BAND_PELT_THLD]);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005140 hdd_debug("5G Penalty Threshold (%d)",
5141 roam_params->drop_rssi_thresh_5g);
5142 /* Parse and fetch 5G Boost Factor */
5143 if (!tb[PARAM_A_BAND_BOOST_FACTOR]) {
5144 hdd_err("5G boost Factor failed");
5145 goto fail;
5146 }
5147 roam_params->raise_factor_5g = nla_get_u32(
5148 tb[PARAM_A_BAND_BOOST_FACTOR]);
5149 hdd_debug("5G Boost Factor (%d)",
5150 roam_params->raise_factor_5g);
5151 /* Parse and fetch 5G Penalty factor */
5152 if (!tb[PARAM_A_BAND_PELT_FACTOR]) {
5153 hdd_err("5G Penalty Factor failed");
5154 goto fail;
5155 }
5156 roam_params->drop_factor_5g = nla_get_u32(
5157 tb[PARAM_A_BAND_PELT_FACTOR]);
5158 hdd_debug("5G Penalty factor (%d)",
5159 roam_params->drop_factor_5g);
5160 /* Parse and fetch 5G Max Boost */
5161 if (!tb[PARAM_A_BAND_MAX_BOOST]) {
5162 hdd_err("5G Max Boost failed");
5163 goto fail;
5164 }
5165 roam_params->max_raise_rssi_5g = nla_get_u32(
5166 tb[PARAM_A_BAND_MAX_BOOST]);
5167 hdd_debug("5G Max Boost (%d)",
5168 roam_params->max_raise_rssi_5g);
5169 /* Parse and fetch Rssi Diff */
5170 if (!tb[PARAM_ROAM_HISTERESYS]) {
5171 hdd_err("Rssi Diff failed");
5172 goto fail;
5173 }
5174 roam_params->rssi_diff = nla_get_s32(
5175 tb[PARAM_ROAM_HISTERESYS]);
5176 hdd_debug("RSSI Diff (%d)",
5177 roam_params->rssi_diff);
5178 /* Parse and fetch Alert Rssi Threshold */
5179 if (!tb[PARAM_RSSI_TRIGGER]) {
5180 hdd_err("Alert Rssi Threshold failed");
5181 goto fail;
5182 }
5183 roam_params->alert_rssi_threshold = nla_get_u32(
5184 tb[PARAM_RSSI_TRIGGER]);
5185 hdd_debug("Alert RSSI Threshold (%d)",
5186 roam_params->alert_rssi_threshold);
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005187 sme_update_roam_params(mac_handle, vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005188 roam_params,
5189 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005190 break;
Srinivas Dasari0cc64372019-08-13 12:04:20 +05305191 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_LAZY_ROAM:
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005192 /* Parse and fetch Activate Good Rssi Roam */
5193 if (!tb[PARAM_ROAM_ENABLE]) {
5194 hdd_err("Activate Good Rssi Roam failed");
5195 goto fail;
5196 }
5197 roam_params->good_rssi_roam = nla_get_s32(
5198 tb[PARAM_ROAM_ENABLE]);
5199 hdd_debug("Activate Good Rssi Roam (%d)",
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005200 roam_params->good_rssi_roam);
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005201 sme_update_roam_params(mac_handle, vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005202 roam_params,
5203 REASON_ROAM_GOOD_RSSI_CHANGED);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005204 break;
Srinivas Dasari0cc64372019-08-13 12:04:20 +05305205 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PREFS:
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005206 ret = hdd_set_bssid_prefs(hdd_ctx, roam_params, tb, vdev_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005207 if (ret)
5208 goto fail;
5209 break;
Srinivas Dasari0cc64372019-08-13 12:04:20 +05305210 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID:
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005211 ret = hdd_set_blacklist_bssid(hdd_ctx, roam_params,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08005212 tb, vdev_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005213 if (ret)
5214 goto fail;
5215 break;
Srinivas Dasari25d77b22019-08-07 16:21:48 +05305216 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET:
5217 ret = hdd_set_roam_with_control_config(hdd_ctx, tb, vdev_id);
5218 if (ret)
5219 goto fail;
5220 break;
Srinivas Dasarib6798ec2019-08-21 12:07:22 +05305221 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR:
5222 ret = hdd_clear_roam_control_config(hdd_ctx, tb, vdev_id);
5223 if (ret)
5224 goto fail;
5225 break;
Srinivas Dasari9ad9e252019-08-20 11:43:06 +05305226 case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET:
5227 ret = hdd_get_roam_control_config(hdd_ctx, tb, vdev_id);
5228 if (ret)
5229 goto fail;
5230 break;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005231 }
5232
5233 return 0;
5234
5235fail:
5236 return -EINVAL;
5237}
5238
5239/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005240 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
5241 * @wiphy: The wiphy structure
5242 * @wdev: The wireless device
5243 * @data: Data passed by framework
5244 * @data_len: Parameters to be configured passed as data
5245 *
5246 * The roaming related parameters are configured by the framework
5247 * using this interface.
5248 *
5249 * Return: Return either success or failure code.
5250 */
5251static int
5252__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
5253 struct wireless_dev *wdev, const void *data, int data_len)
5254{
5255 struct net_device *dev = wdev->netdev;
Jeff Johnsonce2ba702017-10-02 13:30:24 -07005256 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -07005257 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005258 struct roam_ext_params *roam_params = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005259 int ret;
5260
Anurag Chouhan6d760662016-02-20 16:05:43 +05305261 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005262 hdd_err("Command not allowed in FTM mode");
5263 return -EPERM;
5264 }
5265
Jeff Johnsonb8944722017-09-03 09:03:19 -07005266 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305267 if (ret)
5268 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005269
Jeff Johnsonb8944722017-09-03 09:03:19 -07005270 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05305271 hdd_err("Driver Modules are closed");
5272 return -EINVAL;
5273 }
5274
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005275 roam_params = qdf_mem_malloc(sizeof(*roam_params));
Min Liu74a1a502018-10-10 19:59:07 +08005276 if (!roam_params)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005277 return -ENOMEM;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005278
Jeff Johnsonb8944722017-09-03 09:03:19 -07005279 ret = hdd_set_ext_roam_params(hdd_ctx, data, data_len,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005280 adapter->vdev_id, roam_params);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005281 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005282 goto fail;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05305283
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005284 if (roam_params)
5285 qdf_mem_free(roam_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005286 return 0;
5287fail:
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005288 if (roam_params)
5289 qdf_mem_free(roam_params);
5290
5291 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005292}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05305293#undef PARAM_NUM_NW
5294#undef PARAM_SET_BSSID
gaurank kathpalia3ebc17b2019-05-29 10:25:09 +05305295#undef PARAM_SET_BSSID_HINT
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005296#undef PARAM_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05305297#undef PARAM_LIST_SSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07005298#undef MAX_ROAMING_PARAM
5299#undef PARAM_NUM_BSSID
5300#undef PARAM_BSSID_PREFS
5301#undef PARAM_ROAM_BSSID
5302#undef PARAM_RSSI_MODIFIER
5303#undef PARAMS_NUM_BSSID
5304#undef PARAM_BSSID_PARAMS
5305#undef PARAM_A_BAND_BOOST_THLD
5306#undef PARAM_A_BAND_PELT_THLD
5307#undef PARAM_A_BAND_BOOST_FACTOR
5308#undef PARAM_A_BAND_PELT_FACTOR
5309#undef PARAM_A_BAND_MAX_BOOST
5310#undef PARAM_ROAM_HISTERESYS
5311#undef PARAM_RSSI_TRIGGER
5312#undef PARAM_ROAM_ENABLE
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05305313
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005314
5315/**
5316 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
5317 * @wiphy: pointer to wireless wiphy structure.
5318 * @wdev: pointer to wireless_dev structure.
5319 * @data: Pointer to the data to be passed via vendor interface
5320 * @data_len:Length of the data to be passed
5321 *
5322 * Return: Return the Success or Failure code.
5323 */
5324static int
5325wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
5326 struct wireless_dev *wdev,
5327 const void *data,
5328 int data_len)
5329{
Dustin Browna09acf42018-11-08 12:32:26 +05305330 int errno;
5331 struct osif_vdev_sync *vdev_sync;
5332
5333 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
5334 if (errno)
5335 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336
Dustin Browna09acf42018-11-08 12:32:26 +05305337 errno = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005338 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005339
Dustin Browna09acf42018-11-08 12:32:26 +05305340 osif_vdev_sync_op_stop(vdev_sync);
5341
5342 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005343}
5344
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305345#define PWR_SAVE_FAIL_CMD_INDEX \
5346 QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX
Jeff Johnsonb7fa2562018-07-02 08:36:17 -07005347
5348void hdd_chip_pwr_save_fail_detected_cb(hdd_handle_t hdd_handle,
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305349 struct chip_pwr_save_fail_detected_params
5350 *data)
5351{
Jeff Johnsonb7fa2562018-07-02 08:36:17 -07005352 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305353 struct sk_buff *skb;
5354 int flags = cds_get_gfp_flags();
5355
Dustin Brown491d54b2018-03-14 12:39:11 -07005356 hdd_enter();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305357
5358 if (wlan_hdd_validate_context(hdd_ctx))
5359 return;
5360
5361 if (!data) {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07005362 hdd_debug("data is null");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305363 return;
5364 }
5365
5366 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5367 NULL, NLMSG_HDRLEN +
5368 sizeof(data->failure_reason_code) +
5369 NLMSG_HDRLEN, PWR_SAVE_FAIL_CMD_INDEX,
5370 flags);
5371
5372 if (!skb) {
Dustin Brown5e89ef82018-03-14 11:50:23 -07005373 hdd_info("cfg80211_vendor_event_alloc failed");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305374 return;
5375 }
5376
Dustin Brownbacc48f2018-03-14 14:48:44 -07005377 hdd_debug("failure reason code: %u", data->failure_reason_code);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305378
5379 if (nla_put_u32(skb,
5380 QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON,
5381 data->failure_reason_code))
5382 goto fail;
5383
5384 cfg80211_vendor_event(skb, flags);
Dustin Browne74003f2018-03-14 12:51:58 -07005385 hdd_exit();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05305386 return;
5387
5388fail:
5389 kfree_skb(skb);
5390}
5391#undef PWR_SAVE_FAIL_CMD_INDEX
5392
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005393static const struct nla_policy
5394wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
5395 +1] = {
5396 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
5397};
5398
5399/**
5400 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
5401 * @hdd_ctx: HDD context
5402 * @device_mode: device mode
5403 * Return: bool
5404 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005405static bool wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context *hdd_ctx,
Jeff Johnsonc1e62782017-11-09 09:50:17 -08005406 enum QDF_OPMODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005407{
Jeff Johnsone5006672017-08-29 14:39:02 -07005408 struct hdd_adapter *adapter;
Jeff Johnson87251032017-08-29 13:31:11 -07005409 struct hdd_ap_ctx *ap_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07005410 struct hdd_station_ctx *sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005411
Dustin Brown920397d2017-12-13 16:27:50 -08005412 hdd_for_each_adapter(hdd_ctx, adapter) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08005414 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005415 ap_ctx =
5416 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417 /*
5418 * if there is SAP already running on DFS channel,
5419 * do not disable scan on dfs channels. Note that
5420 * with SAP on DFS, there cannot be conurrency on
5421 * single radio. But then we can have multiple
5422 * radios !!
5423 */
Will Huang4b097f52019-08-29 10:51:56 -07005424 if (CHANNEL_STATE_DFS ==
5425 wlan_reg_get_channel_state_for_freq(
5426 hdd_ctx->pdev,
5427 ap_ctx->operating_chan_freq)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005428 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005429 return true;
5430 }
5431 }
5432
5433 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08005434 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005435 sta_ctx =
5436 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005437 /*
5438 * if STA is already connected on DFS channel,
5439 * do not disable scan on dfs channels
5440 */
5441 if (hdd_conn_is_connected(sta_ctx) &&
Will Huang4b097f52019-08-29 10:51:56 -07005442 (CHANNEL_STATE_DFS ==
5443 wlan_reg_get_channel_state_for_freq(
5444 hdd_ctx->pdev,
5445 sta_ctx->conn_info.chan_freq))) {
Jeff Johnson020db452016-06-29 14:37:26 -07005446 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005447 return true;
5448 }
5449 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005450 }
5451
5452 return false;
5453}
5454
5455/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005456 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005457 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005458 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005459 *
5460 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005461 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005462 * Fails the disable request if any device is active on a DFS channel.
5463 *
5464 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005465 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005466
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005467int wlan_hdd_enable_dfs_chan_scan(struct hdd_context *hdd_ctx,
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005468 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005469{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305470 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005471 bool err;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005472 mac_handle_t mac_handle;
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305473 bool enable_dfs_scan = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005474
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305475 ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
5476 &enable_dfs_scan);
5477
5478 if (enable_dfs_channels == enable_dfs_scan) {
Dustin Brown6a8d39b2018-08-14 15:27:26 -07005479 hdd_debug("DFS channels are already %s",
5480 enable_dfs_channels ? "enabled" : "disabled");
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005481 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005482 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005483
5484 if (!enable_dfs_channels) {
5485 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
5486 QDF_STA_MODE);
5487 if (err)
5488 return -EOPNOTSUPP;
5489
5490 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
5491 QDF_SAP_MODE);
5492 if (err)
5493 return -EOPNOTSUPP;
5494 }
5495
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305496 ucfg_scan_cfg_set_dfs_chan_scan_allowed(hdd_ctx->psoc,
5497 enable_dfs_channels);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005498
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005499 mac_handle = hdd_ctx->mac_handle;
5500 status = sme_enable_dfs_chan_scan(mac_handle, enable_dfs_channels);
Min Liu5eaf7242018-03-13 17:32:15 +08005501 if (QDF_IS_STATUS_ERROR(status)) {
5502 hdd_err("Failed to set DFS channel scan flag to %d",
5503 enable_dfs_channels);
5504 return qdf_status_to_os_return(status);
5505 }
5506
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005507 hdd_abort_mac_scan_all_adapters(hdd_ctx);
5508
5509 /* pass dfs channel status to regulatory component */
Dustin Brown07901ec2018-09-07 11:02:41 -07005510 status = ucfg_reg_enable_dfs_channels(hdd_ctx->pdev,
5511 enable_dfs_channels);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07005512
5513 if (QDF_IS_STATUS_ERROR(status))
5514 hdd_err("Failed to %s DFS channels",
5515 enable_dfs_channels ? "enable" : "disable");
5516
5517 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005518}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005519
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005520/**
5521 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
5522 * @wiphy: corestack handler
5523 * @wdev: wireless device
5524 * @data: data
5525 * @data_len: data length
5526 * Return: success(0) or reason code for failure
5527 */
5528static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
5529 struct wireless_dev *wdev,
5530 const void *data,
5531 int data_len)
5532{
5533 struct net_device *dev = wdev->netdev;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005534 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005535 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
5536 int ret_val;
5537 uint32_t no_dfs_flag = 0;
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305538 bool enable_dfs_scan = true;
Dustin Brownfdf17c12018-03-14 12:55:34 -07005539 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005540
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005541 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305542 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005543 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005544
Dustin Brown4ea21db2018-01-05 14:13:17 -08005545 if (wlan_cfg80211_nla_parse(tb,
5546 QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
5547 data, data_len,
5548 wlan_hdd_set_no_dfs_flag_config_policy)) {
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005549 hdd_err("invalid attr");
5550 return -EINVAL;
5551 }
5552
5553 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
5554 hdd_err("attr dfs flag failed");
5555 return -EINVAL;
5556 }
5557
5558 no_dfs_flag = nla_get_u32(
5559 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
5560
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005561 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005562
5563 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07005564 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005565 return -EINVAL;
5566 }
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305567 ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
5568 &enable_dfs_scan);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08005569
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305570 if (enable_dfs_scan) {
bings50112bb2018-12-21 15:51:51 +08005571 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
5572 } else {
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305573 if ((!no_dfs_flag) != enable_dfs_scan) {
bings50112bb2018-12-21 15:51:51 +08005574 hdd_err("DFS chan ini configured %d, no dfs flag: %d",
gaurank kathpalia97c070b2019-01-07 17:23:06 +05305575 enable_dfs_scan,
bings50112bb2018-12-21 15:51:51 +08005576 no_dfs_flag);
5577 return -EINVAL;
5578 }
5579 }
5580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005581 return ret_val;
5582}
5583
5584/**
5585 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
5586 *
5587 * @wiphy: wiphy device pointer
5588 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07005589 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005590 * @data_len: Buffer length
5591 *
5592 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
5593 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
5594 *
5595 * Return: EOK or other error codes.
5596 */
5597
5598static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
5599 struct wireless_dev *wdev,
5600 const void *data,
5601 int data_len)
5602{
Dustin Brown363b4792019-02-05 16:11:55 -08005603 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08005604 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05305605
Dustin Brown363b4792019-02-05 16:11:55 -08005606 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08005607 if (errno)
5608 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005609
Dustin Brownf0f00612019-01-31 16:02:24 -08005610 errno = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
5611 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005612
Dustin Brown363b4792019-02-05 16:11:55 -08005613 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05305614
Dustin Brownf0f00612019-01-31 16:02:24 -08005615 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005616}
5617
Manikandan Mohan80dea792016-04-28 16:36:48 -07005618static const struct nla_policy
5619wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
5620 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
5621};
5622
5623/**
5624 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
5625 * @wiphy: wiphy device pointer
5626 * @wdev: wireless device pointer
5627 * @data: Vendor command data buffer
5628 * @data_len: Buffer length
5629 *
5630 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
5631 * setup WISA Mode features.
5632 *
5633 * Return: Success(0) or reason code for failure
5634 */
5635static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
5636 struct wireless_dev *wdev, const void *data, int data_len)
5637{
5638 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07005639 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005640 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005641 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
5642 struct sir_wisa_params wisa;
5643 int ret_val;
5644 QDF_STATUS status;
5645 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07005646 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005647 mac_handle_t mac_handle;
Manikandan Mohan80dea792016-04-28 16:36:48 -07005648
Dustin Brownfdf17c12018-03-14 12:55:34 -07005649 hdd_enter_dev(dev);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005650 ret_val = wlan_hdd_validate_context(hdd_ctx);
5651 if (ret_val)
5652 goto err;
5653
5654 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5655 hdd_err("Command not allowed in FTM mode");
5656 return -EPERM;
5657 }
5658
Dustin Brown4ea21db2018-01-05 14:13:17 -08005659 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data,
5660 data_len, wlan_hdd_wisa_cmd_policy)) {
Manikandan Mohan80dea792016-04-28 16:36:48 -07005661 hdd_err("Invalid WISA cmd attributes");
5662 ret_val = -EINVAL;
5663 goto err;
5664 }
5665 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
5666 hdd_err("Invalid WISA mode");
5667 ret_val = -EINVAL;
5668 goto err;
5669 }
5670
5671 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005672 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005673 wisa.mode = wisa_mode;
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005674 wisa.vdev_id = adapter->vdev_id;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005675 mac_handle = hdd_ctx->mac_handle;
5676 status = sme_set_wisa_params(mac_handle, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07005677 if (!QDF_IS_STATUS_SUCCESS(status)) {
5678 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005679 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07005680 }
Rakesh Pillai6a36b0a2019-09-06 16:30:05 +05305681 if (QDF_IS_STATUS_SUCCESS(status) || !wisa_mode)
5682 cdp_set_wisa_mode(soc, adapter->vdev_id, wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005683err:
Dustin Browne74003f2018-03-14 12:51:58 -07005684 hdd_exit();
Manikandan Mohan80dea792016-04-28 16:36:48 -07005685 return ret_val;
5686}
5687
5688/**
5689 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
5690 * @wiphy: corestack handler
5691 * @wdev: wireless device
5692 * @data: data
5693 * @data_len: data length
5694 *
5695 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
5696 * setup WISA mode features.
5697 *
5698 * Return: Success(0) or reason code for failure
5699 */
5700static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
5701 struct wireless_dev *wdev,
5702 const void *data,
5703 int data_len)
5704{
Dustin Browna09acf42018-11-08 12:32:26 +05305705 int errno;
5706 struct osif_vdev_sync *vdev_sync;
5707
5708 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
5709 if (errno)
5710 return errno;
Manikandan Mohan80dea792016-04-28 16:36:48 -07005711
Dustin Browna09acf42018-11-08 12:32:26 +05305712 errno = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev,
5713 data, data_len);
Manikandan Mohan80dea792016-04-28 16:36:48 -07005714
Dustin Browna09acf42018-11-08 12:32:26 +05305715 osif_vdev_sync_op_stop(vdev_sync);
5716
5717 return errno;
Manikandan Mohan80dea792016-04-28 16:36:48 -07005718}
5719
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05305720struct hdd_station_info *hdd_get_stainfo(struct hdd_station_info *astainfo,
5721 struct qdf_mac_addr mac_addr)
Will Huang496b36c2017-07-11 16:38:50 +08005722{
Jeff Johnson82155922017-09-30 16:54:14 -07005723 struct hdd_station_info *stainfo = NULL;
Will Huang496b36c2017-07-11 16:38:50 +08005724 int i;
5725
5726 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05305727 if (!qdf_mem_cmp(&astainfo[i].sta_mac,
Will Huang496b36c2017-07-11 16:38:50 +08005728 &mac_addr,
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05305729 QDF_MAC_ADDR_SIZE)) {
5730 stainfo = &astainfo[i];
5731 break;
5732 }
Will Huang496b36c2017-07-11 16:38:50 +08005733 }
5734
5735 return stainfo;
5736}
5737
Anurag Chouhan96919482016-07-13 16:36:57 +05305738/*
5739 * undef short names defined for get station command
5740 * used by __wlan_hdd_cfg80211_get_station_cmd()
5741 */
5742#undef STATION_INVALID
5743#undef STATION_INFO
5744#undef STATION_ASSOC_FAIL_REASON
Will Huang496b36c2017-07-11 16:38:50 +08005745#undef STATION_REMOTE
Anurag Chouhan96919482016-07-13 16:36:57 +05305746#undef STATION_MAX
Will Huang496b36c2017-07-11 16:38:50 +08005747#undef LINK_INFO_STANDARD_NL80211_ATTR
5748#undef AP_INFO_STANDARD_NL80211_ATTR
5749#undef INFO_ROAM_COUNT
5750#undef INFO_AKM
5751#undef WLAN802_11_MODE
5752#undef AP_INFO_HS20_INDICATION
5753#undef HT_OPERATION
5754#undef VHT_OPERATION
5755#undef INFO_ASSOC_FAIL_REASON
5756#undef REMOTE_MAX_PHY_RATE
5757#undef REMOTE_TX_PACKETS
5758#undef REMOTE_TX_BYTES
5759#undef REMOTE_RX_PACKETS
5760#undef REMOTE_RX_BYTES
5761#undef REMOTE_LAST_TX_RATE
5762#undef REMOTE_LAST_RX_RATE
5763#undef REMOTE_WMM
5764#undef REMOTE_SUPPORTED_MODE
5765#undef REMOTE_AMPDU
5766#undef REMOTE_TX_STBC
5767#undef REMOTE_RX_STBC
5768#undef REMOTE_CH_WIDTH
5769#undef REMOTE_SGI_ENABLE
5770#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
5771#undef REMOTE_PAD
5772#endif
Anurag Chouhan96919482016-07-13 16:36:57 +05305773
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005774#ifdef WLAN_FEATURE_ROAM_OFFLOAD
sheenam monga6e49e5c2019-04-04 12:49:04 +05305775
5776/**
5777 * hdd_get_roam_reason() - convert wmi roam reason to
5778 * enum qca_roam_reason
5779 * @roam_scan_trigger: wmi roam scan trigger ID
5780 *
5781 * Return: Meaningful qca_roam_reason from enum WMI_ROAM_TRIGGER_REASON_ID
5782 */
5783static enum qca_roam_reason hdd_get_roam_reason(uint16_t roam_scan_trigger)
5784{
5785 switch (roam_scan_trigger) {
5786 case WMI_ROAM_TRIGGER_REASON_PER:
5787 return QCA_ROAM_REASON_PER;
5788 case WMI_ROAM_TRIGGER_REASON_BMISS:
5789 return QCA_ROAM_REASON_BEACON_MISS;
5790 case WMI_ROAM_TRIGGER_REASON_LOW_RSSI:
5791 case WMI_ROAM_TRIGGER_REASON_BACKGROUND:
5792 return QCA_ROAM_REASON_POOR_RSSI;
5793 case WMI_ROAM_TRIGGER_REASON_HIGH_RSSI:
5794 return QCA_ROAM_REASON_BETTER_RSSI;
5795 case WMI_ROAM_TRIGGER_REASON_DENSE:
5796 return QCA_ROAM_REASON_CONGESTION;
5797 case WMI_ROAM_TRIGGER_REASON_FORCED:
5798 return QCA_ROAM_REASON_USER_TRIGGER;
5799 case WMI_ROAM_TRIGGER_REASON_BTM:
5800 return QCA_ROAM_REASON_BTM;
5801 case WMI_ROAM_TRIGGER_REASON_BSS_LOAD:
5802 return QCA_ROAM_REASON_BSS_LOAD;
5803 default:
5804 return QCA_ROAM_REASON_UNKNOWN;
5805 }
5806
5807 return QCA_ROAM_REASON_UNKNOWN;
5808}
5809
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005810/**
5811 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
5812 * @wiphy: pointer to wireless wiphy structure.
5813 * @wdev: pointer to wireless_dev structure.
5814 * @data: Pointer to the Key data
5815 * @data_len:Length of the data passed
5816 *
5817 * This is called when wlan driver needs to save the keys received via
5818 * vendor specific command.
5819 *
5820 * Return: Return the Success or Failure code.
5821 */
5822static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
5823 struct wireless_dev *wdev,
5824 const void *data, int data_len)
5825{
5826 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
5827 struct net_device *dev = wdev->netdev;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005828 struct hdd_adapter *hdd_adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5829 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005830 int status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005831 struct pmkid_mode_bits pmkid_modes;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005832 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005833
Dustin Brownfdf17c12018-03-14 12:55:34 -07005834 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005835
Anurag Chouhan6d760662016-02-20 16:05:43 +05305836 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005837 hdd_err("Command not allowed in FTM mode");
5838 return -EPERM;
5839 }
5840
Jeff Johnsond36fa332019-03-18 13:42:25 -07005841 if ((!data) || (data_len <= 0) ||
Hanumanth Reddy Pothula53874852018-03-08 19:57:49 +05305842 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005843 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844 return -EINVAL;
5845 }
5846
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005847 hdd_ctx = WLAN_HDD_GET_CTX(hdd_adapter);
5848 if (!hdd_ctx) {
Jeff Johnson020db452016-06-29 14:37:26 -07005849 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005850 return -EINVAL;
5851 }
5852
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005853 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305854 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005855 return status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005856
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005857 hdd_get_pmkid_modes(hdd_ctx, &pmkid_modes);
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005858
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005859 mac_handle = hdd_ctx->mac_handle;
5860 sme_update_roam_key_mgmt_offload_enabled(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005861 hdd_adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005862 true, &pmkid_modes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305863 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
5864 qdf_mem_copy(local_pmk, data, data_len);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005865 sme_roam_set_psk_pmk(mac_handle, hdd_adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005866 local_pmk, data_len);
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +05305867 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005868 return 0;
5869}
5870
5871/**
5872 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
5873 * @wiphy: pointer to wireless wiphy structure.
5874 * @wdev: pointer to wireless_dev structure.
5875 * @data: Pointer to the Key data
5876 * @data_len:Length of the data passed
5877 *
5878 * This is called when wlan driver needs to save the keys received via
5879 * vendor specific command.
5880 *
5881 * Return: Return the Success or Failure code.
5882 */
5883static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
5884 struct wireless_dev *wdev,
5885 const void *data, int data_len)
5886{
Dustin Browna09acf42018-11-08 12:32:26 +05305887 int errno;
5888 struct osif_vdev_sync *vdev_sync;
5889
5890 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
5891 if (errno)
5892 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005893
Dustin Browna09acf42018-11-08 12:32:26 +05305894 errno = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev,
5895 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005896
Dustin Browna09acf42018-11-08 12:32:26 +05305897 osif_vdev_sync_op_stop(vdev_sync);
5898
5899 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005900}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08005901#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005902
5903static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
5904 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
5905 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
5906 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07005907 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005908};
5909
5910/**
5911 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
5912 * @wiphy: pointer to wireless wiphy structure.
5913 * @wdev: pointer to wireless_dev structure.
5914 * @data: Pointer to the data to be passed via vendor interface
5915 * @data_len:Length of the data to be passed
5916 *
5917 * This is called when wlan driver needs to send wifi driver related info
5918 * (driver/fw version) to the user space application upon request.
5919 *
5920 * Return: Return the Success or Failure code.
5921 */
5922static int
5923__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
5924 struct wireless_dev *wdev,
5925 const void *data, int data_len)
5926{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005927 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005928 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07005929 tSirVersionString driver_version;
5930 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005931 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07005932 struct sk_buff *reply_skb;
5933 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005934
Dustin Brownfdf17c12018-03-14 12:55:34 -07005935 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005936
Anurag Chouhan6d760662016-02-20 16:05:43 +05305937 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005938 hdd_err("Command not allowed in FTM mode");
5939 return -EPERM;
5940 }
5941
5942 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305943 if (status)
5944 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005945
Dustin Brown4ea21db2018-01-05 14:13:17 -08005946 if (wlan_cfg80211_nla_parse(tb_vendor,
5947 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
5948 data, data_len,
5949 qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07005950 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005951 return -EINVAL;
5952 }
5953
5954 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08005955 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07005956 strlcpy(driver_version, QWLAN_VERSIONSTR,
5957 sizeof(driver_version));
5958 skb_len += strlen(driver_version) + 1;
5959 count++;
5960 }
5961
5962 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005963 hdd_debug("Rcvd req for FW version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07005964 snprintf(firmware_version, sizeof(firmware_version),
Ashish Kumar Dhanotiyaeadb28b2019-06-28 14:34:19 +05305965 "FW:%d.%d.%d.%d.%d.%d HW:%s",
5966 hdd_ctx->fw_version_info.major_spid,
5967 hdd_ctx->fw_version_info.minor_spid,
5968 hdd_ctx->fw_version_info.siid,
5969 hdd_ctx->fw_version_info.rel_id,
5970 hdd_ctx->fw_version_info.crmid,
5971 hdd_ctx->fw_version_info.sub_id,
5972 hdd_ctx->target_hw_name);
Ryan Hsu7ac88852016-04-28 10:20:34 -07005973 skb_len += strlen(firmware_version) + 1;
5974 count++;
5975 }
5976
Rajeev Kumar Sirasanagandla551613d2018-05-16 17:21:01 +05305977 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
5978 hdd_debug("Rcvd req for Radio index");
5979 skb_len += sizeof(uint32_t);
5980 count++;
5981 }
5982
Ryan Hsu7ac88852016-04-28 10:20:34 -07005983 if (count == 0) {
5984 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005985 return -EINVAL;
5986 }
5987
Ryan Hsu7ac88852016-04-28 10:20:34 -07005988 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
5989 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
5990
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005991 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07005992 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005993 return -ENOMEM;
5994 }
5995
Ryan Hsu7ac88852016-04-28 10:20:34 -07005996 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
5997 if (nla_put_string(reply_skb,
5998 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
5999 driver_version))
6000 goto error_nla_fail;
6001 }
6002
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05306003 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07006004 if (nla_put_string(reply_skb,
6005 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
6006 firmware_version))
6007 goto error_nla_fail;
6008 }
6009
6010 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
6011 if (nla_put_u32(reply_skb,
6012 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
6013 hdd_ctx->radio_index))
6014 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006015 }
6016
6017 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07006018
6019error_nla_fail:
6020 hdd_err("nla put fail");
6021 kfree_skb(reply_skb);
6022 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006023}
6024
6025/**
6026 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
6027 * @wiphy: pointer to wireless wiphy structure.
6028 * @wdev: pointer to wireless_dev structure.
6029 * @data: Pointer to the data to be passed via vendor interface
6030 * @data_len:Length of the data to be passed
6031 *
6032 * This is called when wlan driver needs to send wifi driver related info
6033 * (driver/fw version) to the user space application upon request.
6034 *
6035 * Return: Return the Success or Failure code.
6036 */
6037static int
6038wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
6039 struct wireless_dev *wdev,
6040 const void *data, int data_len)
6041{
Dustin Brown363b4792019-02-05 16:11:55 -08006042 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08006043 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006044
Dustin Brown363b4792019-02-05 16:11:55 -08006045 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08006046 if (errno)
6047 return errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05306048
Dustin Brownf0f00612019-01-31 16:02:24 -08006049 errno = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006050
Dustin Brown363b4792019-02-05 16:11:55 -08006051 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08006052
6053 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006054}
6055
6056/**
6057 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
6058 * @wiphy: pointer to wireless wiphy structure.
6059 * @wdev: pointer to wireless_dev structure.
6060 * @data: Pointer to the data to be passed via vendor interface
6061 * @data_len:Length of the data to be passed
6062 *
6063 * This is called by userspace to know the supported logger features
6064 *
6065 * Return: Return the Success or Failure code.
6066 */
6067static int
6068__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
6069 struct wireless_dev *wdev,
6070 const void *data, int data_len)
6071{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006072 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006073 int status;
6074 uint32_t features;
6075 struct sk_buff *reply_skb = NULL;
sheenam monga63736f62019-12-23 18:44:31 +05306076 bool enable_ring_buffer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006077
Dustin Brownfdf17c12018-03-14 12:55:34 -07006078 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08006079
Anurag Chouhan6d760662016-02-20 16:05:43 +05306080 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006081 hdd_err("Command not allowed in FTM mode");
6082 return -EPERM;
6083 }
6084
6085 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05306086 if (status)
6087 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006088
6089 features = 0;
sheenam monga63736f62019-12-23 18:44:31 +05306090 wlan_mlme_get_status_ring_buffer(hdd_ctx->psoc, &enable_ring_buffer);
6091 if (enable_ring_buffer) {
6092 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
6093 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
6094 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
6095 features |= WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
6096 features |= WIFI_LOGGER_PACKET_FATE_SUPPORTED;
6097 hdd_debug("Supported logger features: 0x%0x", features);
6098 } else {
6099 hdd_info("Ring buffer disable");
6100 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006101
6102 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6103 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
6104 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07006105 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006106 return -ENOMEM;
6107 }
6108
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006109 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
6110 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006111 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006112 kfree_skb(reply_skb);
6113 return -EINVAL;
6114 }
6115
6116 return cfg80211_vendor_cmd_reply(reply_skb);
6117}
6118
6119/**
6120 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
6121 * @wiphy: pointer to wireless wiphy structure.
6122 * @wdev: pointer to wireless_dev structure.
6123 * @data: Pointer to the data to be passed via vendor interface
6124 * @data_len:Length of the data to be passed
6125 *
6126 * This is called by userspace to know the supported logger features
6127 *
6128 * Return: Return the Success or Failure code.
6129 */
6130static int
6131wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
6132 struct wireless_dev *wdev,
6133 const void *data, int data_len)
6134{
Dustin Brown363b4792019-02-05 16:11:55 -08006135 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08006136 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05306137
Dustin Brown363b4792019-02-05 16:11:55 -08006138 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08006139 if (errno)
6140 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006141
Dustin Brownf0f00612019-01-31 16:02:24 -08006142 errno = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
6143 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006144
Dustin Brown363b4792019-02-05 16:11:55 -08006145 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05306146
Dustin Brownf0f00612019-01-31 16:02:24 -08006147 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006148}
6149
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306150#ifdef WLAN_FEATURE_GTK_OFFLOAD
6151void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05306152 uint8_t *kck_ptr, uint8_t kck_len,
6153 uint8_t *kek_ptr, uint32_t kek_len,
6154 uint8_t *replay_ctr, bool big_endian)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306155{
6156 struct hdd_station_ctx *hdd_sta_ctx;
6157 uint8_t *buf;
6158 int i;
6159 struct pmo_gtk_req *gtk_req = NULL;
Min Liu8c5d99e2018-09-10 17:18:44 +08006160 struct wlan_objmgr_vdev *vdev;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306161 QDF_STATUS status = QDF_STATUS_E_FAILURE;
6162
6163 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
Min Liu74a1a502018-10-10 19:59:07 +08006164 if (!gtk_req)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306165 return;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306166
6167 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05306168 if (kck_ptr) {
6169 if (kck_len > sizeof(gtk_req->kck)) {
6170 kck_len = sizeof(gtk_req->kck);
6171 QDF_ASSERT(0);
6172 }
6173 qdf_mem_copy(gtk_req->kck, kck_ptr, kck_len);
Yeshwanth Sriram Guntukae6313412019-08-06 14:18:33 +05306174 gtk_req->kck_len = kck_len;
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05306175 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306176
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08006177 if (kek_ptr) {
6178 /* paranoia */
6179 if (kek_len > sizeof(gtk_req->kek)) {
6180 kek_len = sizeof(gtk_req->kek);
6181 QDF_ASSERT(0);
6182 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306183 qdf_mem_copy(gtk_req->kek, kek_ptr, kek_len);
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08006184 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306185
Jeff Johnsone04b6992019-02-27 14:06:55 -08006186 qdf_copy_macaddr(&gtk_req->bssid, &hdd_sta_ctx->conn_info.bssid);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306187
6188 gtk_req->kek_len = kek_len;
gaurank kathpalia82a1b2b2018-07-10 16:49:10 +05306189 gtk_req->is_fils_connection = hdd_is_fils_connection(adapter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306190
6191 /* convert big to little endian since driver work on little endian */
6192 buf = (uint8_t *)&gtk_req->replay_counter;
6193 for (i = 0; i < 8; i++)
6194 buf[7 - i] = replay_ctr[i];
6195
Min Liu8c5d99e2018-09-10 17:18:44 +08006196 vdev = hdd_objmgr_get_vdev(adapter);
6197 if (!vdev)
6198 goto end;
6199 status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05306200 hdd_objmgr_put_vdev(vdev);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306201 if (status != QDF_STATUS_SUCCESS)
6202 hdd_err("Failed to cache GTK Offload");
6203
Min Liu8c5d99e2018-09-10 17:18:44 +08006204end:
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306205 qdf_mem_free(gtk_req);
6206}
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306207#endif
6208
Sridhar Selvaraje5260442017-08-19 10:12:03 +05306209#if defined(WLAN_FEATURE_FILS_SK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306210/**
6211 * wlan_hdd_add_fils_params_roam_auth_event() - Adds FILS params in roam auth
6212 * @skb: SK buffer
6213 * @roam_info: Roam info
6214 *
6215 * API adds fils params[pmk, pmkid, next sequence number] to roam auth event
6216 *
6217 * Return: zero on success, error code on failure
6218 */
Jeff Johnson172237b2017-11-07 15:32:59 -08006219static int
6220wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
6221 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306222{
6223 if (roam_info->pmk_len &&
6224 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK,
6225 roam_info->pmk_len, roam_info->pmk)) {
6226 hdd_err("pmk send fail");
6227 return -EINVAL;
6228 }
6229
6230 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID,
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -07006231 PMKID_LEN, roam_info->pmkid)) {
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306232 hdd_err("pmkid send fail");
6233 return -EINVAL;
6234 }
6235
Vignesh Viswanathan8da68cf2017-09-07 14:00:04 +05306236 hdd_debug("Update ERP Seq Num %d, Next ERP Seq Num %d",
6237 roam_info->update_erp_next_seq_num,
6238 roam_info->next_erp_seq_num);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306239 if (roam_info->update_erp_next_seq_num &&
6240 nla_put_u16(skb,
6241 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM,
6242 roam_info->next_erp_seq_num)) {
6243 hdd_err("ERP seq num send fail");
6244 return -EINVAL;
6245 }
6246
6247 return 0;
6248}
6249#else
Jeff Johnson172237b2017-11-07 15:32:59 -08006250static inline int
6251wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
6252 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306253{
6254 return 0;
6255}
6256#endif
6257
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08006258#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Abhishek Ambure5e9b6a42020-02-12 21:32:35 +05306259void hdd_send_roam_scan_ch_list_event(struct hdd_context *hdd_ctx,
Abhishek Ambure3823c362020-03-18 14:15:08 +05306260 uint8_t vdev_id, uint16_t buf_len,
6261 uint8_t *buf)
Abhishek Ambure5e9b6a42020-02-12 21:32:35 +05306262{
6263 struct sk_buff *vendor_event;
Abhishek Ambure3823c362020-03-18 14:15:08 +05306264 struct hdd_adapter *adapter;
Abhishek Ambure5e9b6a42020-02-12 21:32:35 +05306265 uint32_t len, ret;
6266
6267 if (!hdd_ctx) {
6268 hdd_err_rl("hdd context is null");
6269 return;
6270 }
6271
Abhishek Ambure3823c362020-03-18 14:15:08 +05306272 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
6273 if (!adapter)
6274 return;
6275
Abhishek Ambure5e9b6a42020-02-12 21:32:35 +05306276 len = nla_total_size(buf_len) + NLMSG_HDRLEN;
6277 vendor_event =
6278 cfg80211_vendor_event_alloc(
Abhishek Ambure3823c362020-03-18 14:15:08 +05306279 hdd_ctx->wiphy, &(adapter->wdev), len,
Abhishek Ambure5e9b6a42020-02-12 21:32:35 +05306280 QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO_INDEX,
6281 GFP_KERNEL);
6282
6283 if (!vendor_event) {
6284 hdd_err("cfg80211_vendor_event_alloc failed");
6285 return;
6286 }
6287
6288 ret = nla_put(vendor_event,
6289 QCA_WLAN_VENDOR_ATTR_UPDATE_STA_INFO_CONNECT_CHANNELS,
6290 buf_len, buf);
6291 if (ret) {
6292 hdd_err("OEM event put fails status %d", ret);
6293 kfree_skb(vendor_event);
6294 return;
6295 }
6296
6297 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
6298}
6299
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006300/**
6301 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05306302 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006303 * @bssid: pointer to bssid of roamed AP.
6304 * @req_rsn_ie: Pointer to request RSN IE
6305 * @req_rsn_len: Length of the request RSN IE
6306 * @rsp_rsn_ie: Pointer to response RSN IE
6307 * @rsp_rsn_len: Length of the response RSN IE
6308 * @roam_info_ptr: Pointer to the roaming related information
6309 *
6310 * This is called when wlan driver needs to send the roaming and
6311 * authorization information after roaming.
6312 *
6313 * The information that would be sent is the request RSN IE, response
6314 * RSN IE and BSSID of the newly roamed AP.
6315 *
6316 * If the Authorized status is authenticated, then additional parameters
6317 * like PTK's KCK and KEK and Replay Counter would also be passed to the
6318 * supplicant.
6319 *
6320 * The supplicant upon receiving this event would ignore the legacy
6321 * cfg80211_roamed call and use the entire information from this event.
6322 * The cfg80211_roamed should still co-exist since the kernel will
6323 * make use of the parameters even if the supplicant ignores it.
6324 *
6325 * Return: Return the Success or Failure code.
6326 */
Jeff Johnsone5006672017-08-29 14:39:02 -07006327int wlan_hdd_send_roam_auth_event(struct hdd_adapter *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006328 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
Jeff Johnson172237b2017-11-07 15:32:59 -08006329 uint32_t rsp_rsn_len, struct csr_roam_info *roam_info_ptr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006330{
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006331 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006332 struct sk_buff *skb = NULL;
Pragaspathi Thilagaraj7a1a08e2019-05-29 01:20:29 +05306333 enum csr_akm_type auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306334 uint32_t fils_params_len;
6335 int status;
sheenam monga6e49e5c2019-04-04 12:49:04 +05306336 enum qca_roam_reason hdd_roam_reason;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -07006337
Dustin Brown491d54b2018-03-14 12:39:11 -07006338 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006339
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006340 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006341 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006342
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006343 if (!roaming_offload_enabled(hdd_ctx) ||
6344 !roam_info_ptr->roamSynchInProgress)
Prashanth Bhattabfc25292015-11-05 11:16:21 -08006345 return 0;
6346
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306347 /*
6348 * PMK is sent from FW in Roam Synch Event for FILS Roaming.
6349 * In that case, add three more NL attributes.ie. PMK, PMKID
6350 * and ERP next sequence number. Add corresponding lengths
6351 * with 3 extra NL message headers for each of the
6352 * aforementioned params.
6353 */
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -07006354 fils_params_len = roam_info_ptr->pmk_len + PMKID_LEN +
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306355 sizeof(uint16_t) + (3 * NLMSG_HDRLEN);
6356
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006357 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05306358 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006359 ETH_ALEN + req_rsn_len + rsp_rsn_len +
6360 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306361 SIR_KCK_KEY_LEN + roam_info_ptr->kek_len +
sheenam monga6e49e5c2019-04-04 12:49:04 +05306362 sizeof(uint16_t) + sizeof(uint8_t) +
6363 (9 * NLMSG_HDRLEN) + fils_params_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006364 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
6365 GFP_KERNEL);
6366
6367 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07006368 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006369 return -EINVAL;
6370 }
6371
6372 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
6373 ETH_ALEN, bssid) ||
6374 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
6375 req_rsn_len, req_rsn_ie) ||
6376 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
6377 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006378 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006379 goto nla_put_failure;
6380 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006381 if (roam_info_ptr->synchAuthStatus ==
6382 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07006383 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08006384 if (nla_put_u8(skb,
6385 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
6386 hdd_err("nla put fail");
6387 goto nla_put_failure;
6388 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08006389 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
6390 /* if FT or CCKM connection: dont send replay counter */
6391 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
6392 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
Pragaspathi Thilagaraj96259b22019-02-15 01:08:27 +05306393 auth_type != eCSR_AUTH_TYPE_FT_SAE &&
6394 auth_type != eCSR_AUTH_TYPE_FT_SUITEB_EAP_SHA384 &&
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08006395 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
6396 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
6397 nla_put(skb,
6398 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
6399 SIR_REPLAY_CTR_LEN,
6400 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006401 hdd_err("non FT/non CCKM connection");
6402 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08006403 goto nla_put_failure;
6404 }
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05306405 if (roam_info_ptr->kek_len > SIR_KEK_KEY_LEN_FILS ||
6406 nla_put(skb,
Naveen Rawat14298b92015-11-25 16:27:41 -08006407 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05306408 roam_info_ptr->kck_len, roam_info_ptr->kck) ||
Naveen Rawat14298b92015-11-25 16:27:41 -08006409 nla_put(skb,
6410 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306411 roam_info_ptr->kek_len, roam_info_ptr->kek)) {
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05306412 hdd_err("nla put fail, kek_len %d",
6413 roam_info_ptr->kek_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006414 goto nla_put_failure;
6415 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306416
sheenam monga6e49e5c2019-04-04 12:49:04 +05306417 hdd_roam_reason =
6418 hdd_get_roam_reason(roam_info_ptr->roam_reason);
6419
6420 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON,
6421 hdd_roam_reason)) {
6422 hdd_err("roam reason send failure");
6423 goto nla_put_failure;
6424 }
6425
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306426 status = wlan_hdd_add_fils_params_roam_auth_event(skb,
6427 roam_info_ptr);
6428 if (status)
6429 goto nla_put_failure;
6430
6431 /*
6432 * Save the gtk rekey parameters in HDD STA context. They will
6433 * be used next time when host enables GTK offload and goes
6434 * into power save state.
6435 */
6436 wlan_hdd_save_gtk_offload_params(adapter, roam_info_ptr->kck,
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +05306437 roam_info_ptr->kck_len,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306438 roam_info_ptr->kek,
6439 roam_info_ptr->kek_len,
6440 roam_info_ptr->replay_ctr,
6441 true);
6442 hdd_debug("roam_info_ptr->replay_ctr 0x%llx",
6443 *((uint64_t *)roam_info_ptr->replay_ctr));
6444
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006445 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07006446 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006447 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
6448 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006449 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006450 goto nla_put_failure;
6451 }
6452 }
6453
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05306454 hdd_debug("Auth Status = %d Subnet Change Status = %d",
6455 roam_info_ptr->synchAuthStatus,
6456 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08006457
6458 /*
6459 * Add subnet change status if subnet has changed
6460 * 0 = unchanged
6461 * 1 = changed
6462 * 2 = unknown
6463 */
6464 if (roam_info_ptr->subnet_change_status) {
6465 if (nla_put_u8(skb,
6466 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
6467 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006468 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08006469 goto nla_put_failure;
6470 }
6471 }
6472
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006473 cfg80211_vendor_event(skb, GFP_KERNEL);
6474 return 0;
6475
6476nla_put_failure:
6477 kfree_skb(skb);
6478 return -EINVAL;
6479}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08006480#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006481
Jeff Johnson91f90ff2018-11-16 07:53:37 -08006482#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
6483 ((1 << 26) | \
6484 (((probe_period) & 0x1fff) << 13) | \
6485 ((stay_period) & 0x1fff))
6486
6487#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
6488 ((1 << 27) | \
6489 ((snr_diff) & 0x1fff))
6490
6491#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
6492 ((1 << 28) | \
6493 ((probe_dwell_time) & 0x1fff))
6494
6495#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
6496 ((1 << 29) | \
6497 (((mgmt_snr_weight) & 0xff) << 16) | \
6498 (((data_snr_weight) & 0xff) << 8) | \
6499 ((ack_snr_weight) & 0xff))
6500
lifeng66831662017-05-19 16:01:35 +08006501#define RX_REORDER_TIMEOUT_VOICE \
6502 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE
6503#define RX_REORDER_TIMEOUT_VIDEO \
6504 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO
6505#define RX_REORDER_TIMEOUT_BESTEFFORT \
6506 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT
6507#define RX_REORDER_TIMEOUT_BACKGROUND \
6508 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND
6509#define RX_BLOCKSIZE_PEER_MAC \
6510 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC
6511#define RX_BLOCKSIZE_WINLIMIT \
6512 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006513static const struct nla_policy
6514wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
6515
6516 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
Sourav Mohapatra0dbdfb42019-03-19 14:31:20 +05306517 [QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED] = {
6518 .type = NLA_U8 },
6519 [QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS] = {.type = NLA_U8 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006520 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
6521 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Jeff Johnson79f6a602017-06-15 09:48:25 -07006522 [QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT] = {.type = NLA_U32},
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05306523 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05306524 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
6525 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006526 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
6527 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
6528 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
6529 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
6530 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08006531 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY] = {
6532 .type = NLA_U32 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05306533 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08006534 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
6535 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
Jeff Johnson91f90ff2018-11-16 07:53:37 -08006536 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
Jeff Johnson77177bc2018-11-16 08:14:20 -08006537 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME] = {
6538 .type = NLA_U32},
Jeff Johnson1350e622018-11-16 18:36:55 -08006539 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT] = {
6540 .type = NLA_U32},
6541 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT] = {
6542 .type = NLA_U32},
6543 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT] = {
6544 .type = NLA_U32},
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306545 [QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL] = {.type = NLA_U8},
lifeng66831662017-05-19 16:01:35 +08006546 [RX_REORDER_TIMEOUT_VOICE] = {.type = NLA_U32},
6547 [RX_REORDER_TIMEOUT_VIDEO] = {.type = NLA_U32},
6548 [RX_REORDER_TIMEOUT_BESTEFFORT] = {.type = NLA_U32},
6549 [RX_REORDER_TIMEOUT_BACKGROUND] = {.type = NLA_U32},
Jeff Johnson19a5a7e2017-06-15 14:51:26 -07006550 [RX_BLOCKSIZE_PEER_MAC] = {
6551 .type = NLA_UNSPEC,
6552 .len = QDF_MAC_ADDR_SIZE},
lifeng66831662017-05-19 16:01:35 +08006553 [RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32},
Mukul Sharma6398b252017-05-01 17:58:12 +05306554 [QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL] = {.type = NLA_U32 },
Poddar, Siddarth4b3f7312017-11-02 17:00:20 +05306555 [QCA_WLAN_VENDOR_ATTR_CONFIG_LRO] = {.type = NLA_U8 },
Jeff Johnson1feb8a62018-11-14 13:18:41 -08006556 [QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER] = {.type = NLA_U8 },
lifengd217d192017-05-09 19:44:16 +08006557 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA] = {.type = NLA_U32 },
6558 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN] = {.type = NLA_U32 },
6559 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST] = {.type = NLA_U32 },
6560 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL] = {.type = NLA_U32 },
Paul Zhang99fe8842017-12-08 14:43:46 +08006561 [QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL] = {.type = NLA_U16 },
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05306562 [QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT] = {.type = NLA_U8},
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07006563 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE] = {.type = NLA_U8 },
Abhishek Singh6454ad32017-12-20 10:42:21 +05306564 [QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] = {.type = NLA_U8},
Ashish Kumar Dhanotiya1e20bcc2018-06-15 11:28:51 +05306565 [QCA_WLAN_VENDOR_ATTR_CONFIG_GTX] = {.type = NLA_U8},
Paul Zhangc9dbaee2019-06-23 22:07:31 +08006566 [QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS] = {.type = NLA_U8},
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08006567 [QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY] = {.type = NLA_U32 },
6568 [QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST] = {
6569 .type = NLA_BINARY,
Srinivas Girigowdacf161402019-03-14 11:37:33 -07006570 .len = WLAN_MAX_IE_LEN + 2},
Srinivas Dasari37e37312019-06-30 23:50:24 +05306571 [QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES] = {
6572 .type = NLA_BINARY,
6573 .len = SIR_MAC_MAX_ADD_IE_LENGTH + 2},
sheenam monga17452ef2020-02-24 13:23:13 +05306574 [QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON] = {.type = NLA_U8 },
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08006575
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006576};
6577
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006578static const struct nla_policy qca_wlan_vendor_twt_add_dialog_policy[
6579 QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1] = {
6580 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP] = {.type = NLA_U8 },
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05306581 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST] = {.type = NLA_FLAG },
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006582 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE] = {.type = NLA_U8 },
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05306583 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER] = {.type = NLA_FLAG },
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006584 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE] = {.type = NLA_U8 },
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05306585 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION] = {.type = NLA_FLAG },
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006586 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME] = {.type = NLA_U32 },
6587 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION] = {.type = NLA_U32 },
6588 [QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA] = {
6589 .type = NLA_U32 },
6590};
6591
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006592static const struct nla_policy
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08006593qca_wlan_vendor_attr_he_omi_tx_policy [QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX + 1] = {
6594 [QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS] = {.type = NLA_U8 },
6595 [QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW] = {.type = NLA_U8 },
6596 [QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE] = {.type = NLA_U8 },
6597 [QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS] = {.type = NLA_U8 },
Kiran Kumar Lokere49e3aff2019-02-06 17:00:48 -08006598 [QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE] = {.type = NLA_U8 },
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08006599};
6600
6601static const struct nla_policy
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006602wlan_hdd_wifi_test_config_policy[
6603 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1] = {
6604 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE] = {
6605 .type = NLA_U8},
6606 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ] = {
6607 .type = NLA_U8},
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08006608 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS] = {
6609 .type = NLA_U8},
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08006610 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ] = {
6611 .type = NLA_U8},
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08006612 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION] = {
6613 .type = NLA_U8},
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006614 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE] = {
6615 .type = NLA_U8},
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006616 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION] = {
6617 .type = NLA_U8},
6618 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID] = {
6619 .type = NLA_U8},
6620 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE] = {
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07006621 .type = NLA_U16},
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08006622 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK] = {
6623 .type = NLA_U8},
6624 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC] = {
6625 .type = NLA_U8},
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08006626 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF] = {
6627 .type = NLA_U8},
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07006628 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE] = {
6629 .type = NLA_U8},
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07006630 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS] = {
6631 .type = NLA_U8},
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07006632 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR] = {
6633 .type = NLA_U8},
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07006634 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AC] = {
6635 .type = NLA_U8},
6636 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA] = {
6637 .type = NLA_U8},
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07006638 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP] = {
6639 .type = NLA_U8},
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07006640 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_BW] = {
6641 .type = NLA_U8},
6642 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_NSS] = {
6643 .type = NLA_U8},
6644 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG] = {
6645 .type = NLA_FLAG},
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07006646 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU] = {
6647 .type = NLA_U8},
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08006648 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP] = {
6649 .type = NLA_U8},
6650 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX] = {
6651 .type = NLA_NESTED},
Kiran Kumar Lokereee205772018-09-27 00:27:27 -07006652 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU] = {
6653 .type = NLA_U8},
Kiran Kumar Lokere921b5a52019-02-24 21:53:20 -08006654 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS]
6655 = {.type = NLA_U8},
Kiran Kumar Lokerea1c29ec2019-02-25 18:19:00 -08006656 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT] = {
6657 .type = NLA_U8},
Arif Hussain1f58cbb2019-03-14 17:06:56 -07006658 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP] = {
6659 .type = NLA_NESTED},
6660 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE] = {
6661 .type = NLA_NESTED},
6662 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT] = {
6663 .type = NLA_U8},
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006664};
6665
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006666/**
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306667 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
6668 * @hdd_ctx: HDD context
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306669 * @adapter: Pointer to HDD adapter
6670 * @ie_data: Pointer to Scan IEs buffer
6671 * @ie_len: Length of Scan IEs
6672 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306673 * This API is used to store the default scan ies received from
6674 * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
6675 *
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306676 * Return: 0 on success; error number otherwise
6677 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006678static int wlan_hdd_save_default_scan_ies(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07006679 struct hdd_adapter *adapter,
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306680 uint8_t *ie_data, uint16_t ie_len)
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306681{
Jeff Johnson37588942017-08-15 16:11:41 -07006682 struct hdd_scan_info *scan_info = &adapter->scan_info;
Wu Gao93816212018-08-31 16:49:54 +08006683 bool add_qcn_ie;
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306684
6685 if (!scan_info)
6686 return -EINVAL;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306687
6688 if (scan_info->default_scan_ies) {
6689 qdf_mem_free(scan_info->default_scan_ies);
6690 scan_info->default_scan_ies = NULL;
6691 }
6692
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306693 scan_info->default_scan_ies_len = ie_len;
Dustin Brown1dbefe62018-09-11 16:32:03 -07006694 ucfg_mlme_get_qcn_ie_support(hdd_ctx->psoc, &add_qcn_ie);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306695 if (add_qcn_ie)
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306696 ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306697
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306698 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306699 if (!scan_info->default_scan_ies) {
6700 scan_info->default_scan_ies_len = 0;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306701 return -ENOMEM;
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306702 }
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306703
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306704 qdf_mem_copy(scan_info->default_scan_ies, ie_data,
6705 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306706
6707 /* Add QCN IE if g_qcn_ie_support INI is enabled */
6708 if (add_qcn_ie)
Kiran Kumar Lokere89f01f02019-08-06 18:22:39 -07006709 sme_add_qcn_ie(hdd_ctx->mac_handle,
6710 scan_info->default_scan_ies,
6711 &scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306712
Abhishek Singh74d06cf2019-09-06 09:23:22 +05306713 hdd_debug("Saved default scan IE:len %d",
6714 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306715 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
6716 (uint8_t *) scan_info->default_scan_ies,
6717 scan_info->default_scan_ies_len);
6718
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306719 return 0;
6720}
6721
6722/**
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306723 * wlan_hdd_handle_restrict_offchan_config() -
6724 * Handle wifi configuration attribute :
6725 * QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL
6726 * @adapter: Pointer to HDD adapter
6727 * @restrict_offchan: Restrict offchannel setting done by
6728 * application
6729 *
6730 * Return: 0 on success; error number otherwise
6731 */
Jeff Johnsone5006672017-08-29 14:39:02 -07006732static int wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter *adapter,
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306733 u8 restrict_offchan)
6734{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006735 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonc1e62782017-11-09 09:50:17 -08006736 enum QDF_OPMODE dev_mode = adapter->device_mode;
Min Liu8c5d99e2018-09-10 17:18:44 +08006737 struct wlan_objmgr_vdev *vdev;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306738 int ret_val = 0;
6739
6740 if (!(dev_mode == QDF_SAP_MODE || dev_mode == QDF_P2P_GO_MODE)) {
6741 hdd_err("Invalid interface type:%d", dev_mode);
6742 return -EINVAL;
6743 }
Min Liu8c5d99e2018-09-10 17:18:44 +08006744 vdev = hdd_objmgr_get_vdev(adapter);
6745 if (!vdev)
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006746 return -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306747 if (restrict_offchan == 1) {
6748 enum policy_mgr_con_mode pmode =
6749 policy_mgr_convert_device_mode_to_qdf_type(dev_mode);
6750 int chan;
6751
Min Liu8c5d99e2018-09-10 17:18:44 +08006752 u32 vdev_id = wlan_vdev_get_id(vdev);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306753
Min Liu8c5d99e2018-09-10 17:18:44 +08006754 wlan_vdev_obj_lock(vdev);
6755 wlan_vdev_mlme_cap_set(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
6756 wlan_vdev_obj_unlock(vdev);
Manikandan Mohan7fdb0252019-08-14 16:49:02 -07006757 chan = wlan_freq_to_chan(
6758 policy_mgr_get_channel(hdd_ctx->psoc, pmode, &vdev_id));
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006759 if (!chan ||
6760 wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, chan)) {
6761 hdd_err("unable to send avoid_freq");
6762 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306763 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006764 hdd_info("vdev %d mode %d dnbs enabled", vdev_id, dev_mode);
6765 } else if (restrict_offchan == 0) {
Min Liu8c5d99e2018-09-10 17:18:44 +08006766 wlan_vdev_obj_lock(vdev);
6767 wlan_vdev_mlme_cap_clear(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
6768 wlan_vdev_obj_unlock(vdev);
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006769 if (wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0)) {
6770 hdd_err("unable to clear avoid_freq");
6771 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306772 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006773 hdd_info("vdev mode %d dnbs disabled", dev_mode);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306774 } else {
6775 ret_val = -EINVAL;
6776 hdd_err("Invalid RESTRICT_OFFCHAN setting");
6777 }
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05306778 hdd_objmgr_put_vdev(vdev);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306779 return ret_val;
6780}
6781
6782/**
Jeff Johnson0dd687e2018-11-16 20:11:27 -08006783 * wlan_hdd_cfg80211_wifi_set_reorder_timeout() - set reorder timeout
6784 * @adapter: Pointer to HDD adapter
lifeng66831662017-05-19 16:01:35 +08006785 * @tb: array of pointer to struct nlattr
6786 *
6787 * Return: 0 on success; error number otherwise
6788 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006789static
Jeff Johnson0dd687e2018-11-16 20:11:27 -08006790int wlan_hdd_cfg80211_wifi_set_reorder_timeout(struct hdd_adapter *adapter,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006791 struct nlattr *tb[])
lifeng66831662017-05-19 16:01:35 +08006792{
Jeff Johnson0dd687e2018-11-16 20:11:27 -08006793 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Min Liuab6ed4f2018-01-09 13:13:57 +08006794 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08006795 QDF_STATUS qdf_status;
6796 struct sir_set_rx_reorder_timeout_val reorder_timeout;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006797 mac_handle_t mac_handle;
lifeng66831662017-05-19 16:01:35 +08006798
6799#define RX_TIMEOUT_VAL_MIN 10
6800#define RX_TIMEOUT_VAL_MAX 1000
6801
6802 if (tb[RX_REORDER_TIMEOUT_VOICE] ||
6803 tb[RX_REORDER_TIMEOUT_VIDEO] ||
6804 tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
6805 tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
6806
6807 /* if one is specified, all must be specified */
6808 if (!tb[RX_REORDER_TIMEOUT_VOICE] ||
6809 !tb[RX_REORDER_TIMEOUT_VIDEO] ||
6810 !tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
6811 !tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
6812 hdd_err("four AC timeout val are required MAC");
6813 return -EINVAL;
6814 }
6815
6816 reorder_timeout.rx_timeout_pri[0] = nla_get_u32(
6817 tb[RX_REORDER_TIMEOUT_VOICE]);
6818 reorder_timeout.rx_timeout_pri[1] = nla_get_u32(
6819 tb[RX_REORDER_TIMEOUT_VIDEO]);
6820 reorder_timeout.rx_timeout_pri[2] = nla_get_u32(
6821 tb[RX_REORDER_TIMEOUT_BESTEFFORT]);
6822 reorder_timeout.rx_timeout_pri[3] = nla_get_u32(
6823 tb[RX_REORDER_TIMEOUT_BACKGROUND]);
6824 /* timeout value is required to be in the rang 10 to 1000ms */
6825 if (reorder_timeout.rx_timeout_pri[0] >= RX_TIMEOUT_VAL_MIN &&
6826 reorder_timeout.rx_timeout_pri[0] <= RX_TIMEOUT_VAL_MAX &&
6827 reorder_timeout.rx_timeout_pri[1] >= RX_TIMEOUT_VAL_MIN &&
6828 reorder_timeout.rx_timeout_pri[1] <= RX_TIMEOUT_VAL_MAX &&
6829 reorder_timeout.rx_timeout_pri[2] >= RX_TIMEOUT_VAL_MIN &&
6830 reorder_timeout.rx_timeout_pri[2] <= RX_TIMEOUT_VAL_MAX &&
6831 reorder_timeout.rx_timeout_pri[3] >= RX_TIMEOUT_VAL_MIN &&
6832 reorder_timeout.rx_timeout_pri[3] <= RX_TIMEOUT_VAL_MAX) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006833 mac_handle = hdd_ctx->mac_handle;
6834 qdf_status = sme_set_reorder_timeout(mac_handle,
lifeng66831662017-05-19 16:01:35 +08006835 &reorder_timeout);
6836 if (qdf_status != QDF_STATUS_SUCCESS) {
6837 hdd_err("failed to set reorder timeout err %d",
6838 qdf_status);
6839 ret_val = -EPERM;
6840 }
6841 } else {
6842 hdd_err("one of the timeout value is not in range");
6843 ret_val = -EINVAL;
6844 }
6845 }
6846
6847 return ret_val;
6848}
6849
6850/**
Jeff Johnson339ede82018-11-16 20:27:52 -08006851 * wlan_hdd_cfg80211_wifi_set_rx_blocksize() - set rx blocksize
lifeng66831662017-05-19 16:01:35 +08006852 * @adapter: hdd adapter
6853 * @tb: array of pointer to struct nlattr
6854 *
6855 * Return: 0 on success; error number otherwise
6856 */
Jeff Johnson339ede82018-11-16 20:27:52 -08006857static int wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct hdd_adapter *adapter,
lifeng66831662017-05-19 16:01:35 +08006858 struct nlattr *tb[])
6859{
Jeff Johnson339ede82018-11-16 20:27:52 -08006860 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Min Liuab6ed4f2018-01-09 13:13:57 +08006861 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08006862 uint32_t set_value;
6863 QDF_STATUS qdf_status;
6864 struct sir_peer_set_rx_blocksize rx_blocksize;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006865 mac_handle_t mac_handle;
lifeng66831662017-05-19 16:01:35 +08006866
6867#define WINDOW_SIZE_VAL_MIN 1
6868#define WINDOW_SIZE_VAL_MAX 64
6869
6870 if (tb[RX_BLOCKSIZE_PEER_MAC] ||
6871 tb[RX_BLOCKSIZE_WINLIMIT]) {
6872
6873 /* if one is specified, both must be specified */
6874 if (!tb[RX_BLOCKSIZE_PEER_MAC] ||
6875 !tb[RX_BLOCKSIZE_WINLIMIT]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07006876 hdd_err("Both Peer MAC and windows limit required");
lifeng66831662017-05-19 16:01:35 +08006877 return -EINVAL;
6878 }
6879
6880 memcpy(&rx_blocksize.peer_macaddr,
6881 nla_data(tb[RX_BLOCKSIZE_PEER_MAC]),
6882 sizeof(rx_blocksize.peer_macaddr)),
6883
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006884 rx_blocksize.vdev_id = adapter->vdev_id;
lifeng66831662017-05-19 16:01:35 +08006885 set_value = nla_get_u32(tb[RX_BLOCKSIZE_WINLIMIT]);
6886 /* maximum window size is 64 */
6887 if (set_value >= WINDOW_SIZE_VAL_MIN &&
6888 set_value <= WINDOW_SIZE_VAL_MAX) {
6889 rx_blocksize.rx_block_ack_win_limit = set_value;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006890 mac_handle = hdd_ctx->mac_handle;
6891 qdf_status = sme_set_rx_set_blocksize(mac_handle,
lifeng66831662017-05-19 16:01:35 +08006892 &rx_blocksize);
6893 if (qdf_status != QDF_STATUS_SUCCESS) {
6894 hdd_err("failed to set aggr sizes err %d",
6895 qdf_status);
6896 ret_val = -EPERM;
6897 }
6898 } else {
6899 hdd_err("window size val is not in range");
6900 ret_val = -EINVAL;
6901 }
6902 }
6903
6904 return ret_val;
6905}
6906
sheenam monga17452ef2020-02-24 13:23:13 +05306907/**
6908 * hdd_set_roam_reason_vsie_status() - enable/disable inclusion of
6909 * roam reason vsie in Reassoc
6910 *
6911 * @adapter: hdd adapter
6912 * @attr: nla attr sent by supplicant
6913 *
6914 * Return: 0 on success, negative errno on failure
6915 */
6916#ifdef WLAN_FEATURE_ROAM_OFFLOAD
6917static int hdd_set_roam_reason_vsie_status(struct hdd_adapter *adapter,
6918 const struct nlattr *attr)
6919{
6920 uint8_t roam_reason_vsie_enabled;
6921 int errno;
6922 QDF_STATUS status = QDF_STATUS_SUCCESS;
6923 struct hdd_context *hdd_ctx = NULL;
6924
6925 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6926 if (!hdd_ctx) {
6927 hdd_err("hdd_ctx failure");
6928 return -EINVAL;
6929 }
6930
6931 roam_reason_vsie_enabled = nla_get_u8(attr);
6932 if (roam_reason_vsie_enabled > 1)
6933 roam_reason_vsie_enabled = 1;
6934
6935 status =
6936 ucfg_mlme_set_roam_reason_vsie_status(hdd_ctx->psoc,
6937 roam_reason_vsie_enabled);
6938 if (QDF_IS_STATUS_ERROR(status)) {
6939 hdd_err("set roam reason vsie failed");
6940 return -EINVAL;
6941 }
6942
6943 errno = sme_cli_set_command
6944 (adapter->vdev_id,
6945 WMI_VDEV_PARAM_ENABLE_DISABLE_ROAM_REASON_VSIE,
6946 roam_reason_vsie_enabled, VDEV_CMD);
6947 if (errno) {
6948 hdd_err("Failed to set beacon report error vsie");
6949 status = QDF_STATUS_E_FAILURE;
6950 }
6951
6952 return qdf_status_to_os_return(status);
6953}
6954#else
6955static int hdd_set_roam_reason_vsie_status(struct hdd_adapter *adapter,
6956 const struct nlattr *attr)
6957{
6958 return -ENOTSUPP;
6959}
6960#endif
6961
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08006962static int hdd_config_access_policy(struct hdd_adapter *adapter,
6963 struct nlattr *tb[])
6964{
6965 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6966 struct nlattr *policy_attr =
6967 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY];
6968 struct nlattr *ielist_attr =
6969 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST];
6970 uint32_t access_policy;
Srinivas Girigowdacf161402019-03-14 11:37:33 -07006971 uint8_t ie[WLAN_MAX_IE_LEN + 2];
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08006972 QDF_STATUS status;
6973
6974 /* nothing to do if neither attribute is present */
6975 if (!ielist_attr && !policy_attr)
6976 return 0;
6977
6978 /* if one is present, both must be present */
6979 if (!ielist_attr || !policy_attr) {
6980 hdd_err("Missing attribute for %s",
6981 policy_attr ?
6982 "ACCESS_POLICY_IE_LIST" : "ACCESS_POLICY");
6983 return -EINVAL;
6984 }
6985
6986 /* validate the access policy */
6987 access_policy = nla_get_u32(policy_attr);
6988 switch (access_policy) {
6989 case QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED:
6990 case QCA_ACCESS_POLICY_DENY_UNLESS_LISTED:
6991 /* valid */
6992 break;
6993 default:
6994 hdd_err("Invalid value. access_policy %u", access_policy);
6995 return -EINVAL;
6996 }
6997
6998 /*
6999 * ie length is validated by the nla_policy. need to make a
Srinivas Girigowdacf161402019-03-14 11:37:33 -07007000 * copy since SME will always read WLAN_MAX_IE_LEN+2 bytes
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08007001 */
7002 nla_memcpy(ie, ielist_attr, sizeof(ie));
7003
7004 hdd_debug("calling sme_update_access_policy_vendor_ie");
7005 status = sme_update_access_policy_vendor_ie(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007006 adapter->vdev_id,
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08007007 ie, access_policy);
7008 if (QDF_IS_STATUS_ERROR(status))
7009 hdd_err("Failed to set vendor ie and access policy, %d",
7010 status);
7011
7012 return qdf_status_to_os_return(status);
7013}
7014
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08007015static int hdd_config_mpdu_aggregation(struct hdd_adapter *adapter,
7016 struct nlattr *tb[])
7017{
7018 struct nlattr *tx_attr =
7019 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION];
7020 struct nlattr *rx_attr =
7021 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION];
7022 uint8_t tx_size, rx_size;
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08007023 QDF_STATUS status;
7024
7025 /* nothing to do if neither attribute is present */
7026 if (!tx_attr && !rx_attr)
7027 return 0;
7028
7029 /* if one is present, both must be present */
7030 if (!tx_attr || !rx_attr) {
7031 hdd_err("Missing attribute for %s",
7032 tx_attr ? "RX" : "TX");
7033 return -EINVAL;
7034 }
7035
7036 tx_size = nla_get_u8(tx_attr);
7037 rx_size = nla_get_u8(rx_attr);
7038 if (!cfg_in_range(CFG_TX_AGGREGATION_SIZE, tx_size) ||
7039 !cfg_in_range(CFG_RX_AGGREGATION_SIZE, rx_size)) {
7040 hdd_err("TX %d RX %d MPDU aggr size not in range",
7041 tx_size, rx_size);
7042
7043 return -EINVAL;
7044 }
7045
Abhishek Ambure74709762019-05-27 19:43:26 +05307046 status = wma_set_tx_rx_aggr_size(adapter->vdev_id,
7047 tx_size,
7048 rx_size,
7049 WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU);
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08007050
7051 return qdf_status_to_os_return(status);
7052}
7053
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08007054static int hdd_config_ant_div_period(struct hdd_adapter *adapter,
7055 struct nlattr *tb[])
7056{
7057 struct nlattr *probe_attr =
7058 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD];
7059 struct nlattr *stay_attr =
7060 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD];
7061 uint32_t probe_period, stay_period, ant_div_usrcfg;
7062 int errno;
7063
7064 /* nothing to do if neither attribute is present */
7065 if (!probe_attr && !stay_attr)
7066 return 0;
7067
7068 /* if one is present, both must be present */
7069 if (!probe_attr || !stay_attr) {
7070 hdd_err("Missing attribute for %s",
7071 probe_attr ? "STAY" : "PROBE");
7072 return -EINVAL;
7073 }
7074
7075 probe_period = nla_get_u32(probe_attr);
7076 stay_period = nla_get_u32(stay_attr);
7077 ant_div_usrcfg = ANT_DIV_SET_PERIOD(probe_period, stay_period);
7078 hdd_debug("ant div set period: %x", ant_div_usrcfg);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007079 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08007080 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7081 ant_div_usrcfg, PDEV_CMD);
7082 if (errno)
7083 hdd_err("Failed to set ant div period, %d", errno);
7084
7085 return errno;
7086}
7087
Jeff Johnson1350e622018-11-16 18:36:55 -08007088static int hdd_config_ant_div_snr_weight(struct hdd_adapter *adapter,
7089 struct nlattr *tb[])
7090{
7091 struct nlattr *mgmt_attr =
7092 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT];
7093 struct nlattr *data_attr =
7094 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT];
7095 struct nlattr *ack_attr =
7096 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT];
7097 uint32_t mgmt_snr, data_snr, ack_snr, ant_div_usrcfg;
7098 int errno;
7099
7100 /* nothing to do if none of the attributes are present */
7101 if (!mgmt_attr && !data_attr && !ack_attr)
7102 return 0;
7103
7104 /* if one is present, all must be present */
7105 if (!mgmt_attr || !data_attr || !ack_attr) {
7106 hdd_err("Missing attribute");
7107 return -EINVAL;
7108 }
7109
7110 mgmt_snr = nla_get_u32(mgmt_attr);
7111 data_snr = nla_get_u32(data_attr);
7112 ack_snr = nla_get_u32(ack_attr);
7113 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(mgmt_snr, data_snr, ack_snr);
7114 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007115 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson1350e622018-11-16 18:36:55 -08007116 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7117 ant_div_usrcfg, PDEV_CMD);
7118 if (errno)
7119 hdd_err("Failed to set ant div weight, %d", errno);
7120
7121 return errno;
7122}
7123
Jeff Johnson7f4fd702018-11-14 11:19:52 -08007124static int hdd_config_fine_time_measurement(struct hdd_adapter *adapter,
7125 const struct nlattr *attr)
7126{
7127 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7128 uint32_t user_capability;
7129 uint32_t target_capability;
7130 uint32_t final_capability;
7131 QDF_STATUS status;
7132
7133 user_capability = nla_get_u32(attr);
7134 target_capability = hdd_ctx->fine_time_meas_cap_target;
7135 final_capability = user_capability & target_capability;
7136
7137 status = ucfg_mlme_set_fine_time_meas_cap(hdd_ctx->psoc,
7138 final_capability);
7139 if (QDF_IS_STATUS_ERROR(status)) {
7140 hdd_err("Unable to set value, status %d", status);
7141 return -EINVAL;
7142 }
7143
7144 sme_update_fine_time_measurement_capab(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007145 adapter->vdev_id,
Jeff Johnson7f4fd702018-11-14 11:19:52 -08007146 final_capability);
7147 ucfg_wifi_pos_set_ftm_cap(hdd_ctx->psoc, final_capability);
7148
7149 hdd_debug("user: 0x%x, target: 0x%x, final: 0x%x",
7150 user_capability, target_capability, final_capability);
7151
7152 return 0;
7153}
7154
Jeff Johnsonbcaeafb2018-11-14 12:14:24 -08007155static int hdd_config_modulated_dtim(struct hdd_adapter *adapter,
7156 const struct nlattr *attr)
7157{
7158 struct wlan_objmgr_vdev *vdev;
7159 uint32_t modulated_dtim;
7160 QDF_STATUS status;
7161
7162 modulated_dtim = nla_get_u32(attr);
7163
7164 vdev = hdd_objmgr_get_vdev(adapter);
7165 if (!vdev)
7166 return -EINVAL;
7167
7168 status = ucfg_pmo_config_modulated_dtim(vdev, modulated_dtim);
7169
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05307170 hdd_objmgr_put_vdev(vdev);
Jeff Johnsonbcaeafb2018-11-14 12:14:24 -08007171
7172 return qdf_status_to_os_return(status);
7173}
7174
Jeff Johnson6db91622018-11-14 12:33:28 -08007175static int hdd_config_listen_interval(struct hdd_adapter *adapter,
7176 const struct nlattr *attr)
7177{
7178 struct wlan_objmgr_vdev *vdev;
7179 uint32_t listen_interval;
7180 QDF_STATUS status;
7181
7182 listen_interval = nla_get_u32(attr);
7183 if (listen_interval > cfg_max(CFG_PMO_ENABLE_DYNAMIC_DTIM)) {
7184 hdd_err_rl("Invalid value for listen interval - %d",
7185 listen_interval);
7186 return -EINVAL;
7187 }
7188
7189 vdev = hdd_objmgr_get_vdev(adapter);
7190 if (!vdev)
7191 return -EINVAL;
7192
7193 status = ucfg_pmo_config_listen_interval(vdev, listen_interval);
7194
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05307195 hdd_objmgr_put_vdev(vdev);
Jeff Johnson6db91622018-11-14 12:33:28 -08007196
7197 return qdf_status_to_os_return(status);
7198}
7199
Jeff Johnson9381d032018-11-14 12:42:22 -08007200static int hdd_config_lro(struct hdd_adapter *adapter,
7201 const struct nlattr *attr)
7202{
7203 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7204 uint8_t enable_flag;
7205
7206 enable_flag = nla_get_u8(attr);
7207
7208 return hdd_lro_set_reset(hdd_ctx, adapter, enable_flag);
7209}
7210
Jeff Johnson3d4f64c2018-11-14 13:13:04 -08007211static int hdd_config_scan_enable(struct hdd_adapter *adapter,
7212 const struct nlattr *attr)
7213{
7214 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7215 uint8_t enable_flag;
7216
7217 enable_flag = nla_get_u8(attr);
7218 if (enable_flag)
7219 ucfg_scan_psoc_set_enable(hdd_ctx->psoc,
7220 REASON_USER_SPACE);
7221 else
7222 ucfg_scan_psoc_set_disable(hdd_ctx->psoc,
7223 REASON_USER_SPACE);
7224
7225 return 0;
7226}
7227
Jeff Johnson1feb8a62018-11-14 13:18:41 -08007228static int hdd_config_qpower(struct hdd_adapter *adapter,
7229 const struct nlattr *attr)
7230{
7231 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7232 uint8_t qpower;
7233
7234 qpower = nla_get_u8(attr);
7235
7236 return hdd_set_qpower_config(hdd_ctx, adapter, qpower);
7237}
7238
Jeff Johnsonf15ede02018-11-14 13:27:13 -08007239static int hdd_config_stats_avg_factor(struct hdd_adapter *adapter,
7240 const struct nlattr *attr)
7241{
7242 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7243 uint16_t stats_avg_factor;
7244 QDF_STATUS status;
7245
7246 stats_avg_factor = nla_get_u16(attr);
7247 status = sme_configure_stats_avg_factor(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007248 adapter->vdev_id,
Jeff Johnsonf15ede02018-11-14 13:27:13 -08007249 stats_avg_factor);
7250
7251 return qdf_status_to_os_return(status);
7252}
7253
Jeff Johnsonf3827502018-11-14 14:00:58 -08007254static int hdd_config_non_agg_retry(struct hdd_adapter *adapter,
7255 const struct nlattr *attr)
7256{
7257 uint8_t retry;
7258 int param_id;
7259
7260 retry = nla_get_u8(attr);
7261 retry = retry > CFG_NON_AGG_RETRY_MAX ?
7262 CFG_NON_AGG_RETRY_MAX : retry;
7263 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
7264
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007265 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnsonf3827502018-11-14 14:00:58 -08007266 retry, PDEV_CMD);
7267}
7268
Jeff Johnsonb9021002018-11-15 15:51:36 -08007269static int hdd_config_agg_retry(struct hdd_adapter *adapter,
7270 const struct nlattr *attr)
7271{
7272 uint8_t retry;
7273 int param_id;
7274
7275 retry = nla_get_u8(attr);
7276 retry = retry > CFG_AGG_RETRY_MAX ?
7277 CFG_AGG_RETRY_MAX : retry;
7278
7279 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
7280 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
7281 CFG_AGG_RETRY_MIN : retry;
7282 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
7283
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007284 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnsonb9021002018-11-15 15:51:36 -08007285 retry, PDEV_CMD);
7286}
7287
Jeff Johnson0e8259c2018-11-15 19:44:57 -08007288static int hdd_config_mgmt_retry(struct hdd_adapter *adapter,
7289 const struct nlattr *attr)
7290{
7291 uint8_t retry;
7292 int param_id;
sheenam monga451c68c2019-12-11 20:00:17 +05307293 uint8_t max_mgmt_retry;
Jeff Johnson0e8259c2018-11-15 19:44:57 -08007294
7295 retry = nla_get_u8(attr);
sheenam monga451c68c2019-12-11 20:00:17 +05307296 max_mgmt_retry = (cfg_max(CFG_MGMT_RETRY_MAX));
7297 retry = retry > max_mgmt_retry ?
7298 max_mgmt_retry : retry;
Jeff Johnson0e8259c2018-11-15 19:44:57 -08007299 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
7300
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007301 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson0e8259c2018-11-15 19:44:57 -08007302 retry, PDEV_CMD);
7303}
7304
Jeff Johnson6b48a2f2018-11-15 19:48:47 -08007305static int hdd_config_ctrl_retry(struct hdd_adapter *adapter,
7306 const struct nlattr *attr)
7307{
7308 uint8_t retry;
7309 int param_id;
7310
7311 retry = nla_get_u8(attr);
7312 retry = retry > CFG_CTRL_RETRY_MAX ?
7313 CFG_CTRL_RETRY_MAX : retry;
7314 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
7315
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007316 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson6b48a2f2018-11-15 19:48:47 -08007317 retry, PDEV_CMD);
7318}
7319
Jeff Johnson98214742018-11-15 19:56:37 -08007320static int hdd_config_propagation_delay(struct hdd_adapter *adapter,
7321 const struct nlattr *attr)
7322{
7323 uint8_t delay;
7324 uint32_t abs_delay;
7325 int param_id;
7326
7327 delay = nla_get_u8(attr);
7328 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
7329 CFG_PROPAGATION_DELAY_MAX : delay;
7330 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
7331 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
7332
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007333 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson98214742018-11-15 19:56:37 -08007334 abs_delay, PDEV_CMD);
7335}
7336
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08007337static int hdd_config_propagation_abs_delay(struct hdd_adapter *adapter,
7338 const struct nlattr *attr)
7339{
7340 uint32_t abs_delay;
7341 int param_id;
7342
7343 abs_delay = nla_get_u32(attr);
7344 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
7345
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007346 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08007347 abs_delay, PDEV_CMD);
7348}
7349
Jeff Johnson7c5e6dc2018-11-15 21:20:18 -08007350static int hdd_config_tx_fail_count(struct hdd_adapter *adapter,
7351 const struct nlattr *attr)
7352{
7353 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7354 uint32_t tx_fail_count;
7355 QDF_STATUS status;
7356
7357 tx_fail_count = nla_get_u32(attr);
7358 if (!tx_fail_count)
7359 return 0;
7360
7361 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007362 adapter->vdev_id,
Jeff Johnson7c5e6dc2018-11-15 21:20:18 -08007363 tx_fail_count);
7364 if (QDF_IS_STATUS_ERROR(status))
7365 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
7366 status);
7367
7368 return qdf_status_to_os_return(status);
7369}
7370
Jeff Johnson7766fd22018-11-15 21:52:37 -08007371static int hdd_config_channel_avoidance_ind(struct hdd_adapter *adapter,
7372 const struct nlattr *attr)
7373{
7374 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7375 uint8_t set_value;
7376
7377 set_value = nla_get_u8(attr);
7378 hdd_debug("set_value: %d", set_value);
7379
7380 return hdd_enable_disable_ca_event(hdd_ctx, set_value);
7381}
7382
Jeff Johnson47e2e842018-11-14 13:49:43 -08007383static int hdd_config_guard_time(struct hdd_adapter *adapter,
7384 const struct nlattr *attr)
7385{
7386 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7387 uint32_t guard_time;
7388 QDF_STATUS status;
7389
7390 guard_time = nla_get_u32(attr);
7391 status = sme_configure_guard_time(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007392 adapter->vdev_id,
Jeff Johnson47e2e842018-11-14 13:49:43 -08007393 guard_time);
7394
7395 return qdf_status_to_os_return(status);
7396}
7397
Jeff Johnson3b2abe92017-12-15 09:03:47 -08007398static int hdd_config_scan_default_ies(struct hdd_adapter *adapter,
7399 const struct nlattr *attr)
7400{
7401 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7402 uint8_t *scan_ie;
7403 uint16_t scan_ie_len;
7404 QDF_STATUS status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007405 mac_handle_t mac_handle;
Jeff Johnson3b2abe92017-12-15 09:03:47 -08007406
Jeff Johnson3b2abe92017-12-15 09:03:47 -08007407 scan_ie_len = nla_len(attr);
7408 hdd_debug("IE len %d session %d device mode %d",
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007409 scan_ie_len, adapter->vdev_id, adapter->device_mode);
Jeff Johnson3b2abe92017-12-15 09:03:47 -08007410
7411 if (!scan_ie_len) {
7412 hdd_err("zero-length IE prohibited");
7413 return -EINVAL;
7414 }
7415
7416 if (scan_ie_len > MAX_DEFAULT_SCAN_IE_LEN) {
7417 hdd_err("IE length %d exceeds max of %d",
7418 scan_ie_len, MAX_DEFAULT_SCAN_IE_LEN);
7419 return -EINVAL;
7420 }
7421
7422 scan_ie = nla_data(attr);
Jeff Johnson4933c3a2018-01-10 19:33:33 -08007423 if (!wlan_is_ie_valid(scan_ie, scan_ie_len)) {
Jeff Johnson3b2abe92017-12-15 09:03:47 -08007424 hdd_err("Invalid default scan IEs");
7425 return -EINVAL;
7426 }
7427
7428 if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
7429 scan_ie, scan_ie_len))
7430 hdd_err("Failed to save default scan IEs");
7431
7432 if (adapter->device_mode == QDF_STA_MODE) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007433 mac_handle = hdd_ctx->mac_handle;
7434 status = sme_set_default_scan_ie(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007435 adapter->vdev_id, scan_ie,
Jeff Johnson3b2abe92017-12-15 09:03:47 -08007436 scan_ie_len);
7437 if (QDF_STATUS_SUCCESS != status) {
7438 hdd_err("failed to set default scan IEs in sme: %d",
7439 status);
7440 return -EPERM;
7441 }
7442 }
7443
7444 return 0;
7445}
7446
Jeff Johnsonf9871e42018-11-15 22:24:06 -08007447static int hdd_config_ant_div_ena(struct hdd_adapter *adapter,
7448 const struct nlattr *attr)
7449{
7450 uint32_t antdiv_enable;
7451 int errno;
7452
7453 antdiv_enable = nla_get_u32(attr);
7454 hdd_debug("antdiv_enable: %d", antdiv_enable);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007455 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonf9871e42018-11-15 22:24:06 -08007456 WMI_PDEV_PARAM_ENA_ANT_DIV,
7457 antdiv_enable, PDEV_CMD);
7458 if (errno)
7459 hdd_err("Failed to set antdiv_enable, %d", errno);
7460
7461 return errno;
7462}
7463
Jeff Johnson91f90ff2018-11-16 07:53:37 -08007464static int hdd_config_ant_div_snr_diff(struct hdd_adapter *adapter,
7465 const struct nlattr *attr)
7466{
7467 uint32_t ant_div_snr_diff;
7468 uint32_t ant_div_usrcfg;
7469 int errno;
7470
7471 ant_div_snr_diff = nla_get_u32(attr);
7472 hdd_debug("snr diff: %x", ant_div_snr_diff);
7473
7474 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(ant_div_snr_diff);
7475 hdd_debug("usrcfg: %x", ant_div_usrcfg);
7476
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007477 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson91f90ff2018-11-16 07:53:37 -08007478 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7479 ant_div_usrcfg, PDEV_CMD);
7480 if (errno)
7481 hdd_err("Failed to set snr diff, %d", errno);
7482
7483 return errno;
7484}
7485
Jeff Johnson77177bc2018-11-16 08:14:20 -08007486static int hdd_config_ant_div_probe_dwell_time(struct hdd_adapter *adapter,
7487 const struct nlattr *attr)
7488{
7489 uint32_t dwell_time;
7490 uint32_t ant_div_usrcfg;
7491 int errno;
7492
7493 dwell_time = nla_get_u32(attr);
7494 hdd_debug("dwell time: %x", dwell_time);
7495
7496 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(dwell_time);
7497 hdd_debug("usrcfg: %x", ant_div_usrcfg);
7498
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007499 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson77177bc2018-11-16 08:14:20 -08007500 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7501 ant_div_usrcfg, PDEV_CMD);
7502 if (errno)
7503 hdd_err("Failed to set probe dwell time, %d", errno);
7504
7505 return errno;
7506}
7507
Jeff Johnsonaa172222018-11-16 09:16:11 -08007508static int hdd_config_ant_div_chain(struct hdd_adapter *adapter,
7509 const struct nlattr *attr)
7510{
7511 uint32_t antdiv_chain;
7512 int errno;
7513
7514 antdiv_chain = nla_get_u32(attr);
7515 hdd_debug("antdiv_chain: %d", antdiv_chain);
7516
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007517 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonaa172222018-11-16 09:16:11 -08007518 WMI_PDEV_PARAM_FORCE_CHAIN_ANT,
7519 antdiv_chain, PDEV_CMD);
7520 if (errno)
7521 hdd_err("Failed to set chain, %d", errno);
7522
7523 return errno;
7524}
7525
Jeff Johnsonef427ad2018-11-16 09:22:17 -08007526static int hdd_config_ant_div_selftest(struct hdd_adapter *adapter,
7527 const struct nlattr *attr)
7528{
7529 uint32_t antdiv_selftest;
7530 int errno;
7531
7532 antdiv_selftest = nla_get_u32(attr);
7533 hdd_debug("antdiv_selftest: %d", antdiv_selftest);
7534
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007535 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonef427ad2018-11-16 09:22:17 -08007536 WMI_PDEV_PARAM_ANT_DIV_SELFTEST,
7537 antdiv_selftest, PDEV_CMD);
7538 if (errno)
7539 hdd_err("Failed to set selftest, %d", errno);
7540
7541 return errno;
7542}
7543
Jeff Johnsonae21be82018-11-16 09:43:53 -08007544static int hdd_config_ant_div_selftest_intvl(struct hdd_adapter *adapter,
7545 const struct nlattr *attr)
7546{
7547 uint32_t antdiv_selftest_intvl;
7548 int errno;
7549
7550 antdiv_selftest_intvl = nla_get_u32(attr);
7551 hdd_debug("antdiv_selftest_intvl: %d", antdiv_selftest_intvl);
7552
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007553 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonae21be82018-11-16 09:43:53 -08007554 WMI_PDEV_PARAM_ANT_DIV_SELFTEST_INTVL,
7555 antdiv_selftest_intvl, PDEV_CMD);
7556 if (errno)
7557 hdd_err("Failed to set selftest interval, %d", errno);
7558
7559 return errno;
7560}
7561
Jeff Johnson3a25de82018-11-16 07:26:46 -08007562static int hdd_config_ignore_assoc_disallowed(struct hdd_adapter *adapter,
7563 const struct nlattr *attr)
7564{
7565 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7566 uint8_t ignore_assoc_disallowed;
7567
7568 ignore_assoc_disallowed = nla_get_u8(attr);
7569 hdd_debug("%u", ignore_assoc_disallowed);
7570 if ((ignore_assoc_disallowed < QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
7571 (ignore_assoc_disallowed > QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
7572 return -EINVAL;
7573
7574 sme_update_session_param(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007575 adapter->vdev_id,
Jeff Johnson3a25de82018-11-16 07:26:46 -08007576 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
7577 ignore_assoc_disallowed);
7578
7579 return 0;
7580}
7581
Jeff Johnson72dc91e2018-11-16 08:46:12 -08007582static int hdd_config_restrict_offchannel(struct hdd_adapter *adapter,
7583 const struct nlattr *attr)
7584{
7585 uint8_t restrict_offchan;
7586
7587 restrict_offchan = nla_get_u8(attr);
7588 hdd_debug("%u", restrict_offchan);
7589
7590 if (restrict_offchan > 1) {
7591 hdd_err("Invalid value %u", restrict_offchan);
7592 return -EINVAL;
7593 }
7594
7595 return wlan_hdd_handle_restrict_offchan_config(adapter,
7596 restrict_offchan);
7597}
7598
Jeff Johnson320feeb2018-11-16 10:14:24 -08007599static int hdd_config_total_beacon_miss_count(struct hdd_adapter *adapter,
7600 const struct nlattr *attr)
7601{
7602 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7603 uint8_t first_miss_count;
7604 uint8_t final_miss_count;
7605 uint8_t total_miss_count;
7606 QDF_STATUS status;
7607
7608 total_miss_count = nla_get_u8(attr);
7609 ucfg_mlme_get_roam_bmiss_first_bcnt(hdd_ctx->psoc,
7610 &first_miss_count);
7611 if (total_miss_count <= first_miss_count) {
7612 hdd_err("Total %u needs to exceed first %u",
7613 total_miss_count, first_miss_count);
7614 return -EINVAL;
7615 }
7616
7617 final_miss_count = total_miss_count - first_miss_count;
7618
7619 hdd_debug("First count %u, final count %u",
7620 first_miss_count, final_miss_count);
7621
7622 /*****
Jeff Johnson55d2ab42019-03-06 11:43:49 -08007623 * TODO: research why is 0 being passed for vdev id???
Jeff Johnson320feeb2018-11-16 10:14:24 -08007624 */
7625 status = sme_set_roam_bmiss_final_bcnt(hdd_ctx->mac_handle,
7626 0,
7627 final_miss_count);
7628 if (QDF_IS_STATUS_ERROR(status)) {
7629 hdd_err("Failed to set final count, status %u", status);
7630 return qdf_status_to_os_return(status);
7631 }
7632
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007633 status = sme_set_bmiss_bcnt(adapter->vdev_id,
Jeff Johnson320feeb2018-11-16 10:14:24 -08007634 first_miss_count,
7635 final_miss_count);
7636 if (QDF_IS_STATUS_ERROR(status))
7637 hdd_err("Failed to set count, status %u", status);
7638
7639 return qdf_status_to_os_return(status);
7640}
7641
Jeff Johnson2502ddd2018-11-16 10:59:30 -08007642static int hdd_config_latency_level(struct hdd_adapter *adapter,
7643 const struct nlattr *attr)
7644{
7645 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7646 uint16_t latency_level;
7647 QDF_STATUS status;
7648
7649 latency_level = nla_get_u16(attr);
7650 switch (latency_level) {
7651 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL:
7652 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE:
7653 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW:
7654 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW:
7655 /* valid values */
7656 break;
7657 default:
7658 hdd_err("Invalid value %u", latency_level);
7659 return -EINVAL;
7660 }
7661
7662 /* Map the latency value to the level which fw expected
7663 * 0 - normal, 1 - moderate, 2 - low, 3 - ultralow
7664 */
Paul Zhang1ef2b7c2019-10-31 16:09:55 +08007665 adapter->latency_level = latency_level - 1;
Jeff Johnson2502ddd2018-11-16 10:59:30 -08007666 status = sme_set_wlm_latency_level(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007667 adapter->vdev_id,
Paul Zhang1ef2b7c2019-10-31 16:09:55 +08007668 adapter->latency_level);
Jeff Johnson2502ddd2018-11-16 10:59:30 -08007669 if (QDF_IS_STATUS_ERROR(status))
7670 hdd_err("set latency level failed, %u", status);
7671
7672 return qdf_status_to_os_return(status);
7673}
7674
Jeff Johnson0a315912018-11-16 11:18:21 -08007675static int hdd_config_disable_fils(struct hdd_adapter *adapter,
7676 const struct nlattr *attr)
7677{
7678 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7679 uint8_t disable_fils;
7680 bool enabled;
7681 QDF_STATUS status;
7682
7683 /* ignore unless in STA mode */
7684 if (adapter->device_mode != QDF_STA_MODE)
7685 return 0;
7686
7687 disable_fils = nla_get_u8(attr);
7688 hdd_debug("%u", disable_fils);
7689
7690 enabled = !disable_fils;
7691 status = ucfg_mlme_set_fils_enabled_info(hdd_ctx->psoc, enabled);
7692 if (QDF_IS_STATUS_ERROR(status))
7693 hdd_err("could not set fils enabled info, %d", status);
7694
7695 status = ucfg_mlme_set_enable_bcast_probe_rsp(hdd_ctx->psoc, enabled);
7696 if (QDF_IS_STATUS_ERROR(status))
7697 hdd_err("could not set enable bcast probe resp info, %d",
7698 status);
7699
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007700 status = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson0a315912018-11-16 11:18:21 -08007701 WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE,
7702 !disable_fils, VDEV_CMD);
7703 if (QDF_IS_STATUS_ERROR(status))
7704 hdd_err("failed to set enable bcast probe resp, %d",
7705 status);
7706
7707 return qdf_status_to_os_return(status);
7708}
7709
Jeff Johnson0bdbb962018-11-16 11:42:10 -08007710static int hdd_config_rsn_ie(struct hdd_adapter *adapter,
7711 const struct nlattr *attr)
7712{
7713 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson0bdbb962018-11-16 11:42:10 -08007714 uint8_t force_rsne_override;
7715
Jeff Johnson0bdbb962018-11-16 11:42:10 -08007716 force_rsne_override = nla_get_u8(attr);
7717 if (force_rsne_override > 1) {
7718 hdd_err("Invalid value %d", force_rsne_override);
7719 return -EINVAL;
7720 }
7721
7722 hdd_ctx->force_rsne_override = force_rsne_override;
7723 hdd_debug("force_rsne_override - %d", force_rsne_override);
7724
7725 return 0;
7726}
7727
Jeff Johnson7acca0d2018-11-16 11:53:18 -08007728static int hdd_config_gtx(struct hdd_adapter *adapter,
7729 const struct nlattr *attr)
7730{
7731 uint8_t config_gtx;
7732 int errno;
7733
7734 config_gtx = nla_get_u8(attr);
7735 if (config_gtx > 1) {
7736 hdd_err_rl("Invalid config_gtx value %d", config_gtx);
7737 return -EINVAL;
7738 }
7739
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007740 errno = sme_cli_set_command(adapter->vdev_id,
Jeff Johnson7acca0d2018-11-16 11:53:18 -08007741 WMI_VDEV_PARAM_GTX_ENABLE,
7742 config_gtx, VDEV_CMD);
7743 if (errno)
7744 hdd_err("Failed to set GTX, %d", errno);
7745
7746 return errno;
7747}
7748
lifeng66831662017-05-19 16:01:35 +08007749/**
Srinivas Dasari37e37312019-06-30 23:50:24 +05307750 * hdd_config_disconnect_ies() - Configure disconnect IEs
7751 * @adapter: Pointer to HDD adapter
7752 * @attr: array of pointer to struct nlattr
7753 *
7754 * Return: 0 on success; error number otherwise
7755 */
7756static int hdd_config_disconnect_ies(struct hdd_adapter *adapter,
7757 const struct nlattr *attr)
7758{
7759 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7760 QDF_STATUS status;
7761
7762 hdd_debug("IE len %u session %u device mode %u",
7763 nla_len(attr), adapter->vdev_id, adapter->device_mode);
7764 if (!nla_len(attr) ||
7765 nla_len(attr) > SIR_MAC_MAX_ADD_IE_LENGTH + 2 ||
7766 !wlan_is_ie_valid(nla_data(attr), nla_len(attr))) {
7767 hdd_err("Invalid disconnect IEs");
7768 return -EINVAL;
7769 }
7770
7771 status = sme_set_disconnect_ies(hdd_ctx->mac_handle,
7772 adapter->vdev_id,
7773 nla_data(attr),
7774 nla_len(attr));
7775 if (QDF_IS_STATUS_ERROR(status))
7776 hdd_err("Failed to set disconnect_ies");
7777
7778 return qdf_status_to_os_return(status);
7779}
7780
Paul Zhangc9dbaee2019-06-23 22:07:31 +08007781#ifdef WLAN_FEATURE_ELNA
7782/**
7783 * hdd_set_elna_bypass() - Set eLNA bypass
7784 * @adapter: Pointer to HDD adapter
7785 * @attr: Pointer to struct nlattr
7786 *
7787 * Return: 0 on success; error number otherwise
7788 */
7789static int hdd_set_elna_bypass(struct hdd_adapter *adapter,
7790 const struct nlattr *attr)
7791{
7792 int ret;
7793 struct wlan_objmgr_vdev *vdev;
7794
7795 vdev = hdd_objmgr_get_vdev(adapter);
7796 if (!vdev)
7797 return -EINVAL;
7798
7799 ret = os_if_fwol_set_elna_bypass(vdev, attr);
7800
7801 hdd_objmgr_put_vdev(vdev);
7802
7803 return ret;
7804}
7805#endif
7806
Srinivas Dasari37e37312019-06-30 23:50:24 +05307807/**
Jeff Johnsonb48efe22018-11-15 11:53:09 -08007808 * typedef independent_setter_fn - independent attribute handler
7809 * @adapter: The adapter being configured
7810 * @attr: The nl80211 attribute being applied
7811 *
7812 * Defines the signature of functions in the independent attribute vtable
7813 *
7814 * Return: 0 if the attribute was handled successfully, otherwise an errno
7815 */
7816typedef int (*independent_setter_fn)(struct hdd_adapter *adapter,
7817 const struct nlattr *attr);
7818
7819/**
7820 * struct independent_setters
7821 * @id: vendor attribute which this entry handles
7822 * @cb: callback function to invoke to process the attribute when present
7823 */
7824struct independent_setters {
7825 uint32_t id;
7826 independent_setter_fn cb;
7827};
7828
7829/* vtable for independent setters */
7830static const struct independent_setters independent_setters[] = {
Jeff Johnson522464b2018-11-15 13:07:26 -08007831 {QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES,
7832 hdd_config_scan_default_ies},
Jeff Johnson7f4fd702018-11-14 11:19:52 -08007833 {QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT,
7834 hdd_config_fine_time_measurement},
Jeff Johnsonbcaeafb2018-11-14 12:14:24 -08007835 {QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM,
7836 hdd_config_modulated_dtim},
Jeff Johnson6db91622018-11-14 12:33:28 -08007837 {QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL,
7838 hdd_config_listen_interval},
Jeff Johnson9381d032018-11-14 12:42:22 -08007839 {QCA_WLAN_VENDOR_ATTR_CONFIG_LRO,
7840 hdd_config_lro},
Jeff Johnson3d4f64c2018-11-14 13:13:04 -08007841 {QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE,
7842 hdd_config_scan_enable},
Jeff Johnson1feb8a62018-11-14 13:18:41 -08007843 {QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER,
7844 hdd_config_qpower},
Jeff Johnsonf15ede02018-11-14 13:27:13 -08007845 {QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR,
7846 hdd_config_stats_avg_factor},
Jeff Johnson47e2e842018-11-14 13:49:43 -08007847 {QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME,
7848 hdd_config_guard_time},
Jeff Johnsonf3827502018-11-14 14:00:58 -08007849 {QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY,
7850 hdd_config_non_agg_retry},
Jeff Johnsonb9021002018-11-15 15:51:36 -08007851 {QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY,
7852 hdd_config_agg_retry},
Jeff Johnson0e8259c2018-11-15 19:44:57 -08007853 {QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY,
7854 hdd_config_mgmt_retry},
Jeff Johnson6b48a2f2018-11-15 19:48:47 -08007855 {QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY,
7856 hdd_config_ctrl_retry},
Jeff Johnson98214742018-11-15 19:56:37 -08007857 {QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY,
7858 hdd_config_propagation_delay},
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08007859 {QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY,
7860 hdd_config_propagation_abs_delay},
Jeff Johnson7c5e6dc2018-11-15 21:20:18 -08007861 {QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT,
7862 hdd_config_tx_fail_count},
Jeff Johnson7766fd22018-11-15 21:52:37 -08007863 {QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND,
7864 hdd_config_channel_avoidance_ind},
Jeff Johnsonf9871e42018-11-15 22:24:06 -08007865 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA,
7866 hdd_config_ant_div_ena},
Jeff Johnson91f90ff2018-11-16 07:53:37 -08007867 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF,
7868 hdd_config_ant_div_snr_diff},
Jeff Johnson77177bc2018-11-16 08:14:20 -08007869 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME,
7870 hdd_config_ant_div_probe_dwell_time},
Jeff Johnsonaa172222018-11-16 09:16:11 -08007871 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN,
7872 hdd_config_ant_div_chain},
Jeff Johnsonef427ad2018-11-16 09:22:17 -08007873 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST,
7874 hdd_config_ant_div_selftest},
Jeff Johnsonae21be82018-11-16 09:43:53 -08007875 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL,
7876 hdd_config_ant_div_selftest_intvl},
Jeff Johnson3a25de82018-11-16 07:26:46 -08007877 {QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED,
7878 hdd_config_ignore_assoc_disallowed},
Jeff Johnson72dc91e2018-11-16 08:46:12 -08007879 {QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL,
7880 hdd_config_restrict_offchannel},
Jeff Johnson320feeb2018-11-16 10:14:24 -08007881 {QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT,
7882 hdd_config_total_beacon_miss_count},
Jeff Johnson2502ddd2018-11-16 10:59:30 -08007883 {QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL,
7884 hdd_config_latency_level},
Jeff Johnson0a315912018-11-16 11:18:21 -08007885 {QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS,
7886 hdd_config_disable_fils},
Jeff Johnson0bdbb962018-11-16 11:42:10 -08007887 {QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE,
7888 hdd_config_rsn_ie},
Jeff Johnson7acca0d2018-11-16 11:53:18 -08007889 {QCA_WLAN_VENDOR_ATTR_CONFIG_GTX,
7890 hdd_config_gtx},
Srinivas Dasari37e37312019-06-30 23:50:24 +05307891 {QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES,
7892 hdd_config_disconnect_ies},
Paul Zhangc9dbaee2019-06-23 22:07:31 +08007893#ifdef WLAN_FEATURE_ELNA
7894 {QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
7895 hdd_set_elna_bypass},
7896#endif
sheenam monga17452ef2020-02-24 13:23:13 +05307897 {QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
7898 hdd_set_roam_reason_vsie_status},
Jeff Johnsonb48efe22018-11-15 11:53:09 -08007899};
7900
Paul Zhangc9dbaee2019-06-23 22:07:31 +08007901#ifdef WLAN_FEATURE_ELNA
7902/**
7903 * hdd_get_elna_bypass() - Get eLNA bypass
7904 * @adapter: Pointer to HDD adapter
7905 * @skb: sk buffer to hold nl80211 attributes
7906 * @attr: Pointer to struct nlattr
7907 *
7908 * Return: 0 on success; error number otherwise
7909 */
7910static int hdd_get_elna_bypass(struct hdd_adapter *adapter,
7911 struct sk_buff *skb,
7912 const struct nlattr *attr)
7913{
7914 int ret;
7915 struct wlan_objmgr_vdev *vdev;
7916
7917 vdev = hdd_objmgr_get_vdev(adapter);
7918 if (!vdev)
7919 return -EINVAL;
7920
7921 ret = os_if_fwol_get_elna_bypass(vdev, skb, attr);
7922
7923 hdd_objmgr_put_vdev(vdev);
7924
7925 return ret;
7926}
7927#endif
7928
7929/**
sheenam monga17452ef2020-02-24 13:23:13 +05307930 * hdd_get_roam_reason_vsie_status() - Get roam_reason_vsie
7931 * @adapter: Pointer to HDD adapter
7932 * @skb: sk buffer to hold nl80211 attributes
7933 * @attr: Pointer to struct nlattr
7934 *
7935 * Return: 0 on success; error number otherwise
7936 */
7937#ifdef WLAN_FEATURE_ROAM_OFFLOAD
7938static int hdd_get_roam_reason_vsie_status(struct hdd_adapter *adapter,
7939 struct sk_buff *skb,
7940 const struct nlattr *attr)
7941{
7942 uint8_t roam_reason_vsie_enabled;
7943 struct hdd_context *hdd_ctx = NULL;
7944 QDF_STATUS status;
7945
7946 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7947
7948 status = ucfg_mlme_get_roam_reason_vsie_status
7949 (hdd_ctx->psoc,
7950 &roam_reason_vsie_enabled);
7951 if (QDF_IS_STATUS_ERROR(status)) {
7952 hdd_err("get roam reason vsie failed");
7953 return -EINVAL;
7954 }
7955 hdd_debug("is roam_reason_vsie_enabled %d", roam_reason_vsie_enabled);
7956 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
7957 roam_reason_vsie_enabled)) {
7958 hdd_err("nla_put failure");
7959 return -EINVAL;
7960 }
7961
7962 return 0;
7963}
7964#else
7965static int hdd_get_roam_reason_vsie_status(struct hdd_adapter *adapter,
7966 struct sk_buff *skb,
7967 const struct nlattr *attr)
7968{
7969 return -EINVAL;
7970}
7971#endif
7972
7973/**
Paul Zhangc9dbaee2019-06-23 22:07:31 +08007974 * typedef config_getter_fn - get configuration handler
7975 * @adapter: The adapter being configured
7976 * @skb: sk buffer to hold nl80211 attributes
7977 * @attr: The nl80211 attribute being applied
7978 *
7979 * Defines the signature of functions in the attribute vtable
7980 *
7981 * Return: 0 if the attribute was handled successfully, otherwise an errno
7982 */
7983typedef int (*config_getter_fn)(struct hdd_adapter *adapter,
7984 struct sk_buff *skb,
7985 const struct nlattr *attr);
7986
7987/**
7988 * struct config_getters
7989 * @id: vendor attribute which this entry handles
7990 * @cb: callback function to invoke to process the attribute when present
7991 */
7992struct config_getters {
7993 uint32_t id;
7994 size_t max_attr_len;
7995 config_getter_fn cb;
7996};
7997
7998/* vtable for config getters */
7999static const struct config_getters config_getters[] = {
8000#ifdef WLAN_FEATURE_ELNA
8001 {QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
8002 sizeof(uint8_t),
8003 hdd_get_elna_bypass},
8004#endif
sheenam monga17452ef2020-02-24 13:23:13 +05308005 {QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
8006 sizeof(uint8_t),
8007 hdd_get_roam_reason_vsie_status},
Paul Zhangc9dbaee2019-06-23 22:07:31 +08008008};
8009
8010/**
8011 * hdd_get_configuration() - Handle get configuration
8012 * @adapter: adapter upon which the vendor command was received
8013 * @tb: parsed attribute array
8014 *
8015 * This is a table-driven function which dispatches attributes
8016 * in a QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION
8017 * vendor command.
8018 *
8019 * Return: 0 if there were no issues, otherwise errno of the last issue
8020 */
8021static int hdd_get_configuration(struct hdd_adapter *adapter,
8022 struct nlattr **tb)
8023{
8024 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8025 uint32_t i, id;
8026 unsigned long nl_buf_len = NLMSG_HDRLEN;
8027 struct sk_buff *skb;
8028 struct nlattr *attr;
8029 config_getter_fn cb;
8030 int errno = 0;
8031
8032 for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
8033 id = config_getters[i].id;
8034 attr = tb[id];
8035 if (!attr)
8036 continue;
8037
8038 nl_buf_len += NLA_HDRLEN +
8039 NLA_ALIGN(config_getters[i].max_attr_len);
8040 }
8041
8042 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8043 if (!skb) {
8044 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8045 return -ENOMEM;
8046 }
8047
8048 for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
8049 id = config_getters[i].id;
8050 attr = tb[id];
8051 if (!attr)
8052 continue;
8053
8054 cb = config_getters[i].cb;
8055 errno = cb(adapter, skb, attr);
8056 if (errno)
8057 break;
8058 }
8059
8060 if (errno) {
8061 hdd_err("Failed to get wifi configuration, errno = %d", errno);
8062 kfree_skb(skb);
8063 return -EINVAL;
8064 }
8065
8066 cfg80211_vendor_cmd_reply(skb);
8067
8068 return errno;
8069}
8070
Jeff Johnsonb48efe22018-11-15 11:53:09 -08008071/**
8072 * hdd_set_independent_configuration() - Handle independent attributes
8073 * @adapter: adapter upon which the vendor command was received
8074 * @tb: parsed attribute array
8075 *
8076 * This is a table-driven function which dispatches independent
8077 * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
8078 * vendor command. An attribute is considered independent if it
8079 * doesn't depend upon any other attributes
8080 *
8081 * Return: 0 if there were no issues, otherwise errno of the last issue
8082 */
8083static int hdd_set_independent_configuration(struct hdd_adapter *adapter,
8084 struct nlattr **tb)
8085{
8086 uint32_t i;
8087 uint32_t id;
8088 struct nlattr *attr;
8089 independent_setter_fn cb;
8090 int errno = 0;
8091 int ret;
8092
8093 for (i = 0; i < QDF_ARRAY_SIZE(independent_setters); i++) {
8094 id = independent_setters[i].id;
8095 attr = tb[id];
8096 if (!attr)
8097 continue;
8098
8099 cb = independent_setters[i].cb;
8100 ret = cb(adapter, attr);
8101 if (ret)
8102 errno = ret;
8103 }
8104
8105 return errno;
8106}
8107
8108/**
8109 * typedef interdependent_setter_fn - interdependent attribute handler
8110 * @adapter: The adapter being configured
8111 * @tb: The parsed nl80211 attributes being applied
8112 *
8113 * Defines the signature of functions in the interdependent attribute vtable
8114 *
8115 * Return: 0 if attributes were handled successfully, otherwise an errno
8116 */
8117typedef int (*interdependent_setter_fn)(struct hdd_adapter *adapter,
8118 struct nlattr **tb);
8119
8120/* vtable for interdependent setters */
8121static const interdependent_setter_fn interdependent_setters[] = {
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08008122 hdd_config_access_policy,
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08008123 hdd_config_mpdu_aggregation,
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08008124 hdd_config_ant_div_period,
Jeff Johnson1350e622018-11-16 18:36:55 -08008125 hdd_config_ant_div_snr_weight,
Jeff Johnson0dd687e2018-11-16 20:11:27 -08008126 wlan_hdd_cfg80211_wifi_set_reorder_timeout,
Jeff Johnson339ede82018-11-16 20:27:52 -08008127 wlan_hdd_cfg80211_wifi_set_rx_blocksize,
Jeff Johnsonb48efe22018-11-15 11:53:09 -08008128};
8129
8130/**
8131 * hdd_set_interdependent_configuration() - Handle interdependent attributes
8132 * @adapter: adapter upon which the vendor command was received
8133 * @tb: parsed attribute array
8134 *
8135 * This is a table-driven function which handles interdependent
8136 * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
8137 * vendor command. A set of attributes is considered interdependent if
8138 * they depend upon each other. In the typical case if one of the
8139 * attributes is present in the the attribute array, then all of the
8140 * attributes must be present.
8141 *
8142 * Return: 0 if there were no issues, otherwise errno of the last issue
8143 */
8144static int hdd_set_interdependent_configuration(struct hdd_adapter *adapter,
8145 struct nlattr **tb)
8146{
8147 uint32_t i;
8148 interdependent_setter_fn cb;
8149 int errno = 0;
8150 int ret;
8151
8152 for (i = 0; i < QDF_ARRAY_SIZE(interdependent_setters); i++) {
8153 cb = interdependent_setters[i];
8154 ret = cb(adapter, tb);
8155 if (ret)
8156 errno = ret;
8157 }
8158
8159 return errno;
8160}
8161
8162/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008163 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
8164 * vendor command
8165 *
8166 * @wiphy: wiphy device pointer
8167 * @wdev: wireless device pointer
8168 * @data: Vendor command data buffer
8169 * @data_len: Buffer length
8170 *
8171 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
8172 *
8173 * Return: Error code.
8174 */
8175static int
8176__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
8177 struct wireless_dev *wdev,
8178 const void *data,
8179 int data_len)
8180{
8181 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008182 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008183 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008184 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
Jeff Johnsonb48efe22018-11-15 11:53:09 -08008185 int errno;
Jeff Johnson3b2abe92017-12-15 09:03:47 -08008186 int ret;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05308187
Dustin Brownfdf17c12018-03-14 12:55:34 -07008188 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08008189
Anurag Chouhan6d760662016-02-20 16:05:43 +05308190 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008191 hdd_err("Command not allowed in FTM mode");
8192 return -EPERM;
8193 }
8194
Jeff Johnsonb48efe22018-11-15 11:53:09 -08008195 errno = wlan_hdd_validate_context(hdd_ctx);
8196 if (errno)
8197 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008198
Dustin Brown4ea21db2018-01-05 14:13:17 -08008199 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
8200 data_len, wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008201 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008202 return -EINVAL;
8203 }
8204
Jeff Johnsonb48efe22018-11-15 11:53:09 -08008205 ret = hdd_set_independent_configuration(adapter, tb);
8206 if (ret)
8207 errno = ret;
8208
8209 ret = hdd_set_interdependent_configuration(adapter, tb);
8210 if (ret)
8211 errno = ret;
8212
Jeff Johnsonb48efe22018-11-15 11:53:09 -08008213 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008214}
8215
8216/**
8217 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
8218 * vendor command
8219 *
8220 * @wiphy: wiphy device pointer
8221 * @wdev: wireless device pointer
8222 * @data: Vendor command data buffer
8223 * @data_len: Buffer length
8224 *
8225 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
8226 *
8227 * Return: EOK or other error codes.
8228 */
8229static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
8230 struct wireless_dev *wdev,
8231 const void *data,
8232 int data_len)
8233{
Dustin Browna09acf42018-11-08 12:32:26 +05308234 int errno;
8235 struct osif_vdev_sync *vdev_sync;
8236
8237 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
8238 if (errno)
8239 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008240
Dustin Browna09acf42018-11-08 12:32:26 +05308241 errno = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
8242 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008243
Dustin Browna09acf42018-11-08 12:32:26 +05308244 osif_vdev_sync_op_stop(vdev_sync);
8245
8246 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008247}
8248
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008249/**
Paul Zhangc9dbaee2019-06-23 22:07:31 +08008250 * __wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
8251 * vendor command
8252 * @wiphy: wiphy device pointer
8253 * @wdev: wireless device pointer
8254 * @data: Vendor command data buffer
8255 * @data_len: Buffer length
8256 *
8257 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
8258 *
8259 * Return: Error code.
8260 */
8261static int
8262__wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
8263 struct wireless_dev *wdev,
8264 const void *data,
8265 int data_len)
8266{
8267 struct net_device *dev = wdev->netdev;
8268 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8269 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
8270 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
8271 int errno;
8272 int ret;
8273
8274 hdd_enter_dev(dev);
8275
8276 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8277 hdd_err("Command not allowed in FTM mode");
8278 return -EPERM;
8279 }
8280
8281 errno = wlan_hdd_validate_context(hdd_ctx);
8282 if (errno)
8283 return errno;
8284
8285 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
8286 data_len, wlan_hdd_wifi_config_policy)) {
8287 hdd_err("invalid attr");
8288 return -EINVAL;
8289 }
8290
8291 ret = hdd_get_configuration(adapter, tb);
8292 if (ret)
8293 errno = ret;
8294
8295 return errno;
8296}
8297
8298/**
8299 * wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
8300 * vendor command
8301 *
8302 * @wiphy: wiphy device pointer
8303 * @wdev: wireless device pointer
8304 * @data: Vendor command data buffer
8305 * @data_len: Buffer length
8306 *
8307 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
8308 *
8309 * Return: EOK or other error codes.
8310 */
8311static int wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
8312 struct wireless_dev *wdev,
8313 const void *data,
8314 int data_len)
8315{
8316 int errno;
8317 struct osif_vdev_sync *vdev_sync;
8318
8319 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
8320 if (errno)
8321 return errno;
8322
8323 errno = __wlan_hdd_cfg80211_wifi_configuration_get(wiphy, wdev,
8324 data, data_len);
8325
8326 osif_vdev_sync_op_stop(vdev_sync);
8327
8328 return errno;
8329}
8330
Alan Chendf858ef2019-10-10 15:44:29 -07008331static void hdd_disable_runtime_pm_for_user(struct hdd_context *hdd_ctx)
8332{
8333 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
8334
8335 if (!ctx)
8336 return;
8337
8338 if (ctx->is_user_wakelock_acquired)
8339 return;
8340
8341 ctx->is_user_wakelock_acquired = true;
8342 qdf_runtime_pm_prevent_suspend(&ctx->user);
8343}
8344
Paul Zhangc9dbaee2019-06-23 22:07:31 +08008345/**
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008346 * __wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
8347 * vendor command
8348 *
8349 * @wiphy: wiphy device pointer
8350 * @wdev: wireless device pointer
8351 * @data: Vendor command data buffer
8352 * @data_len: Buffer length
8353 *
8354 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
8355 *
8356 * Return: Error code.
8357 */
8358static int
8359__wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
Srinivas Girigowdaa19eafd2018-09-07 15:28:21 -07008360 struct wireless_dev *wdev, const void *data, int data_len)
8361{
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008362 struct net_device *dev = wdev->netdev;
8363 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8364 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
8365 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1];
8366 int ret_val = 0;
8367 uint8_t cfg_val = 0;
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08008368 uint8_t set_val = 0;
Jeff Johnson46b4f0e2019-03-08 10:48:35 -08008369 struct sme_config_params *sme_config;
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008370 bool update_sme_cfg = false;
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08008371 uint8_t tid = 0, ac;
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008372 uint16_t buff_size = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008373 mac_handle_t mac_handle;
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308374 QDF_STATUS status;
8375 bool bval = false;
8376 uint8_t value = 0;
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +05308377 uint8_t wmm_mode = 0;
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07008378 uint32_t cmd_id;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008379
Dustin Brownfdf17c12018-03-14 12:55:34 -07008380 hdd_enter_dev(dev);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008381
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008382 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Min Liu74a1a502018-10-10 19:59:07 +08008383 if (!sme_config)
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008384 return -ENOMEM;
Min Liu74a1a502018-10-10 19:59:07 +08008385
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008386 mac_handle = hdd_ctx->mac_handle;
8387 sme_get_config_param(mac_handle, sme_config);
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008388
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008389 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8390 hdd_err("Command not allowed in FTM mode");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008391 ret_val = -EPERM;
8392 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008393 }
8394
8395 ret_val = wlan_hdd_validate_context(hdd_ctx);
8396 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008397 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008398
8399 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
8400 hdd_err("Driver Modules are closed, can not start logger");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008401 ret_val = -EINVAL;
8402 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008403 }
8404
8405 if (wlan_cfg80211_nla_parse(tb,
8406 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX,
8407 data, data_len, wlan_hdd_wifi_test_config_policy)) {
8408 hdd_err("invalid attr");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008409 ret_val = -EINVAL;
8410 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008411 }
8412
8413 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]) {
8414 cfg_val = nla_get_u8(tb[
8415 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]
8416 );
8417 hdd_debug("set addba accept req from peer value %d", cfg_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008418 ret_val = sme_set_addba_accept(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008419 cfg_val);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008420 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008421 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08008422 }
8423
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08008424 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]) {
8425 cfg_val = nla_get_u8(tb[
8426 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]);
8427 hdd_debug("set HE MCS value 0x%0X", cfg_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008428 ret_val = sme_update_he_mcs(mac_handle, adapter->vdev_id,
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08008429 cfg_val);
8430 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008431 goto send_err;
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08008432 }
8433
Krunal Soni707eb782018-01-18 12:04:19 -08008434 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]) {
8435 cfg_val = nla_get_u8(tb[
8436 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]);
Krunal Soni707eb782018-01-18 12:04:19 -08008437 if (!cfg_val) {
Jeff Johnsone94ccd02019-04-02 15:02:56 -07008438 sme_config->csr_config.WMMSupportMode =
Krunal Soni707eb782018-01-18 12:04:19 -08008439 hdd_to_csr_wmm_mode(HDD_WMM_USER_MODE_NO_QOS);
8440 hdd_debug("wmm is disabled");
8441 } else {
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +05308442 status = ucfg_mlme_get_wmm_mode(hdd_ctx->psoc,
8443 &wmm_mode);
8444 if (!QDF_IS_STATUS_SUCCESS(status)) {
8445 hdd_err("Get wmm_mode failed");
8446 return QDF_STATUS_E_FAILURE;
8447 }
Jeff Johnsone94ccd02019-04-02 15:02:56 -07008448 sme_config->csr_config.WMMSupportMode =
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +05308449 hdd_to_csr_wmm_mode(wmm_mode);
Krunal Soni707eb782018-01-18 12:04:19 -08008450 hdd_debug("using wmm default value");
8451 }
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008452 update_sme_cfg = true;
Krunal Soni707eb782018-01-18 12:04:19 -08008453 }
8454
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08008455 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]) {
8456 cfg_val = nla_get_u8(tb[
8457 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]);
8458 if (cfg_val) {
8459 /*Auto BA mode*/
8460 set_val = 0;
8461 hdd_debug("BA operating mode is set to auto");
8462 } else {
8463 /*Manual BA mode*/
8464 set_val = 1;
8465 hdd_debug("BA operating mode is set to Manual");
8466 }
8467
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008468 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08008469 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
Kiran Kumar Lokere015f77f2018-04-24 18:25:28 -07008470 if (ret_val) {
8471 hdd_err("Set BA operating mode failed");
8472 goto send_err;
8473 }
8474 if (!cfg_val) {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008475 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere015f77f2018-04-24 18:25:28 -07008476 WMI_VDEV_PARAM_AMSDU_AGGREGATION_SIZE_OPTIMIZATION,
8477 0, VDEV_CMD);
8478 }
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08008479 }
8480
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08008481 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]) {
8482 cfg_val = nla_get_u8(tb[
8483 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]
8484 );
8485 if (cfg_val > HE_FRAG_LEVEL1)
8486 set_val = HE_FRAG_LEVEL1;
8487 else
8488 set_val = cfg_val;
8489
8490 hdd_debug("set HE fragmention to %d", set_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008491 ret_val = sme_update_he_frag_supp(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008492 adapter->vdev_id, set_val);
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08008493 }
8494
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008495 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]) {
8496 cfg_val = nla_get_u8(tb[
8497 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]);
Jeff Johnsone94ccd02019-04-02 15:02:56 -07008498 sme_config->csr_config.wep_tkip_in_he = cfg_val;
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08008499 hdd_debug("Set WEP/TKIP allow in HE %d", cfg_val);
8500
8501 update_sme_cfg = true;
8502 }
8503
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008504 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]) {
8505 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]) {
8506 tid = nla_get_u8(tb[
8507 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]);
8508 } else {
8509 hdd_err("TID is not set for ADD/DEL BA cfg");
8510 ret_val = -EINVAL;
8511 goto send_err;
8512 }
8513 cfg_val = nla_get_u8(tb[
8514 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]);
8515 if (cfg_val == QCA_WLAN_ADD_BA) {
8516 if (tb[
8517 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE])
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07008518 buff_size = nla_get_u16(tb[
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008519 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008520 ret_val = sme_send_addba_req(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008521 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008522 tid, buff_size);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008523 } else if (cfg_val == QCA_WLAN_DELETE_BA) {
8524 } else {
8525 hdd_err("Invalid BA session cfg");
8526 ret_val = -EINVAL;
8527 goto send_err;
8528 }
8529 } else if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]) {
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07008530 buff_size = nla_get_u16(tb[
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008531 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
8532 hdd_debug("set buff size to %d for all tids", buff_size);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008533 ret_val = sme_set_ba_buff_size(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008534 adapter->vdev_id, buff_size);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008535 if (ret_val)
8536 goto send_err;
8537 if (buff_size > 64)
8538 /* Configure ADDBA req buffer size to 256 */
8539 set_val = 3;
8540 else
8541 /* Configure ADDBA req buffer size to 64 */
8542 set_val = 2;
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008543 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008544 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07008545 if (ret_val)
8546 hdd_err("Failed to set BA operating mode %d", set_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008547 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07008548 GEN_VDEV_PARAM_AMPDU,
8549 buff_size, GEN_CMD);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08008550 }
8551
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08008552 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]) {
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07008553 int he_mcs_val;
Srinivas Girigowda50335342018-09-07 15:21:01 -07008554
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08008555 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]) {
8556 ac = nla_get_u8(tb[
8557 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]);
8558 } else {
8559 hdd_err("AC is not set for NO ACK policy config");
8560 ret_val = -EINVAL;
8561 goto send_err;
8562 }
8563 cfg_val = nla_get_u8(tb[
8564 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]);
8565 hdd_debug("Set NO_ACK to %d for ac %d", cfg_val, ac);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008566 ret_val = sme_set_no_ack_policy(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008567 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008568 cfg_val, ac);
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07008569 if (cfg_val) {
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308570 status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc,
8571 &bval);
8572 if (!QDF_IS_STATUS_SUCCESS(status))
8573 hdd_err("unable to get vht_enable2x2");
8574 if (bval)
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07008575 /*2x2 MCS 5 value*/
8576 he_mcs_val = 0x45;
8577 else
8578 /*1x1 MCS 5 value*/
8579 he_mcs_val = 0x25;
8580
8581 if (hdd_set_11ax_rate(adapter, he_mcs_val, NULL))
8582 hdd_err("HE MCS set failed, MCS val %0x",
8583 he_mcs_val);
8584 } else {
8585 if (hdd_set_11ax_rate(adapter, 0xFF, NULL))
8586 hdd_err("disable fixed rate failed");
8587 }
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08008588 }
8589
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08008590 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]) {
8591 cfg_val = nla_get_u8(tb[
8592 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]);
8593 hdd_debug("Set HE LTF to %d", cfg_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008594 ret_val = sme_set_auto_rate_he_ltf(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008595 adapter->vdev_id,
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08008596 cfg_val);
8597 if (ret_val)
8598 sme_err("Failed to set auto rate HE LTF");
8599
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008600 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08008601 WMI_VDEV_PARAM_HE_LTF,
8602 cfg_val, VDEV_CMD);
8603 if (ret_val)
8604 goto send_err;
8605 }
8606
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07008607 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]) {
8608 cfg_val = nla_get_u8(tb[
8609 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]);
8610 hdd_debug("Set Tx beamformee to %d", cfg_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008611 ret_val = sme_update_tx_bfee_supp(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008612 adapter->vdev_id,
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07008613 cfg_val);
8614 if (ret_val)
8615 sme_err("Failed to set Tx beamformee cap");
8616
8617 }
8618
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008619 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]) {
8620 cfg_val = nla_get_u8(tb[
8621 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]);
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308622 status = ucfg_mlme_cfg_get_vht_tx_bfee_ant_supp(hdd_ctx->psoc,
Abhinav Kumare057b412018-10-09 17:28:16 +05308623 &value);
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308624 if (!QDF_IS_STATUS_SUCCESS(status))
8625 hdd_err("unable to get tx_bfee_ant_supp");
8626
Kiran Kumar Lokerea67af052018-12-12 19:18:51 -08008627 if (!cfg_in_range(CFG_VHT_BEAMFORMEE_ANT_SUPP, cfg_val)) {
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008628 hdd_err("NSTS %d not supported, supp_val %d", cfg_val,
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308629 value);
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008630 ret_val = -ENOTSUPP;
8631 goto send_err;
8632 }
8633 hdd_debug("Set Tx beamformee NSTS to %d", cfg_val);
8634 ret_val = sme_update_tx_bfee_nsts(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008635 adapter->vdev_id,
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008636 cfg_val,
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05308637 value);
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07008638 if (ret_val)
8639 sme_err("Failed to set Tx beamformee cap");
8640
8641 }
8642
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008643 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]) {
8644 cfg_val = nla_get_u8(tb[
8645 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]);
8646 if (cfg_val) {
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07008647 hdd_debug("Set HE mac padding dur to %d", cfg_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008648 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008649 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
8650 0, VDEV_CMD);
8651 if (ret_val)
8652 hdd_err("MU_EDCA update disable failed");
8653 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
8654 sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
8655 if (sme_update_mu_edca_params(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008656 adapter->vdev_id))
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008657 hdd_err("Failed to send mu edca params");
8658 } else {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008659 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008660 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
8661 1, VDEV_CMD);
8662 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
8663 }
8664 ret_val = sme_update_he_trigger_frm_mac_pad(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008665 adapter->vdev_id,
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07008666 cfg_val);
8667 if (ret_val)
8668 hdd_err("Failed to set Trig frame mac padding cap");
8669 }
8670
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07008671 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]) {
8672 cfg_val = nla_get_u8(tb[
8673 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]);
8674 if (cfg_val) {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008675 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07008676 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
8677 0, VDEV_CMD);
8678 if (ret_val)
8679 hdd_err("MU_EDCA update disable failed");
8680 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
8681 sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
8682 if (sme_update_mu_edca_params(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008683 adapter->vdev_id))
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07008684 hdd_err("Failed to send mu edca params");
8685 } else {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008686 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07008687 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
8688 1, VDEV_CMD);
8689 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
8690 }
8691 }
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07008692
8693 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]) {
8694 cfg_val = nla_get_u8(tb[
8695 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]);
8696 ret_val = sme_update_he_om_ctrl_supp(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008697 adapter->vdev_id,
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07008698 cfg_val);
8699 }
8700
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008701 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX;
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07008702 if (tb[cmd_id]) {
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008703 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX + 1];
8704 struct nlattr *curr_attr;
8705 int tmp, rc;
8706 nla_for_each_nested(curr_attr, tb[cmd_id], tmp) {
8707 rc = wlan_cfg80211_nla_parse(
8708 tb2, QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX,
8709 nla_data(curr_attr),
8710 nla_len(curr_attr),
8711 qca_wlan_vendor_attr_he_omi_tx_policy);
8712 if (rc) {
8713 hdd_err("Invalid ATTR");
8714 goto send_err;
8715 }
8716 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW;
8717 if (tb2[cmd_id]) {
8718 cfg_val = nla_get_u8(tb2[cmd_id]);
8719 ret_val = sme_set_he_om_ctrl_param(
8720 hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008721 adapter->vdev_id,
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008722 cmd_id, cfg_val);
8723 }
8724 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS;
8725 if (tb2[cmd_id]) {
8726 cfg_val = nla_get_u8(tb2[cmd_id]);
8727 ret_val = sme_set_he_om_ctrl_param(
8728 hdd_ctx->mac_handle,
8729 adapter->vdev_id,
8730 cmd_id, cfg_val);
8731 }
8732
8733 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE;
8734 if (tb2[cmd_id]) {
8735 cfg_val = nla_get_u8(tb2[cmd_id]);
8736 ret_val = sme_set_he_om_ctrl_param(
8737 hdd_ctx->mac_handle,
8738 adapter->vdev_id,
8739 cmd_id, cfg_val);
8740 }
8741
8742 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS;
8743 if (tb2[cmd_id]) {
8744 cfg_val = nla_get_u8(tb2[cmd_id]);
8745 ret_val = sme_set_he_om_ctrl_param(
8746 hdd_ctx->mac_handle,
8747 adapter->vdev_id,
8748 cmd_id, cfg_val);
8749 }
Kiran Kumar Lokere49e3aff2019-02-06 17:00:48 -08008750
8751 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE;
8752 if (tb2[cmd_id]) {
8753 cfg_val = nla_get_u8(tb2[cmd_id]);
8754 ret_val = sme_set_he_om_ctrl_param(
8755 hdd_ctx->mac_handle,
8756 adapter->vdev_id,
8757 cmd_id, cfg_val);
8758 }
8759
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008760 }
8761 if (ret_val) {
8762 sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
8763 goto send_err;
8764 }
8765 ret_val = sme_send_he_om_ctrl_update(hdd_ctx->mac_handle,
8766 adapter->vdev_id);
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07008767 }
8768
8769 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG])
8770 sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
8771
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07008772 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU;
8773 if (tb[cmd_id]) {
8774 cfg_val = nla_get_u8(tb[cmd_id]);
8775 hdd_debug("Configure Tx SU PPDU enable %d", cfg_val);
8776 if (cfg_val)
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008777 sme_config_su_ppdu_queue(adapter->vdev_id, true);
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07008778 else
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008779 sme_config_su_ppdu_queue(adapter->vdev_id, false);
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07008780 }
8781
Kiran Kumar Lokerea1c29ec2019-02-25 18:19:00 -08008782 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT;
8783 if (tb[cmd_id]) {
8784 cfg_val = nla_get_u8(tb[cmd_id]);
8785 hdd_debug("Configure 2G VHT support %d", cfg_val);
8786 ucfg_mlme_set_vht_for_24ghz(hdd_ctx->psoc,
8787 (cfg_val ? true : false));
8788 }
8789
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08008790 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP;
8791 if (tb[cmd_id]) {
8792 cfg_val = nla_get_u8(tb[cmd_id]);
8793 hdd_debug("Configure +HTC_HE support %d", cfg_val);
8794 sme_update_he_htc_he_supp(hdd_ctx->mac_handle,
8795 adapter->vdev_id,
8796 (cfg_val ? true : false));
8797 }
8798
Kiran Kumar Lokere921b5a52019-02-24 21:53:20 -08008799 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS;
8800 if (tb[cmd_id]) {
Alan Chendf858ef2019-10-10 15:44:29 -07008801 hdd_disable_runtime_pm_for_user(hdd_ctx);
Kiran Kumar Lokere921b5a52019-02-24 21:53:20 -08008802 cfg_val = nla_get_u8(tb[cmd_id]);
8803 hdd_debug("Configure HE testbed defaults %d", cfg_val);
8804 if (!cfg_val)
8805 sme_reset_he_caps(hdd_ctx->mac_handle,
8806 adapter->vdev_id);
8807 else
8808 sme_set_he_testbed_def(hdd_ctx->mac_handle,
8809 adapter->vdev_id);
8810 }
8811
Kiran Kumar Lokereee205772018-09-27 00:27:27 -07008812 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU;
8813 if (tb[cmd_id]) {
8814 cfg_val = nla_get_u8(tb[cmd_id]);
8815 hdd_debug("Configure Action frame Tx in TB PPDU %d", cfg_val);
8816 sme_config_action_tx_in_tb_ppdu(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008817 adapter->vdev_id, cfg_val);
Kiran Kumar Lokereee205772018-09-27 00:27:27 -07008818 }
8819
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008820 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP]) {
8821 struct wmi_twt_add_dialog_param params = {0};
8822 struct hdd_station_ctx *hdd_sta_ctx =
8823 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8824 uint32_t wake_intvl_exp = 0, result = 0;
8825 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1];
8826 struct nlattr *twt_session;
8827 int tmp, rc;
Kiran Kumar Lokere54819a32019-10-04 18:30:43 -07008828 uint32_t congestion_timeout = 0;
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008829
8830 if ((adapter->device_mode != QDF_STA_MODE &&
8831 adapter->device_mode != QDF_P2P_CLIENT_MODE) ||
8832 hdd_sta_ctx->conn_info.conn_state !=
8833 eConnectionState_Associated) {
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308834 hdd_err_rl("Invalid state, vdev %d mode %d state %d",
8835 adapter->vdev_id, adapter->device_mode,
8836 hdd_sta_ctx->conn_info.conn_state);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008837 goto send_err;
8838 }
8839
8840 qdf_mem_copy(params.peer_macaddr,
8841 hdd_sta_ctx->conn_info.bssid.bytes,
8842 QDF_MAC_ADDR_SIZE);
8843 params.vdev_id = adapter->vdev_id;
8844 params.dialog_id = 0;
8845
8846 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP;
8847 nla_for_each_nested(twt_session, tb[cmd_id], tmp) {
8848 rc = wlan_cfg80211_nla_parse(
8849 tb2, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX,
8850 nla_data(twt_session),
8851 nla_len(twt_session),
8852 qca_wlan_vendor_twt_add_dialog_policy);
8853 if (rc) {
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308854 hdd_err_rl("Invalid twt ATTR");
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008855 goto send_err;
8856 }
8857
8858 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308859 if (!tb2[cmd_id]) {
8860 hdd_err_rl("TWT_SETUP_WAKE_INTVL_EXP is must");
8861 goto send_err;
8862 }
8863 wake_intvl_exp = nla_get_u8(tb2[cmd_id]);
8864 if (wake_intvl_exp > TWT_SETUP_WAKE_INTVL_EXP_MAX) {
8865 hdd_err_rl("Invalid wake_intvl_exp %u > %u",
8866 wake_intvl_exp,
8867 TWT_SETUP_WAKE_INTVL_EXP_MAX);
8868 goto send_err;
8869 }
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008870
8871 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST;
8872 if (tb2[cmd_id])
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308873 params.flag_bcast = nla_get_flag(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008874
8875 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308876 if (!tb2[cmd_id]) {
8877 hdd_err_rl("TWT_SETUP_REQ_TYPE is must");
8878 goto send_err;
8879 }
8880 params.twt_cmd = nla_get_u8(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008881
8882 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER;
8883 if (tb2[cmd_id])
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308884 params.flag_trigger = nla_get_flag(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008885
8886 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308887 if (!tb2[cmd_id]) {
8888 hdd_err_rl("TWT_SETUP_FLOW_TYPE is must");
8889 goto send_err;
8890 }
8891 params.flag_flow_type = nla_get_u8(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008892
8893 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION;
8894 if (tb2[cmd_id])
8895 params.flag_protection =
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308896 nla_get_flag(tb2[cmd_id]);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008897
8898 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME;
8899 if (tb2[cmd_id])
8900 params.sp_offset_us = nla_get_u32(tb2[cmd_id]);
8901
8902 cmd_id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308903 if (!tb2[cmd_id]) {
8904 hdd_err_rl("TWT_SETUP_WAKE_DURATION is must");
8905 goto send_err;
8906 }
8907 params.wake_dura_us = 256 * nla_get_u32(tb2[cmd_id]);
8908 if (params.wake_dura_us > TWT_SETUP_WAKE_DURATION_MAX) {
8909 hdd_err_rl("Invalid wake_dura_us %u",
8910 params.wake_dura_us);
8911 goto send_err;
8912 }
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008913
8914 cmd_id =
8915 QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA;
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308916 if (!tb2[cmd_id]) {
8917 hdd_err_rl("SETUP_WAKE_INTVL_MANTISSA is must");
8918 goto send_err;
8919 }
8920 params.wake_intvl_mantis = nla_get_u32(tb2[cmd_id]);
8921 if (params.wake_intvl_mantis >
8922 TWT_SETUP_WAKE_INTVL_MANTISSA_MAX) {
8923 hdd_err_rl("Invalid wake_intvl_mantis %u",
8924 params.wake_dura_us);
8925 goto send_err;
8926 }
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008927
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308928 if (wake_intvl_exp && params.wake_intvl_mantis) {
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008929 result = 2 << (wake_intvl_exp - 1);
8930 if (result >
8931 (UINT_MAX / params.wake_intvl_mantis)) {
Rajeev Kumar Sirasanagandla05f1f2d2019-05-02 17:01:36 +05308932 hdd_err_rl("Invalid exp %d mantissa %d",
8933 wake_intvl_exp,
8934 params.wake_intvl_mantis);
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008935 goto send_err;
8936 }
8937 params.wake_intvl_us =
8938 params.wake_intvl_mantis * result;
8939 } else {
8940 params.wake_intvl_us = params.wake_intvl_mantis;
8941 }
8942
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008943 hdd_debug("twt: vdev %d, intvl_us %d, mantis %d",
8944 params.vdev_id, params.wake_intvl_us,
8945 params.wake_intvl_mantis);
8946 hdd_debug("twt: dura %d, offset %d, cmd %d",
8947 params.wake_dura_us, params.sp_offset_us,
8948 params.twt_cmd);
8949 hdd_debug("twt: bcast %d, trigger %d, type %d, prot %d",
8950 params.flag_bcast, params.flag_trigger,
8951 params.flag_flow_type,
8952 params.flag_protection);
8953
Kiran Kumar Lokere54819a32019-10-04 18:30:43 -07008954 ucfg_mlme_get_twt_congestion_timeout(hdd_ctx->psoc,
8955 &congestion_timeout);
8956 if (congestion_timeout) {
8957 ret_val = qdf_status_to_os_return(
8958 hdd_send_twt_disable_cmd(hdd_ctx));
8959 if (ret_val) {
8960 hdd_err("Failed to disable TWT");
8961 goto send_err;
8962 }
8963 ucfg_mlme_set_twt_congestion_timeout(
8964 hdd_ctx->psoc, 0);
8965 hdd_send_twt_enable_cmd(hdd_ctx);
8966 }
Arif Hussain1f58cbb2019-03-14 17:06:56 -07008967 ret_val = qdf_status_to_os_return(
8968 wma_twt_process_add_dialog(&params));
8969 if (ret_val)
8970 goto send_err;
8971 }
8972 }
8973
8974 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE]) {
8975 struct wmi_twt_del_dialog_param params = {0};
8976 struct hdd_station_ctx *hdd_sta_ctx =
8977 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8978
8979 if ((adapter->device_mode != QDF_STA_MODE &&
8980 adapter->device_mode != QDF_P2P_CLIENT_MODE) ||
8981 hdd_sta_ctx->conn_info.conn_state !=
8982 eConnectionState_Associated) {
8983 hdd_err("Invalid state, vdev %d mode %d state %d",
8984 adapter->vdev_id, adapter->device_mode,
8985 hdd_sta_ctx->conn_info.conn_state);
8986 goto send_err;
8987 }
8988 qdf_mem_copy(params.peer_macaddr,
8989 hdd_sta_ctx->conn_info.bssid.bytes,
8990 QDF_MAC_ADDR_SIZE);
8991 params.vdev_id = adapter->vdev_id;
8992 params.dialog_id = 0;
8993 hdd_debug("twt_terminate: vdev_id %d", params.vdev_id);
8994 ret_val = qdf_status_to_os_return(
8995 wma_twt_process_del_dialog(&params));
8996 if (ret_val)
8997 goto send_err;
8998 }
8999
9000 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT;
9001 if (tb[cmd_id]) {
9002 cfg_val = nla_get_u8(tb[cmd_id]);
9003 hdd_debug("twt_request: val %d", cfg_val);
9004 ret_val = sme_update_he_twt_req_support(hdd_ctx->mac_handle,
9005 adapter->vdev_id,
9006 cfg_val);
9007 }
9008
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08009009 if (update_sme_cfg)
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009010 sme_update_config(mac_handle, sme_config);
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08009011
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08009012send_err:
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08009013 qdf_mem_free(sme_config);
9014
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08009015 return ret_val;
9016}
9017
9018/**
9019 * wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
9020 * vendor command
9021 *
9022 * @wiphy: wiphy device pointer
9023 * @wdev: wireless device pointer
9024 * @data: Vendor command data buffer
9025 * @data_len: Buffer length
9026 *
9027 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
9028 *
9029 * Return: EOK or other error codes.
9030 */
9031static int wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
9032 struct wireless_dev *wdev, const void *data, int data_len)
9033{
Dustin Browna09acf42018-11-08 12:32:26 +05309034 int errno;
9035 struct osif_vdev_sync *vdev_sync;
9036
9037 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
9038 if (errno)
9039 return errno;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08009040
Dustin Browna09acf42018-11-08 12:32:26 +05309041 errno = __wlan_hdd_cfg80211_set_wifi_test_config(wiphy, wdev,
9042 data, data_len);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08009043
Dustin Browna09acf42018-11-08 12:32:26 +05309044 osif_vdev_sync_op_stop(vdev_sync);
9045
9046 return errno;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08009047}
9048
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009049static const struct
9050nla_policy
9051qca_wlan_vendor_wifi_logger_start_policy
9052[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
9053 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
9054 = {.type = NLA_U32 },
9055 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
9056 = {.type = NLA_U32 },
9057 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
9058 = {.type = NLA_U32 },
9059};
9060
9061/**
9062 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
9063 * or disable the collection of packet statistics from the firmware
9064 * @wiphy: WIPHY structure pointer
9065 * @wdev: Wireless device structure pointer
9066 * @data: Pointer to the data received
9067 * @data_len: Length of the data received
9068 *
9069 * This function enables or disables the collection of packet statistics from
9070 * the firmware
9071 *
9072 * Return: 0 on success and errno on failure
9073 */
9074static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
9075 struct wireless_dev *wdev,
9076 const void *data,
9077 int data_len)
9078{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309079 QDF_STATUS status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009080 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009081 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
Hanumanth Reddy Pothulae9af1162018-06-13 13:41:44 +05309082 struct sir_wifi_start_log start_log = { 0 };
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009083 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009084
Dustin Brownfdf17c12018-03-14 12:55:34 -07009085 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08009086
Anurag Chouhan6d760662016-02-20 16:05:43 +05309087 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009088 hdd_err("Command not allowed in FTM mode");
9089 return -EPERM;
9090 }
9091
9092 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309093 if (status)
9094 return status;
9095
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05309096 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
9097 hdd_err("Driver Modules are closed, can not start logger");
9098 return -EINVAL;
9099 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009100
Dustin Brown4ea21db2018-01-05 14:13:17 -08009101 if (wlan_cfg80211_nla_parse(tb,
9102 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
9103 data, data_len,
9104 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009105 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009106 return -EINVAL;
9107 }
9108
9109 /* Parse and fetch ring id */
9110 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009111 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009112 return -EINVAL;
9113 }
9114 start_log.ring_id = nla_get_u32(
9115 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009116 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009117
9118 /* Parse and fetch verbose level */
9119 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009120 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009121 return -EINVAL;
9122 }
9123 start_log.verbose_level = nla_get_u32(
9124 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009125 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009126
9127 /* Parse and fetch flag */
9128 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009129 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009130 return -EINVAL;
9131 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05309132 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009133 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009134
Hanumanth Reddy Pothulae9af1162018-06-13 13:41:44 +05309135 start_log.user_triggered = 1;
9136
Poddar, Siddarth176c4362016-10-03 12:25:00 +05309137 /* size is buff size which can be set using iwpriv command*/
9138 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05309139 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05309140
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009141 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
9142
9143 if (start_log.ring_id == RING_ID_WAKELOCK) {
9144 /* Start/stop wakelock events */
9145 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
9146 cds_set_wakelock_logging(true);
9147 else
9148 cds_set_wakelock_logging(false);
9149 return 0;
9150 }
9151
Venkata Sharath Chandra Manchalaf0296dd2019-09-19 13:50:02 -07009152 if (hdd_ctx->is_pktlog_enabled &&
9153 (start_log.verbose_level == WLAN_LOG_LEVEL_ACTIVE))
9154 return 0;
9155
9156 if ((!hdd_ctx->is_pktlog_enabled) &&
9157 (start_log.verbose_level != WLAN_LOG_LEVEL_ACTIVE))
9158 return 0;
9159
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009160 mac_handle = hdd_ctx->mac_handle;
9161 status = sme_wifi_start_logger(mac_handle, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309162 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009163 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009164 status);
9165 return -EINVAL;
9166 }
Venkata Sharath Chandra Manchalaf0296dd2019-09-19 13:50:02 -07009167
9168 if (start_log.verbose_level != WLAN_LOG_LEVEL_ACTIVE)
9169 hdd_ctx->is_pktlog_enabled = true;
9170 else
9171 hdd_ctx->is_pktlog_enabled = false;
9172
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009173 return 0;
9174}
9175
9176/**
9177 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
9178 * or disable the collection of packet statistics from the firmware
9179 * @wiphy: WIPHY structure pointer
9180 * @wdev: Wireless device structure pointer
9181 * @data: Pointer to the data received
9182 * @data_len: Length of the data received
9183 *
9184 * This function is used to enable or disable the collection of packet
9185 * statistics from the firmware
9186 *
9187 * Return: 0 on success and errno on failure
9188 */
9189static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
9190 struct wireless_dev *wdev,
9191 const void *data,
9192 int data_len)
9193{
Dustin Brown363b4792019-02-05 16:11:55 -08009194 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08009195 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309196
Dustin Brown363b4792019-02-05 16:11:55 -08009197 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08009198 if (errno)
9199 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009200
Dustin Brownf0f00612019-01-31 16:02:24 -08009201 errno = __wlan_hdd_cfg80211_wifi_logger_start(wiphy, wdev,
9202 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009203
Dustin Brown363b4792019-02-05 16:11:55 -08009204 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309205
Dustin Brownf0f00612019-01-31 16:02:24 -08009206 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009207}
9208
9209static const struct
9210nla_policy
9211qca_wlan_vendor_wifi_logger_get_ring_data_policy
9212[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
9213 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
9214 = {.type = NLA_U32 },
9215};
9216
9217/**
9218 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
9219 * @wiphy: WIPHY structure pointer
9220 * @wdev: Wireless device structure pointer
9221 * @data: Pointer to the data received
9222 * @data_len: Length of the data received
9223 *
9224 * This function is used to flush or retrieve the per packet statistics from
9225 * the driver
9226 *
9227 * Return: 0 on success and errno on failure
9228 */
9229static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
9230 struct wireless_dev *wdev,
9231 const void *data,
9232 int data_len)
9233{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309234 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009235 uint32_t ring_id;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009236 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009237 struct nlattr *tb
9238 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
9239
Karthik Kantamneni0b95f9e2019-11-21 13:03:22 +05309240 hdd_enter();
Jeff Johnson1f61b612016-02-12 16:28:33 -08009241
Anurag Chouhan6d760662016-02-20 16:05:43 +05309242 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009243 hdd_err("Command not allowed in FTM mode");
9244 return -EPERM;
9245 }
9246
9247 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309248 if (status)
9249 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009250
Dustin Brown4ea21db2018-01-05 14:13:17 -08009251 if (wlan_cfg80211_nla_parse(tb,
9252 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
9253 data, data_len,
9254 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009255 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009256 return -EINVAL;
9257 }
9258
9259 /* Parse and fetch ring id */
9260 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009261 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009262 return -EINVAL;
9263 }
9264
9265 ring_id = nla_get_u32(
9266 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
9267
9268 if (ring_id == RING_ID_PER_PACKET_STATS) {
9269 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009270 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05309271 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
9272 /*
9273 * As part of DRIVER ring ID, flush both driver and fw logs.
9274 * For other Ring ID's driver doesn't have any rings to flush
9275 */
Arun Kumar Khandavalliafcb0552020-01-20 11:46:36 +05309276 hdd_debug("Bug report triggered by framework");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05309277
9278 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
9279 WLAN_LOG_INDICATOR_FRAMEWORK,
9280 WLAN_LOG_REASON_CODE_UNUSED,
Abhishek Singh29405dc2020-02-17 13:08:32 +05309281 false, false);
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05309282 if (QDF_STATUS_SUCCESS != status) {
9283 hdd_err("Failed to trigger bug report");
9284 return -EINVAL;
9285 }
9286 } else {
9287 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
9288 WLAN_LOG_INDICATOR_FRAMEWORK,
Agrawal Ashishaff28982017-05-30 15:25:47 +05309289 WLAN_LOG_REASON_CODE_UNUSED,
9290 ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009291 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009292 return 0;
9293}
9294
9295/**
9296 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
9297 * @wiphy: WIPHY structure pointer
9298 * @wdev: Wireless device structure pointer
9299 * @data: Pointer to the data received
9300 * @data_len: Length of the data received
9301 *
9302 * This function is used to flush or retrieve the per packet statistics from
9303 * the driver
9304 *
9305 * Return: 0 on success and errno on failure
9306 */
9307static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
9308 struct wireless_dev *wdev,
9309 const void *data,
9310 int data_len)
9311{
Dustin Brown363b4792019-02-05 16:11:55 -08009312 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08009313 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309314
Dustin Brown363b4792019-02-05 16:11:55 -08009315 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08009316 if (errno)
9317 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009318
Dustin Brownf0f00612019-01-31 16:02:24 -08009319 errno = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy, wdev,
9320 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009321
Dustin Brown363b4792019-02-05 16:11:55 -08009322 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08009323
9324 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009325}
9326
9327#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9328/**
9329 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
9330 * @hdd_ctx: HDD context
9331 * @request_id: [input] request id
9332 * @pattern_id: [output] pattern id
9333 *
9334 * This function loops through request id to pattern id array
9335 * if the slot is available, store the request id and return pattern id
9336 * if entry exists, return the pattern id
9337 *
9338 * Return: 0 on success and errno on failure
9339 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009340static int hdd_map_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009341 uint32_t request_id,
9342 uint8_t *pattern_id)
9343{
9344 uint32_t i;
9345
9346 mutex_lock(&hdd_ctx->op_ctx.op_lock);
9347 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
9348 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
9349 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
9350 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
9351 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
9352 return 0;
9353 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
9354 request_id) {
9355 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
9356 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
9357 return 0;
9358 }
9359 }
9360 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309361 return -ENOBUFS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009362}
9363
9364/**
9365 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
9366 * @hdd_ctx: HDD context
9367 * @request_id: [input] request id
9368 * @pattern_id: [output] pattern id
9369 *
9370 * This function loops through request id to pattern id array
9371 * reset request id to 0 (slot available again) and
9372 * return pattern id
9373 *
9374 * Return: 0 on success and errno on failure
9375 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009376static int hdd_unmap_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009377 uint32_t request_id,
9378 uint8_t *pattern_id)
9379{
9380 uint32_t i;
9381
9382 mutex_lock(&hdd_ctx->op_ctx.op_lock);
9383 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
9384 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
9385 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
9386 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
9387 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
9388 return 0;
9389 }
9390 }
9391 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
9392 return -EINVAL;
9393}
9394
9395
9396/*
9397 * define short names for the global vendor params
9398 * used by __wlan_hdd_cfg80211_offloaded_packets()
9399 */
9400#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
9401#define PARAM_REQUEST_ID \
9402 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
9403#define PARAM_CONTROL \
9404 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
9405#define PARAM_IP_PACKET \
9406 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
9407#define PARAM_SRC_MAC_ADDR \
9408 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
9409#define PARAM_DST_MAC_ADDR \
9410 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
9411#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05309412#define PARAM_PROTO_TYPE \
9413 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009414
9415/**
9416 * wlan_hdd_add_tx_ptrn() - add tx pattern
9417 * @adapter: adapter pointer
9418 * @hdd_ctx: hdd context
9419 * @tb: nl attributes
9420 *
9421 * This function reads the NL attributes and forms a AddTxPtrn message
9422 * posts it to SME.
9423 *
9424 */
9425static int
Jeff Johnsone5006672017-08-29 14:39:02 -07009426wlan_hdd_add_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009427 struct nlattr **tb)
9428{
9429 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309430 QDF_STATUS status;
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309431 uint32_t request_id, len;
9432 int32_t ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009433 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309434 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009435 uint16_t eth_type = htons(ETH_P_IP);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009436 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009437
9438 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07009439 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009440 return -ENOTSUPP;
9441 }
9442
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309443 add_req = qdf_mem_malloc(sizeof(*add_req));
Min Liu74a1a502018-10-10 19:59:07 +08009444 if (!add_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009445 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009446
9447 /* Parse and fetch request Id */
9448 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009449 hdd_err("attr request id failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309450 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009451 goto fail;
9452 }
9453
9454 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
9455 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07009456 hdd_err("request_id cannot be MAX");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309457 ret = -EINVAL;
SaidiReddy Yenuga466b3ce2017-05-02 18:50:25 +05309458 goto fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009459 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009460 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009461
9462 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009463 hdd_err("attr period failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309464 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009465 goto fail;
9466 }
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05309467
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009468 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009469 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009470 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07009471 hdd_err("Invalid interval zero, return failure");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309472 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009473 goto fail;
9474 }
9475
9476 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009477 hdd_err("attr source mac address failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309478 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009479 goto fail;
9480 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08009481 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05309482 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07009483 hdd_debug("input src mac address: "QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07009484 QDF_MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009485
Anurag Chouhanc5548422016-02-24 18:33:27 +05309486 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Jeff Johnson1e851a12017-10-28 14:36:12 -07009487 &adapter->mac_addr)) {
Srinivas Girigowda31896552015-11-18 22:59:52 -08009488 hdd_err("input src mac address and connected ap bssid are different");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309489 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009490 goto fail;
9491 }
9492
9493 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009494 hdd_err("attr dst mac address failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309495 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009496 goto fail;
9497 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05309498 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07009499 hdd_debug("input dst mac address: "QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07009500 QDF_MAC_ADDR_ARRAY(dst_addr.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009501
9502 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009503 hdd_err("attr ip packet failed");
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309504 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009505 goto fail;
9506 }
9507 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009508 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009509
9510 if (add_req->ucPtrnSize < 0 ||
9511 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
9512 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009513 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009514 add_req->ucPtrnSize);
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309515 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009516 goto fail;
9517 }
9518
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05309519 if (!tb[PARAM_PROTO_TYPE])
9520 eth_type = htons(ETH_P_IP);
9521 else
9522 eth_type = htons(nla_get_u16(tb[PARAM_PROTO_TYPE]));
9523
9524 hdd_debug("packet proto type: %u", eth_type);
9525
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009526 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309527 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05309528 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309529 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309530 QDF_MAC_ADDR_SIZE);
9531 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309532 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009533 len += 2;
9534
9535 /*
9536 * This is the IP packet, add 14 bytes Ethernet (802.3) header
9537 * ------------------------------------------------------------
9538 * | 14 bytes Ethernet (802.3) header | IP header and payload |
9539 * ------------------------------------------------------------
9540 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309541 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009542 nla_data(tb[PARAM_IP_PACKET]),
9543 add_req->ucPtrnSize);
9544 add_req->ucPtrnSize += len;
9545
9546 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
9547 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009548 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009549 goto fail;
9550 }
9551 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009552 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009553
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009554 mac_handle = hdd_ctx->mac_handle;
9555 status = sme_add_periodic_tx_ptrn(mac_handle, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309556 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009557 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309558 ret = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009559 goto fail;
9560 }
9561
Dustin Browne74003f2018-03-14 12:51:58 -07009562 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009563
9564fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309565 qdf_mem_free(add_req);
Ankita Bajaj5ea0f032019-05-02 19:29:09 +05309566 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009567}
9568
9569/**
9570 * wlan_hdd_del_tx_ptrn() - delete tx pattern
9571 * @adapter: adapter pointer
9572 * @hdd_ctx: hdd context
9573 * @tb: nl attributes
9574 *
9575 * This function reads the NL attributes and forms a DelTxPtrn message
9576 * posts it to SME.
9577 *
9578 */
9579static int
Jeff Johnsone5006672017-08-29 14:39:02 -07009580wlan_hdd_del_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009581 struct nlattr **tb)
9582{
9583 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309584 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009585 uint32_t request_id, ret;
9586 uint8_t pattern_id = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009587 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009588
9589 /* Parse and fetch request Id */
9590 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009591 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009592 return -EINVAL;
9593 }
9594 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
9595 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07009596 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009597 return -EINVAL;
9598 }
9599
9600 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
9601 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009602 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009603 return -EINVAL;
9604 }
9605
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309606 del_req = qdf_mem_malloc(sizeof(*del_req));
Min Liu74a1a502018-10-10 19:59:07 +08009607 if (!del_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009608 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009609
Jeff Johnson1e851a12017-10-28 14:36:12 -07009610 qdf_copy_macaddr(&del_req->mac_address, &adapter->mac_addr);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -07009611 hdd_debug(QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -07009612 QDF_MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009613 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009614 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009615 request_id, del_req->ucPtrnId);
9616
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009617 mac_handle = hdd_ctx->mac_handle;
9618 status = sme_del_periodic_tx_ptrn(mac_handle, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309619 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009620 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009621 goto fail;
9622 }
9623
Dustin Browne74003f2018-03-14 12:51:58 -07009624 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309625 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009626 return 0;
9627
9628fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309629 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009630 return -EINVAL;
9631}
9632
9633
9634/**
9635 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
9636 * @wiphy: Pointer to wireless phy
9637 * @wdev: Pointer to wireless device
9638 * @data: Pointer to data
9639 * @data_len: Data length
9640 *
9641 * Return: 0 on success, negative errno on failure
9642 */
9643static int
9644__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
9645 struct wireless_dev *wdev,
9646 const void *data,
9647 int data_len)
9648{
9649 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009650 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009651 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009652 struct nlattr *tb[PARAM_MAX + 1];
9653 uint8_t control;
9654 int ret;
9655 static const struct nla_policy policy[PARAM_MAX + 1] = {
9656 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
9657 [PARAM_CONTROL] = { .type = NLA_U32 },
9658 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309659 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009660 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309661 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009662 [PARAM_PERIOD] = { .type = NLA_U32 },
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05309663 [PARAM_PROTO_TYPE] = {.type = NLA_U16},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009664 };
9665
Dustin Brownfdf17c12018-03-14 12:55:34 -07009666 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009667
Anurag Chouhan6d760662016-02-20 16:05:43 +05309668 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009669 hdd_err("Command not allowed in FTM mode");
9670 return -EPERM;
9671 }
9672
9673 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309674 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009675 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009676
9677 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009678 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009679 return -ENOTSUPP;
9680 }
9681
Dustin Brown4ea21db2018-01-05 14:13:17 -08009682 if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009683 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009684 return -EINVAL;
9685 }
9686
9687 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009688 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009689 return -EINVAL;
9690 }
9691 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009692 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009693
9694 if (control == WLAN_START_OFFLOADED_PACKETS)
9695 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08009696 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009697 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08009698
9699 hdd_err("Invalid control: %d", control);
Jeff Johnson68755312017-02-10 11:46:55 -08009700 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009701}
9702
9703/*
9704 * done with short names for the global vendor params
9705 * used by __wlan_hdd_cfg80211_offloaded_packets()
9706 */
9707#undef PARAM_MAX
9708#undef PARAM_REQUEST_ID
9709#undef PARAM_CONTROL
9710#undef PARAM_IP_PACKET
9711#undef PARAM_SRC_MAC_ADDR
9712#undef PARAM_DST_MAC_ADDR
9713#undef PARAM_PERIOD
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05309714#undef PARAM_PROTO_TYPE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009715
9716/**
9717 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
9718 * @wiphy: wiphy structure pointer
9719 * @wdev: Wireless device structure pointer
9720 * @data: Pointer to the data received
9721 * @data_len: Length of @data
9722 *
9723 * Return: 0 on success; errno on failure
9724 */
9725static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
9726 struct wireless_dev *wdev,
9727 const void *data,
9728 int data_len)
9729{
Dustin Browna09acf42018-11-08 12:32:26 +05309730 int errno;
9731 struct osif_vdev_sync *vdev_sync;
9732
9733 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
9734 if (errno)
9735 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009736
Dustin Browna09acf42018-11-08 12:32:26 +05309737 errno = __wlan_hdd_cfg80211_offloaded_packets(wiphy, wdev,
9738 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009739
Dustin Browna09acf42018-11-08 12:32:26 +05309740 osif_vdev_sync_op_stop(vdev_sync);
9741
9742 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009743}
9744#endif
9745
Qiwei Cai1083f5b2018-07-02 19:10:11 +08009746#ifdef WLAN_NS_OFFLOAD
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309747static const struct nla_policy
9748ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
9749 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
9750};
9751
9752/**
9753 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
9754 * @wiphy: Pointer to wireless phy
9755 * @wdev: Pointer to wireless device
9756 * @data: Pointer to data
9757 * @data_len: Length of @data
9758 *
9759 * Return: 0 on success, negative errno on failure
9760 */
9761static int
9762__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
9763 struct wireless_dev *wdev,
9764 const void *data, int data_len)
9765{
9766 int status;
9767 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
Jeff Johnsonb8944722017-09-03 09:03:19 -07009768 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07009769 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009770 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309771
Dustin Brownfdf17c12018-03-14 12:55:34 -07009772 hdd_enter_dev(wdev->netdev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309773
Jeff Johnsonb8944722017-09-03 09:03:19 -07009774 status = wlan_hdd_validate_context(hdd_ctx);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309775 if (0 != status)
9776 return status;
Wu Gao66454f12018-09-26 19:55:41 +08009777
9778 if (!ucfg_pmo_is_ns_offloaded(hdd_ctx->psoc)) {
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309779 hdd_err("ND Offload not supported");
9780 return -EINVAL;
9781 }
9782
Wu Gao66454f12018-09-26 19:55:41 +08009783 if (!ucfg_pmo_is_active_mode_offloaded(hdd_ctx->psoc)) {
Mukul Sharma495df602017-09-25 14:52:18 +05309784 hdd_warn("Active mode offload is disabled");
9785 return -EINVAL;
9786 }
9787
Dustin Brown4ea21db2018-01-05 14:13:17 -08009788 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
9789 (struct nlattr *)data, data_len,
9790 ns_offload_set_policy)) {
9791 hdd_err("nla_parse failed");
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309792 return -EINVAL;
9793 }
9794
9795 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
9796 hdd_err("ND Offload flag attribute not present");
9797 return -EINVAL;
9798 }
9799
Jeff Johnsonb8944722017-09-03 09:03:19 -07009800 hdd_ctx->ns_offload_enable =
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309801 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
9802
Nachiket Kukadedbffab82017-04-25 19:26:02 +05309803 if (QDF_IBSS_MODE == adapter->device_mode) {
9804 hdd_debug("NS Offload is not supported in IBSS mode");
9805 return -EINVAL;
9806 }
9807
Dustin Brownd8279d22016-09-07 14:52:57 -07009808 /* update ns offload in case it is already enabled/disabled */
Jeff Johnsonb8944722017-09-03 09:03:19 -07009809 if (hdd_ctx->ns_offload_enable)
Mukul Sharma3ba26b82017-01-12 21:59:41 +05309810 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
9811 else
9812 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07009813
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309814 return 0;
9815}
9816
9817/**
9818 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
9819 * @wiphy: pointer to wireless wiphy structure.
9820 * @wdev: pointer to wireless_dev structure.
9821 * @data: Pointer to the data to be passed via vendor interface
9822 * @data_len:Length of the data to be passed
9823 *
9824 * Return: Return the Success or Failure code.
9825 */
9826static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
9827 struct wireless_dev *wdev,
9828 const void *data, int data_len)
9829{
Dustin Browna09acf42018-11-08 12:32:26 +05309830 int errno;
9831 struct osif_vdev_sync *vdev_sync;
9832
9833 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
9834 if (errno)
9835 return errno;
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309836
Dustin Browna09acf42018-11-08 12:32:26 +05309837 errno = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309838
Dustin Browna09acf42018-11-08 12:32:26 +05309839 osif_vdev_sync_op_stop(vdev_sync);
9840
9841 return errno;
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309842}
Qiwei Cai1083f5b2018-07-02 19:10:11 +08009843#endif /* WLAN_NS_OFFLOAD */
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309844
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309845/**
9846 * struct weighed_pcl: Preferred channel info
9847 * @freq: Channel frequency
9848 * @weight: Weightage of the channel
9849 * @flag: Validity of the channel in p2p negotiation
9850 */
9851struct weighed_pcl {
9852 u32 freq;
9853 u32 weight;
9854 u32 flag;
9855};
9856
Jeff Johnsondd7bd3e2017-06-05 13:25:24 -07009857static const struct nla_policy get_preferred_freq_list_policy
9858 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1] = {
9859 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE] = {
9860 .type = NLA_U32},
9861};
9862
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309863static uint32_t wlan_hdd_populate_weigh_pcl(
9864 struct policy_mgr_pcl_chan_weights *
9865 chan_weights,
9866 struct weighed_pcl *w_pcl,
9867 enum policy_mgr_con_mode intf_mode)
9868{
9869 int i, j;
9870 uint32_t chan_idx = 0;
9871 uint32_t set = 0;
9872 uint32_t pcl_len = chan_weights->pcl_len;
9873 uint32_t valid_weight;
9874
9875 /* convert channel number to frequency */
9876 for (i = 0; i < chan_weights->pcl_len; i++) {
Liangwei Dongc213d8e2019-10-28 12:57:43 +08009877 w_pcl[i].freq = chan_weights->pcl_list[i];
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309878 w_pcl[i].weight = chan_weights->weight_list[i];
9879
9880 if (intf_mode == PM_SAP_MODE || intf_mode == PM_P2P_GO_MODE)
9881 w_pcl[i].flag = set | PCL_CHANNEL_SUPPORT_GO;
9882 else
9883 w_pcl[i].flag = set | PCL_CHANNEL_SUPPORT_CLI;
9884 }
9885 chan_idx = pcl_len;
Rajeev Kumar Sirasanagandla50b2c102019-07-18 19:27:49 +05309886 if (pcl_len && chan_weights->weight_list[pcl_len - 1] >
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309887 PCL_GROUPS_WEIGHT_DIFFERENCE)
9888 /* Set non-pcl channels weight 20 point less than the last PCL entry */
9889 valid_weight = chan_weights->weight_list[pcl_len - 1] -
9890 PCL_GROUPS_WEIGHT_DIFFERENCE;
9891 else
9892 valid_weight = 1;
9893
9894 /* Include rest of the valid channels */
9895 for (i = 0; i < chan_weights->saved_num_chan; i++) {
9896 for (j = 0; j < chan_weights->pcl_len; j++) {
9897 if (chan_weights->saved_chan_list[i] ==
9898 chan_weights->pcl_list[j])
9899 break;
9900 }
9901 if (j == chan_weights->pcl_len) {
Liangwei Dongc213d8e2019-10-28 12:57:43 +08009902 w_pcl[chan_idx].freq =
9903 chan_weights->saved_chan_list[i];
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309904
9905 if (!chan_weights->weighed_valid_list[i]) {
9906 w_pcl[chan_idx].flag =
9907 set | PCL_CHANNEL_EXCLUDE_IN_GO_NEG;
9908 w_pcl[chan_idx].weight = 0;
9909 } else {
9910 if (intf_mode == PM_SAP_MODE ||
9911 intf_mode == PM_P2P_GO_MODE)
9912 w_pcl[chan_idx].flag =
9913 set | PCL_CHANNEL_SUPPORT_GO;
9914 else
9915 w_pcl[chan_idx].flag =
9916 set | PCL_CHANNEL_SUPPORT_CLI;
9917 w_pcl[chan_idx].weight = valid_weight;
9918 }
9919 chan_idx++;
9920 }
9921 }
9922 return chan_idx;
9923}
9924
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009925/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
9926 * @wiphy: Pointer to wireless phy
9927 * @wdev: Pointer to wireless device
9928 * @data: Pointer to data
9929 * @data_len: Data length
9930 *
9931 * This function return the preferred frequency list generated by the policy
9932 * manager.
9933 *
9934 * Return: success or failure code
9935 */
9936static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
9937 struct wireless_dev
9938 *wdev, const void *data,
9939 int data_len)
9940{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009941 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009942 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309943 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009944 uint32_t pcl_len = 0;
Tushnim Bhattacharyya36b1a8a2020-01-28 11:42:28 -08009945 uint32_t pcl_len_legacy = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05309946 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya36b1a8a2020-01-28 11:42:28 -08009947 uint32_t freq_list_legacy[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08009948 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009949 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
9950 struct sk_buff *reply_skb;
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309951 struct weighed_pcl *w_pcl;
9952 struct nlattr *nla_attr, *channel;
9953 struct policy_mgr_pcl_chan_weights *chan_weights;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009954
Dustin Brownfdf17c12018-03-14 12:55:34 -07009955 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08009956
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009957 ret = wlan_hdd_validate_context(hdd_ctx);
9958 if (ret)
9959 return -EINVAL;
9960
Dustin Brown4ea21db2018-01-05 14:13:17 -08009961 if (wlan_cfg80211_nla_parse(tb,
9962 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
9963 data, data_len,
9964 get_preferred_freq_list_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009965 hdd_err("Invalid ATTR");
9966 return -EINVAL;
9967 }
9968
9969 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
9970 hdd_err("attr interface type failed");
9971 return -EINVAL;
9972 }
9973
9974 intf_mode = nla_get_u32(tb
9975 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
9976
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08009977 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009978 hdd_err("Invalid interface type");
9979 return -EINVAL;
9980 }
9981
9982 hdd_debug("Userspace requested pref freq list");
9983
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309984 chan_weights =
9985 qdf_mem_malloc(sizeof(struct policy_mgr_pcl_chan_weights));
9986 if (!chan_weights)
9987 return -ENOMEM;
9988
Manikandan Mohan19f36092019-08-15 15:54:02 -07009989 status = policy_mgr_get_pcl(
Manikandan Mohan932c11e2019-08-14 14:09:08 -07009990 hdd_ctx->psoc, intf_mode, chan_weights->pcl_list,
9991 &chan_weights->pcl_len, chan_weights->weight_list,
9992 QDF_ARRAY_SIZE(chan_weights->weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309993 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009994 hdd_err("Get pcl failed");
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05309995 qdf_mem_free(chan_weights);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009996 return -EINVAL;
9997 }
Tushnim Bhattacharyya36b1a8a2020-01-28 11:42:28 -08009998 /*
9999 * save the pcl in freq_list_legacy to be sent up with
10000 * QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST.
10001 * freq_list will carry the extended pcl in
10002 * QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL.
10003 */
10004 pcl_len_legacy = chan_weights->pcl_len;
10005 for (i = 0; i < pcl_len_legacy; i++)
10006 freq_list_legacy[i] = chan_weights->pcl_list[i];
gaurank kathpalia5aafb672019-06-24 17:11:15 +053010007 chan_weights->saved_num_chan = POLICY_MGR_MAX_CHANNEL_LIST;
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010008 sme_get_valid_channels(chan_weights->saved_chan_list,
10009 &chan_weights->saved_num_chan);
10010 policy_mgr_get_valid_chan_weights(hdd_ctx->psoc, chan_weights);
10011 w_pcl = qdf_mem_malloc(sizeof(struct weighed_pcl) * QDF_MAX_NUM_CHAN);
10012 if (!w_pcl) {
10013 qdf_mem_free(chan_weights);
10014 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010015 }
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010016 pcl_len = wlan_hdd_populate_weigh_pcl(chan_weights, w_pcl, intf_mode);
10017 qdf_mem_free(chan_weights);
10018
10019 for (i = 0; i < pcl_len; i++)
10020 freq_list[i] = w_pcl[i].freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010021
10022 /* send the freq_list back to supplicant */
Liangwei Dongc213d8e2019-10-28 12:57:43 +080010023 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(
10024 wiphy,
10025 (sizeof(u32) + NLA_HDRLEN) +
Tushnim Bhattacharyya36b1a8a2020-01-28 11:42:28 -080010026 (sizeof(u32) * pcl_len_legacy + NLA_HDRLEN) +
Liangwei Dongc213d8e2019-10-28 12:57:43 +080010027 NLA_HDRLEN +
10028 (NLA_HDRLEN * 4 + sizeof(u32) * 3) * pcl_len +
10029 NLMSG_HDRLEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010030
10031 if (!reply_skb) {
10032 hdd_err("Allocate reply_skb failed");
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010033 qdf_mem_free(w_pcl);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010034 return -EINVAL;
10035 }
10036
10037 if (nla_put_u32(reply_skb,
10038 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
10039 intf_mode) ||
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010040 nla_put(reply_skb,
10041 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
Tushnim Bhattacharyya36b1a8a2020-01-28 11:42:28 -080010042 sizeof(uint32_t) * pcl_len_legacy,
10043 freq_list_legacy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010044 hdd_err("nla put fail");
10045 kfree_skb(reply_skb);
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010046 qdf_mem_free(w_pcl);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010047 return -EINVAL;
10048 }
10049
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +053010050 i = QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL;
10051 nla_attr = nla_nest_start(reply_skb, i);
10052
10053 if (!nla_attr) {
10054 hdd_err("nla nest start fail");
10055 kfree_skb(reply_skb);
10056 qdf_mem_free(w_pcl);
10057 return -EINVAL;
10058 }
10059
10060 for (i = 0; i < pcl_len; i++) {
10061 channel = nla_nest_start(reply_skb, i);
10062 if (!channel) {
10063 hdd_err("updating pcl list failed");
10064 kfree_skb(reply_skb);
10065 qdf_mem_free(w_pcl);
10066 return -EINVAL;
10067 }
10068 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FREQ,
10069 w_pcl[i].freq) ||
10070 nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
10071 w_pcl[i].weight) ||
10072 nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FLAG,
10073 w_pcl[i].flag)) {
10074 hdd_err("nla put fail");
10075 kfree_skb(reply_skb);
10076 qdf_mem_free(w_pcl);
10077 return -EINVAL;
10078 }
10079 nla_nest_end(reply_skb, channel);
10080 }
10081 nla_nest_end(reply_skb, nla_attr);
10082 qdf_mem_free(w_pcl);
10083
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010084 return cfg80211_vendor_cmd_reply(reply_skb);
10085}
10086
10087/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
10088 * @wiphy: Pointer to wireless phy
10089 * @wdev: Pointer to wireless device
10090 * @data: Pointer to data
10091 * @data_len: Data length
10092 *
10093 * This function return the preferred frequency list generated by the policy
10094 * manager.
10095 *
10096 * Return: success or failure code
10097 */
10098static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
10099 struct wireless_dev
10100 *wdev, const void *data,
10101 int data_len)
10102{
Dustin Brown363b4792019-02-05 16:11:55 -080010103 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080010104 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010105
Dustin Brown363b4792019-02-05 16:11:55 -080010106 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080010107 if (errno)
10108 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010109
Dustin Brownf0f00612019-01-31 16:02:24 -080010110 errno = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
10111 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010112
Dustin Brown363b4792019-02-05 16:11:55 -080010113 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010114
Dustin Brownf0f00612019-01-31 16:02:24 -080010115 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010116}
10117
Jeff Johnsone5f33ba2017-06-05 14:48:48 -070010118static const struct nla_policy set_probable_oper_channel_policy
10119 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1] = {
10120 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE] = {
10121 .type = NLA_U32},
10122 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ] = {
10123 .type = NLA_U32},
10124};
10125
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010126/**
10127 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
10128 * @wiphy: Pointer to wireless phy
10129 * @wdev: Pointer to wireless device
10130 * @data: Pointer to data
10131 * @data_len: Data length
10132 *
10133 * Return: 0 on success, negative errno on failure
10134 */
10135static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
10136 struct wireless_dev *wdev,
10137 const void *data,
10138 int data_len)
10139{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +053010140 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010141 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010142 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010143 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010144 enum policy_mgr_con_mode intf_mode;
Jeff Johnsone5f33ba2017-06-05 14:48:48 -070010145 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1];
Tushnim Bhattacharyyac682bfb2019-12-11 17:11:10 -080010146 uint32_t ch_freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010147
Dustin Brownfdf17c12018-03-14 12:55:34 -070010148 hdd_enter_dev(ndev);
Jeff Johnson1f61b612016-02-12 16:28:33 -080010149
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010150 ret = wlan_hdd_validate_context(hdd_ctx);
10151 if (ret)
10152 return ret;
10153
Dustin Brown4ea21db2018-01-05 14:13:17 -080010154 if (wlan_cfg80211_nla_parse(tb,
10155 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
10156 data, data_len,
10157 set_probable_oper_channel_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010158 hdd_err("Invalid ATTR");
10159 return -EINVAL;
10160 }
10161
10162 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
10163 hdd_err("attr interface type failed");
10164 return -EINVAL;
10165 }
10166
10167 intf_mode = nla_get_u32(tb
10168 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
10169
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010170 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010171 hdd_err("Invalid interface type");
10172 return -EINVAL;
10173 }
10174
10175 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
10176 hdd_err("attr probable freq failed");
10177 return -EINVAL;
10178 }
10179
Manikandan Mohan282c4b62019-08-14 17:42:22 -070010180 ch_freq = nla_get_u32(tb[
10181 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010182 /* check pcl table */
Dustin Brown76cd2932018-09-11 16:03:05 -070010183 if (!policy_mgr_allow_concurrency(hdd_ctx->psoc, intf_mode,
Manikandan Mohan282c4b62019-08-14 17:42:22 -070010184 ch_freq, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010185 hdd_err("Set channel hint failed due to concurrency check");
10186 return -EINVAL;
10187 }
10188
Krunal Soni09e55032016-06-07 10:06:55 -070010189 if (0 != wlan_hdd_check_remain_on_channel(adapter))
10190 hdd_warn("Remain On Channel Pending");
10191
Tushnim Bhattacharyyac682bfb2019-12-11 17:11:10 -080010192 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, ch_freq,
Krunal Sonied3bc8e2018-01-26 12:13:34 -080010193 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
10194 hdd_err("Failed to change hw mode");
Krunal Soni3091bcc2016-06-23 12:28:21 -070010195 return -EINVAL;
10196 }
10197
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010198 return 0;
10199}
10200
10201/**
10202 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
10203 * @wiphy: Pointer to wireless phy
10204 * @wdev: Pointer to wireless device
10205 * @data: Pointer to data
10206 * @data_len: Data length
10207 *
10208 * Return: 0 on success, negative errno on failure
10209 */
10210static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
10211 struct wireless_dev *wdev,
10212 const void *data,
10213 int data_len)
10214{
Dustin Browna09acf42018-11-08 12:32:26 +053010215 int errno;
10216 struct osif_vdev_sync *vdev_sync;
10217
10218 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
10219 if (errno)
10220 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010221
Dustin Browna09acf42018-11-08 12:32:26 +053010222 errno = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
10223 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010224
Dustin Browna09acf42018-11-08 12:32:26 +053010225 osif_vdev_sync_op_stop(vdev_sync);
10226
10227 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010228}
10229
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010230static const struct
10231nla_policy
10232qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +053010233 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {
10234 .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010235};
10236
10237/**
10238 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
10239 * @wiphy: WIPHY structure pointer
10240 * @wdev: Wireless device structure pointer
10241 * @data: Pointer to the data received
10242 * @data_len: Length of the data received
10243 *
10244 * This function is used to get link properties like nss, rate flags and
10245 * operating frequency for the active connection with the given peer.
10246 *
10247 * Return: 0 on success and errno on failure
10248 */
10249static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
10250 struct wireless_dev *wdev,
10251 const void *data,
10252 int data_len)
10253{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010254 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010255 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010256 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson40dae4e2017-08-29 14:00:25 -070010257 struct hdd_station_ctx *hdd_sta_ctx;
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053010258 struct hdd_station_info *sta_info;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010259 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +053010260 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010261 struct sk_buff *reply_skb;
10262 uint32_t rate_flags = 0;
10263 uint8_t nss;
10264 uint8_t final_rate_flags = 0;
10265 uint32_t freq;
10266
Dustin Brownfdf17c12018-03-14 12:55:34 -070010267 hdd_enter_dev(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010268
Anurag Chouhan6d760662016-02-20 16:05:43 +053010269 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010270 hdd_err("Command not allowed in FTM mode");
10271 return -EPERM;
10272 }
10273
10274 if (0 != wlan_hdd_validate_context(hdd_ctx))
10275 return -EINVAL;
10276
Dustin Brown4ea21db2018-01-05 14:13:17 -080010277 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
10278 data_len, qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010279 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010280 return -EINVAL;
10281 }
10282
10283 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -070010284 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010285 adapter->device_mode);
10286 return -EINVAL;
10287 }
10288
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +053010289 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) < QDF_MAC_ADDR_SIZE) {
10290 hdd_err("Attribute peerMac is invalid for mode=%d",
10291 adapter->device_mode);
10292 return -EINVAL;
10293 }
10294
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010295 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +053010296 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070010297 hdd_debug("peerMac="QDF_MAC_ADDR_STR" for device_mode:%d",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070010298 QDF_MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010299
Krunal Sonib4326f22016-03-10 13:05:51 -080010300 if (adapter->device_mode == QDF_STA_MODE ||
10301 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010302 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnsone7951512019-02-27 10:02:51 -080010303 if ((hdd_sta_ctx->conn_info.conn_state !=
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010304 eConnectionState_Associated) ||
Jeff Johnsone04b6992019-02-27 14:06:55 -080010305 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssid.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053010306 peer_mac, QDF_MAC_ADDR_SIZE)) {
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070010307 hdd_err("Not Associated to mac "QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070010308 QDF_MAC_ADDR_ARRAY(peer_mac));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010309 return -EINVAL;
10310 }
10311
10312 nss = hdd_sta_ctx->conn_info.nss;
Jingxiang Geae80dc62019-08-13 17:32:22 +080010313 freq = hdd_sta_ctx->conn_info.chan_freq;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010314 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -080010315 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
10316 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010317
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053010318 if (QDF_IS_ADDR_BROADCAST(peer_mac)) {
10319 hdd_err("Ignore bcast/self sta");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010320 return -EINVAL;
10321 }
10322
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053010323 sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
10324 peer_mac);
10325
10326 if (!sta_info) {
10327 hdd_err("No active peer with mac = " QDF_MAC_ADDR_STR,
10328 QDF_MAC_ADDR_ARRAY(peer_mac));
10329 return -EINVAL;
10330 }
10331
10332 nss = sta_info->nss;
Will Huang4b097f52019-08-29 10:51:56 -070010333 freq = (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operating_chan_freq;
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053010334 rate_flags = sta_info->rate_flags;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010335 } else {
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070010336 hdd_err("Not Associated! with mac "QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070010337 QDF_MAC_ADDR_ARRAY(peer_mac));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010338 return -EINVAL;
10339 }
10340
Naveen Rawatea1564b2018-05-17 15:56:11 -070010341 if (!(rate_flags & TX_RATE_LEGACY)) {
10342 if (rate_flags & TX_RATE_VHT80) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010343 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -080010344#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010345 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -080010346#endif
Naveen Rawatea1564b2018-05-17 15:56:11 -070010347 } else if (rate_flags & TX_RATE_VHT40) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010348 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -080010349#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010350 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -080010351#endif
Naveen Rawatea1564b2018-05-17 15:56:11 -070010352 } else if (rate_flags & TX_RATE_VHT20) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010353 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
10354 } else if (rate_flags &
Naveen Rawatea1564b2018-05-17 15:56:11 -070010355 (TX_RATE_HT20 | TX_RATE_HT40)) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010356 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -080010357#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Naveen Rawatea1564b2018-05-17 15:56:11 -070010358 if (rate_flags & TX_RATE_HT40)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010359 final_rate_flags |=
10360 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -080010361#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010362 }
10363
Naveen Rawatea1564b2018-05-17 15:56:11 -070010364 if (rate_flags & TX_RATE_SGI) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010365 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
10366 final_rate_flags |= RATE_INFO_FLAGS_MCS;
10367 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
10368 }
10369 }
10370
10371 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
10372 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
10373
Jeff Johnsond36fa332019-03-18 13:42:25 -070010374 if (!reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -070010375 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010376 return -EINVAL;
10377 }
10378
10379 if (nla_put_u8(reply_skb,
10380 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
10381 nss) ||
10382 nla_put_u8(reply_skb,
10383 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
10384 final_rate_flags) ||
10385 nla_put_u32(reply_skb,
10386 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
10387 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010388 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010389 kfree_skb(reply_skb);
10390 return -EINVAL;
10391 }
10392
10393 return cfg80211_vendor_cmd_reply(reply_skb);
10394}
10395
10396/**
10397 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
10398 * properties.
10399 * @wiphy: WIPHY structure pointer
10400 * @wdev: Wireless device structure pointer
10401 * @data: Pointer to the data received
10402 * @data_len: Length of the data received
10403 *
10404 * This function is used to get link properties like nss, rate flags and
10405 * operating frequency for the active connection with the given peer.
10406 *
10407 * Return: 0 on success and errno on failure
10408 */
10409static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
10410 struct wireless_dev *wdev,
10411 const void *data,
10412 int data_len)
10413{
Dustin Browna09acf42018-11-08 12:32:26 +053010414 int errno;
10415 struct osif_vdev_sync *vdev_sync;
10416
10417 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
10418 if (errno)
10419 return errno;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010420
Dustin Browna09acf42018-11-08 12:32:26 +053010421 errno = __wlan_hdd_cfg80211_get_link_properties(wiphy, wdev,
10422 data, data_len);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010423
Dustin Browna09acf42018-11-08 12:32:26 +053010424 osif_vdev_sync_op_stop(vdev_sync);
10425
10426 return errno;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010427}
10428
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010429static const struct nla_policy
10430wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053010431 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8},
10432 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY] = {.type = NLA_U32},
Ganesh Kondabattini099e6e82017-06-28 12:24:20 +053010433 [QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST] = {
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053010434 .type = NLA_NESTED},
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010435};
10436
Agrawal Ashish65634612016-08-18 13:24:32 +053010437static const struct nla_policy
10438wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
Rajeev Kumar Sirasanagandlae83ac292019-09-19 16:35:26 +053010439 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8},
10440 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8},
10441 [QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT] = {.type = NLA_U32},
Agrawal Ashish65634612016-08-18 13:24:32 +053010442};
10443
10444/**
10445 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
10446 * @wiphy: Pointer to wireless phy
10447 * @wdev: Pointer to wireless device
10448 * @data: Pointer to data
10449 * @data_len: Length of @data
10450 *
10451 * This function parses the incoming NL vendor command data attributes and
10452 * updates the SAP context about channel_hint and DFS mode.
10453 * If channel_hint is set, SAP will choose that channel
10454 * as operating channel.
10455 *
10456 * If DFS mode is enabled, driver will include DFS channels
10457 * in ACS else driver will skip DFS channels.
10458 *
10459 * Return: 0 on success, negative errno on failure
10460 */
10461static int
10462__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
10463 struct wireless_dev *wdev,
10464 const void *data, int data_len)
10465{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010466 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish65634612016-08-18 13:24:32 +053010467 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
10468 int ret;
10469 struct acs_dfs_policy *acs_policy;
10470 int mode = DFS_MODE_NONE;
Rajeev Kumar Sirasanagandlae83ac292019-09-19 16:35:26 +053010471 uint32_t freq_hint = 0;
Agrawal Ashish65634612016-08-18 13:24:32 +053010472
Dustin Brownfdf17c12018-03-14 12:55:34 -070010473 hdd_enter_dev(wdev->netdev);
Agrawal Ashish65634612016-08-18 13:24:32 +053010474
10475 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10476 hdd_err("Command not allowed in FTM mode");
10477 return -EINVAL;
10478 }
10479
10480 ret = wlan_hdd_validate_context(hdd_ctx);
10481 if (0 != ret)
10482 return ret;
10483
Dustin Brown4ea21db2018-01-05 14:13:17 -080010484 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
10485 data, data_len,
10486 wlan_hdd_set_acs_dfs_config_policy)) {
Agrawal Ashish65634612016-08-18 13:24:32 +053010487 hdd_err("invalid attr");
10488 return -EINVAL;
10489 }
10490
10491 acs_policy = &hdd_ctx->acs_policy;
10492 /*
10493 * SCM sends this attribute to restrict SAP from choosing
10494 * DFS channels from ACS.
10495 */
10496 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
10497 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
10498
10499 if (!IS_DFS_MODE_VALID(mode)) {
10500 hdd_err("attr acs dfs mode is not valid");
10501 return -EINVAL;
10502 }
10503 acs_policy->acs_dfs_mode = mode;
10504
10505 /*
10506 * SCM sends this attribute to provide an active channel,
10507 * to skip redundant ACS between drivers, and save driver start up time
10508 */
Rajeev Kumar Sirasanagandlae83ac292019-09-19 16:35:26 +053010509 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT]) {
10510 freq_hint = nla_get_u32(
10511 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT]);
10512 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]) {
10513 uint32_t channel_hint = nla_get_u8(
Agrawal Ashish65634612016-08-18 13:24:32 +053010514 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
10515
Rajeev Kumar Sirasanagandlae83ac292019-09-19 16:35:26 +053010516 freq_hint = wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev,
10517 channel_hint);
10518 }
10519
10520 if (freq_hint && !WLAN_REG_IS_24GHZ_CH_FREQ(freq_hint) &&
10521 !WLAN_REG_IS_5GHZ_CH_FREQ(freq_hint) &&
10522 !WLAN_REG_IS_6GHZ_CHAN_FREQ(freq_hint)) {
10523 hdd_err("acs channel frequency is not valid");
Agrawal Ashish65634612016-08-18 13:24:32 +053010524 return -EINVAL;
10525 }
Rajeev Kumar Sirasanagandlae83ac292019-09-19 16:35:26 +053010526
10527 acs_policy->acs_chan_freq = freq_hint;
Agrawal Ashish65634612016-08-18 13:24:32 +053010528
10529 return 0;
10530}
10531
10532/**
10533 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
10534 * @wiphy: wiphy structure pointer
10535 * @wdev: Wireless device structure pointer
10536 * @data: Pointer to the data received
10537 * @data_len: Length of @data
10538 *
10539 * This function parses the incoming NL vendor command data attributes and
10540 * updates the SAP context about channel_hint and DFS mode.
10541 *
10542 * Return: 0 on success; errno on failure
10543 */
10544static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
10545 struct wireless_dev *wdev,
10546 const void *data, int data_len)
10547{
Dustin Brown363b4792019-02-05 16:11:55 -080010548 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080010549 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010550
Dustin Brown363b4792019-02-05 16:11:55 -080010551 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080010552 if (errno)
10553 return errno;
Agrawal Ashish65634612016-08-18 13:24:32 +053010554
Dustin Brownf0f00612019-01-31 16:02:24 -080010555 errno = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
Agrawal Ashish65634612016-08-18 13:24:32 +053010556
Dustin Brown363b4792019-02-05 16:11:55 -080010557 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010558
Dustin Brownf0f00612019-01-31 16:02:24 -080010559 return errno;
Agrawal Ashish65634612016-08-18 13:24:32 +053010560}
10561
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010562/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010563 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
10564 * @mode : cfg80211 dfs mode
10565 *
10566 * Return: return csr sta roam dfs mode else return NONE
10567 */
10568static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
10569 enum dfs_mode mode)
10570{
10571 switch (mode) {
10572 case DFS_MODE_ENABLE:
10573 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010574 case DFS_MODE_DISABLE:
10575 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010576 case DFS_MODE_DEPRIORITIZE:
10577 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010578 default:
10579 hdd_err("STA Roam policy dfs mode is NONE");
10580 return CSR_STA_ROAM_POLICY_NONE;
10581 }
10582}
10583
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010584/*
10585 * hdd_get_sap_operating_band: Get current operating channel
10586 * for sap.
10587 * @hdd_ctx: hdd context
10588 *
10589 * Return : Corresponding band for SAP operating channel
10590 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010591uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010592{
Jeff Johnsone5006672017-08-29 14:39:02 -070010593 struct hdd_adapter *adapter;
Will Huang4b097f52019-08-29 10:51:56 -070010594 uint32_t operating_chan_freq;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010595 uint8_t sap_operating_band = 0;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070010596
Dustin Brown920397d2017-12-13 16:27:50 -080010597 hdd_for_each_adapter(hdd_ctx, adapter) {
10598 if (adapter->device_mode != QDF_SAP_MODE)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010599 continue;
Dustin Brown920397d2017-12-13 16:27:50 -080010600
Will Huang4b097f52019-08-29 10:51:56 -070010601 operating_chan_freq = adapter->session.ap.operating_chan_freq;
10602 if (WLAN_REG_IS_24GHZ_CH_FREQ(operating_chan_freq))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010603 sap_operating_band = BAND_2G;
Will Huang4b097f52019-08-29 10:51:56 -070010604 else if (WLAN_REG_IS_5GHZ_CH_FREQ(operating_chan_freq))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010605 sap_operating_band = BAND_5G;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010606 else
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010607 sap_operating_band = BAND_ALL;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010608 }
Dustin Brown920397d2017-12-13 16:27:50 -080010609
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010610 return sap_operating_band;
10611}
10612
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010613static const struct nla_policy
10614wlan_hdd_set_sta_roam_config_policy[
10615QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
10616 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
10617 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
10618};
10619
10620/**
10621 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
10622 * for station connection or roaming.
10623 * @wiphy: Pointer to wireless phy
10624 * @wdev: Pointer to wireless device
10625 * @data: Pointer to data
10626 * @data_len: Length of @data
10627 *
10628 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
10629 * channels needs to be skipped in scanning or not.
10630 * If dfs_mode is disabled, driver will not scan DFS channels.
10631 * If skip_unsafe_channels is set, driver will skip unsafe channels
10632 * in Scanning.
10633 *
10634 * Return: 0 on success, negative errno on failure
10635 */
10636static int
10637__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
10638 struct wireless_dev *wdev,
10639 const void *data, int data_len)
10640{
10641 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010642 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010643 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010644 struct nlattr *tb[
10645 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
10646 int ret;
10647 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
10648 enum dfs_mode mode = DFS_MODE_NONE;
10649 bool skip_unsafe_channels = false;
10650 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010651 uint8_t sap_operating_band;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010652 mac_handle_t mac_handle;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010653
Dustin Brownfdf17c12018-03-14 12:55:34 -070010654 hdd_enter_dev(dev);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010655
10656 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10657 hdd_err("Command not allowed in FTM mode");
10658 return -EINVAL;
10659 }
10660
10661 ret = wlan_hdd_validate_context(hdd_ctx);
10662 if (0 != ret)
10663 return ret;
Dustin Brown4ea21db2018-01-05 14:13:17 -080010664 if (wlan_cfg80211_nla_parse(tb,
10665 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
10666 data, data_len,
10667 wlan_hdd_set_sta_roam_config_policy)) {
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010668 hdd_err("invalid attr");
10669 return -EINVAL;
10670 }
10671 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
10672 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
10673 if (!IS_DFS_MODE_VALID(mode)) {
10674 hdd_err("attr sta roam dfs mode policy is not valid");
10675 return -EINVAL;
10676 }
10677
10678 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
10679
10680 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
10681 skip_unsafe_channels = nla_get_u8(
10682 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010683 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010684 mac_handle = hdd_ctx->mac_handle;
10685 status = sme_update_sta_roam_policy(mac_handle, sta_roam_dfs_mode,
10686 skip_unsafe_channels,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080010687 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010688 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010689
10690 if (!QDF_IS_STATUS_SUCCESS(status)) {
10691 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
10692 return -EINVAL;
10693 }
10694 return 0;
10695}
10696
10697/**
10698 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
10699 * connection and roaming for station.
10700 * @wiphy: wiphy structure pointer
10701 * @wdev: Wireless device structure pointer
10702 * @data: Pointer to the data received
10703 * @data_len: Length of @data
10704 *
10705 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
10706 * channels needs to be skipped in scanning or not.
10707 * If dfs_mode is disabled, driver will not scan DFS channels.
10708 * If skip_unsafe_channels is set, driver will skip unsafe channels
10709 * in Scanning.
10710 * Return: 0 on success; errno on failure
10711 */
10712static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
10713 struct wireless_dev *wdev,
10714 const void *data, int data_len)
10715{
Dustin Browna09acf42018-11-08 12:32:26 +053010716 int errno;
10717 struct osif_vdev_sync *vdev_sync;
10718
10719 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
10720 if (errno)
10721 return errno;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010722
Dustin Browna09acf42018-11-08 12:32:26 +053010723 errno = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev,
10724 data, data_len);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010725
Dustin Browna09acf42018-11-08 12:32:26 +053010726 osif_vdev_sync_op_stop(vdev_sync);
10727
10728 return errno;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010729}
10730
Agrawal Ashish467dde42016-09-08 18:44:22 +053010731#ifdef FEATURE_WLAN_CH_AVOID
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010732
10733static int hdd_validate_avoid_freq_chanlist(
10734 struct hdd_context *hdd_ctx,
10735 struct ch_avoid_ind_type *channel_list)
10736{
10737 unsigned int range_idx, ch_idx;
10738 unsigned int unsafe_channel_index, unsafe_channel_count = 0;
10739 bool ch_found = false;
hqubcd0a8f2019-11-25 21:56:35 +080010740 uint32_t ch_idx_freq;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010741
10742 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
10743 (uint16_t)NUM_CHANNELS);
10744
10745 for (range_idx = 0; range_idx < channel_list->ch_avoid_range_cnt;
10746 range_idx++) {
10747 if ((channel_list->avoid_freq_range[range_idx].start_freq <
10748 CDS_24_GHZ_CHANNEL_1) ||
10749 (channel_list->avoid_freq_range[range_idx].end_freq >
10750 CDS_5_GHZ_CHANNEL_165) ||
10751 (channel_list->avoid_freq_range[range_idx].start_freq >
10752 channel_list->avoid_freq_range[range_idx].end_freq))
10753 continue;
10754
10755 for (ch_idx = channel_list->
10756 avoid_freq_range[range_idx].start_freq;
10757 ch_idx <= channel_list->
10758 avoid_freq_range[range_idx].end_freq;
10759 ch_idx++) {
Ashish Kumar Dhanotiyaaa9fdbb2018-12-14 15:29:14 +053010760 if (INVALID_CHANNEL == wlan_reg_get_chan_enum(ch_idx))
Ashish Kumar Dhanotiyabf00f822018-11-30 20:29:09 +053010761 continue;
hqubcd0a8f2019-11-25 21:56:35 +080010762 ch_idx_freq = wlan_reg_chan_to_freq(hdd_ctx->pdev,
10763 ch_idx);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010764 for (unsafe_channel_index = 0;
10765 unsafe_channel_index < unsafe_channel_count;
10766 unsafe_channel_index++) {
hqubcd0a8f2019-11-25 21:56:35 +080010767 if (ch_idx_freq ==
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010768 hdd_ctx->unsafe_channel_list[
10769 unsafe_channel_index]) {
hqubcd0a8f2019-11-25 21:56:35 +080010770 hdd_info("Duplicate channel freq %d",
10771 ch_idx_freq);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010772 ch_found = true;
10773 break;
10774 }
10775 }
10776 if (!ch_found) {
10777 hdd_ctx->unsafe_channel_list[
hqubcd0a8f2019-11-25 21:56:35 +080010778 unsafe_channel_count++] = (uint16_t)ch_idx_freq;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010779 }
10780 ch_found = false;
10781 }
10782 }
10783 return unsafe_channel_count;
10784}
10785
Agrawal Ashish467dde42016-09-08 18:44:22 +053010786/**
10787 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
10788 * is on unsafe channel.
10789 * @wiphy: wiphy structure pointer
10790 * @wdev: Wireless device structure pointer
10791 * @data: Pointer to the data received
10792 * @data_len: Length of @data
10793 *
10794 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
10795 * on any of unsafe channels.
10796 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
10797 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
10798 *
10799 * Return: 0 on success; errno on failure
10800 */
10801static int
10802__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
10803 struct wireless_dev *wdev,
10804 const void *data, int data_len)
10805{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010806 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010807 int ret;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010808 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
Liangwei Dong6e1a2092017-08-30 16:29:06 +080010809 uint16_t *local_unsafe_list;
hqubf1b6182018-08-14 17:22:41 +080010810 uint16_t unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010811 uint16_t unsafe_channel_index, local_unsafe_list_count;
10812 struct ch_avoid_ind_type *channel_list;
Jeff Johnson2e60a142018-05-20 12:08:12 -070010813 enum QDF_GLOBAL_MODE curr_mode;
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +053010814 uint8_t num_args = 0;
hqubf1b6182018-08-14 17:22:41 +080010815 bool user_set_avoid_channel = true;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010816
Dustin Brownfdf17c12018-03-14 12:55:34 -070010817 hdd_enter_dev(wdev->netdev);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010818
10819 if (!qdf_ctx) {
Jeff Johnson6867ec32017-09-29 20:30:20 -070010820 hdd_err("qdf_ctx is NULL");
Agrawal Ashish467dde42016-09-08 18:44:22 +053010821 return -EINVAL;
10822 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010823 curr_mode = hdd_get_conparam();
10824 if (QDF_GLOBAL_FTM_MODE == curr_mode ||
10825 QDF_GLOBAL_MONITOR_MODE == curr_mode) {
10826 hdd_err("Command not allowed in FTM/MONITOR mode");
Agrawal Ashish467dde42016-09-08 18:44:22 +053010827 return -EINVAL;
10828 }
10829
10830 ret = wlan_hdd_validate_context(hdd_ctx);
10831 if (0 != ret)
10832 return ret;
hqubf1b6182018-08-14 17:22:41 +080010833 if (!data && data_len == 0) {
10834 hdd_debug("Userspace doesn't set avoid frequency channel list");
10835 user_set_avoid_channel = false;
10836 goto process_unsafe_channel;
10837 }
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +053010838 if (!data || data_len < (sizeof(channel_list->ch_avoid_range_cnt) +
10839 sizeof(struct ch_avoid_freq_type))) {
10840 hdd_err("Avoid frequency channel list empty");
10841 return -EINVAL;
10842 }
10843 num_args = (data_len - sizeof(channel_list->ch_avoid_range_cnt)) /
10844 sizeof(channel_list->avoid_freq_range[0].start_freq);
10845
10846 if (num_args < 2 || num_args > CH_AVOID_MAX_RANGE * 2 ||
10847 num_args % 2 != 0) {
10848 hdd_err("Invalid avoid frequency channel list");
10849 return -EINVAL;
10850 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010851
10852 channel_list = (struct ch_avoid_ind_type *)data;
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +053010853 if (channel_list->ch_avoid_range_cnt == 0 ||
10854 channel_list->ch_avoid_range_cnt > CH_AVOID_MAX_RANGE ||
10855 2 * channel_list->ch_avoid_range_cnt != num_args) {
10856 hdd_err("Invalid frequency range count %d",
10857 channel_list->ch_avoid_range_cnt);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010858 return -EINVAL;
10859 }
10860
hqubf1b6182018-08-14 17:22:41 +080010861process_unsafe_channel:
Liangwei Dong6e1a2092017-08-30 16:29:06 +080010862 ret = hdd_clone_local_unsafe_chan(hdd_ctx,
10863 &local_unsafe_list,
10864 &local_unsafe_list_count);
10865 if (0 != ret) {
10866 hdd_err("failed to clone the cur unsafe chan list");
10867 return ret;
10868 }
10869
Agrawal Ashish467dde42016-09-08 18:44:22 +053010870 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
10871 &(hdd_ctx->unsafe_channel_count),
10872 sizeof(hdd_ctx->unsafe_channel_list));
hqubf1b6182018-08-14 17:22:41 +080010873 if (user_set_avoid_channel) {
10874 hdd_ctx->unsafe_channel_count =
10875 hdd_validate_avoid_freq_chanlist(
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010876 hdd_ctx,
10877 channel_list);
hqubf1b6182018-08-14 17:22:41 +080010878 unsafe_channel_count = hdd_ctx->unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010879
hqubf1b6182018-08-14 17:22:41 +080010880 pld_set_wlan_unsafe_channel(qdf_ctx->dev,
10881 hdd_ctx->unsafe_channel_list,
10882 hdd_ctx->unsafe_channel_count);
10883 } else {
10884 unsafe_channel_count = QDF_MIN(
10885 (uint16_t)hdd_ctx->unsafe_channel_count,
10886 (uint16_t)NUM_CHANNELS);
10887 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010888
Agrawal Ashish467dde42016-09-08 18:44:22 +053010889 for (unsafe_channel_index = 0;
hqubf1b6182018-08-14 17:22:41 +080010890 unsafe_channel_index < unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010891 unsafe_channel_index++) {
hqubcd0a8f2019-11-25 21:56:35 +080010892 hdd_debug("Channel frequency %d is not safe",
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010893 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010894 }
Liangwei Dong6e1a2092017-08-30 16:29:06 +080010895 if (hdd_local_unsafe_channel_updated(hdd_ctx, local_unsafe_list,
10896 local_unsafe_list_count))
10897 hdd_unsafe_channel_restart_sap(hdd_ctx);
10898 qdf_mem_free(local_unsafe_list);
10899
Agrawal Ashish467dde42016-09-08 18:44:22 +053010900 return 0;
10901}
10902
10903/**
10904 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
10905 * is on unsafe channel.
10906 * @wiphy: wiphy structure pointer
10907 * @wdev: Wireless device structure pointer
10908 * @data: Pointer to the data received
10909 * @data_len: Length of @data
10910 *
10911 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
10912 * on any of unsafe channels.
10913 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
10914 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
10915 *
10916 * Return: 0 on success; errno on failure
10917 */
10918static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
10919 struct wireless_dev *wdev,
10920 const void *data, int data_len)
10921{
Dustin Brown363b4792019-02-05 16:11:55 -080010922 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080010923 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010924
Dustin Brown363b4792019-02-05 16:11:55 -080010925 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080010926 if (errno)
10927 return errno;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010928
Dustin Brownf0f00612019-01-31 16:02:24 -080010929 errno = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010930
Dustin Brown363b4792019-02-05 16:11:55 -080010931 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010932
Dustin Brownf0f00612019-01-31 16:02:24 -080010933 return errno;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010934}
10935
10936#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010937/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010938 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
10939 * SAP is on unsafe channel.
10940 * @wiphy: wiphy structure pointer
10941 * @wdev: Wireless device structure pointer
10942 * @data: Pointer to the data received
10943 * @data_len: Length of @data
10944 *
10945 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
10946 * driver.
10947 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
10948 * will initiate restart of sap.
10949 *
10950 * Return: 0 on success; errno on failure
10951 */
10952static int
10953__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
10954 struct wireless_dev *wdev,
10955 const void *data, int data_len)
10956{
10957 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010958 struct hdd_adapter *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010959 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010960 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
Jeff Johnson87251032017-08-29 13:31:11 -070010961 struct hdd_ap_ctx *ap_ctx;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010962 int ret;
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053010963 uint32_t chan_freq = 0;
Min Liu71abe092019-11-25 14:09:25 +080010964 bool chan_freq_present = false;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053010965 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010966
Dustin Brown491d54b2018-03-14 12:39:11 -070010967 hdd_enter();
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010968
10969 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010970 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010971 return -EINVAL;
10972 }
10973
10974 ret = wlan_hdd_validate_context(hdd_ctx);
10975 if (0 != ret)
10976 return -EINVAL;
10977
Dustin Brown4ea21db2018-01-05 14:13:17 -080010978 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
10979 data, data_len,
10980 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010981 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010982 return -EINVAL;
10983 }
10984
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053010985 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY]) {
10986 chan_freq = nla_get_u32(
10987 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY]);
Min Liu71abe092019-11-25 14:09:25 +080010988 chan_freq_present = true;
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053010989 } else if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
10990 uint32_t config_channel =
10991 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
10992
10993 chan_freq = wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev,
10994 config_channel);
Min Liu71abe092019-11-25 14:09:25 +080010995 chan_freq_present = true;
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053010996 }
10997
Min Liu71abe092019-11-25 14:09:25 +080010998 if (chan_freq_present) {
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010999 if (!test_bit(SOFTAP_BSS_STARTED,
11000 &hostapd_adapter->event_flags)) {
11001 hdd_err("SAP is not started yet. Restart sap will be invalid");
11002 return -EINVAL;
11003 }
11004
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053011005 if (!WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq) &&
11006 !WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq) &&
11007 !WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq)) {
11008 hdd_err("Channel frequency %u is invalid to restart SAP",
11009 chan_freq);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011010 return -ENOTSUPP;
11011 }
11012
11013 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053011014 ap_ctx->sap_config.chan_freq = chan_freq;
Jeff Johnson91df29d2017-10-27 19:29:50 -070011015 ap_ctx->sap_config.ch_params.ch_width =
11016 ap_ctx->sap_config.ch_width_orig;
hqu73bccf22017-10-28 15:34:17 +080011017 ap_ctx->bss_stop_reason = BSS_STOP_DUE_TO_VENDOR_CONFIG_CHAN;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011018
Rajeev Kumar Sirasanagandlac567f5f2019-09-19 17:50:05 +053011019 wlan_reg_set_channel_params_for_freq(
11020 hdd_ctx->pdev, chan_freq,
11021 ap_ctx->sap_config.sec_ch_freq,
11022 &ap_ctx->sap_config.ch_params);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011023
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011024 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011025 }
11026
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053011027 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
11028 uint32_t freq_len, i;
11029 uint32_t *freq;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053011030
11031 hdd_debug("setting mandatory freq/chan list");
11032
11033 freq_len = nla_len(
11034 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
11035 sizeof(uint32_t);
11036
11037 if (freq_len > QDF_MAX_NUM_CHAN) {
11038 hdd_err("insufficient space to hold channels");
11039 return -ENOMEM;
11040 }
11041
11042 freq = nla_data(
11043 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
11044
11045 hdd_debug("freq_len=%d", freq_len);
11046
11047 for (i = 0; i < freq_len; i++) {
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053011048 hdd_debug("freq[%d]=%d", i, freq[i]);
11049 }
11050
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011051 status = policy_mgr_set_sap_mandatory_channels(
Manikandan Mohan19f36092019-08-15 15:54:02 -070011052 hdd_ctx->psoc, freq, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053011053 if (QDF_IS_STATUS_ERROR(status))
11054 return -EINVAL;
11055 }
11056
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011057 return 0;
11058}
11059
11060/**
11061 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
11062 * @wiphy: wiphy structure pointer
11063 * @wdev: Wireless device structure pointer
11064 * @data: Pointer to the data received
11065 * @data_len: Length of @data
11066 *
11067 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
11068 * driver.
11069 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
11070 * will initiate restart of sap.
11071 *
11072 * Return: 0 on success; errno on failure
11073 */
11074static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
11075 struct wireless_dev *wdev,
11076 const void *data, int data_len)
11077{
Dustin Browna09acf42018-11-08 12:32:26 +053011078 int errno;
11079 struct osif_vdev_sync *vdev_sync;
11080
11081 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
11082 if (errno)
11083 return errno;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011084
Dustin Browna09acf42018-11-08 12:32:26 +053011085 errno = __wlan_hdd_cfg80211_sap_configuration_set(wiphy, wdev,
11086 data, data_len);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011087
Dustin Browna09acf42018-11-08 12:32:26 +053011088 osif_vdev_sync_op_stop(vdev_sync);
11089
11090 return errno;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011091}
11092
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011093/**
11094 * wlan_hdd_process_wake_lock_stats() - wrapper function to absract cp_stats
11095 * or legacy get_wake_lock_stats API.
11096 * @hdd_ctx: pointer to hdd_ctx
11097 *
11098 * Return: 0 on success; error number otherwise.
11099 */
11100static int wlan_hdd_process_wake_lock_stats(struct hdd_context *hdd_ctx)
11101{
Ashish Kumar Dhanotiya136bc8e2019-06-04 16:20:31 +053011102 return wlan_cfg80211_mc_cp_stats_get_wakelock_stats(hdd_ctx->psoc,
11103 hdd_ctx->wiphy);
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011104}
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011105
11106/**
11107 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
11108 * @wiphy: wiphy pointer
11109 * @wdev: pointer to struct wireless_dev
11110 * @data: pointer to incoming NL vendor data
11111 * @data_len: length of @data
11112 *
11113 * This function parses the incoming NL vendor command data attributes and
11114 * invokes the SME Api and blocks on a completion variable.
11115 * WMA copies required data and invokes callback
11116 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
11117 *
11118 * Return: 0 on success; error number otherwise.
11119 */
11120static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
11121 struct wireless_dev *wdev,
11122 const void *data,
11123 int data_len)
11124{
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011125 int ret;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011126 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011127
Dustin Brown491d54b2018-03-14 12:39:11 -070011128 hdd_enter();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011129
11130 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -070011131 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011132 return -EINVAL;
11133 }
11134
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011135 ret = wlan_hdd_validate_context(hdd_ctx);
11136 if (0 != ret)
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011137 return -EINVAL;
11138
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011139 ret = wlan_hdd_process_wake_lock_stats(hdd_ctx);
Dustin Browne74003f2018-03-14 12:51:58 -070011140 hdd_exit();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011141 return ret;
11142}
11143
11144/**
11145 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
11146 * @wiphy: wiphy pointer
11147 * @wdev: pointer to struct wireless_dev
11148 * @data: pointer to incoming NL vendor data
11149 * @data_len: length of @data
11150 *
11151 * This function parses the incoming NL vendor command data attributes and
11152 * invokes the SME Api and blocks on a completion variable.
11153 * WMA copies required data and invokes callback
11154 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
11155 *
11156 * Return: 0 on success; error number otherwise.
11157 */
11158static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
11159 struct wireless_dev *wdev,
11160 const void *data, int data_len)
11161{
Dustin Brown363b4792019-02-05 16:11:55 -080011162 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080011163 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053011164
Dustin Brown363b4792019-02-05 16:11:55 -080011165 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080011166 if (errno)
11167 return errno;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011168
Dustin Brownf0f00612019-01-31 16:02:24 -080011169 errno = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev,
11170 data, data_len);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011171
Dustin Brown363b4792019-02-05 16:11:55 -080011172 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080011173
11174 return errno;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011175}
11176
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011177/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011178 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
11179 * @wiphy: wiphy structure pointer
11180 * @wdev: Wireless device structure pointer
11181 * @data: Pointer to the data received
11182 * @data_len: Length of @data
11183 *
11184 * This function reads wmi max bus size and fill in the skb with
11185 * NL attributes and send up the NL event.
11186 * Return: 0 on success; errno on failure
11187 */
11188static int
11189__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
11190 struct wireless_dev *wdev,
11191 const void *data, int data_len)
11192{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011193 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011194 int ret_val;
11195 struct sk_buff *skb;
11196 uint32_t nl_buf_len;
11197
Dustin Brown491d54b2018-03-14 12:39:11 -070011198 hdd_enter();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011199
11200 ret_val = wlan_hdd_validate_context(hdd_ctx);
11201 if (ret_val)
11202 return ret_val;
11203
11204 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
11205 hdd_err("Command not allowed in FTM mode");
11206 return -EINVAL;
11207 }
11208
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011209 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011210
11211 nl_buf_len = NLMSG_HDRLEN;
11212 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
11213
11214 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
11215 if (!skb) {
11216 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
11217 return -ENOMEM;
11218 }
11219
11220 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
11221 hdd_ctx->wmi_max_len)) {
11222 hdd_err("nla put failure");
11223 goto nla_put_failure;
11224 }
11225
11226 cfg80211_vendor_cmd_reply(skb);
11227
Dustin Browne74003f2018-03-14 12:51:58 -070011228 hdd_exit();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011229
11230 return 0;
11231
11232nla_put_failure:
11233 kfree_skb(skb);
11234 return -EINVAL;
11235}
11236
11237/**
11238 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
11239 * @wiphy: wiphy structure pointer
11240 * @wdev: Wireless device structure pointer
11241 * @data: Pointer to the data received
11242 * @data_len: Length of @data
11243 *
11244 * Return: 0 on success; errno on failure
11245 */
11246static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
11247 struct wireless_dev *wdev,
11248 const void *data, int data_len)
11249{
Dustin Brown363b4792019-02-05 16:11:55 -080011250 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080011251 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053011252
Dustin Brown363b4792019-02-05 16:11:55 -080011253 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080011254 if (errno)
11255 return errno;
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011256
Dustin Brownf0f00612019-01-31 16:02:24 -080011257 errno = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011258
Dustin Brown363b4792019-02-05 16:11:55 -080011259 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080011260
11261 return errno;
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011262}
11263
11264/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011265 *__wlan_hdd_cfg80211_setband() - set band
11266 * @wiphy: Pointer to wireless phy
11267 * @wdev: Pointer to wireless device
11268 * @data: Pointer to data
11269 * @data_len: Length of @data
11270 *
11271 * Return: 0 on success, negative errno on failure
11272 */
11273static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
11274 struct wireless_dev *wdev,
11275 const void *data, int data_len)
11276{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011277 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -070011278 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011279 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
11280 int ret;
11281 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
11282 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
11283
Dustin Brown491d54b2018-03-14 12:39:11 -070011284 hdd_enter();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011285
11286 ret = wlan_hdd_validate_context(hdd_ctx);
11287 if (ret)
11288 return ret;
11289
Dustin Brown4ea21db2018-01-05 14:13:17 -080011290 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
11291 data, data_len, policy)) {
Dustin Brownbacc48f2018-03-14 14:48:44 -070011292 hdd_err("Invalid ATTR");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011293 return -EINVAL;
11294 }
11295
11296 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -070011297 hdd_err("attr SETBAND_VALUE failed");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011298 return -EINVAL;
11299 }
11300
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -070011301 ret = hdd_reg_set_band(dev,
11302 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011303
Dustin Browne74003f2018-03-14 12:51:58 -070011304 hdd_exit();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011305 return ret;
11306}
11307
11308/**
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011309 *wlan_hdd_validate_acs_channel() - validate channel frequency provided by ACS
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011310 * @adapter: hdd adapter
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011311 * @chan_freq: channel frequency in MHz
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011312 *
11313 * return: QDF status based on success or failure
11314 */
Jeff Johnsone5006672017-08-29 14:39:02 -070011315static QDF_STATUS wlan_hdd_validate_acs_channel(struct hdd_adapter *adapter,
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011316 uint32_t chan_freq, int chan_bw)
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011317{
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070011318 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011319 uint8_t channel;
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070011320
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011321 if (QDF_STATUS_SUCCESS !=
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011322 wlan_hdd_validate_operation_channel(adapter, chan_freq))
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011323 return QDF_STATUS_E_FAILURE;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011324
11325 channel = (uint8_t)wlan_reg_freq_to_chan(hdd_ctx->pdev, chan_freq);
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011326 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
11327 channel,
11328 PHY_SINGLE_CHANNEL_CENTERED))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -070011329 hdd_info("channel %d is in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011330 return -EINVAL;
11331 }
11332
11333 if ((wlansap_is_channel_leaking_in_nol(
11334 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
11335 channel, chan_bw))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -070011336 hdd_info("channel %d is leaking in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011337 return -EINVAL;
11338 }
11339
11340 return 0;
11341
11342}
11343
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011344static void hdd_update_acs_sap_config(struct hdd_context *hdd_ctx,
Jeff Johnson8f8ceb92019-03-24 08:16:55 -070011345 struct sap_config *sap_config,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011346 struct hdd_vendor_chan_info *channel_list)
11347{
Abhinav Kumarb074f2f2018-09-15 15:32:11 +053011348 uint8_t ch_width;
11349 QDF_STATUS status;
Wu Gaoed616a12019-01-16 15:19:21 +080011350 uint32_t channel_bonding_mode;
11351
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011352 sap_config->chan_freq = channel_list->pri_chan_freq;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011353
11354 sap_config->ch_params.center_freq_seg0 =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011355 wlan_reg_freq_to_chan(hdd_ctx->pdev,
11356 channel_list->vht_seg0_center_chan_freq);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011357 sap_config->ch_params.center_freq_seg1 =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011358 wlan_reg_freq_to_chan(hdd_ctx->pdev,
11359 channel_list->vht_seg1_center_chan_freq);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011360
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011361 sap_config->ch_params.sec_ch_offset =
11362 wlan_reg_freq_to_chan(hdd_ctx->pdev,
11363 channel_list->ht_sec_chan_freq);
11364
Kapil Gupta8878ad92017-02-13 11:56:04 +053011365 sap_config->ch_params.ch_width = channel_list->chan_width;
Kiran Kumar Lokere229212a2019-08-20 19:03:30 -070011366 if (WLAN_REG_IS_5GHZ_CH_FREQ(sap_config->chan_freq)) {
Abhinav Kumarb074f2f2018-09-15 15:32:11 +053011367 status =
11368 ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
11369 &ch_width);
11370 if (!QDF_IS_STATUS_SUCCESS(status))
11371 hdd_err("Failed to set channel_width");
11372 sap_config->ch_width_orig = ch_width;
11373 } else {
Wu Gaoed616a12019-01-16 15:19:21 +080011374 ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
11375 &channel_bonding_mode);
11376 sap_config->ch_width_orig = channel_bonding_mode ?
11377 eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ;
Abhinav Kumarb074f2f2018-09-15 15:32:11 +053011378 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011379 sap_config->acs_cfg.pri_ch_freq = channel_list->pri_chan_freq;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011380 sap_config->acs_cfg.ch_width = channel_list->chan_width;
Liangwei Dong0e18c472019-11-08 17:59:09 +080011381 sap_config->acs_cfg.vht_seg0_center_ch_freq =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011382 channel_list->vht_seg0_center_chan_freq;
Liangwei Dong0e18c472019-11-08 17:59:09 +080011383 sap_config->acs_cfg.vht_seg1_center_ch_freq =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011384 channel_list->vht_seg1_center_chan_freq;
gaurank kathpalia92b81ce2019-10-30 17:21:48 +053011385 sap_config->acs_cfg.ht_sec_ch_freq =
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011386 channel_list->ht_sec_chan_freq;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011387}
11388
Jeff Johnsone5006672017-08-29 14:39:02 -070011389static int hdd_update_acs_channel(struct hdd_adapter *adapter, uint8_t reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011390 uint8_t channel_cnt,
11391 struct hdd_vendor_chan_info *channel_list)
11392{
Jeff Johnson8f8ceb92019-03-24 08:16:55 -070011393 struct sap_config *sap_config;
Jeff Johnson87251032017-08-29 13:31:11 -070011394 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011395 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011396 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011397 mac_handle_t mac_handle;
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011398 uint32_t ch;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011399
Min Liuab6ed4f2018-01-09 13:13:57 +080011400 if (!channel_list) {
11401 hdd_err("channel_list is NULL");
11402 return -EINVAL;
11403 }
11404
Kapil Gupta8878ad92017-02-13 11:56:04 +053011405 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnsonb9424862017-10-30 08:49:35 -070011406 sap_config = &adapter->session.ap.sap_config;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011407
11408 if (QDF_TIMER_STATE_RUNNING ==
Jeff Johnsonb9424862017-10-30 08:49:35 -070011409 qdf_mc_timer_get_current_state(&adapter->session.
Kapil Gupta8878ad92017-02-13 11:56:04 +053011410 ap.vendor_acs_timer)) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070011411 qdf_mc_timer_stop(&adapter->session.ap.vendor_acs_timer);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011412 }
11413
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011414 if (channel_list->pri_chan_freq == 0) {
Kapil Gupta8878ad92017-02-13 11:56:04 +053011415 /* Check mode, set default channel */
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011416 channel_list->pri_chan_freq = 2437;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011417 /*
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011418 * sap_select_default_oper_chan(mac_handle,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011419 * sap_config->acs_cfg.hw_mode);
11420 */
11421 }
11422
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011423 mac_handle = hdd_ctx->mac_handle;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011424 switch (reason) {
11425 /* SAP init case */
11426 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
11427 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
11428 /* Update Hostapd */
11429 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
11430 break;
11431
11432 /* DFS detected on current channel */
11433 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011434 ch = wlan_reg_freq_to_chan(hdd_ctx->pdev,
11435 channel_list->pri_chan_freq);
11436
Kapil Gupta8878ad92017-02-13 11:56:04 +053011437 wlan_sap_update_next_channel(
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011438 WLAN_HDD_GET_SAP_CTX_PTR(adapter), (uint8_t)ch,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011439 channel_list->chan_width);
11440 status = sme_update_new_channel_event(
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011441 mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080011442 adapter->vdev_id);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011443 break;
11444
11445 /* LTE coex event on current channel */
11446 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011447 ch = wlan_reg_freq_to_chan(hdd_ctx->pdev,
11448 channel_list->pri_chan_freq);
11449 sap_config->acs_cfg.pri_ch_freq = channel_list->pri_chan_freq;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011450 sap_config->acs_cfg.ch_width = channel_list->chan_width;
Jeff Johnson91df29d2017-10-27 19:29:50 -070011451 hdd_ap_ctx->sap_config.ch_width_orig =
Kapil Gupta8878ad92017-02-13 11:56:04 +053011452 channel_list->chan_width;
Bala Venkatesh8b9bbde2019-07-03 16:25:16 +053011453 wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->vdev_id,
11454 CSA_REASON_LTE_COEX);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011455 hdd_switch_sap_channel(adapter, (uint8_t)ch, true);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011456 break;
11457
11458 default:
11459 hdd_info("invalid reason for timer invoke");
11460 }
Dustin Browne74003f2018-03-14 12:51:58 -070011461 hdd_exit();
Min Liuab6ed4f2018-01-09 13:13:57 +080011462 return qdf_status_to_os_return(status);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011463}
11464
11465/**
11466 * Define short name for vendor channel set config
11467 */
11468#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
Kapil Gupta8878ad92017-02-13 11:56:04 +053011469#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
11470#define SET_CHAN_PRIMARY_CHANNEL \
11471 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
11472#define SET_CHAN_SECONDARY_CHANNEL \
11473 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
11474#define SET_CHAN_SEG0_CENTER_CHANNEL \
11475 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
11476#define SET_CHAN_SEG1_CENTER_CHANNEL \
11477 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
11478#define SET_CHAN_CHANNEL_WIDTH \
11479 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011480
11481#define SET_CHAN_FREQ_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_LIST
11482#define SET_CHAN_FREQUENCY_PRIMARY \
11483 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_PRIMARY
11484#define SET_CHAN_FREQUENCY_SECONDARY \
11485 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY
11486#define SET_CHAN_SEG0_CENTER_FREQUENCY \
11487 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0
11488#define SET_CHAN_SEG1_CENTER_FREQUENCY \
11489 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1
11490
11491#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
Kapil Gupta63e75282017-05-18 20:55:10 +053011492#define SET_EXT_ACS_BAND QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND
Kapil Gupta8878ad92017-02-13 11:56:04 +053011493
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011494static const struct nla_policy acs_chan_config_policy[SET_CHAN_MAX + 1] = {
11495 [SET_CHAN_REASON] = {.type = NLA_U8},
11496 [SET_CHAN_CHAN_LIST] = {.type = NLA_NESTED},
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011497 [SET_CHAN_FREQ_LIST] = {.type = NLA_NESTED},
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011498};
11499
11500static const struct nla_policy acs_chan_list_policy[SET_CHAN_MAX + 1] = {
11501 [SET_CHAN_PRIMARY_CHANNEL] = {.type = NLA_U8},
11502 [SET_CHAN_SECONDARY_CHANNEL] = {.type = NLA_U8},
11503 [SET_CHAN_SEG0_CENTER_CHANNEL] = {.type = NLA_U8},
11504 [SET_CHAN_SEG1_CENTER_CHANNEL] = {.type = NLA_U8},
11505 [SET_CHAN_CHANNEL_WIDTH] = {.type = NLA_U8},
11506 [SET_EXT_ACS_BAND] = {.type = NLA_U8},
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011507
11508 [SET_CHAN_FREQUENCY_PRIMARY] = {.type = NLA_U32},
11509 [SET_CHAN_FREQUENCY_SECONDARY] = {.type = NLA_U32},
11510 [SET_CHAN_SEG0_CENTER_FREQUENCY] = {.type = NLA_U32},
11511 [SET_CHAN_SEG1_CENTER_FREQUENCY] = {.type = NLA_U32},
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011512};
11513
Kapil Gupta8878ad92017-02-13 11:56:04 +053011514/**
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011515 * hdd_extract_external_acs_frequencies() - API to parse and extract vendor acs
11516 * channel frequency (in MHz) configuration.
11517 * @hdd_ctx: pointer to hdd context
11518 * @list_ptr: pointer to hdd_vendor_chan_info
Kapil Gupta8878ad92017-02-13 11:56:04 +053011519 * @channel_cnt: channel count
11520 * @data: data
11521 * @data_len: data len
11522 *
11523 * Return: 0 on success, negative errno on failure
11524 */
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011525static int
11526hdd_extract_external_acs_frequencies(struct hdd_context *hdd_ctx,
11527 struct hdd_vendor_chan_info **list_ptr,
11528 uint8_t *channel_cnt,
11529 const void *data, int data_len)
Kapil Gupta8878ad92017-02-13 11:56:04 +053011530{
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011531 int rem;
11532 uint32_t i = 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011533 struct nlattr *tb[SET_CHAN_MAX + 1];
11534 struct nlattr *tb2[SET_CHAN_MAX + 1];
11535 struct nlattr *curr_attr;
11536 struct hdd_vendor_chan_info *channel_list;
11537
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011538 if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
11539 acs_chan_config_policy)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +053011540 hdd_err("Invalid ATTR");
11541 return -EINVAL;
11542 }
11543
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011544 nla_for_each_nested(curr_attr, tb[SET_CHAN_FREQ_LIST], rem)
11545 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011546
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011547 if (!i) {
11548 hdd_err_rl("Error: channel count is zero");
11549 return -EINVAL;
11550 }
11551
11552 if (i > NUM_CHANNELS) {
11553 hdd_err_rl("Error: Exceeded max channels: %u", NUM_CHANNELS);
11554 return -ENOMEM;
11555 }
11556
11557 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) * i);
11558 if (!channel_list)
11559 return -ENOMEM;
11560
11561 *channel_cnt = (uint8_t)i;
11562 i = 0;
11563 nla_for_each_nested(curr_attr, tb[SET_CHAN_FREQ_LIST], rem) {
11564 if (wlan_cfg80211_nla_parse_nested(tb2, SET_CHAN_MAX,
11565 curr_attr,
11566 acs_chan_list_policy)) {
11567 hdd_err_rl("nla_parse failed");
11568 qdf_mem_free(channel_list);
11569 *channel_cnt = 0;
11570 return -EINVAL;
11571 }
11572
11573 if (tb2[SET_EXT_ACS_BAND])
11574 channel_list[i].band =
11575 nla_get_u8(tb2[SET_EXT_ACS_BAND]);
11576
11577 if (tb2[SET_CHAN_FREQUENCY_PRIMARY])
11578 channel_list[i].pri_chan_freq =
11579 nla_get_u32(tb2[SET_CHAN_FREQUENCY_PRIMARY]);
11580
11581 if (tb2[SET_CHAN_FREQUENCY_SECONDARY])
11582 channel_list[i].ht_sec_chan_freq =
11583 nla_get_u32(tb2[SET_CHAN_FREQUENCY_SECONDARY]);
11584
11585 if (tb2[SET_CHAN_SEG0_CENTER_FREQUENCY])
11586 channel_list[i].vht_seg0_center_chan_freq =
11587 nla_get_u32(tb2[SET_CHAN_SEG0_CENTER_FREQUENCY]);
11588
11589 if (tb2[SET_CHAN_SEG1_CENTER_FREQUENCY])
11590 channel_list[i].vht_seg1_center_chan_freq =
11591 nla_get_u32(tb2[SET_CHAN_SEG1_CENTER_FREQUENCY]);
11592
11593 if (tb2[SET_CHAN_CHANNEL_WIDTH])
11594 channel_list[i].chan_width =
11595 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
11596
11597 hdd_debug("index %d, pri_chan_freq %u, ht_sec_chan_freq %u seg0_freq %u seg1_freq %u width %u",
11598 i, channel_list[i].pri_chan_freq,
11599 channel_list[i].ht_sec_chan_freq,
11600 channel_list[i].vht_seg0_center_chan_freq,
11601 channel_list[i].vht_seg1_center_chan_freq,
11602 channel_list[i].chan_width);
11603 i++;
11604 }
11605 *list_ptr = channel_list;
11606
11607 return 0;
11608}
11609
11610/**
11611 * hdd_extract_external_acs_channels() - API to parse and extract vendor acs
11612 * channel configuration.
11613 * @hdd_ctx: pointer to hdd context
11614 * @list_ptr: pointer to hdd_vendor_chan_info
11615 * @channel_cnt: channel count
11616 * @data: data
11617 * @data_len: data len
11618 *
11619 * Return: 0 on success, negative errno on failure
11620 */
11621static int
11622hdd_extract_external_acs_channels(struct hdd_context *hdd_ctx,
11623 struct hdd_vendor_chan_info **list_ptr,
11624 uint8_t *channel_cnt,
11625 const void *data, int data_len)
11626{
11627 int rem;
11628 uint32_t i = 0;
11629 struct nlattr *tb[SET_CHAN_MAX + 1];
11630 struct nlattr *tb2[SET_CHAN_MAX + 1];
11631 struct nlattr *curr_attr;
11632 struct hdd_vendor_chan_info *channel_list;
11633
11634 if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
11635 acs_chan_config_policy)) {
11636 hdd_err("Invalid ATTR");
sheenam monga5440bdd2019-03-11 17:32:37 +053011637 return -EINVAL;
11638 }
11639
Kapil Gupta63e75282017-05-18 20:55:10 +053011640 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem)
11641 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011642
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011643 if (!i) {
11644 hdd_err_rl("Error: channel count is zero");
11645 return -EINVAL;
11646 }
11647
Liangwei Dong2eb654f2019-09-11 15:54:09 +080011648 if (i > NUM_CHANNELS) {
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011649 hdd_err_rl("Error: Exceeded max channels: %u", NUM_CHANNELS);
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011650 return -ENOMEM;
11651 }
11652
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011653 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) * i);
Min Liu74a1a502018-10-10 19:59:07 +080011654 if (!channel_list)
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011655 return -ENOMEM;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011656
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011657 *channel_cnt = (uint8_t)i;
Kapil Gupta63e75282017-05-18 20:55:10 +053011658 i = 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011659 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
Rajeev Kumar Sirasanagandla5054f662019-03-14 21:25:58 +053011660 if (wlan_cfg80211_nla_parse_nested(tb2, SET_CHAN_MAX,
11661 curr_attr,
11662 acs_chan_list_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -080011663 hdd_err("nla_parse failed");
Rajeev Kumar Sirasanagandla2feb4212019-03-14 22:15:02 +053011664 qdf_mem_free(channel_list);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011665 *channel_cnt = 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011666 return -EINVAL;
11667 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011668
Kapil Gupta63e75282017-05-18 20:55:10 +053011669 if (tb2[SET_EXT_ACS_BAND]) {
11670 channel_list[i].band =
11671 nla_get_u8(tb2[SET_EXT_ACS_BAND]);
11672 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011673
Kapil Gupta8878ad92017-02-13 11:56:04 +053011674 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011675 uint32_t ch =
11676 nla_get_u8(tb2[SET_CHAN_PRIMARY_CHANNEL]);
11677
11678 channel_list[i].pri_chan_freq =
11679 wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011680 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011681
Kapil Gupta8878ad92017-02-13 11:56:04 +053011682 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011683 uint32_t ch =
Kapil Gupta8878ad92017-02-13 11:56:04 +053011684 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011685
11686 channel_list[i].ht_sec_chan_freq =
11687 wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011688 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011689
Kapil Gupta8878ad92017-02-13 11:56:04 +053011690 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011691 uint32_t ch =
Kapil Gupta8878ad92017-02-13 11:56:04 +053011692 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011693
11694 channel_list[i].vht_seg0_center_chan_freq =
11695 wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011696 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011697
Kapil Gupta8878ad92017-02-13 11:56:04 +053011698 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011699 uint32_t ch =
Kapil Gupta8878ad92017-02-13 11:56:04 +053011700 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011701
11702 channel_list[i].vht_seg1_center_chan_freq =
11703 wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011704 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011705
Kapil Gupta8878ad92017-02-13 11:56:04 +053011706 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
11707 channel_list[i].chan_width =
11708 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
11709 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011710 hdd_debug("index %d, pri_chan_freq %u, ht_sec_chan_freq %u seg0_freq %u seg1_freq %u width %u",
11711 i, channel_list[i].pri_chan_freq,
11712 channel_list[i].ht_sec_chan_freq,
11713 channel_list[i].vht_seg0_center_chan_freq,
11714 channel_list[i].vht_seg1_center_chan_freq,
11715 channel_list[i].chan_width);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011716 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011717 }
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011718 *list_ptr = channel_list;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011719
11720 return 0;
11721}
11722
11723/**
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011724 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
11725 * @hdd_ctx: pointer to hdd context
11726 * @channel_list: pointer to hdd_vendor_chan_info
11727 * @reason: channel change reason
11728 * @channel_cnt: channel count
11729 * @data: data
11730 * @data_len: data len
11731 *
11732 * Return: 0 on success, negative errno on failure
11733 */
11734static int
11735hdd_parse_vendor_acs_chan_config(struct hdd_context *hdd_ctx,
11736 struct hdd_vendor_chan_info **chan_list_ptr,
11737 uint8_t *reason, uint8_t *channel_cnt,
11738 const void *data, int data_len)
11739{
11740 struct nlattr *tb[SET_CHAN_MAX + 1];
11741 int ret;
11742
11743 if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
11744 acs_chan_config_policy)) {
11745 hdd_err("Invalid ATTR");
11746 return -EINVAL;
11747 }
11748
11749 if (tb[SET_CHAN_REASON])
11750 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
11751
11752 if (!tb[SET_CHAN_FREQ_LIST] && !tb[SET_CHAN_CHAN_LIST]) {
11753 hdd_err("Both channel list and frequency list are empty");
11754 return -EINVAL;
11755 }
11756
11757 if (tb[SET_CHAN_FREQ_LIST]) {
11758 ret = hdd_extract_external_acs_frequencies(hdd_ctx,
11759 chan_list_ptr,
11760 channel_cnt,
11761 data, data_len);
11762 if (ret) {
11763 hdd_err("Failed to extract frequencies");
11764 return ret;
11765 }
11766
11767 return 0;
11768 }
11769
11770 ret = hdd_extract_external_acs_channels(hdd_ctx, chan_list_ptr,
11771 channel_cnt, data, data_len);
11772 if (ret)
11773 hdd_err("Failed to extract channels");
11774
11775 return ret;
11776}
11777
11778/**
Kapil Gupta8878ad92017-02-13 11:56:04 +053011779 * Undef short names for vendor set channel configuration
11780 */
11781#undef SET_CHAN_REASON
Kapil Gupta8878ad92017-02-13 11:56:04 +053011782#undef SET_CHAN_CHAN_LIST
11783#undef SET_CHAN_PRIMARY_CHANNEL
11784#undef SET_CHAN_SECONDARY_CHANNEL
11785#undef SET_CHAN_SEG0_CENTER_CHANNEL
11786#undef SET_CHAN_SEG1_CENTER_CHANNEL
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011787
11788#undef SET_CHAN_FREQ_LIST
11789#undef SET_CHAN_FREQUENCY_PRIMARY
11790#undef SET_CHAN_FREQUENCY_SECONDARY
11791#undef SET_CHAN_SEG0_CENTER_FREQUENCY
11792#undef SET_CHAN_SEG1_CENTER_FREQUENCY
11793
Kapil Gupta8878ad92017-02-13 11:56:04 +053011794#undef SET_CHAN_CHANNEL_WIDTH
11795#undef SET_CHAN_MAX
11796
11797/**
11798 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
11799 * @wiphy: Pointer to wireless phy
11800 * @wdev: Pointer to wireless device
11801 * @data: Pointer to data
11802 * @data_len: Length of @data
11803 *
11804 * Return: 0 on success, negative errno on failure
11805 */
11806static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
11807 struct wireless_dev *wdev,
11808 const void *data, int data_len)
11809{
11810 int ret_val;
11811 QDF_STATUS qdf_status;
11812 uint8_t channel_cnt = 0, reason = -1;
11813 struct hdd_vendor_chan_info *channel_list = NULL;
Jeff Johnsone5006672017-08-29 14:39:02 -070011814 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011815 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011816 struct hdd_vendor_chan_info *channel_list_ptr;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011817
Dustin Brown491d54b2018-03-14 12:39:11 -070011818 hdd_enter();
Kapil Gupta8878ad92017-02-13 11:56:04 +053011819
11820 ret_val = wlan_hdd_validate_context(hdd_ctx);
11821 if (ret_val)
11822 return ret_val;
11823
11824 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
11825 hdd_err("Command not allowed in FTM mode");
11826 return -EINVAL;
11827 }
11828
11829 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
11830 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
11831 else {
11832 hdd_err("already timeout happened for acs");
11833 return -EINVAL;
11834 }
11835
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011836 ret_val = hdd_parse_vendor_acs_chan_config(hdd_ctx, &channel_list,
11837 &reason, &channel_cnt, data,
11838 data_len);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011839 channel_list_ptr = channel_list;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011840 if (ret_val)
11841 return ret_val;
11842
11843 /* Validate channel to be set */
11844 while (channel_cnt && channel_list) {
11845 qdf_status = wlan_hdd_validate_acs_channel(adapter,
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011846 channel_list->pri_chan_freq,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011847 channel_list->chan_width);
11848 if (qdf_status == QDF_STATUS_SUCCESS)
11849 break;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011850 else if (channel_cnt == 1) {
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011851 hdd_err("invalid channel frequ %u received from app",
11852 channel_list->pri_chan_freq);
11853 channel_list->pri_chan_freq = 0;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011854 break;
11855 }
11856
Kapil Gupta8878ad92017-02-13 11:56:04 +053011857 channel_cnt--;
11858 channel_list++;
11859 }
Min Liuab6ed4f2018-01-09 13:13:57 +080011860
Kapil Gupta8878ad92017-02-13 11:56:04 +053011861 if ((channel_cnt <= 0) || !channel_list) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070011862 hdd_err("no available channel/chanlist %d/%pK", channel_cnt,
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011863 channel_list);
11864 qdf_mem_free(channel_list_ptr);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011865 return -EINVAL;
11866 }
11867
Rajeev Kumar Sirasanagandla95f202a2019-09-05 22:30:44 +053011868 hdd_debug("received primary channel freq as %d",
11869 channel_list->pri_chan_freq);
Min Liuab6ed4f2018-01-09 13:13:57 +080011870
11871 ret_val = hdd_update_acs_channel(adapter, reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011872 channel_cnt, channel_list);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011873 qdf_mem_free(channel_list_ptr);
Min Liuab6ed4f2018-01-09 13:13:57 +080011874 return ret_val;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011875}
11876
11877/**
11878 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
11879 * @wiphy: Pointer to wireless phy
11880 * @wdev: Pointer to wireless device
11881 * @data: Pointer to data
11882 * @data_len: Length of @data
11883 *
11884 * Return: 0 on success, negative errno on failure
11885 */
11886static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
11887 struct wireless_dev *wdev,
11888 const void *data, int data_len)
11889{
Dustin Browna09acf42018-11-08 12:32:26 +053011890 int errno;
11891 struct osif_vdev_sync *vdev_sync;
11892
11893 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
11894 if (errno)
11895 return errno;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011896
Dustin Browna09acf42018-11-08 12:32:26 +053011897 errno = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev,
11898 data, data_len);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011899
Dustin Browna09acf42018-11-08 12:32:26 +053011900 osif_vdev_sync_op_stop(vdev_sync);
11901
11902 return errno;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011903}
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011904
11905/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011906 * wlan_hdd_cfg80211_setband() - Wrapper to setband
11907 * @wiphy: wiphy structure pointer
11908 * @wdev: Wireless device structure pointer
11909 * @data: Pointer to the data received
11910 * @data_len: Length of @data
11911 *
11912 * Return: 0 on success; errno on failure
11913 */
11914static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
11915 struct wireless_dev *wdev,
11916 const void *data, int data_len)
11917{
Dustin Browna09acf42018-11-08 12:32:26 +053011918 int errno;
11919 struct osif_vdev_sync *vdev_sync;
11920
11921 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
11922 if (errno)
11923 return errno;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011924
Dustin Browna09acf42018-11-08 12:32:26 +053011925 errno = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011926
Dustin Browna09acf42018-11-08 12:32:26 +053011927 osif_vdev_sync_op_stop(vdev_sync);
11928
11929 return errno;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011930}
11931
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011932/**
11933 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
11934 * @nl80211_value: Vendor command attribute value
11935 * @wmi_value: Pointer to return converted WMI return value
11936 *
11937 * Convert NL80211 vendor command value for SAR limit set to WMI value
11938 * Return: 0 on success, -1 on invalid value
11939 */
11940static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
11941 u32 *wmi_value)
11942{
11943 int ret = 0;
11944
11945 switch (nl80211_value) {
11946 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
11947 *wmi_value = WMI_SAR_FEATURE_OFF;
11948 break;
11949 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
11950 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
11951 break;
11952 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
11953 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
11954 break;
11955 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
11956 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
11957 break;
11958 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
11959 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
11960 break;
11961 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
11962 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
11963 break;
11964 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
11965 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
11966 break;
Kabilan Kannancaa85502018-04-13 18:04:58 -070011967 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0:
11968 *wmi_value = WMI_SAR_FEATURE_ON_SAR_V2_0;
11969 break;
11970
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011971 default:
11972 ret = -1;
11973 }
11974 return ret;
11975}
11976
Jeff Johnson354c20b2018-07-17 20:15:56 -070011977#ifdef WLAN_FEATURE_SARV1_TO_SARV2
11978/**
11979 * hdd_convert_sarv1_to_sarv2() - convert SAR V1 BDF reference to SAR V2
11980 * @hdd_ctx: The HDD global context
11981 * @tb: The parsed array of netlink attributes
11982 * @sar_limit_cmd: The WMI command to be filled
11983 *
11984 * This feature/function is designed to solve the following problem:
11985 * 1) Userspace application was written to use SARv1 BDF entries
11986 * 2) Product is configured with SAR V2 BDF entries
11987 *
11988 * So if this feature is enabled, and if the firmware is configured
11989 * with SAR V2 support, and if the incoming request is to enable a SAR
11990 * V1 BDF entry, then the WMI command is generated to actually
11991 * configure a SAR V2 BDF entry.
11992 *
11993 * Return: true if conversion was performed and @sar_limit_cmd is
11994 * ready to be sent to firmware. Otherwise false in which case the
11995 * normal parsing logic should be applied.
11996 */
11997
11998static bool
11999hdd_convert_sarv1_to_sarv2(struct hdd_context *hdd_ctx,
12000 struct nlattr *tb[],
12001 struct sar_limit_cmd_params *sar_limit_cmd)
12002{
12003 struct nlattr *attr;
12004 uint32_t bdf_index, set;
12005 struct sar_limit_cmd_row *row;
12006
Ashish Kumar Dhanotiya3257cee2019-12-13 20:30:03 +053012007 hdd_enter();
Jeff Johnson354c20b2018-07-17 20:15:56 -070012008 if (hdd_ctx->sar_version != SAR_VERSION_2) {
12009 hdd_debug("SAR version: %d", hdd_ctx->sar_version);
12010 return false;
12011 }
12012
12013 attr = tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE];
12014 if (!attr)
12015 return false;
12016
12017 bdf_index = nla_get_u32(attr);
12018
12019 if ((bdf_index >= QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0) &&
12020 (bdf_index <= QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4)) {
12021 set = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0;
12022 } else if (bdf_index == QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE) {
12023 set = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE;
12024 bdf_index = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0;
12025 } else {
12026 return false;
12027 }
12028
12029 /* Need two rows to hold the per-chain V2 power index
12030 * To disable SARv2 limit, send chain, num_limits_row and
12031 * power limit set to 0 (except power index 0xff)
12032 */
12033 row = qdf_mem_malloc(2 * sizeof(*row));
12034 if (!row)
12035 return false;
12036
12037 if (wlan_hdd_cfg80211_sar_convert_limit_set(
12038 set, &sar_limit_cmd->sar_enable)) {
12039 hdd_err("Failed to convert SAR limit to WMI value");
12040 return false;
12041 }
12042
12043 sar_limit_cmd->commit_limits = 1;
12044 sar_limit_cmd->num_limit_rows = 2;
12045 sar_limit_cmd->sar_limit_row_list = row;
12046 row[0].limit_value = bdf_index;
12047 row[1].limit_value = row[0].limit_value;
12048 row[0].chain_id = 0;
12049 row[1].chain_id = 1;
12050 row[0].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
12051 row[1].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
12052
Ashish Kumar Dhanotiya3257cee2019-12-13 20:30:03 +053012053 hdd_exit();
Jeff Johnson354c20b2018-07-17 20:15:56 -070012054 return true;
12055}
12056
12057#else /* WLAN_FEATURE_SARV1_TO_SARV2 */
Jeff Johnson354c20b2018-07-17 20:15:56 -070012058static bool
12059hdd_convert_sarv1_to_sarv2(struct hdd_context *hdd_ctx,
12060 struct nlattr *tb[],
12061 struct sar_limit_cmd_params *sar_limit_cmd)
12062{
12063 return false;
12064}
12065
12066#endif /* WLAN_FEATURE_SARV1_TO_SARV2 */
12067
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012068/**
12069 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
12070 * @nl80211_value: Vendor command attribute value
12071 * @wmi_value: Pointer to return converted WMI return value
12072 *
12073 * Convert NL80211 vendor command value for SAR BAND to WMI value
12074 * Return: 0 on success, -1 on invalid value
12075 */
12076static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
12077{
12078 int ret = 0;
12079
12080 switch (nl80211_value) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012081 case HDD_NL80211_BAND_2GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012082 *wmi_value = WMI_SAR_2G_ID;
12083 break;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012084 case HDD_NL80211_BAND_5GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012085 *wmi_value = WMI_SAR_5G_ID;
12086 break;
12087 default:
12088 ret = -1;
12089 }
12090 return ret;
12091}
12092
12093/**
12094 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
12095 * @nl80211_value: Vendor command attribute value
12096 * @wmi_value: Pointer to return converted WMI return value
12097 *
12098 * Convert NL80211 vendor command value for SAR Modulation to WMI value
12099 * Return: 0 on success, -1 on invalid value
12100 */
12101static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
12102 u32 *wmi_value)
12103{
12104 int ret = 0;
12105
12106 switch (nl80211_value) {
12107 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
12108 *wmi_value = WMI_SAR_MOD_CCK;
12109 break;
12110 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
12111 *wmi_value = WMI_SAR_MOD_OFDM;
12112 break;
12113 default:
12114 ret = -1;
12115 }
12116 return ret;
12117}
12118
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012119void hdd_store_sar_config(struct hdd_context *hdd_ctx,
12120 struct sar_limit_cmd_params *sar_limit_cmd)
12121{
12122 /* Free the previously stored sar_limit_cmd */
12123 wlan_hdd_free_sar_config(hdd_ctx);
12124
12125 hdd_ctx->sar_cmd_params = sar_limit_cmd;
12126}
12127
12128void wlan_hdd_free_sar_config(struct hdd_context *hdd_ctx)
12129{
12130 struct sar_limit_cmd_params *sar_limit_cmd;
12131
12132 if (!hdd_ctx->sar_cmd_params)
12133 return;
12134
12135 sar_limit_cmd = hdd_ctx->sar_cmd_params;
12136 hdd_ctx->sar_cmd_params = NULL;
12137 qdf_mem_free(sar_limit_cmd->sar_limit_row_list);
12138 qdf_mem_free(sar_limit_cmd);
12139}
12140
12141#define SAR_LIMITS_SAR_ENABLE QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE
12142#define SAR_LIMITS_NUM_SPECS QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS
12143#define SAR_LIMITS_SPEC QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC
12144#define SAR_LIMITS_SPEC_BAND QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND
12145#define SAR_LIMITS_SPEC_CHAIN QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN
12146#define SAR_LIMITS_SPEC_MODULATION \
12147 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION
12148#define SAR_LIMITS_SPEC_POWER_LIMIT \
12149 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT
12150#define SAR_LIMITS_SPEC_POWER_LIMIT_INDEX \
12151 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX
12152#define SAR_LIMITS_MAX QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX
12153
Jeff Johnsonb17a93c2017-06-02 12:26:55 -070012154static const struct nla_policy
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012155sar_limits_policy[SAR_LIMITS_MAX + 1] = {
12156 [SAR_LIMITS_SAR_ENABLE] = {.type = NLA_U32},
12157 [SAR_LIMITS_NUM_SPECS] = {.type = NLA_U32},
12158 [SAR_LIMITS_SPEC_BAND] = {.type = NLA_U32},
12159 [SAR_LIMITS_SPEC_CHAIN] = {.type = NLA_U32},
12160 [SAR_LIMITS_SPEC_MODULATION] = {.type = NLA_U32},
12161 [SAR_LIMITS_SPEC_POWER_LIMIT] = {.type = NLA_U32},
12162 [SAR_LIMITS_SPEC_POWER_LIMIT_INDEX] = {.type = NLA_U32},
Jeff Johnsonb17a93c2017-06-02 12:26:55 -070012163};
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012164
12165/**
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012166 * hdd_extract_sar_nested_attrs() - Extract nested SAR attribute
12167 * @spec: nested nla attribue
12168 * @row: output to hold extract nested attribute
12169 *
12170 * This function extracts nested SAR attribute one at a time which means
12171 * for each nested attribute this has to be invoked from
12172 * __wlan_hdd_set_sar_power_limits().
12173 *
12174 * Return: On success - 0
12175 * On Failure - Negative value
12176 */
12177static int hdd_extract_sar_nested_attrs(struct nlattr *spec[],
12178 struct sar_limit_cmd_row *row)
12179{
12180 uint32_t limit;
12181 uint32_t band;
12182 uint32_t modulation;
12183 int ret;
12184
12185 row->validity_bitmap = 0;
12186
12187 if (spec[SAR_LIMITS_SPEC_POWER_LIMIT]) {
12188 limit = nla_get_u32(spec[SAR_LIMITS_SPEC_POWER_LIMIT]);
12189 row->limit_value = limit;
12190 } else if (spec[SAR_LIMITS_SPEC_POWER_LIMIT_INDEX]) {
12191 limit = nla_get_u32(spec[SAR_LIMITS_SPEC_POWER_LIMIT_INDEX]);
12192 row->limit_value = limit;
12193 } else {
12194 hdd_err("SAR Spec does not have power limit or index value");
12195 return -EINVAL;
12196 }
12197
12198 if (spec[SAR_LIMITS_SPEC_BAND]) {
12199 band = nla_get_u32(spec[SAR_LIMITS_SPEC_BAND]);
12200 ret = wlan_hdd_cfg80211_sar_convert_band(band, &row->band_id);
12201 if (ret) {
12202 hdd_err("Invalid SAR Band attr");
12203 return ret;
12204 }
12205
12206 row->validity_bitmap |= WMI_SAR_BAND_ID_VALID_MASK;
12207 }
12208
12209 if (spec[SAR_LIMITS_SPEC_CHAIN]) {
12210 row->chain_id = nla_get_u32(spec[SAR_LIMITS_SPEC_CHAIN]);
12211 row->validity_bitmap |= WMI_SAR_CHAIN_ID_VALID_MASK;
12212 }
12213
12214 if (spec[SAR_LIMITS_SPEC_MODULATION]) {
12215 modulation = nla_get_u32(spec[SAR_LIMITS_SPEC_MODULATION]);
12216 ret = wlan_hdd_cfg80211_sar_convert_modulation(modulation,
12217 &row->mod_id);
12218 if (ret) {
12219 hdd_err("Invalid SAR Modulation attr");
12220 return ret;
12221 }
12222
12223 row->validity_bitmap |= WMI_SAR_MOD_ID_VALID_MASK;
12224 }
12225
12226 return 0;
12227}
12228
12229/**
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012230 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
12231 * @wiphy: Pointer to wireless phy
12232 * @wdev: Pointer to wireless device
12233 * @data: Pointer to data
12234 * @data_len: Length of @data
12235 *
12236 * This function is used to setup Specific Absorption Rate limit specs.
12237 *
12238 * Return: 0 on success, negative errno on failure
12239 */
12240static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
12241 struct wireless_dev *wdev,
12242 const void *data, int data_len)
12243{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012244 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012245 struct nlattr *spec[SAR_LIMITS_MAX + 1];
12246 struct nlattr *tb[SAR_LIMITS_MAX + 1];
12247 struct nlattr *spec_list;
12248 struct sar_limit_cmd_params *sar_limit_cmd;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012249 int ret = -EINVAL, i = 0, rem = 0;
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012250 QDF_STATUS status;
12251 uint32_t num_limit_rows = 0;
12252 struct sar_limit_cmd_row *row;
Ashish Kumar Dhanotiya3257cee2019-12-13 20:30:03 +053012253 uint32_t sar_enable;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012254
Dustin Brown491d54b2018-03-14 12:39:11 -070012255 hdd_enter();
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012256
12257 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12258 hdd_err("Command not allowed in FTM mode");
12259 return -EPERM;
12260 }
12261
12262 if (wlan_hdd_validate_context(hdd_ctx))
12263 return -EINVAL;
12264
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012265 if (wlan_cfg80211_nla_parse(tb, SAR_LIMITS_MAX, data, data_len,
12266 sar_limits_policy)) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012267 hdd_err("Invalid SAR attributes");
12268 return -EINVAL;
12269 }
12270
Ashish Kumar Dhanotiya3257cee2019-12-13 20:30:03 +053012271 if (tb[SAR_LIMITS_SAR_ENABLE]) {
12272 sar_enable = nla_get_u32(tb[SAR_LIMITS_SAR_ENABLE]);
12273
12274 if ((sar_enable >=
12275 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0 &&
12276 sar_enable <=
12277 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4) &&
12278 hdd_ctx->sar_version == SAR_VERSION_2 &&
12279 !hdd_ctx->config->enable_sar_conversion) {
12280 hdd_err("SARV1 to SARV2 is disabled from ini");
12281 return -EINVAL;
12282 } else if (sar_enable ==
12283 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0 &&
12284 hdd_ctx->sar_version == SAR_VERSION_1) {
12285 hdd_err("FW expects SARV1 given command is SARV2");
12286 return -EINVAL;
12287 }
12288 }
12289
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012290 sar_limit_cmd = qdf_mem_malloc(sizeof(struct sar_limit_cmd_params));
12291 if (!sar_limit_cmd)
12292 return -ENOMEM;
12293
Ashish Kumar Dhanotiya97de5e62020-01-17 21:15:26 +053012294 wlan_hdd_sar_timers_reset(hdd_ctx);
12295
Jeff Johnson354c20b2018-07-17 20:15:56 -070012296 /* is special SAR V1 => SAR V2 logic enabled and applicable? */
Ashish Kumar Dhanotiya3257cee2019-12-13 20:30:03 +053012297 if (hdd_ctx->config->enable_sar_conversion &&
Ashish Kumar Dhanotiya95498182019-04-29 13:59:20 +053012298 (hdd_convert_sarv1_to_sarv2(hdd_ctx, tb, sar_limit_cmd)))
Jeff Johnson354c20b2018-07-17 20:15:56 -070012299 goto send_sar_limits;
12300
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012301 /* Vendor command manadates all SAR Specs in single call */
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012302 sar_limit_cmd->commit_limits = 1;
12303 sar_limit_cmd->sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
12304 if (tb[SAR_LIMITS_SAR_ENABLE]) {
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012305 uint32_t *sar_ptr = &sar_limit_cmd->sar_enable;
12306
Ashish Kumar Dhanotiya3257cee2019-12-13 20:30:03 +053012307 sar_enable = nla_get_u32(tb[SAR_LIMITS_SAR_ENABLE]);
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012308 ret = wlan_hdd_cfg80211_sar_convert_limit_set(sar_enable,
12309 sar_ptr);
12310 if (ret) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012311 hdd_err("Invalid SAR Enable attr");
12312 goto fail;
12313 }
12314 }
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012315
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012316 hdd_debug("attr sar sar_enable %d", sar_limit_cmd->sar_enable);
12317
12318 if (tb[SAR_LIMITS_NUM_SPECS]) {
12319 num_limit_rows = nla_get_u32(tb[SAR_LIMITS_NUM_SPECS]);
12320 hdd_debug("attr sar num_limit_rows %u", num_limit_rows);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012321 }
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012322
12323 if (num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012324 hdd_err("SAR Spec list exceed supported size");
12325 goto fail;
12326 }
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012327
12328 if (num_limit_rows == 0)
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012329 goto send_sar_limits;
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012330
12331 row = qdf_mem_malloc(sizeof(*row) * num_limit_rows);
12332 if (!row) {
12333 hdd_err("Failed to allocate memory for sar_limit_row_list");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012334 goto fail;
12335 }
12336
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012337 sar_limit_cmd->num_limit_rows = num_limit_rows;
12338 sar_limit_cmd->sar_limit_row_list = row;
12339
12340 if (!tb[SAR_LIMITS_SPEC]) {
12341 hdd_err("Invalid SAR specification list");
12342 goto fail;
12343 }
12344
12345 nla_for_each_nested(spec_list, tb[SAR_LIMITS_SPEC], rem) {
12346 if (i == num_limit_rows) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012347 hdd_warn("SAR Cmd has excess SPECs in list");
12348 break;
12349 }
12350
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012351 if (wlan_cfg80211_nla_parse(spec,
12352 SAR_LIMITS_MAX,
12353 nla_data(spec_list),
12354 nla_len(spec_list),
Dustin Brown4ea21db2018-01-05 14:13:17 -080012355 sar_limits_policy)) {
12356 hdd_err("nla_parse failed for SAR Spec list");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012357 goto fail;
12358 }
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012359
12360 ret = hdd_extract_sar_nested_attrs(spec, row);
12361 if (ret) {
12362 hdd_err("Failed to extract SAR nested attrs");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012363 goto fail;
12364 }
12365
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012366 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012367 i, row->band_id, row->chain_id, row->mod_id,
12368 row->limit_value, row->validity_bitmap);
12369
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012370 i++;
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012371 row++;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012372 }
12373
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012374 if (i < sar_limit_cmd->num_limit_rows) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012375 hdd_warn("SAR Cmd has less SPECs in list");
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012376 sar_limit_cmd->num_limit_rows = i;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012377 }
12378
12379send_sar_limits:
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012380 status = sme_set_sar_power_limits(hdd_ctx->mac_handle, sar_limit_cmd);
12381 if (QDF_IS_STATUS_ERROR(status)) {
12382 hdd_err("Failed to set sar power limits");
12383 goto fail;
12384 }
12385
12386 /* After SSR, the SAR configuration is lost. As SSR is hidden from
12387 * userland, this command will not come from userspace after a SSR. To
12388 * restore this configuration, save this in hdd context and restore
12389 * after re-init.
12390 */
12391 hdd_store_sar_config(hdd_ctx, sar_limit_cmd);
12392 return 0;
12393
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012394fail:
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012395 if (sar_limit_cmd) {
12396 qdf_mem_free(sar_limit_cmd->sar_limit_row_list);
12397 qdf_mem_free(sar_limit_cmd);
12398 }
12399
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012400 return ret;
12401}
12402
Sourav Mohapatra9036f652019-04-02 15:02:59 +053012403#undef SAR_LIMITS_SAR_ENABLE
12404#undef SAR_LIMITS_NUM_SPECS
12405#undef SAR_LIMITS_SPEC
12406#undef SAR_LIMITS_SPEC_BAND
12407#undef SAR_LIMITS_SPEC_CHAIN
12408#undef SAR_LIMITS_SPEC_MODULATION
12409#undef SAR_LIMITS_SPEC_POWER_LIMIT
12410#undef SAR_LIMITS_SPEC_POWER_LIMIT_INDEX
12411#undef SAR_LIMITS_MAX
12412
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012413/**
12414 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
12415 * @wiphy: Pointer to wireless phy
12416 * @wdev: Pointer to wireless device
12417 * @data: Pointer to data
12418 * @data_len: Length of @data
12419 *
12420 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
12421 *
12422 * Return: 0 on success, negative errno on failure
12423 */
12424static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
12425 struct wireless_dev *wdev,
12426 const void *data,
12427 int data_len)
12428{
Dustin Brown363b4792019-02-05 16:11:55 -080012429 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080012430 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053012431
Dustin Brown363b4792019-02-05 16:11:55 -080012432 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080012433 if (errno)
12434 return errno;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012435
Dustin Brownf0f00612019-01-31 16:02:24 -080012436 errno = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data, data_len);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012437
Dustin Brown363b4792019-02-05 16:11:55 -080012438 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053012439
Dustin Brownf0f00612019-01-31 16:02:24 -080012440 return errno;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012441}
12442
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012443static const struct
12444nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
12445 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
12446 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
12447 .len = QDF_MAC_ADDR_SIZE},
12448};
12449
Jeff Johnson43975142018-07-04 15:33:47 -070012450void wlan_hdd_rso_cmd_status_cb(hdd_handle_t hdd_handle,
12451 struct rso_cmd_status *rso_status)
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012452{
Jeff Johnson43975142018-07-04 15:33:47 -070012453 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Jeff Johnsone5006672017-08-29 14:39:02 -070012454 struct hdd_adapter *adapter;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012455
12456 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
12457 if (!adapter) {
12458 hdd_err("adapter NULL");
12459 return;
12460 }
12461
12462 adapter->lfr_fw_status.is_disabled = rso_status->status;
12463 complete(&adapter->lfr_fw_status.disable_lfr_event);
12464}
12465
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012466/**
12467 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
12468 * @wiphy: Pointer to wireless phy
12469 * @wdev: Pointer to wireless device
12470 * @data: Pointer to data
12471 * @data_len: Length of @data
12472 *
12473 * This function is used to enable/disable roaming using vendor commands
12474 *
12475 * Return: 0 on success, negative errno on failure
12476 */
12477static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
12478 struct wireless_dev *wdev,
12479 const void *data, int data_len)
12480{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012481 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012482 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070012483 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012484 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012485 uint32_t is_fast_roam_enabled;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012486 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +053012487 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012488 unsigned long rc;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012489 struct hdd_station_ctx *hdd_sta_ctx =
12490 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
12491 mac_handle_t mac_handle;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012492
Dustin Brownfdf17c12018-03-14 12:55:34 -070012493 hdd_enter_dev(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012494
12495 ret = wlan_hdd_validate_context(hdd_ctx);
12496 if (0 != ret)
12497 return ret;
12498
12499 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12500 hdd_err("Command not allowed in FTM mode");
12501 return -EINVAL;
12502 }
12503
Dustin Brown4ea21db2018-01-05 14:13:17 -080012504 ret = wlan_cfg80211_nla_parse(tb,
12505 QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
12506 qca_wlan_vendor_attr);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012507 if (ret) {
12508 hdd_err("Invalid ATTR");
12509 return -EINVAL;
12510 }
12511
12512 /* Parse and fetch Enable flag */
12513 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
12514 hdd_err("attr enable failed");
12515 return -EINVAL;
12516 }
12517
12518 is_fast_roam_enabled = nla_get_u32(
12519 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012520 hdd_debug("isFastRoamEnabled %d", is_fast_roam_enabled);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012521
12522 /* Update roaming */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012523 mac_handle = hdd_ctx->mac_handle;
Jeff Johnsoncf07c312019-02-04 13:53:29 -080012524 qdf_status = sme_config_fast_roaming(mac_handle, adapter->vdev_id,
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012525 is_fast_roam_enabled);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +053012526 if (qdf_status != QDF_STATUS_SUCCESS)
12527 hdd_err("sme_config_fast_roaming failed with status=%d",
12528 qdf_status);
12529 ret = qdf_status_to_os_return(qdf_status);
12530
Jeff Johnsone7951512019-02-27 10:02:51 -080012531 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.conn_state &&
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012532 QDF_IS_STATUS_SUCCESS(qdf_status) && !is_fast_roam_enabled) {
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +053012533
12534 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012535 /*
12536 * wait only for LFR disable in fw as LFR enable
12537 * is always success
12538 */
12539 rc = wait_for_completion_timeout(
12540 &adapter->lfr_fw_status.disable_lfr_event,
12541 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
12542 if (!rc) {
12543 hdd_err("Timed out waiting for RSO CMD status");
12544 return -ETIMEDOUT;
12545 }
12546
12547 if (!adapter->lfr_fw_status.is_disabled) {
12548 hdd_err("Roam disable attempt in FW fails");
12549 return -EBUSY;
12550 }
12551 }
12552
Dustin Browne74003f2018-03-14 12:51:58 -070012553 hdd_exit();
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012554 return ret;
12555}
12556
12557/**
12558 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
12559 * @wiphy: Pointer to wireless phy
12560 * @wdev: Pointer to wireless device
12561 * @data: Pointer to data
12562 * @data_len: Length of @data
12563 *
12564 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
12565 *
12566 * Return: 0 on success, negative errno on failure
12567 */
12568static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
12569 struct wireless_dev *wdev,
12570 const void *data, int data_len)
12571{
Dustin Browna09acf42018-11-08 12:32:26 +053012572 int errno;
12573 struct osif_vdev_sync *vdev_sync;
12574
12575 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
12576 if (errno)
12577 return errno;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012578
Dustin Browna09acf42018-11-08 12:32:26 +053012579 errno = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev,
12580 data, data_len);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012581
Dustin Browna09acf42018-11-08 12:32:26 +053012582 osif_vdev_sync_op_stop(vdev_sync);
12583
12584 return errno;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012585}
12586
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012587/*
12588 * define short names for the global vendor params
12589 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
12590 */
12591#define STATS_SET_INVALID \
12592 QCA_ATTR_NUD_STATS_SET_INVALID
12593#define STATS_SET_START \
12594 QCA_ATTR_NUD_STATS_SET_START
12595#define STATS_GW_IPV4 \
12596 QCA_ATTR_NUD_STATS_GW_IPV4
12597#define STATS_SET_DATA_PKT_INFO \
12598 QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
12599#define STATS_SET_MAX \
12600 QCA_ATTR_NUD_STATS_SET_MAX
12601
12602const struct nla_policy
12603qca_wlan_vendor_set_nud_stats[STATS_SET_MAX + 1] = {
12604 [STATS_SET_START] = {.type = NLA_FLAG },
12605 [STATS_GW_IPV4] = {.type = NLA_U32 },
12606 [STATS_SET_DATA_PKT_INFO] = {.type = NLA_U32 },
12607};
12608
12609/* define short names for the global vendor params */
12610#define CONNECTIVITY_STATS_SET_INVALID \
12611 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
12612#define STATS_PKT_INFO_TYPE \
12613 QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
12614#define STATS_DNS_DOMAIN_NAME \
12615 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
12616#define STATS_SRC_PORT \
12617 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
12618#define STATS_DEST_PORT \
12619 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
12620#define STATS_DEST_IPV4 \
12621 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
12622#define STATS_DEST_IPV6 \
12623 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
12624#define CONNECTIVITY_STATS_SET_MAX \
12625 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
12626
12627const struct nla_policy
12628qca_wlan_vendor_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
12629 [STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
Sourav Mohapatraaaa0f882019-03-07 09:28:40 +053012630 [STATS_DNS_DOMAIN_NAME] = {.type = NLA_NUL_STRING,
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012631 .len = DNS_DOMAIN_NAME_MAX_LEN },
12632 [STATS_SRC_PORT] = {.type = NLA_U32 },
12633 [STATS_DEST_PORT] = {.type = NLA_U32 },
12634 [STATS_DEST_IPV4] = {.type = NLA_U32 },
12635 [STATS_DEST_IPV6] = {.type = NLA_BINARY,
12636 .len = ICMPv6_ADDR_LEN },
12637};
12638
12639/**
12640 * hdd_dns_unmake_name_query() - Convert an uncompressed DNS name to a
12641 * NUL-terminated string
12642 * @name: DNS name
12643 *
12644 * Return: Produce a printable version of a DNS name.
12645 */
12646static inline uint8_t *hdd_dns_unmake_name_query(uint8_t *name)
12647{
12648 uint8_t *p;
12649 unsigned int len;
12650
12651 p = name;
12652 while ((len = *p)) {
12653 *(p++) = '.';
12654 p += len;
12655 }
12656
12657 return name + 1;
12658}
12659
12660/**
12661 * hdd_dns_make_name_query() - Convert a standard NUL-terminated string
12662 * to DNS name
12663 * @string: Name as a NUL-terminated string
12664 * @buf: Buffer in which to place DNS name
12665 *
12666 * DNS names consist of "<length>element" pairs.
12667 *
12668 * Return: Byte following constructed DNS name
12669 */
Sourav Mohapatra47710c32018-11-30 16:27:05 +053012670static uint8_t *hdd_dns_make_name_query(const uint8_t *string,
12671 uint8_t *buf, uint8_t len)
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012672{
12673 uint8_t *length_byte = buf++;
12674 uint8_t c;
12675
Sourav Mohapatra47710c32018-11-30 16:27:05 +053012676 if (string[len - 1]) {
12677 hdd_debug("DNS name is not null terminated");
12678 return NULL;
12679 }
12680
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012681 while ((c = *(string++))) {
12682 if (c == '.') {
12683 *length_byte = buf - length_byte - 1;
12684 length_byte = buf;
12685 }
12686 *(buf++) = c;
12687 }
12688 *length_byte = buf - length_byte - 1;
12689 *(buf++) = '\0';
12690 return buf;
12691}
12692
12693/**
12694 * hdd_set_clear_connectivity_check_stats_info() - set/clear stats info
12695 * @adapter: Pointer to hdd adapter
12696 * @arp_stats_params: arp stats structure to be sent to FW
12697 * @tb: nl attribute
12698 * @is_set_stats: set/clear stats
12699 *
12700 *
12701 * Return: 0 on success, negative errno on failure
12702 */
12703static int hdd_set_clear_connectivity_check_stats_info(
12704 struct hdd_adapter *adapter,
12705 struct set_arp_stats_params *arp_stats_params,
12706 struct nlattr **tb, bool is_set_stats)
12707{
12708 struct nlattr *tb2[CONNECTIVITY_STATS_SET_MAX + 1];
12709 struct nlattr *curr_attr = NULL;
12710 int err = 0;
12711 uint32_t pkt_bitmap;
12712 int rem;
12713
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012714 /* Set NUD command for start tracking is received. */
12715 nla_for_each_nested(curr_attr,
12716 tb[STATS_SET_DATA_PKT_INFO],
12717 rem) {
12718
12719 if (wlan_cfg80211_nla_parse(tb2,
12720 CONNECTIVITY_STATS_SET_MAX,
12721 nla_data(curr_attr), nla_len(curr_attr),
12722 qca_wlan_vendor_set_connectivity_check_stats)) {
12723 hdd_err("nla_parse failed");
12724 err = -EINVAL;
12725 goto end;
12726 }
12727
12728 if (tb2[STATS_PKT_INFO_TYPE]) {
12729 pkt_bitmap = nla_get_u32(tb2[STATS_PKT_INFO_TYPE]);
12730 if (!pkt_bitmap) {
12731 hdd_err("pkt tracking bitmap is empty");
12732 err = -EINVAL;
12733 goto end;
12734 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012735
12736 if (is_set_stats) {
12737 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
12738 arp_stats_params->flag = true;
12739 adapter->pkt_type_bitmap |=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012740 arp_stats_params->pkt_type_bitmap;
12741
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012742 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
Srinivas Girigowda683726a2018-09-07 15:10:40 -070012743 if (!tb[STATS_GW_IPV4]) {
12744 hdd_err("GW ipv4 address is not present");
12745 err = -EINVAL;
12746 goto end;
12747 }
12748 arp_stats_params->ip_addr =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012749 nla_get_u32(tb[STATS_GW_IPV4]);
Srinivas Girigowda683726a2018-09-07 15:10:40 -070012750 arp_stats_params->pkt_type =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012751 WLAN_NUD_STATS_ARP_PKT_TYPE;
Srinivas Girigowda683726a2018-09-07 15:10:40 -070012752 adapter->track_arp_ip =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012753 arp_stats_params->ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012754 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012755
12756 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
12757 uint8_t *domain_name;
12758
12759 if (!tb2[STATS_DNS_DOMAIN_NAME]) {
12760 hdd_err("DNS domain id is not present");
12761 err = -EINVAL;
12762 goto end;
12763 }
12764 domain_name = nla_data(
12765 tb2[STATS_DNS_DOMAIN_NAME]);
12766 adapter->track_dns_domain_len =
12767 nla_len(tb2[
12768 STATS_DNS_DOMAIN_NAME]);
Sourav Mohapatra47710c32018-11-30 16:27:05 +053012769 if (!hdd_dns_make_name_query(
12770 domain_name,
12771 adapter->dns_payload,
12772 adapter->track_dns_domain_len))
12773 adapter->track_dns_domain_len =
12774 0;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012775 /* DNStracking isn't supported in FW. */
12776 arp_stats_params->pkt_type_bitmap &=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012777 ~CONNECTIVITY_CHECK_SET_DNS;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012778 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012779
12780 if (pkt_bitmap &
12781 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
12782 if (!tb2[STATS_SRC_PORT] ||
12783 !tb2[STATS_DEST_PORT]) {
12784 hdd_err("Source/Dest port is not present");
12785 err = -EINVAL;
12786 goto end;
12787 }
12788 arp_stats_params->tcp_src_port =
12789 nla_get_u32(
12790 tb2[STATS_SRC_PORT]);
12791 arp_stats_params->tcp_dst_port =
12792 nla_get_u32(
12793 tb2[STATS_DEST_PORT]);
12794 adapter->track_src_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012795 arp_stats_params->tcp_src_port;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012796 adapter->track_dest_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012797 arp_stats_params->tcp_dst_port;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012798 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012799
12800 if (pkt_bitmap &
12801 CONNECTIVITY_CHECK_SET_ICMPV4) {
12802 if (!tb2[STATS_DEST_IPV4]) {
12803 hdd_err("destination ipv4 address to track ping packets is not present");
12804 err = -EINVAL;
12805 goto end;
12806 }
12807 arp_stats_params->icmp_ipv4 =
12808 nla_get_u32(
12809 tb2[STATS_DEST_IPV4]);
12810 adapter->track_dest_ipv4 =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012811 arp_stats_params->icmp_ipv4;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012812 }
12813 } else {
12814 /* clear stats command received */
12815 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
12816 arp_stats_params->flag = false;
12817 adapter->pkt_type_bitmap &=
12818 (~arp_stats_params->pkt_type_bitmap);
12819
12820 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
12821 arp_stats_params->pkt_type =
12822 WLAN_NUD_STATS_ARP_PKT_TYPE;
12823 qdf_mem_zero(&adapter->hdd_stats.
12824 hdd_arp_stats,
12825 sizeof(adapter->hdd_stats.
12826 hdd_arp_stats));
12827 adapter->track_arp_ip = 0;
12828 }
12829
12830 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
12831 /* DNStracking isn't supported in FW. */
12832 arp_stats_params->pkt_type_bitmap &=
12833 ~CONNECTIVITY_CHECK_SET_DNS;
12834 qdf_mem_zero(&adapter->hdd_stats.
12835 hdd_dns_stats,
12836 sizeof(adapter->hdd_stats.
12837 hdd_dns_stats));
12838 qdf_mem_zero(adapter->dns_payload,
12839 adapter->track_dns_domain_len);
12840 adapter->track_dns_domain_len = 0;
12841 }
12842
12843 if (pkt_bitmap &
12844 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
12845 qdf_mem_zero(&adapter->hdd_stats.
12846 hdd_tcp_stats,
12847 sizeof(adapter->hdd_stats.
12848 hdd_tcp_stats));
12849 adapter->track_src_port = 0;
12850 adapter->track_dest_port = 0;
12851 }
12852
12853 if (pkt_bitmap &
12854 CONNECTIVITY_CHECK_SET_ICMPV4) {
12855 qdf_mem_zero(&adapter->hdd_stats.
12856 hdd_icmpv4_stats,
12857 sizeof(adapter->hdd_stats.
12858 hdd_icmpv4_stats));
12859 adapter->track_dest_ipv4 = 0;
12860 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012861 }
12862 } else {
12863 hdd_err("stats list empty");
12864 err = -EINVAL;
12865 goto end;
12866 }
12867 }
12868
12869end:
12870 return err;
12871}
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053012872
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012873static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
12874 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
12875 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
12876 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
12877 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
12878};
12879
12880/**
12881 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
12882 * @wiphy: Pointer to wireless phy
12883 * @wdev: Pointer to wireless device
12884 * @data: Pointer to data
12885 * @data_len: Length of @data
12886 *
12887 * Return: 0 on success, negative errno on failure
12888 */
12889static int
12890__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
12891 struct wireless_dev *wdev,
12892 const void *data,
12893 int data_len)
12894{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012895 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012896 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
12897 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
12898 struct nlattr *apth;
12899 int rem;
12900 int ret = 1;
12901 int print_idx = -1;
12902 int module_id = -1;
12903 int bit_mask = -1;
12904 int status;
12905
Dustin Brown491d54b2018-03-14 12:39:11 -070012906 hdd_enter();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012907
12908 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
12909 hdd_err("Command not allowed in FTM mode");
12910 return -EINVAL;
12911 }
12912
12913 ret = wlan_hdd_validate_context(hdd_ctx);
12914 if (ret != 0)
12915 return -EINVAL;
12916
12917 print_idx = qdf_get_pidx();
12918 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
12919 hdd_err("Invalid print controle object index");
12920 return -EINVAL;
12921 }
12922
Dustin Brown4ea21db2018-01-05 14:13:17 -080012923 if (wlan_cfg80211_nla_parse(tb1,
12924 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
12925 data, data_len,
12926 qca_wlan_vendor_set_trace_level_policy)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012927 hdd_err("Invalid attr");
12928 return -EINVAL;
12929 }
12930
12931 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
12932 hdd_err("attr trace level param failed");
12933 return -EINVAL;
12934 }
12935
12936 nla_for_each_nested(apth,
12937 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -080012938 if (wlan_cfg80211_nla_parse(tb2,
Ashish Kumar Dhanotiya69903252019-03-18 20:23:47 +053012939 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
12940 nla_data(apth), nla_len(apth),
12941 qca_wlan_vendor_set_trace_level_policy)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012942 hdd_err("Invalid attr");
12943 return -EINVAL;
12944 }
12945
12946 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
12947 hdd_err("attr Module ID failed");
12948 return -EINVAL;
12949 }
12950 module_id = nla_get_u32
12951 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
12952
12953 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
12954 hdd_err("attr Verbose mask failed");
12955 return -EINVAL;
12956 }
12957 bit_mask = nla_get_u32
12958 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
12959
12960 status = hdd_qdf_trace_enable(module_id, bit_mask);
12961
12962 if (status != 0)
12963 hdd_err("can not set verbose mask %d for the category %d",
12964 bit_mask, module_id);
12965 }
12966
Dustin Browne74003f2018-03-14 12:51:58 -070012967 hdd_exit();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012968 return ret;
12969}
12970
12971/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +053012972 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
12973 * @wiphy: Pointer to wireless phy
12974 * @wdev: Pointer to wireless device
12975 * @data: Pointer to data
12976 * @data_len: Length of @data
12977 *
12978 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
12979 *
12980 * Return: 0 on success, negative errno on failure
12981 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012982
12983static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
12984 struct wireless_dev *wdev,
12985 const void *data,
12986 int data_len)
12987{
Dustin Brown363b4792019-02-05 16:11:55 -080012988 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080012989 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053012990
Dustin Brown363b4792019-02-05 16:11:55 -080012991 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080012992 if (errno)
12993 return errno;
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012994
Dustin Brownf0f00612019-01-31 16:02:24 -080012995 errno = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev,
12996 data, data_len);
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012997
Dustin Brown363b4792019-02-05 16:11:55 -080012998 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053012999
Dustin Brownf0f00612019-01-31 16:02:24 -080013000 return errno;
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053013001}
13002
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013003/**
13004 * __wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
13005 * @wiphy: pointer to wireless wiphy structure.
13006 * @wdev: pointer to wireless_dev structure.
13007 * @data: pointer to apfind configuration data.
13008 * @data_len: the length in byte of apfind data.
13009 *
13010 * This is called when wlan driver needs to send arp stats to
13011 * firmware.
13012 *
13013 * Return: An error code or 0 on success.
13014 */
13015static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
13016 struct wireless_dev *wdev,
13017 const void *data, int data_len)
13018{
13019 struct nlattr *tb[STATS_SET_MAX + 1];
13020 struct net_device *dev = wdev->netdev;
13021 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Alan Chen7890beb2020-01-27 11:11:03 -080013022 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013023 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013024 struct set_arp_stats_params arp_stats_params = {0};
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013025 int err = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013026 mac_handle_t mac_handle;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013027
Dustin Brown491d54b2018-03-14 12:39:11 -070013028 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013029
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053013030 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13031 hdd_err("Command not allowed in FTM mode");
13032 return -EINVAL;
13033 }
13034
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013035 err = wlan_hdd_validate_context(hdd_ctx);
13036 if (0 != err)
13037 return err;
13038
Jeff Johnson912b1bb2019-03-06 10:12:36 -080013039 if (adapter->vdev_id == WLAN_UMAC_VDEV_ID_MAX) {
13040 hdd_err("Invalid vdev id");
Yeshwanth Sriram Guntukad5aae7f2017-11-27 14:33:51 +053013041 return -EINVAL;
13042 }
13043
Poddar, Siddarthdf076672018-02-26 14:21:45 +053013044 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070013045 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053013046 return -EINVAL;
13047 }
13048
Alan Chen7890beb2020-01-27 11:11:03 -080013049 if (eConnectionState_Associated != sta_ctx->conn_info.conn_state) {
13050 hdd_debug("Not Associated");
13051 return 0;
13052 }
13053
Jeff Johnson912b1bb2019-03-06 10:12:36 -080013054 err = wlan_cfg80211_nla_parse(tb, STATS_SET_MAX, data, data_len,
13055 qca_wlan_vendor_set_nud_stats);
13056 if (err) {
13057 hdd_err("STATS_SET_START ATTR");
13058 return err;
13059 }
13060
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013061 if (tb[STATS_SET_START]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013062 /* tracking is enabled for stats other than arp. */
13063 if (tb[STATS_SET_DATA_PKT_INFO]) {
13064 err = hdd_set_clear_connectivity_check_stats_info(
13065 adapter,
13066 &arp_stats_params, tb, true);
13067 if (err)
13068 return -EINVAL;
13069
13070 /*
13071 * if only tracking dns, then don't send
13072 * wmi command to FW.
13073 */
13074 if (!arp_stats_params.pkt_type_bitmap)
13075 return err;
13076 } else {
13077 if (!tb[STATS_GW_IPV4]) {
Dustin Browna2868622018-03-20 11:38:14 -070013078 hdd_err("STATS_SET_START CMD");
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013079 return -EINVAL;
13080 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053013081
13082 arp_stats_params.pkt_type_bitmap =
13083 CONNECTIVITY_CHECK_SET_ARP;
13084 adapter->pkt_type_bitmap |=
13085 arp_stats_params.pkt_type_bitmap;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013086 arp_stats_params.flag = true;
13087 arp_stats_params.ip_addr =
13088 nla_get_u32(tb[STATS_GW_IPV4]);
13089 adapter->track_arp_ip = arp_stats_params.ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013090 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013091 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013092 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053013093 /* clear stats command received. */
13094 if (tb[STATS_SET_DATA_PKT_INFO]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013095 err = hdd_set_clear_connectivity_check_stats_info(
13096 adapter,
13097 &arp_stats_params, tb, false);
13098 if (err)
13099 return -EINVAL;
13100
13101 /*
13102 * if only tracking dns, then don't send
13103 * wmi command to FW.
13104 */
13105 if (!arp_stats_params.pkt_type_bitmap)
13106 return err;
13107 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053013108 arp_stats_params.pkt_type_bitmap =
13109 CONNECTIVITY_CHECK_SET_ARP;
13110 adapter->pkt_type_bitmap &=
13111 (~arp_stats_params.pkt_type_bitmap);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013112 arp_stats_params.flag = false;
13113 qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
13114 sizeof(adapter->hdd_stats.hdd_arp_stats));
13115 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
13116 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013117 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013118
Abhinav Kumar50d4dc72018-06-15 16:35:50 +053013119 hdd_debug("STATS_SET_START Received flag %d!", arp_stats_params.flag);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013120
Jeff Johnsoncf07c312019-02-04 13:53:29 -080013121 arp_stats_params.vdev_id = adapter->vdev_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013122
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013123 mac_handle = hdd_ctx->mac_handle;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013124 if (QDF_STATUS_SUCCESS !=
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013125 sme_set_nud_debug_stats(mac_handle, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070013126 hdd_err("STATS_SET_START CMD Failed!");
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013127 return -EINVAL;
13128 }
13129
Dustin Browne74003f2018-03-14 12:51:58 -070013130 hdd_exit();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013131
13132 return err;
13133}
13134
13135/**
13136 * wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
13137 * @wiphy: pointer to wireless wiphy structure.
13138 * @wdev: pointer to wireless_dev structure.
13139 * @data: pointer to apfind configuration data.
13140 * @data_len: the length in byte of apfind data.
13141 *
13142 * This is called when wlan driver needs to send arp stats to
13143 * firmware.
13144 *
13145 * Return: An error code or 0 on success.
13146 */
13147static int wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
13148 struct wireless_dev *wdev,
13149 const void *data, int data_len)
13150{
Dustin Browna09acf42018-11-08 12:32:26 +053013151 int errno;
13152 struct osif_vdev_sync *vdev_sync;
13153
13154 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
13155 if (errno)
13156 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013157
Dustin Browna09acf42018-11-08 12:32:26 +053013158 errno = __wlan_hdd_cfg80211_set_nud_stats(wiphy, wdev, data, data_len);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013159
Dustin Browna09acf42018-11-08 12:32:26 +053013160 osif_vdev_sync_op_stop(vdev_sync);
13161
13162 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013163}
13164
13165#undef STATS_SET_INVALID
13166#undef STATS_SET_START
13167#undef STATS_GW_IPV4
13168#undef STATS_SET_MAX
13169
13170/*
13171 * define short names for the global vendor params
13172 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
13173 */
13174#define STATS_GET_INVALID \
13175 QCA_ATTR_NUD_STATS_SET_INVALID
13176#define COUNT_FROM_NETDEV \
13177 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
13178#define COUNT_TO_LOWER_MAC \
13179 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
13180#define RX_COUNT_BY_LOWER_MAC \
13181 QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
13182#define COUNT_TX_SUCCESS \
13183 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
13184#define RSP_RX_COUNT_BY_LOWER_MAC \
13185 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
13186#define RSP_RX_COUNT_BY_UPPER_MAC \
13187 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
13188#define RSP_COUNT_TO_NETDEV \
13189 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
13190#define RSP_COUNT_OUT_OF_ORDER_DROP \
13191 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
13192#define AP_LINK_ACTIVE \
13193 QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
13194#define AP_LINK_DAD \
13195 QCA_ATTR_NUD_STATS_IS_DAD
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013196#define DATA_PKT_STATS \
13197 QCA_ATTR_NUD_STATS_DATA_PKT_STATS
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013198#define STATS_GET_MAX \
13199 QCA_ATTR_NUD_STATS_GET_MAX
13200
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013201#define CHECK_STATS_INVALID \
13202 QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
13203#define CHECK_STATS_PKT_TYPE \
13204 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
13205#define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
13206 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
13207#define CHECK_STATS_PKT_SRC_PORT \
13208 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
13209#define CHECK_STATS_PKT_DEST_PORT \
13210 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
13211#define CHECK_STATS_PKT_DEST_IPV4 \
13212 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
13213#define CHECK_STATS_PKT_DEST_IPV6 \
13214 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
13215#define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
13216 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
13217#define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
13218 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
13219#define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
13220 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
13221#define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
13222 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
13223#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
13224 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
13225#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
13226 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
13227#define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
13228 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
13229#define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
13230 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
13231#define CHECK_DATA_STATS_MAX \
13232 QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
13233
13234
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013235const struct nla_policy
13236qca_wlan_vendor_get_nud_stats[STATS_GET_MAX + 1] = {
13237 [COUNT_FROM_NETDEV] = {.type = NLA_U16 },
13238 [COUNT_TO_LOWER_MAC] = {.type = NLA_U16 },
13239 [RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
13240 [COUNT_TX_SUCCESS] = {.type = NLA_U16 },
13241 [RSP_RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
13242 [RSP_RX_COUNT_BY_UPPER_MAC] = {.type = NLA_U16 },
13243 [RSP_COUNT_TO_NETDEV] = {.type = NLA_U16 },
13244 [RSP_COUNT_OUT_OF_ORDER_DROP] = {.type = NLA_U16 },
13245 [AP_LINK_ACTIVE] = {.type = NLA_FLAG },
13246 [AP_LINK_DAD] = {.type = NLA_FLAG },
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013247 [DATA_PKT_STATS] = {.type = NLA_U16 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013248};
13249
13250/**
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013251 * hdd_populate_dns_stats_info() - send dns stats info to network stack
13252 * @adapter: pointer to adapter context
13253 * @skb: pointer to skb
13254 *
13255 *
13256 * Return: An error code or 0 on success.
13257 */
13258static int hdd_populate_dns_stats_info(struct hdd_adapter *adapter,
13259 struct sk_buff *skb)
13260{
13261 uint8_t *dns_query;
13262
13263 dns_query = qdf_mem_malloc(adapter->track_dns_domain_len + 1);
Min Liu74a1a502018-10-10 19:59:07 +080013264 if (!dns_query)
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013265 return -EINVAL;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013266
13267 qdf_mem_copy(dns_query, adapter->dns_payload,
13268 adapter->track_dns_domain_len);
13269
13270 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13271 CONNECTIVITY_CHECK_SET_DNS) ||
13272 nla_put(skb, CHECK_STATS_PKT_DNS_DOMAIN_NAME,
13273 adapter->track_dns_domain_len,
13274 hdd_dns_unmake_name_query(dns_query)) ||
13275 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13276 adapter->hdd_stats.hdd_dns_stats.tx_dns_req_count) ||
13277 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13278 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
13279 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13280 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
13281 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13282 adapter->hdd_stats.hdd_dns_stats.tx_ack_cnt) ||
13283 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
13284 adapter->hdd_stats.hdd_dns_stats.rx_dns_rsp_count) ||
13285 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
13286 adapter->hdd_stats.hdd_dns_stats.rx_delivered) ||
13287 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
13288 adapter->hdd_stats.hdd_dns_stats.rx_host_drop)) {
13289 hdd_err("nla put fail");
13290 qdf_mem_free(dns_query);
13291 kfree_skb(skb);
13292 return -EINVAL;
13293 }
13294 qdf_mem_free(dns_query);
13295 return 0;
13296}
13297
13298/**
13299 * hdd_populate_tcp_stats_info() - send tcp stats info to network stack
13300 * @adapter: pointer to adapter context
13301 * @skb: pointer to skb
13302 * @pkt_type: tcp pkt type
13303 *
13304 * Return: An error code or 0 on success.
13305 */
13306static int hdd_populate_tcp_stats_info(struct hdd_adapter *adapter,
13307 struct sk_buff *skb,
13308 uint8_t pkt_type)
13309{
13310 switch (pkt_type) {
13311 case CONNECTIVITY_CHECK_SET_TCP_SYN:
13312 /* Fill info for tcp syn packets (tx packet) */
13313 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13314 CONNECTIVITY_CHECK_SET_TCP_SYN) ||
13315 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
13316 adapter->track_src_port) ||
13317 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
13318 adapter->track_dest_port) ||
13319 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13320 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_count) ||
13321 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13322 adapter->hdd_stats.hdd_tcp_stats.
13323 tx_tcp_syn_host_fw_sent) ||
13324 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13325 adapter->hdd_stats.hdd_tcp_stats.
13326 tx_tcp_syn_host_fw_sent) ||
13327 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13328 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_ack_cnt)) {
13329 hdd_err("nla put fail");
13330 kfree_skb(skb);
13331 return -EINVAL;
13332 }
13333 break;
13334 case CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
13335 /* Fill info for tcp syn-ack packets (rx packet) */
13336 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13337 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK) ||
13338 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
13339 adapter->track_src_port) ||
13340 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
13341 adapter->track_dest_port) ||
13342 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
13343 adapter->hdd_stats.hdd_tcp_stats.rx_fw_cnt) ||
13344 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
13345 adapter->hdd_stats.hdd_tcp_stats.
13346 rx_tcp_syn_ack_count) ||
13347 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
13348 adapter->hdd_stats.hdd_tcp_stats.rx_delivered) ||
13349 nla_put_u16(skb,
13350 CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
13351 adapter->hdd_stats.hdd_tcp_stats.rx_host_drop)) {
13352 hdd_err("nla put fail");
13353 kfree_skb(skb);
13354 return -EINVAL;
13355 }
13356 break;
13357 case CONNECTIVITY_CHECK_SET_TCP_ACK:
13358 /* Fill info for tcp ack packets (tx packet) */
13359 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13360 CONNECTIVITY_CHECK_SET_TCP_ACK) ||
13361 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
13362 adapter->track_src_port) ||
13363 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
13364 adapter->track_dest_port) ||
13365 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13366 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_count) ||
13367 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13368 adapter->hdd_stats.hdd_tcp_stats.
13369 tx_tcp_ack_host_fw_sent) ||
13370 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13371 adapter->hdd_stats.hdd_tcp_stats.
13372 tx_tcp_ack_host_fw_sent) ||
13373 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13374 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_ack_cnt)) {
13375 hdd_err("nla put fail");
13376 kfree_skb(skb);
13377 return -EINVAL;
13378 }
13379 break;
13380 default:
13381 break;
13382 }
13383 return 0;
13384}
13385
13386/**
13387 * hdd_populate_icmpv4_stats_info() - send icmpv4 stats info to network stack
13388 * @adapter: pointer to adapter context
13389 * @skb: pointer to skb
13390 *
13391 *
13392 * Return: An error code or 0 on success.
13393 */
13394static int hdd_populate_icmpv4_stats_info(struct hdd_adapter *adapter,
13395 struct sk_buff *skb)
13396{
13397 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13398 CONNECTIVITY_CHECK_SET_ICMPV4) ||
13399 nla_put_u32(skb, CHECK_STATS_PKT_DEST_IPV4,
13400 adapter->track_dest_ipv4) ||
13401 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13402 adapter->hdd_stats.hdd_icmpv4_stats.tx_icmpv4_req_count) ||
13403 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13404 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
13405 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13406 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
13407 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13408 adapter->hdd_stats.hdd_icmpv4_stats.tx_ack_cnt) ||
13409 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
13410 adapter->hdd_stats.hdd_icmpv4_stats.rx_fw_cnt) ||
13411 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
13412 adapter->hdd_stats.hdd_icmpv4_stats.rx_icmpv4_rsp_count) ||
13413 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
13414 adapter->hdd_stats.hdd_icmpv4_stats.rx_delivered) ||
13415 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
13416 adapter->hdd_stats.hdd_icmpv4_stats.rx_host_drop)) {
13417 hdd_err("nla put fail");
13418 kfree_skb(skb);
13419 return -EINVAL;
13420 }
13421 return 0;
13422}
13423
13424/**
13425 * hdd_populate_connectivity_check_stats_info() - send connectivity stats info
13426 * to network stack
13427 * @adapter: pointer to adapter context
13428 * @skb: pointer to skb
13429 *
13430 *
13431 * Return: An error code or 0 on success.
13432 */
13433
13434static int hdd_populate_connectivity_check_stats_info(
13435 struct hdd_adapter *adapter, struct sk_buff *skb)
13436{
13437 struct nlattr *connect_stats, *connect_info;
13438 uint32_t count = 0;
13439
13440 connect_stats = nla_nest_start(skb, DATA_PKT_STATS);
Jeff Johnsond36fa332019-03-18 13:42:25 -070013441 if (!connect_stats) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013442 hdd_err("nla_nest_start failed");
13443 return -EINVAL;
13444 }
13445
13446 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
13447 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070013448 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013449 hdd_err("nla_nest_start failed count %u", count);
13450 return -EINVAL;
13451 }
13452
13453 if (hdd_populate_dns_stats_info(adapter, skb))
13454 goto put_attr_fail;
13455 nla_nest_end(skb, connect_info);
13456 count++;
13457 }
13458
13459 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
13460 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070013461 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013462 hdd_err("nla_nest_start failed count %u", count);
13463 return -EINVAL;
13464 }
13465 if (hdd_populate_tcp_stats_info(adapter, skb,
13466 CONNECTIVITY_CHECK_SET_TCP_SYN))
13467 goto put_attr_fail;
13468 nla_nest_end(skb, connect_info);
13469 count++;
13470
13471 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070013472 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013473 hdd_err("nla_nest_start failed count %u", count);
13474 return -EINVAL;
13475 }
13476 if (hdd_populate_tcp_stats_info(adapter, skb,
13477 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK))
13478 goto put_attr_fail;
13479 nla_nest_end(skb, connect_info);
13480 count++;
13481
13482 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070013483 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013484 hdd_err("nla_nest_start failed count %u", count);
13485 return -EINVAL;
13486 }
13487 if (hdd_populate_tcp_stats_info(adapter, skb,
13488 CONNECTIVITY_CHECK_SET_TCP_ACK))
13489 goto put_attr_fail;
13490 nla_nest_end(skb, connect_info);
13491 count++;
13492 }
13493
13494 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ICMPV4) {
13495 connect_info = nla_nest_start(skb, count);
Jeff Johnsond36fa332019-03-18 13:42:25 -070013496 if (!connect_info) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013497 hdd_err("nla_nest_start failed count %u", count);
13498 return -EINVAL;
13499 }
13500
13501 if (hdd_populate_icmpv4_stats_info(adapter, skb))
13502 goto put_attr_fail;
13503 nla_nest_end(skb, connect_info);
13504 count++;
13505 }
13506
13507 nla_nest_end(skb, connect_stats);
13508 return 0;
13509
13510put_attr_fail:
13511 hdd_err("QCA_WLAN_VENDOR_ATTR put fail. count %u", count);
13512 return -EINVAL;
13513}
13514
13515
13516/**
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013517 * __wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
13518 * @wiphy: pointer to wireless wiphy structure.
13519 * @wdev: pointer to wireless_dev structure.
13520 * @data: pointer to apfind configuration data.
13521 * @data_len: the length in byte of apfind data.
13522 *
13523 * This is called when wlan driver needs to get arp stats to
13524 * firmware.
13525 *
13526 * Return: An error code or 0 on success.
13527 */
13528static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
13529 struct wireless_dev *wdev,
13530 const void *data, int data_len)
13531{
13532 int err = 0;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013533 struct net_device *dev = wdev->netdev;
13534 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13535 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
13536 struct get_arp_stats_params arp_stats_params;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013537 mac_handle_t mac_handle;
Poddar, Siddarthdb568162017-07-27 18:16:38 +053013538 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013539 uint32_t pkt_type_bitmap;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013540 struct sk_buff *skb;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013541 struct osif_request *request = NULL;
13542 static const struct osif_request_params params = {
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013543 .priv_size = 0,
13544 .timeout_ms = WLAN_WAIT_TIME_NUD_STATS,
13545 };
13546 void *cookie = NULL;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013547
Dustin Brown491d54b2018-03-14 12:39:11 -070013548 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013549
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053013550 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13551 hdd_err("Command not allowed in FTM mode");
13552 return -EINVAL;
13553 }
13554
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013555 err = wlan_hdd_validate_context(hdd_ctx);
13556 if (0 != err)
13557 return err;
13558
Rajeev Kumar7f28e8a32017-08-23 15:41:30 -070013559 err = hdd_validate_adapter(adapter);
13560 if (err)
13561 return err;
13562
Poddar, Siddarthdf076672018-02-26 14:21:45 +053013563 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070013564 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053013565 return -EINVAL;
13566 }
13567
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013568 request = osif_request_alloc(&params);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013569 if (!request) {
13570 hdd_err("Request allocation failure");
13571 return -ENOMEM;
13572 }
13573
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013574 cookie = osif_request_cookie(request);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013575
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013576 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Jeff Johnsoncf07c312019-02-04 13:53:29 -080013577 arp_stats_params.vdev_id = adapter->vdev_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013578
Poddar, Siddarth762c5472018-03-20 14:55:35 +053013579 pkt_type_bitmap = adapter->pkt_type_bitmap;
13580
13581 /* send NUD failure event only when ARP tracking is enabled. */
jitiphil377bcc12018-10-05 19:46:08 +053013582 if (cdp_cfg_get(soc, cfg_dp_enable_data_stall) &&
Alok Kumar939ca502019-11-11 11:34:37 +053013583 (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ARP)) {
13584 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
13585 "Data stall due to NUD failure");
Poddar, Siddarth37033032017-10-11 15:47:40 +053013586 cdp_post_data_stall_event(soc,
13587 DATA_STALL_LOG_INDICATOR_FRAMEWORK,
Poddar, Siddarthdb568162017-07-27 18:16:38 +053013588 DATA_STALL_LOG_NUD_FAILURE,
Rakesh Pillai6a36b0a2019-09-06 16:30:05 +053013589 OL_TXRX_PDEV_ID, 0XFF,
Poddar, Siddarthdb568162017-07-27 18:16:38 +053013590 DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
Alok Kumar939ca502019-11-11 11:34:37 +053013591 }
Poddar, Siddarthdb568162017-07-27 18:16:38 +053013592
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013593 mac_handle = hdd_ctx->mac_handle;
13594 if (sme_set_nud_debug_stats_cb(mac_handle, hdd_get_nud_stats_cb,
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013595 cookie) != QDF_STATUS_SUCCESS) {
13596 hdd_err("Setting NUD debug stats callback failure");
13597 err = -EINVAL;
13598 goto exit;
13599 }
13600
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013601 if (QDF_STATUS_SUCCESS !=
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013602 sme_get_nud_debug_stats(mac_handle, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070013603 hdd_err("STATS_SET_START CMD Failed!");
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013604 err = -EINVAL;
13605 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013606 }
13607
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013608 err = osif_request_wait_for_response(request);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013609 if (err) {
13610 hdd_err("SME timedout while retrieving NUD stats");
13611 err = -ETIMEDOUT;
13612 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013613 }
13614
13615 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
13616 WLAN_NUD_STATS_LEN);
13617 if (!skb) {
13618 hdd_err("%s: cfg80211_vendor_cmd_alloc_reply_skb failed",
13619 __func__);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013620 err = -ENOMEM;
13621 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013622 }
13623
13624 if (nla_put_u16(skb, COUNT_FROM_NETDEV,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053013625 adapter->hdd_stats.hdd_arp_stats.tx_arp_req_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013626 nla_put_u16(skb, COUNT_TO_LOWER_MAC,
13627 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
13628 nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053013629 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013630 nla_put_u16(skb, COUNT_TX_SUCCESS,
13631 adapter->hdd_stats.hdd_arp_stats.tx_ack_cnt) ||
13632 nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC,
13633 adapter->hdd_stats.hdd_arp_stats.rx_fw_cnt) ||
13634 nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053013635 adapter->hdd_stats.hdd_arp_stats.rx_arp_rsp_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013636 nla_put_u16(skb, RSP_COUNT_TO_NETDEV,
13637 adapter->hdd_stats.hdd_arp_stats.rx_delivered) ||
13638 nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP,
13639 adapter->hdd_stats.hdd_arp_stats.
13640 rx_host_drop_reorder)) {
13641 hdd_err("nla put fail");
13642 kfree_skb(skb);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013643 err = -EINVAL;
13644 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013645 }
13646 if (adapter->con_status)
13647 nla_put_flag(skb, AP_LINK_ACTIVE);
13648 if (adapter->dad)
13649 nla_put_flag(skb, AP_LINK_DAD);
13650
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013651 /* ARP tracking is done above. */
13652 pkt_type_bitmap &= ~CONNECTIVITY_CHECK_SET_ARP;
13653
13654 if (pkt_type_bitmap) {
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013655 if (hdd_populate_connectivity_check_stats_info(adapter, skb)) {
13656 err = -EINVAL;
13657 goto exit;
13658 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013659 }
13660
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013661 cfg80211_vendor_cmd_reply(skb);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013662exit:
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013663 osif_request_put(request);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013664 return err;
13665}
13666
13667/**
13668 * wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
13669 * @wiphy: pointer to wireless wiphy structure.
13670 * @wdev: pointer to wireless_dev structure.
13671 * @data: pointer to apfind configuration data.
13672 * @data_len: the length in byte of apfind data.
13673 *
13674 * This is called when wlan driver needs to get arp stats to
13675 * firmware.
13676 *
13677 * Return: An error code or 0 on success.
13678 */
13679static int wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
13680 struct wireless_dev *wdev,
13681 const void *data, int data_len)
13682{
Dustin Browna09acf42018-11-08 12:32:26 +053013683 int errno;
13684 struct osif_vdev_sync *vdev_sync;
13685
13686 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
13687 if (errno)
13688 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013689
Dustin Browna09acf42018-11-08 12:32:26 +053013690 errno = __wlan_hdd_cfg80211_get_nud_stats(wiphy, wdev, data, data_len);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013691
Dustin Browna09acf42018-11-08 12:32:26 +053013692 osif_vdev_sync_op_stop(vdev_sync);
13693
13694 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013695}
13696
13697#undef QCA_ATTR_NUD_STATS_SET_INVALID
13698#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
13699#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
13700#undef QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
13701#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
13702#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
13703#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
13704#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
13705#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
13706#undef QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
13707#undef QCA_ATTR_NUD_STATS_GET_MAX
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013708
Jeff Johnsond0b6c7e2018-07-04 14:53:06 -070013709void hdd_bt_activity_cb(hdd_handle_t hdd_handle, uint32_t bt_activity)
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013710{
Jeff Johnsond0b6c7e2018-07-04 14:53:06 -070013711 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013712 int status;
13713
13714 status = wlan_hdd_validate_context(hdd_ctx);
13715 if (0 != status)
13716 return;
13717
13718 if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_ADD)
13719 hdd_ctx->bt_a2dp_active = 1;
13720 else if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_REMOVE)
13721 hdd_ctx->bt_a2dp_active = 0;
13722 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_ADD)
13723 hdd_ctx->bt_vo_active = 1;
13724 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_REMOVE)
13725 hdd_ctx->bt_vo_active = 0;
13726 else
13727 return;
13728
Dustin Brown76cd2932018-09-11 16:03:05 -070013729 ucfg_scan_set_bt_activity(hdd_ctx->psoc, hdd_ctx->bt_a2dp_active);
Srinivas Girigowda6598eea2017-07-06 19:26:19 -070013730 hdd_debug("a2dp_active: %d vo_active: %d", hdd_ctx->bt_a2dp_active,
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013731 hdd_ctx->bt_vo_active);
13732}
13733
lifengd217d192017-05-09 19:44:16 +080013734struct chain_rssi_priv {
13735 struct chain_rssi_result chain_rssi;
13736};
13737
13738/**
13739 * hdd_get_chain_rssi_cb() - Callback function to get chain rssi
13740 * @context: opaque context originally passed to SME. HDD always passes
13741 * a cookie for the request context
13742 * @data: struct for get chain rssi
13743 *
13744 * This function receives the response/data from the lower layer and
13745 * checks to see if the thread is still waiting then post the results to
13746 * upper layer, if the request has timed out then ignore.
13747 *
13748 * Return: None
13749 */
13750static void hdd_get_chain_rssi_cb(void *context,
13751 struct chain_rssi_result *data)
13752{
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013753 struct osif_request *request;
lifengd217d192017-05-09 19:44:16 +080013754 struct chain_rssi_priv *priv;
13755
Dustin Brown491d54b2018-03-14 12:39:11 -070013756 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080013757
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013758 request = osif_request_get(context);
lifengd217d192017-05-09 19:44:16 +080013759 if (!request) {
13760 hdd_err("Obsolete request");
13761 return;
13762 }
13763
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013764 priv = osif_request_priv(request);
lifengd217d192017-05-09 19:44:16 +080013765 priv->chain_rssi = *data;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013766 osif_request_complete(request);
13767 osif_request_put(request);
lifengd217d192017-05-09 19:44:16 +080013768}
13769
13770/**
13771 * hdd_post_get_chain_rssi_rsp - send rsp to user space
13772 * @hdd_ctx: pointer to hdd context
13773 * @result: chain rssi result
13774 *
13775 * Return: 0 for success, non-zero for failure
13776 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013777static int hdd_post_get_chain_rssi_rsp(struct hdd_context *hdd_ctx,
lifengd217d192017-05-09 19:44:16 +080013778 struct chain_rssi_result *result)
13779{
13780 struct sk_buff *skb;
lifengd217d192017-05-09 19:44:16 +080013781
13782 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
lifengfe6c3e22018-04-03 12:10:04 +080013783 (sizeof(result->chain_rssi) + NLA_HDRLEN) +
stonez396a9732019-01-16 12:29:16 +080013784 (sizeof(result->chain_evm) + NLA_HDRLEN) +
lifengfe6c3e22018-04-03 12:10:04 +080013785 (sizeof(result->ant_id) + NLA_HDRLEN) +
13786 NLMSG_HDRLEN);
lifengd217d192017-05-09 19:44:16 +080013787
13788 if (!skb) {
13789 hdd_err("cfg80211_vendor_event_alloc failed");
13790 return -ENOMEM;
13791 }
13792
lifengfe6c3e22018-04-03 12:10:04 +080013793 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI,
stonez396a9732019-01-16 12:29:16 +080013794 sizeof(result->chain_rssi),
13795 result->chain_rssi)) {
13796 hdd_err("put fail");
13797 goto nla_put_failure;
13798 }
13799
13800 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_EVM,
13801 sizeof(result->chain_evm),
13802 result->chain_evm)) {
lifengd217d192017-05-09 19:44:16 +080013803 hdd_err("put fail");
13804 goto nla_put_failure;
13805 }
13806
lifengfe6c3e22018-04-03 12:10:04 +080013807 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO,
stonez396a9732019-01-16 12:29:16 +080013808 sizeof(result->ant_id),
13809 result->ant_id)) {
lifengfe6c3e22018-04-03 12:10:04 +080013810 hdd_err("put fail");
13811 goto nla_put_failure;
13812 }
13813
lifengd217d192017-05-09 19:44:16 +080013814 cfg80211_vendor_cmd_reply(skb);
13815 return 0;
13816
13817nla_put_failure:
13818 kfree_skb(skb);
13819 return -EINVAL;
13820}
13821
13822/**
13823 * __wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
13824 * @wiphy: wiphy pointer
13825 * @wdev: pointer to struct wireless_dev
13826 * @data: pointer to incoming NL vendor data
13827 * @data_len: length of @data
13828 *
13829 * Return: 0 on success; error number otherwise.
13830 */
13831static int __wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
13832 struct wireless_dev *wdev,
13833 const void *data,
13834 int data_len)
13835{
Jeff Johnsone5006672017-08-29 14:39:02 -070013836 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013837 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013838 mac_handle_t mac_handle;
lifengd217d192017-05-09 19:44:16 +080013839 struct get_chain_rssi_req_params req_msg;
13840 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
13841 QDF_STATUS status;
13842 int retval;
13843 void *cookie;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013844 struct osif_request *request;
lifengd217d192017-05-09 19:44:16 +080013845 struct chain_rssi_priv *priv;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013846 static const struct osif_request_params params = {
lifengd217d192017-05-09 19:44:16 +080013847 .priv_size = sizeof(*priv),
13848 .timeout_ms = WLAN_WAIT_TIME_STATS,
13849 };
13850
Dustin Brown491d54b2018-03-14 12:39:11 -070013851 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080013852
13853 retval = wlan_hdd_validate_context(hdd_ctx);
13854 if (0 != retval)
13855 return retval;
13856
Dustin Brown4ea21db2018-01-05 14:13:17 -080013857 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
13858 data, data_len, NULL)) {
lifengd217d192017-05-09 19:44:16 +080013859 hdd_err("Invalid ATTR");
13860 return -EINVAL;
13861 }
13862
13863 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
13864 hdd_err("attr mac addr failed");
13865 return -EINVAL;
13866 }
13867 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) !=
13868 QDF_MAC_ADDR_SIZE) {
13869 hdd_err("incorrect mac size");
13870 return -EINVAL;
13871 }
13872 memcpy(&req_msg.peer_macaddr,
13873 nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
13874 QDF_MAC_ADDR_SIZE);
Jeff Johnsoncf07c312019-02-04 13:53:29 -080013875 req_msg.session_id = adapter->vdev_id;
lifengd217d192017-05-09 19:44:16 +080013876
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013877 request = osif_request_alloc(&params);
lifengd217d192017-05-09 19:44:16 +080013878 if (!request) {
13879 hdd_err("Request allocation failure");
13880 return -ENOMEM;
13881 }
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013882 cookie = osif_request_cookie(request);
lifengd217d192017-05-09 19:44:16 +080013883
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013884 mac_handle = hdd_ctx->mac_handle;
13885 status = sme_get_chain_rssi(mac_handle,
13886 &req_msg,
13887 hdd_get_chain_rssi_cb,
13888 cookie);
lifengd217d192017-05-09 19:44:16 +080013889 if (QDF_STATUS_SUCCESS != status) {
13890 hdd_err("Unable to get chain rssi");
13891 retval = qdf_status_to_os_return(status);
13892 } else {
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013893 retval = osif_request_wait_for_response(request);
lifengd217d192017-05-09 19:44:16 +080013894 if (retval) {
13895 hdd_err("Target response timed out");
13896 } else {
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013897 priv = osif_request_priv(request);
lifengd217d192017-05-09 19:44:16 +080013898 retval = hdd_post_get_chain_rssi_rsp(hdd_ctx,
13899 &priv->chain_rssi);
13900 if (retval)
13901 hdd_err("Failed to post chain rssi");
13902 }
13903 }
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070013904 osif_request_put(request);
lifengd217d192017-05-09 19:44:16 +080013905
Dustin Browne74003f2018-03-14 12:51:58 -070013906 hdd_exit();
lifengd217d192017-05-09 19:44:16 +080013907 return retval;
13908}
13909
13910/**
13911 * wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
13912 * @wiphy: wiphy pointer
13913 * @wdev: pointer to struct wireless_dev
13914 * @data: pointer to incoming NL vendor data
13915 * @data_len: length of @data
13916 *
13917 * Return: 0 on success; error number otherwise.
13918 */
13919static int wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
13920 struct wireless_dev *wdev,
13921 const void *data,
13922 int data_len)
13923{
Dustin Browna09acf42018-11-08 12:32:26 +053013924 int errno;
13925 struct osif_vdev_sync *vdev_sync;
13926
13927 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
13928 if (errno)
13929 return errno;
lifengd217d192017-05-09 19:44:16 +080013930
Dustin Browna09acf42018-11-08 12:32:26 +053013931 errno = __wlan_hdd_cfg80211_get_chain_rssi(wiphy, wdev, data, data_len);
lifengd217d192017-05-09 19:44:16 +080013932
Dustin Browna09acf42018-11-08 12:32:26 +053013933 osif_vdev_sync_op_stop(vdev_sync);
13934
13935 return errno;
lifengd217d192017-05-09 19:44:16 +080013936}
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013937
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053013938/**
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053013939 * wlan_hdd_fill_intf_info() - Fill skb buffer with interface info
13940 * @skb: Pointer to skb
13941 * @info: mac mode info
13942 * @index: attribute type index for nla_nest_start()
13943 *
13944 * Return : 0 on success and errno on failure
13945 */
13946static int wlan_hdd_fill_intf_info(struct sk_buff *skb,
13947 struct connection_info *info, int index)
13948{
13949 struct nlattr *attr;
13950 uint32_t freq;
13951 struct hdd_context *hdd_ctx;
13952 struct hdd_adapter *hdd_adapter;
13953
13954 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13955 if (!hdd_ctx)
13956 goto error;
13957
13958 hdd_adapter = hdd_get_adapter_by_vdev(hdd_ctx, info->vdev_id);
13959 if (!hdd_adapter)
13960 goto error;
13961
13962 attr = nla_nest_start(skb, index);
13963 if (!attr)
13964 goto error;
13965
13966 freq = sme_chn_to_freq(info->channel);
13967
13968 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX,
13969 hdd_adapter->dev->ifindex) ||
13970 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ, freq))
13971 goto error;
13972
13973 nla_nest_end(skb, attr);
13974
13975 return 0;
13976error:
13977 hdd_err("Fill buffer with interface info failed");
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053013978 return -EINVAL;
13979}
13980
13981/**
13982 * wlan_hdd_fill_mac_info() - Fill skb buffer with mac info
13983 * @skb: Pointer to skb
13984 * @info: mac mode info
13985 * @mac_id: MAC id
13986 * @conn_count: number of current connections
13987 *
13988 * Return : 0 on success and errno on failure
13989 */
13990static int wlan_hdd_fill_mac_info(struct sk_buff *skb,
13991 struct connection_info *info, uint32_t mac_id,
13992 uint32_t conn_count)
13993{
13994 struct nlattr *attr, *intf_attr;
13995 uint32_t band = 0, i = 0, j = 0;
13996 bool present = false;
13997
13998 while (i < conn_count) {
13999 if (info[i].mac_id == mac_id) {
14000 present = true;
14001 if (info[i].channel <= SIR_11B_CHANNEL_END)
14002 band |= 1 << NL80211_BAND_2GHZ;
14003 else if (info[i].channel <= SIR_11A_CHANNEL_END)
14004 band |= 1 << NL80211_BAND_5GHZ;
14005 }
14006 i++;
14007 }
14008
14009 if (!present)
14010 return 0;
14011
14012 i = 0;
14013 attr = nla_nest_start(skb, mac_id);
14014 if (!attr)
14015 goto error;
14016
14017 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID, mac_id) ||
14018 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND, band))
14019 goto error;
14020
14021 intf_attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO);
14022 if (!intf_attr)
14023 goto error;
14024
14025 while (i < conn_count) {
14026 if (info[i].mac_id == mac_id) {
14027 if (wlan_hdd_fill_intf_info(skb, &info[i], j))
14028 return -EINVAL;
14029 j++;
14030 }
14031 i++;
14032 }
14033
14034 nla_nest_end(skb, intf_attr);
14035
14036 nla_nest_end(skb, attr);
14037
14038 return 0;
14039error:
14040 hdd_err("Fill buffer with mac info failed");
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014041 return -EINVAL;
14042}
14043
14044
14045int wlan_hdd_send_mode_change_event(void)
14046{
14047 int err;
14048 struct hdd_context *hdd_ctx;
14049 struct sk_buff *skb;
14050 struct nlattr *attr;
14051 struct connection_info info[MAX_NUMBER_OF_CONC_CONNECTIONS];
14052 uint32_t conn_count, mac_id;
14053
Dustin Brown491d54b2018-03-14 12:39:11 -070014054 hdd_enter();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014055 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
14056 if (!hdd_ctx) {
14057 hdd_err("HDD context is NULL");
14058 return -EINVAL;
14059 }
14060
14061 err = wlan_hdd_validate_context(hdd_ctx);
14062 if (0 != err)
14063 return err;
14064
Dustin Brown76cd2932018-09-11 16:03:05 -070014065 conn_count = policy_mgr_get_connection_info(hdd_ctx->psoc, info);
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014066 if (!conn_count)
14067 return -EINVAL;
14068
14069 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
14070 (sizeof(uint32_t) * 4) *
14071 MAX_NUMBER_OF_CONC_CONNECTIONS + NLMSG_HDRLEN,
14072 QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX,
14073 GFP_KERNEL);
14074 if (!skb) {
14075 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
14076 return -ENOMEM;
14077 }
14078
14079 attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO);
14080 if (!attr) {
14081 hdd_err("nla_nest_start failed");
14082 kfree_skb(skb);
14083 return -EINVAL;
14084 }
14085
14086 for (mac_id = 0; mac_id < MAX_MAC; mac_id++) {
Lin Baifac77972018-07-05 19:51:49 +080014087 if (wlan_hdd_fill_mac_info(skb, info, mac_id, conn_count)) {
14088 kfree_skb(skb);
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014089 return -EINVAL;
Lin Baifac77972018-07-05 19:51:49 +080014090 }
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014091 }
14092
14093 nla_nest_end(skb, attr);
14094
14095 cfg80211_vendor_event(skb, GFP_KERNEL);
Dustin Browne74003f2018-03-14 12:51:58 -070014096 hdd_exit();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014097
14098 return err;
14099}
14100
Ashish Kumar Dhanotiya1a720e72019-09-06 15:42:05 +053014101
14102/* Short name for QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS command */
14103
14104#define EXTSCAN_CONFIG_MAX \
14105 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
14106#define EXTSCAN_CONFIG_REQUEST_ID \
14107 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
14108#define EXTSCAN_CONFIG_WIFI_BAND \
14109 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND
14110#define ETCAN_CONFIG_MAX_CHANNELS \
14111QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS
14112#define EXTSCAN_RESULTS_NUM_CHANNELS \
14113 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS
14114#define EXTSCAN_RESULTS_CHANNELS \
14115 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS
14116
14117/**
14118 * hdd_remove_dsrc_channels () - remove dsrc chanels
14119 * @hdd_ctx: hdd context
14120 * @wiphy: Pointer to wireless phy
14121 * @chan_list: channel list
14122 * @num_channels: number of channels
14123 *
14124 * Return: none
14125 */
14126static void hdd_remove_dsrc_channels(struct hdd_context *hdd_ctx,
14127 struct wiphy *wiphy, uint32_t *chan_list,
14128 uint8_t *num_channels)
14129{
14130 uint8_t num_chan_temp = 0;
14131 int i;
14132
14133 for (i = 0; i < *num_channels; i++) {
14134 if (!wlan_reg_is_dsrc_chan(hdd_ctx->pdev,
14135 wlan_reg_freq_to_chan(
14136 hdd_ctx->pdev,
14137 chan_list[i]))) {
14138 chan_list[num_chan_temp] = chan_list[i];
14139 num_chan_temp++;
14140 }
14141 }
14142 *num_channels = num_chan_temp;
14143}
14144
14145/**
14146 * hdd_remove_passive_channels () - remove passive channels
14147 * @wiphy: Pointer to wireless phy
14148 * @chan_list: channel list
14149 * @num_channels: number of channels
14150 *
14151 * Return: none
14152 */
14153static void hdd_remove_passive_channels(struct wiphy *wiphy,
14154 uint32_t *chan_list,
14155 uint8_t *num_channels)
14156{
14157 uint8_t num_chan_temp = 0;
14158 int i, j, k;
14159
14160 for (i = 0; i < *num_channels; i++)
14161 for (j = 0; j < HDD_NUM_NL80211_BANDS; j++) {
14162 if (!wiphy->bands[j])
14163 continue;
14164 for (k = 0; k < wiphy->bands[j]->n_channels; k++) {
14165 if ((chan_list[i] ==
14166 wiphy->bands[j]->channels[k].center_freq)
14167 && (!(wiphy->bands[j]->channels[k].flags &
14168 IEEE80211_CHAN_PASSIVE_SCAN))
14169 ) {
14170 chan_list[num_chan_temp] = chan_list[i];
14171 num_chan_temp++;
14172 }
14173 }
14174 }
14175
14176 *num_channels = num_chan_temp;
14177}
14178
14179/**
14180 * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels
14181 * @wiphy: Pointer to wireless phy
14182 * @wdev: Pointer to wireless device
14183 * @data: Pointer to data
14184 * @data_len: Data length
14185 *
14186 * Return: none
14187 */
14188static int
14189__wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
14190 struct wireless_dev
14191 *wdev, const void *data,
14192 int data_len)
14193{
14194 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
14195 struct net_device *dev = wdev->netdev;
14196 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14197 uint32_t chan_list[CFG_VALID_CHANNEL_LIST_LEN] = {0};
14198 uint8_t num_channels = 0, i, buf[256] = {0};
14199 struct nlattr *tb[EXTSCAN_CONFIG_MAX +
14200 1];
14201 uint32_t requestId, maxChannels;
14202 tWifiBand wifi_band;
14203 QDF_STATUS status;
14204 struct sk_buff *reply_skb;
14205 int ret, len = 0;
14206
14207 /* ENTER_DEV() intentionally not used in a frequently invoked API */
14208
14209 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
14210 hdd_err("Command not allowed in FTM mode");
14211 return -EPERM;
14212 }
14213
14214 ret = wlan_hdd_validate_context(hdd_ctx);
14215 if (0 != ret)
14216 return -EINVAL;
14217
14218 if (wlan_cfg80211_nla_parse(
14219 tb,
14220 EXTSCAN_CONFIG_MAX,
14221 data, data_len, wlan_hdd_extscan_config_policy)) {
14222 hdd_err("Invalid ATTR");
14223 return -EINVAL;
14224 }
14225
14226 /* Parse and fetch request Id */
14227 if (!tb[EXTSCAN_CONFIG_REQUEST_ID]) {
14228 hdd_err("attr request id failed");
14229 return -EINVAL;
14230 }
14231 requestId =
14232 nla_get_u32(tb
14233 [EXTSCAN_CONFIG_REQUEST_ID]);
14234
14235 /* Parse and fetch wifi band */
14236 if (!tb
14237 [EXTSCAN_CONFIG_WIFI_BAND]) {
14238 hdd_err("attr wifi band failed");
14239 return -EINVAL;
14240 }
14241 wifi_band =
14242 nla_get_u32(tb
14243 [EXTSCAN_CONFIG_WIFI_BAND]);
14244 if (!tb
14245 [ETCAN_CONFIG_MAX_CHANNELS]) {
14246 hdd_err("attr max channels failed");
14247 return -EINVAL;
14248 }
14249 maxChannels =
14250 nla_get_u32(tb
14251 [ETCAN_CONFIG_MAX_CHANNELS]);
14252
14253 if (maxChannels > CFG_VALID_CHANNEL_LIST_LEN) {
14254 hdd_err("Max channels %d exceeded Valid channel list len %d",
14255 maxChannels, CFG_VALID_CHANNEL_LIST_LEN);
14256 return -EINVAL;
14257 }
14258
14259 hdd_err("Req Id: %u Wifi band: %d Max channels: %d", requestId,
14260 wifi_band, maxChannels);
14261 status = sme_get_valid_channels_by_band(hdd_ctx->mac_handle,
14262 wifi_band, chan_list,
14263 &num_channels);
14264 if (QDF_STATUS_SUCCESS != status) {
14265 hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
14266 status);
14267 return -EINVAL;
14268 }
14269
14270 num_channels = QDF_MIN(num_channels, maxChannels);
14271
14272 hdd_remove_dsrc_channels(hdd_ctx, wiphy, chan_list, &num_channels);
14273 if ((QDF_SAP_MODE == adapter->device_mode) ||
14274 !strncmp(hdd_get_fwpath(), "ap", 2))
14275 hdd_remove_passive_channels(wiphy, chan_list,
14276 &num_channels);
14277
14278 hdd_debug("Number of channels: %d", num_channels);
14279 for (i = 0; i < num_channels; i++)
14280 len += scnprintf(buf + len, sizeof(buf) - len,
14281 "%u ", chan_list[i]);
14282
14283 hdd_debug("Channels: %s", buf);
14284
14285 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
14286 sizeof(u32) *
14287 num_channels +
14288 NLMSG_HDRLEN);
14289
14290 if (reply_skb) {
14291 if (nla_put_u32(
14292 reply_skb,
14293 EXTSCAN_RESULTS_NUM_CHANNELS,
14294 num_channels) ||
14295 nla_put(
14296 reply_skb,
14297 EXTSCAN_RESULTS_CHANNELS,
14298 sizeof(u32) * num_channels, chan_list)) {
14299 hdd_err("nla put fail");
14300 kfree_skb(reply_skb);
14301 return -EINVAL;
14302 }
14303 ret = cfg80211_vendor_cmd_reply(reply_skb);
14304 return ret;
14305 }
14306
14307 hdd_err("valid channels: buffer alloc fail");
14308 return -EINVAL;
14309}
14310
14311#undef EXTSCAN_CONFIG_MAX
14312#undef EXTSCAN_CONFIG_REQUEST_ID
14313#undef EXTSCAN_CONFIG_WIFI_BAND
14314#undef ETCAN_CONFIG_MAX_CHANNELS
14315#undef EXTSCAN_RESULTS_NUM_CHANNELS
14316#undef EXTSCAN_RESULTS_CHANNELS
14317
14318/**
14319 * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
14320 * @wiphy: Pointer to wireless phy
14321 * @wdev: Pointer to wireless device
14322 * @data: Pointer to data
14323 * @data_len: Data length
14324 *
14325 * Return: 0 on success, negative errno on failure
14326 */
14327static int wlan_hdd_cfg80211_extscan_get_valid_channels(
14328 struct wiphy *wiphy,
14329 struct wireless_dev *wdev,
14330 const void *data, int data_len)
14331{
14332 struct osif_psoc_sync *psoc_sync;
14333 int errno;
14334
14335 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
14336 if (errno)
14337 return errno;
14338
14339 errno = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev,
14340 data, data_len);
14341
14342 osif_psoc_sync_op_stop(psoc_sync);
14343
14344 return errno;
14345}
14346
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
14348 {
14349 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14350 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
14351 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +053014352 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014353 .doit = is_driver_dfs_capable
14354 },
Ashish Kumar Dhanotiya1a720e72019-09-06 15:42:05 +053014355 {
14356 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14357 .info.subcmd =
14358 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
14359 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14360 WIPHY_VENDOR_CMD_NEED_NETDEV |
14361 WIPHY_VENDOR_CMD_NEED_RUNNING,
14362 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
14363 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014364#ifdef WLAN_FEATURE_STATS_EXT
14365 {
14366 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14367 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
14368 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14369 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14370 .doit = wlan_hdd_cfg80211_stats_ext_request
14371 },
14372#endif
14373#ifdef FEATURE_WLAN_EXTSCAN
14374 {
14375 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14376 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
14377 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14378 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14379 .doit = wlan_hdd_cfg80211_extscan_start
14380 },
14381 {
14382 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14383 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
14384 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14385 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14386 .doit = wlan_hdd_cfg80211_extscan_stop
14387 },
14388 {
14389 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014390 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
14391 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14392 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14393 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
14394 },
14395 {
14396 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14397 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
14398 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14399 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14400 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
14401 },
14402 {
14403 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14404 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
14405 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14406 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14407 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
14408 },
14409 {
14410 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14411 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
14412 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14413 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14414 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
14415 },
14416 {
14417 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14418 .info.subcmd =
14419 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
14420 .flags =
14421 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
14422 WIPHY_VENDOR_CMD_NEED_RUNNING,
14423 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
14424 },
14425 {
14426 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14427 .info.subcmd =
14428 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
14429 .flags =
14430 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
14431 WIPHY_VENDOR_CMD_NEED_RUNNING,
14432 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
14433 },
14434 {
14435 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14436 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
14437 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14438 WIPHY_VENDOR_CMD_NEED_NETDEV |
14439 WIPHY_VENDOR_CMD_NEED_RUNNING,
14440 .doit = wlan_hdd_cfg80211_set_epno_list
14441 },
14442#endif /* FEATURE_WLAN_EXTSCAN */
14443
14444#ifdef WLAN_FEATURE_LINK_LAYER_STATS
14445 {
14446 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14447 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
14448 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14449 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14450 .doit = wlan_hdd_cfg80211_ll_stats_clear
14451 },
14452
14453 {
14454 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14455 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
14456 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14457 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14458 .doit = wlan_hdd_cfg80211_ll_stats_set
14459 },
14460
14461 {
14462 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14463 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
14464 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14465 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14466 .doit = wlan_hdd_cfg80211_ll_stats_get
14467 },
14468#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
14469#ifdef FEATURE_WLAN_TDLS
14470 {
14471 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14472 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
14473 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14474 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14475 .doit = wlan_hdd_cfg80211_exttdls_enable
14476 },
14477 {
14478 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14479 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
14480 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14481 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14482 .doit = wlan_hdd_cfg80211_exttdls_disable
14483 },
14484 {
14485 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14486 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
14487 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
14488 .doit = wlan_hdd_cfg80211_exttdls_get_status
14489 },
14490#endif
14491 {
14492 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14493 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
14494 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
14495 .doit = wlan_hdd_cfg80211_get_supported_features
14496 },
14497 {
14498 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14499 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014500 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14501 WIPHY_VENDOR_CMD_NEED_NETDEV |
14502 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014503 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
14504 },
Qiwei Caie689a262018-07-26 15:50:22 +080014505
14506 FEATURE_CONCURRENCY_MATRIX_VENDOR_COMMANDS
14507
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014508 {
14509 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14510 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
14511 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014512 WIPHY_VENDOR_CMD_NEED_NETDEV |
14513 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014514 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
14515 },
Manikandan Mohan80dea792016-04-28 16:36:48 -070014516 {
14517 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14518 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
14519 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014520 WIPHY_VENDOR_CMD_NEED_NETDEV |
14521 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -070014522 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
14523 },
Qiwei Caie689a262018-07-26 15:50:22 +080014524
14525 FEATURE_STATION_INFO_VENDOR_COMMANDS
14526
Anurag Chouhan96919482016-07-13 16:36:57 +053014527 {
14528 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014529 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
14530 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14531 WIPHY_VENDOR_CMD_NEED_NETDEV |
14532 WIPHY_VENDOR_CMD_NEED_RUNNING,
14533 .doit = wlan_hdd_cfg80211_do_acs
14534 },
14535
14536 {
14537 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14538 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
14539 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14540 WIPHY_VENDOR_CMD_NEED_NETDEV,
14541 .doit = wlan_hdd_cfg80211_get_features
14542 },
14543#ifdef WLAN_FEATURE_ROAM_OFFLOAD
14544 {
14545 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14546 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
14547 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14548 WIPHY_VENDOR_CMD_NEED_NETDEV |
14549 WIPHY_VENDOR_CMD_NEED_RUNNING,
14550 .doit = wlan_hdd_cfg80211_keymgmt_set_key
14551 },
14552#endif
14553#ifdef FEATURE_WLAN_EXTSCAN
14554 {
14555 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14556 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
14557 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14558 WIPHY_VENDOR_CMD_NEED_NETDEV |
14559 WIPHY_VENDOR_CMD_NEED_RUNNING,
14560 .doit = wlan_hdd_cfg80211_set_passpoint_list
14561 },
14562 {
14563 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14564 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
14565 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14566 WIPHY_VENDOR_CMD_NEED_NETDEV |
14567 WIPHY_VENDOR_CMD_NEED_RUNNING,
14568 .doit = wlan_hdd_cfg80211_reset_passpoint_list
14569 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014570#endif /* FEATURE_WLAN_EXTSCAN */
14571 {
14572 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14573 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
14574 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14575 WIPHY_VENDOR_CMD_NEED_NETDEV,
14576 .doit = wlan_hdd_cfg80211_get_wifi_info
14577 },
14578 {
14579 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14580 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
14581 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14582 WIPHY_VENDOR_CMD_NEED_NETDEV |
14583 WIPHY_VENDOR_CMD_NEED_RUNNING,
14584 .doit = wlan_hdd_cfg80211_wifi_configuration_set
14585 },
14586 {
14587 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Paul Zhangc9dbaee2019-06-23 22:07:31 +080014588 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION,
14589 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14590 WIPHY_VENDOR_CMD_NEED_NETDEV |
14591 WIPHY_VENDOR_CMD_NEED_RUNNING,
14592 .doit = wlan_hdd_cfg80211_wifi_configuration_get
14593 },
14594 {
14595 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -080014596 .info.subcmd =
14597 QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION,
14598 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14599 WIPHY_VENDOR_CMD_NEED_NETDEV |
14600 WIPHY_VENDOR_CMD_NEED_RUNNING,
14601 .doit = wlan_hdd_cfg80211_set_wifi_test_config
14602 },
14603
14604 {
14605 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014606 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
14607 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014608 WIPHY_VENDOR_CMD_NEED_NETDEV |
14609 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014610 .doit = wlan_hdd_cfg80211_set_ext_roam_params
14611 },
14612 {
14613 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14614 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
14615 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014616 WIPHY_VENDOR_CMD_NEED_NETDEV |
14617 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014618 .doit = wlan_hdd_cfg80211_wifi_logger_start
14619 },
14620 {
14621 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14622 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
Karthik Kantamneni0b95f9e2019-11-21 13:03:22 +053014623 .flags = WIPHY_VENDOR_CMD_NEED_WDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014624 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
14625 },
14626 {
14627 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14628 .info.subcmd =
14629 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
14630 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14631 WIPHY_VENDOR_CMD_NEED_NETDEV |
14632 WIPHY_VENDOR_CMD_NEED_RUNNING,
14633 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
14634 },
14635 {
14636 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14637 .info.subcmd =
14638 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
14639 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14640 WIPHY_VENDOR_CMD_NEED_NETDEV |
14641 WIPHY_VENDOR_CMD_NEED_RUNNING,
14642 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
14643 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070014644#ifdef WLAN_FEATURE_TSF
14645 {
14646 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14647 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
14648 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14649 WIPHY_VENDOR_CMD_NEED_NETDEV |
14650 WIPHY_VENDOR_CMD_NEED_RUNNING,
14651 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
14652 },
14653#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014654#ifdef FEATURE_WLAN_TDLS
14655 {
14656 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14657 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
14658 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14659 WIPHY_VENDOR_CMD_NEED_NETDEV |
14660 WIPHY_VENDOR_CMD_NEED_RUNNING,
14661 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
14662 },
14663#endif
14664#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
14665 {
14666 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14667 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
14668 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14669 WIPHY_VENDOR_CMD_NEED_NETDEV |
14670 WIPHY_VENDOR_CMD_NEED_RUNNING,
14671 .doit = wlan_hdd_cfg80211_offloaded_packets
14672 },
14673#endif
Qiwei Caie689a262018-07-26 15:50:22 +080014674 FEATURE_RSSI_MONITOR_VENDOR_COMMANDS
Paul Zhangda2970b2019-06-23 18:16:38 +080014675 FEATURE_OEM_DATA_VENDOR_COMMANDS
Paul Zhang37185672019-05-14 11:20:14 +080014676 FEATURE_INTEROP_ISSUES_AP_VENDOR_COMMANDS
Qiwei Caie689a262018-07-26 15:50:22 +080014677
Qiwei Cai1083f5b2018-07-02 19:10:11 +080014678#ifdef WLAN_NS_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014679 {
14680 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053014681 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
14682 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14683 WIPHY_VENDOR_CMD_NEED_NETDEV |
14684 WIPHY_VENDOR_CMD_NEED_RUNNING,
14685 .doit = wlan_hdd_cfg80211_set_ns_offload
14686 },
Qiwei Cai1083f5b2018-07-02 19:10:11 +080014687#endif /* WLAN_NS_OFFLOAD */
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053014688 {
14689 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014690 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
14691 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Sourav Mohapatra412ceb92018-03-07 18:41:16 +053014692 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014693 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
14694 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014695 {
14696 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14697 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
14698 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14699 WIPHY_VENDOR_CMD_NEED_NETDEV |
14700 WIPHY_VENDOR_CMD_NEED_RUNNING,
14701 .doit = wlan_hdd_cfg80211_vendor_scan
14702 },
14703
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014704 /* Vendor abort scan */
14705 {
14706 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14707 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
14708 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14709 WIPHY_VENDOR_CMD_NEED_NETDEV |
14710 WIPHY_VENDOR_CMD_NEED_RUNNING,
14711 .doit = wlan_hdd_vendor_abort_scan
14712 },
14713
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014714 /* OCB commands */
14715 {
14716 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14717 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
14718 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14719 WIPHY_VENDOR_CMD_NEED_NETDEV |
14720 WIPHY_VENDOR_CMD_NEED_RUNNING,
14721 .doit = wlan_hdd_cfg80211_ocb_set_config
14722 },
14723 {
14724 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14725 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
14726 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14727 WIPHY_VENDOR_CMD_NEED_NETDEV |
14728 WIPHY_VENDOR_CMD_NEED_RUNNING,
14729 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
14730 },
14731 {
14732 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14733 .info.subcmd =
14734 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
14735 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14736 WIPHY_VENDOR_CMD_NEED_NETDEV |
14737 WIPHY_VENDOR_CMD_NEED_RUNNING,
14738 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
14739 },
14740 {
14741 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14742 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
14743 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14744 WIPHY_VENDOR_CMD_NEED_NETDEV |
14745 WIPHY_VENDOR_CMD_NEED_RUNNING,
14746 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
14747 },
14748 {
14749 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14750 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
14751 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14752 WIPHY_VENDOR_CMD_NEED_NETDEV |
14753 WIPHY_VENDOR_CMD_NEED_RUNNING,
14754 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
14755 },
14756 {
14757 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14758 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
14759 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14760 WIPHY_VENDOR_CMD_NEED_NETDEV |
14761 WIPHY_VENDOR_CMD_NEED_RUNNING,
14762 .doit = wlan_hdd_cfg80211_dcc_get_stats
14763 },
14764 {
14765 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14766 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
14767 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14768 WIPHY_VENDOR_CMD_NEED_NETDEV |
14769 WIPHY_VENDOR_CMD_NEED_RUNNING,
14770 .doit = wlan_hdd_cfg80211_dcc_clear_stats
14771 },
14772 {
14773 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14774 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
14775 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14776 WIPHY_VENDOR_CMD_NEED_NETDEV |
14777 WIPHY_VENDOR_CMD_NEED_RUNNING,
14778 .doit = wlan_hdd_cfg80211_dcc_update_ndl
14779 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053014780 {
14781 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14782 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
14783 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14784 WIPHY_VENDOR_CMD_NEED_NETDEV |
14785 WIPHY_VENDOR_CMD_NEED_RUNNING,
14786 .doit = wlan_hdd_cfg80211_get_link_properties
14787 },
Qiwei Caie689a262018-07-26 15:50:22 +080014788
14789 FEATURE_OTA_TEST_VENDOR_COMMANDS
14790
Ravi Joshideb5a8d2015-11-09 19:11:43 -080014791#ifdef FEATURE_LFR_SUBNET_DETECTION
14792 {
14793 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14794 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
14795 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14796 WIPHY_VENDOR_CMD_NEED_NETDEV |
14797 WIPHY_VENDOR_CMD_NEED_RUNNING,
14798 .doit = wlan_hdd_cfg80211_set_gateway_params
14799 },
14800#endif /* FEATURE_LFR_SUBNET_DETECTION */
Qiwei Caie689a262018-07-26 15:50:22 +080014801
14802 FEATURE_TX_POWER_VENDOR_COMMANDS
14803
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053014804#ifdef FEATURE_WLAN_APF
Arun Khandavalli2476ef52016-04-26 20:19:43 +053014805 {
14806 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14807 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
14808 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14809 WIPHY_VENDOR_CMD_NEED_NETDEV |
14810 WIPHY_VENDOR_CMD_NEED_RUNNING,
Nachiket Kukadee547a482018-05-22 16:43:30 +053014811 .doit = wlan_hdd_cfg80211_apf_offload
Arun Khandavalli2476ef52016-04-26 20:19:43 +053014812 },
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053014813#endif /* FEATURE_WLAN_APF */
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053014814 {
14815 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053014816 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
14817 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14818 WIPHY_VENDOR_CMD_NEED_NETDEV |
14819 WIPHY_VENDOR_CMD_NEED_RUNNING,
14820 .doit = wlan_hdd_cfg80211_acs_dfs_mode
14821 },
14822 {
14823 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053014824 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
14825 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14826 WIPHY_VENDOR_CMD_NEED_NETDEV |
14827 WIPHY_VENDOR_CMD_NEED_RUNNING,
14828 .doit = wlan_hdd_cfg80211_sta_roam_policy
14829 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053014830#ifdef FEATURE_WLAN_CH_AVOID
14831 {
14832 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14833 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
14834 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14835 WIPHY_VENDOR_CMD_NEED_NETDEV |
14836 WIPHY_VENDOR_CMD_NEED_RUNNING,
14837 .doit = wlan_hdd_cfg80211_avoid_freq
14838 },
14839#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053014840 {
14841 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053014842 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
14843 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14844 WIPHY_VENDOR_CMD_NEED_NETDEV |
14845 WIPHY_VENDOR_CMD_NEED_RUNNING,
14846 .doit = wlan_hdd_cfg80211_sap_configuration_set
14847 },
Qiwei Caie689a262018-07-26 15:50:22 +080014848
14849 FEATURE_P2P_LISTEN_OFFLOAD_VENDOR_COMMANDS
14850
14851 FEATURE_SAP_COND_CHAN_SWITCH_VENDOR_COMMANDS
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053014852 {
14853 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14854 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
14855 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14856 WIPHY_VENDOR_CMD_NEED_NETDEV |
14857 WIPHY_VENDOR_CMD_NEED_RUNNING,
14858 .doit = wlan_hdd_cfg80211_get_wakelock_stats
14859 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053014860 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053014861 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14862 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
14863 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14864 WIPHY_VENDOR_CMD_NEED_NETDEV |
14865 WIPHY_VENDOR_CMD_NEED_RUNNING,
14866 .doit = wlan_hdd_cfg80211_get_bus_size
14867 },
14868 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053014869 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14870 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
14871 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14872 WIPHY_VENDOR_CMD_NEED_NETDEV |
14873 WIPHY_VENDOR_CMD_NEED_RUNNING,
14874 .doit = wlan_hdd_cfg80211_update_vendor_channel
14875 },
14876 {
bingsd09dea32017-03-17 10:08:26 +080014877 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053014878 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
14879 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14880 WIPHY_VENDOR_CMD_NEED_NETDEV |
14881 WIPHY_VENDOR_CMD_NEED_RUNNING,
14882 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053014883 },
14884 {
14885 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14886 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
14887 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14888 WIPHY_VENDOR_CMD_NEED_NETDEV |
14889 WIPHY_VENDOR_CMD_NEED_RUNNING,
14890 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053014891 },
14892#ifdef WLAN_FEATURE_DISA
14893 {
14894 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14895 .info.subcmd =
14896 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
14897 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14898 WIPHY_VENDOR_CMD_NEED_NETDEV |
14899 WIPHY_VENDOR_CMD_NEED_RUNNING,
14900 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
14901 },
14902#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070014903#ifdef FEATURE_WLAN_TDLS
14904 {
14905 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14906 .info.subcmd =
14907 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
14908 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14909 WIPHY_VENDOR_CMD_NEED_NETDEV |
14910 WIPHY_VENDOR_CMD_NEED_RUNNING,
14911 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080014912 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070014913#endif
Qiwei Caie689a262018-07-26 15:50:22 +080014914 FEATURE_SAR_LIMITS_VENDOR_COMMANDS
Abhinav Kumardbbfd2c2019-05-07 12:22:06 +053014915 BCN_RECV_FEATURE_VENDOR_COMMANDS
Qiwei Caie689a262018-07-26 15:50:22 +080014916
Jeff Johnson8c83f132017-12-18 16:41:37 -080014917 {
14918 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080014919 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
14920 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14921 WIPHY_VENDOR_CMD_NEED_RUNNING,
14922 .doit = wlan_hdd_cfg80211_set_sar_power_limits
14923 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053014924 {
14925 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14926 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
14927 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14928 WIPHY_VENDOR_CMD_NEED_NETDEV |
14929 WIPHY_VENDOR_CMD_NEED_RUNNING,
14930 .doit = wlan_hdd_cfg80211_set_trace_level
14931 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080014932 {
14933 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14934 .info.subcmd =
14935 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
14936 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14937 WIPHY_VENDOR_CMD_NEED_NETDEV |
14938 WIPHY_VENDOR_CMD_NEED_RUNNING,
14939 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
14940 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053014941 {
14942 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14943 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET,
14944 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14945 WIPHY_VENDOR_CMD_NEED_NETDEV |
14946 WIPHY_VENDOR_CMD_NEED_RUNNING,
14947 .doit = wlan_hdd_cfg80211_set_nud_stats
14948 },
14949 {
14950 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14951 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
14952 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14953 WIPHY_VENDOR_CMD_NEED_NETDEV |
14954 WIPHY_VENDOR_CMD_NEED_RUNNING,
14955 .doit = wlan_hdd_cfg80211_get_nud_stats
14956 },
Qiwei Caie689a262018-07-26 15:50:22 +080014957
14958 FEATURE_BSS_TRANSITION_VENDOR_COMMANDS
Sandeep Puligilla063a4342018-01-10 02:50:14 -080014959 FEATURE_SPECTRAL_SCAN_VENDOR_COMMANDS
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080014960 FEATURE_11AX_VENDOR_COMMANDS
lifengd217d192017-05-09 19:44:16 +080014961
14962 {
14963 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14964 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI,
14965 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14966 WIPHY_VENDOR_CMD_NEED_NETDEV |
14967 WIPHY_VENDOR_CMD_NEED_RUNNING,
14968 .doit = wlan_hdd_cfg80211_get_chain_rssi
14969 },
Qiwei Caie689a262018-07-26 15:50:22 +080014970
14971 FEATURE_ACTIVE_TOS_VENDOR_COMMANDS
Nachiket Kukadea6a70a92018-10-09 20:07:21 +053014972 FEATURE_NAN_VENDOR_COMMANDS
Qun Zhangef655622019-02-25 10:48:10 +080014973 FEATURE_FW_STATE_COMMANDS
Jiani Liua5f17222019-03-04 16:22:33 +080014974 FEATURE_COEX_CONFIG_COMMANDS
stonez2d686482019-03-12 14:54:26 +080014975 FEATURE_MPTA_HELPER_COMMANDS
guangde4853c402019-05-06 15:54:04 +080014976 FEATURE_HW_CAPABILITY_COMMANDS
Pankaj Singh50e40422020-01-09 15:29:35 +053014977 FEATURE_THERMAL_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014978};
14979
Dustin Brown92bd8382018-10-31 15:49:46 -070014980struct hdd_context *hdd_cfg80211_wiphy_alloc(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014981{
14982 struct wiphy *wiphy;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070014983 struct hdd_context *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080014984
Dustin Brown491d54b2018-03-14 12:39:11 -070014985 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014986
Dustin Brown92bd8382018-10-31 15:49:46 -070014987 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, sizeof(*hdd_ctx));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014988 if (!wiphy) {
Dustin Brown92bd8382018-10-31 15:49:46 -070014989 hdd_err("failed to allocate wiphy!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014990 return NULL;
14991 }
14992
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080014993 hdd_ctx = wiphy_priv(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080014994 hdd_ctx->wiphy = wiphy;
14995
14996 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014997}
14998
Jeff Johnson459d2732019-03-02 10:13:25 -080014999int wlan_hdd_cfg80211_update_band(struct hdd_context *hdd_ctx,
15000 struct wiphy *wiphy,
15001 enum band_info new_band)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015002{
15003 int i, j;
Jeff Johnson9cb757b2019-03-11 15:29:02 -070015004 enum channel_state channel_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015005
Dustin Brown491d54b2018-03-14 12:39:11 -070015006 hdd_enter();
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070015007
15008 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015009
Jeff Johnsond36fa332019-03-18 13:42:25 -070015010 if (!wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015011 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015012
15013 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
15014 struct ieee80211_supported_band *band = wiphy->bands[i];
15015
Jeff Johnson9cb757b2019-03-11 15:29:02 -070015016 channel_state = wlan_reg_get_channel_state(
Dustin Brown07901ec2018-09-07 11:02:41 -070015017 hdd_ctx->pdev,
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070015018 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015019
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015020 if (HDD_NL80211_BAND_2GHZ == i &&
Jeff Johnson459d2732019-03-02 10:13:25 -080015021 BAND_5G == new_band) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015022 /* 5G only */
15023#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
15024 /* Enable Social channels for P2P */
15025 if (WLAN_HDD_IS_SOCIAL_CHANNEL
15026 (band->channels[j].center_freq)
15027 && CHANNEL_STATE_ENABLE ==
Jeff Johnson9cb757b2019-03-11 15:29:02 -070015028 channel_state)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015029 band->channels[j].flags &=
15030 ~IEEE80211_CHAN_DISABLED;
15031 else
15032#endif
15033 band->channels[j].flags |=
15034 IEEE80211_CHAN_DISABLED;
15035 continue;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015036 } else if (HDD_NL80211_BAND_5GHZ == i &&
Jeff Johnson459d2732019-03-02 10:13:25 -080015037 BAND_2G == new_band) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015038 /* 2G only */
15039 band->channels[j].flags |=
15040 IEEE80211_CHAN_DISABLED;
15041 continue;
15042 }
15043
Jeff Johnson9cb757b2019-03-11 15:29:02 -070015044 if (CHANNEL_STATE_DISABLE != channel_state)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015045 band->channels[j].flags &=
15046 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015047 }
15048 }
15049 return 0;
15050}
15051
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053015052#if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \
15053 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
15054static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
15055{
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +053015056 wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
15057 wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053015058}
15059#else
15060static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
15061{
15062}
15063#endif
15064
Peng Xuacfdda12017-02-06 16:15:38 -080015065#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053015066
Liangwei Dong3abfe8f2018-09-20 02:25:44 -040015067#if defined(CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME) || \
15068 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
15069/**
15070 * wlan_hdd_cfg80211_action_frame_randomization_init() - Randomize SA of MA
15071 * frames
15072 * @wiphy: Pointer to wiphy
15073 *
15074 * This function is used to indicate the support of source mac address
15075 * randomization of management action frames
15076 *
15077 * Return: None
15078 */
15079static void
15080wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
15081{
15082 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA);
15083}
15084#else
15085static void
15086wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
15087{
15088}
15089#endif
15090
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053015091#if defined(WLAN_FEATURE_FILS_SK) && \
15092 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
15093 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015094static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
15095{
15096 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
15097}
15098#else
15099static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
15100{
15101}
15102#endif
15103
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053015104#if defined (CFG80211_SCAN_DBS_CONTROL_SUPPORT) || \
15105 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
15106static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
15107{
15108 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
15109 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
15110 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
15111}
15112#else
15113static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
15114{
15115}
15116#endif
15117
Veerendranath Jakkam62fedb92019-03-20 16:32:17 +053015118#if defined(CFG80211_SCAN_OCE_CAPABILITY_SUPPORT) || \
15119 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
15120static void wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy *wiphy)
15121{
15122 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME);
15123 wiphy_ext_feature_set(wiphy,
15124 NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP);
15125 wiphy_ext_feature_set(wiphy,
15126 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE);
15127 wiphy_ext_feature_set(
15128 wiphy, NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION);
15129}
15130#else
15131static void wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy *wiphy)
15132{
15133}
15134#endif
15135
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053015136#if defined(WLAN_FEATURE_SAE) && \
15137 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015138/**
15139 * wlan_hdd_cfg80211_set_wiphy_sae_feature() - Indicates support of SAE feature
15140 * @wiphy: Pointer to wiphy
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015141 *
15142 * This function is used to indicate the support of SAE
15143 *
15144 * Return: None
15145 */
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080015146static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015147{
Manikandan Mohand350c192018-11-29 14:01:12 -080015148 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Manikandan Mohand350c192018-11-29 14:01:12 -080015149
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080015150 if (ucfg_fwol_get_sae_enable(hdd_ctx->psoc))
Manikandan Mohan5dba1c72019-01-07 16:57:03 -080015151 wiphy->features |= NL80211_FEATURE_SAE;
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015152}
15153#else
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080015154static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015155{
15156}
15157#endif
15158
Peng Xu8e8b0392018-04-30 11:32:34 -070015159#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
15160 defined(CFG80211_DFS_OFFLOAD_BACKPORT)
15161static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
15162{
15163 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
15164}
15165#else
15166static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
15167{
15168 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
15169}
15170#endif
15171
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070015172#ifdef WLAN_FEATURE_DSRC
15173static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
15174 int *num_ch, int *ch_len)
15175{
15176 *num_ch = QDF_ARRAY_SIZE(hdd_channels_dot11p);
15177 *ch_len = sizeof(hdd_channels_dot11p);
15178}
15179
15180static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
15181{
15182 if (!ch_arr_len)
15183 return;
15184 qdf_mem_copy(ch_ptr, &hdd_channels_dot11p[0], ch_arr_len);
15185}
15186
15187static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
15188 int *num_ch, int *ch_len)
15189{
15190 *num_ch = 0;
15191 *ch_len = 0;
15192}
15193
15194static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
15195{
15196}
15197
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053015198/**
15199 * wlan_hdd_populate_srd_chan_info() - Populate SRD chan info in hdd context
15200 * @hdd_ctx: pointer to hdd context
15201 * @index: SRD channel beginning index in chan_info of @hdd_ctx
15202 *
15203 * Return: Number of SRD channels populated
15204 */
15205static uint32_t
15206wlan_hdd_populate_srd_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
15207{
15208 return 0;
15209}
15210
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070015211#else
15212
15213static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
15214 int *num_ch, int *ch_len)
15215{
15216 *num_ch = 0;
15217 *ch_len = 0;
15218}
15219
15220static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
15221{
15222}
15223
15224static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
15225 int *num_ch, int *ch_len)
15226{
15227 *num_ch = QDF_ARRAY_SIZE(hdd_etsi13_srd_ch);
15228 *ch_len = sizeof(hdd_etsi13_srd_ch);
15229}
15230
15231static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
15232{
15233 if (!ch_arr_len)
15234 return;
15235 qdf_mem_copy(ch_ptr, &hdd_etsi13_srd_ch[0], ch_arr_len);
15236}
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053015237
15238/**
15239 * wlan_hdd_populate_srd_chan_info() - Populate SRD chan info in hdd context
15240 * @hdd_ctx: pointer to hdd context
15241 * @index: SRD channel beginning index in chan_info of @hdd_ctx
15242 *
15243 * Return: Number of SRD channels populated
15244 */
15245static uint32_t
15246wlan_hdd_populate_srd_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
15247{
15248 uint32_t num_srd_ch, i;
15249 struct scan_chan_info *chan_info;
15250
15251 num_srd_ch = QDF_ARRAY_SIZE(hdd_etsi13_srd_ch);
15252 chan_info = hdd_ctx->chan_info;
15253
15254 for (i = 0; i < num_srd_ch; i++)
15255 chan_info[index + i].freq = hdd_etsi13_srd_ch[i].center_freq;
15256
15257 return num_srd_ch;
15258}
15259
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070015260#endif
15261
bings3d9cd952019-12-23 17:41:52 +080015262#if (defined(CONFIG_BAND_6GHZ) && defined(CFG80211_6GHZ_BAND_SUPPORTED)) || \
15263 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
gaurank kathpalia54bc4a32019-12-05 20:43:15 +053015264#if defined(CONFIG_BAND_6GHZ) && (defined(CFG80211_6GHZ_BAND_SUPPORTED) || \
15265 (KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE))
15266static QDF_STATUS
15267wlan_hdd_iftype_data_alloc_6ghz(struct hdd_context *hdd_ctx)
15268{
15269 hdd_ctx->iftype_data_6g =
15270 qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_6g));
15271
15272 if (!hdd_ctx->iftype_data_6g)
15273 return QDF_STATUS_E_NOMEM;
15274
15275 return QDF_STATUS_SUCCESS;
15276}
bings3d9cd952019-12-23 17:41:52 +080015277
15278static void
15279wlan_hdd_iftype_data_mem_free_6ghz(struct hdd_context *hdd_ctx)
15280{
15281 qdf_mem_free(hdd_ctx->iftype_data_6g);
15282 hdd_ctx->iftype_data_6g = NULL;
15283}
gaurank kathpalia54bc4a32019-12-05 20:43:15 +053015284#else
15285static inline QDF_STATUS
15286wlan_hdd_iftype_data_alloc_6ghz(struct hdd_context *hdd_ctx)
15287{
15288 return QDF_STATUS_SUCCESS;
15289}
bings3d9cd952019-12-23 17:41:52 +080015290
15291static inline void
15292wlan_hdd_iftype_data_mem_free_6ghz(struct hdd_context *hdd_ctx)
15293{
15294}
gaurank kathpalia54bc4a32019-12-05 20:43:15 +053015295#endif
15296
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015297static QDF_STATUS
15298wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx)
15299{
15300 hdd_ctx->iftype_data_2g =
15301 qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_2g));
15302
15303 if (!hdd_ctx->iftype_data_2g) {
15304 hdd_err("mem alloc failed for 2g iftype data");
15305 return QDF_STATUS_E_NOMEM;
15306 }
15307 hdd_ctx->iftype_data_5g =
15308 qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_5g));
15309
15310 if (!hdd_ctx->iftype_data_5g) {
15311 hdd_err("mem alloc failed for 5g iftype data");
15312 qdf_mem_free(hdd_ctx->iftype_data_2g);
15313 hdd_ctx->iftype_data_2g = NULL;
15314 return QDF_STATUS_E_NOMEM;
15315 }
15316
gaurank kathpalia54bc4a32019-12-05 20:43:15 +053015317 if (QDF_IS_STATUS_ERROR(wlan_hdd_iftype_data_alloc_6ghz(hdd_ctx))) {
15318 hdd_err("mem alloc failed for 6g iftype data");
15319 qdf_mem_free(hdd_ctx->iftype_data_5g);
15320 qdf_mem_free(hdd_ctx->iftype_data_2g);
15321 hdd_ctx->iftype_data_2g = NULL;
15322 hdd_ctx->iftype_data_5g = NULL;
15323 return QDF_STATUS_E_NOMEM;
15324 }
15325
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015326 return QDF_STATUS_SUCCESS;
15327}
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015328
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015329static void
15330wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx)
15331{
gaurank kathpalia54bc4a32019-12-05 20:43:15 +053015332 wlan_hdd_iftype_data_mem_free_6ghz(hdd_ctx);
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015333 qdf_mem_free(hdd_ctx->iftype_data_5g);
15334 qdf_mem_free(hdd_ctx->iftype_data_2g);
15335 hdd_ctx->iftype_data_5g = NULL;
15336 hdd_ctx->iftype_data_2g = NULL;
15337}
15338#else
bings3d9cd952019-12-23 17:41:52 +080015339static QDF_STATUS
15340wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx)
15341
15342{
15343 return QDF_STATUS_SUCCESS;
15344}
15345
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015346static inline void
15347wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx)
15348{
15349}
15350#endif
15351
Srinivas Dasarid2ba2612019-12-11 17:27:52 +053015352#if defined(WLAN_FEATURE_NAN) && \
15353 (KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE)
15354static void wlan_hdd_set_nan_if_mode(struct wiphy *wiphy)
15355{
15356 wiphy->interface_modes |= BIT(NL80211_IFTYPE_NAN);
15357}
15358
15359static void wlan_hdd_set_nan_supported_bands(struct wiphy *wiphy)
15360{
15361 wiphy->nan_supported_bands =
15362 BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ);
15363}
15364#else
15365static void wlan_hdd_set_nan_if_mode(struct wiphy *wiphy)
15366{
15367}
15368
15369static void wlan_hdd_set_nan_supported_bands(struct wiphy *wiphy)
15370{
15371}
15372#endif
15373
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015374/*
15375 * FUNCTION: wlan_hdd_cfg80211_init
15376 * This function is called by hdd_wlan_startup()
15377 * during initialization.
15378 * This function is used to initialize and register wiphy structure.
15379 */
15380int wlan_hdd_cfg80211_init(struct device *dev,
Jeff Johnson30f5bba2019-03-08 11:58:08 -080015381 struct wiphy *wiphy, struct hdd_config *config)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015382{
Jeff Johnsonb8944722017-09-03 09:03:19 -070015383 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015384 uint32_t *cipher_suites;
Dustin Brown491d54b2018-03-14 12:39:11 -070015385 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015386
15387 /* Now bind the underlying wlan device with wiphy */
15388 set_wiphy_dev(wiphy, dev);
15389
15390 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
15391
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015392 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
15393 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
15394 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
15395#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
15396 | WIPHY_FLAG_4ADDR_STATION
15397#endif
15398 | WIPHY_FLAG_OFFCHAN_TX;
15399
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015400#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
15401 wiphy->wowlan = &wowlan_support_cfg80211_init;
15402#else
15403 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
15404 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
15405 wiphy->wowlan.pattern_min_len = 1;
15406 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
15407#endif
15408
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015409#ifdef FEATURE_WLAN_TDLS
15410 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
15411 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
15412#endif
15413
15414 wiphy->features |= NL80211_FEATURE_HT_IBSS;
15415
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015416#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
15417 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
15418#endif
15419
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053015420 wlan_hdd_cfg80211_set_wiphy_scan_flags(wiphy);
15421
Pragaspathi Thilagaraj24789d32018-12-10 22:28:03 +053015422 wlan_scan_cfg80211_add_connected_pno_support(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015423
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015424 wiphy->max_scan_ssids = MAX_SCAN_SSID;
15425
15426 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
15427
15428 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
15429
Arun Khandavallifae92942016-08-01 13:31:08 +053015430 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
15431 | BIT(NL80211_IFTYPE_ADHOC)
15432 | BIT(NL80211_IFTYPE_P2P_CLIENT)
15433 | BIT(NL80211_IFTYPE_P2P_GO)
15434 | BIT(NL80211_IFTYPE_AP)
15435 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015436
Srinivas Dasarid2ba2612019-12-11 17:27:52 +053015437 wlan_hdd_set_nan_if_mode(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015438
Abhishek Singhf512bf32016-05-04 16:47:46 +053015439 /*
15440 * In case of static linked driver at the time of driver unload,
15441 * module exit doesn't happens. Module cleanup helps in cleaning
15442 * of static memory.
15443 * If driver load happens statically, at the time of driver unload,
15444 * wiphy flags don't get reset because of static memory.
15445 * It's better not to store channel in static memory.
Qun Zhang043635a2019-02-27 15:19:29 +080015446 * The memory is for channels of struct wiphy and shouldn't be
15447 * released during stop modules. So if it's allocated in active
15448 * domain, the memory leak detector would catch the leak during
15449 * stop modules. To avoid this,alloc in init domain in advance.
Abhishek Singhf512bf32016-05-04 16:47:46 +053015450 */
Qun Zhang043635a2019-02-27 15:19:29 +080015451 hdd_ctx->channels_2ghz = qdf_mem_malloc(band_2_ghz_channels_size);
15452 if (!hdd_ctx->channels_2ghz) {
15453 hdd_err("Not enough memory to allocate channels");
Abhishek Singhf512bf32016-05-04 16:47:46 +053015454 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015455 }
Qun Zhang043635a2019-02-27 15:19:29 +080015456 hdd_ctx->channels_5ghz = qdf_mem_malloc(band_5_ghz_chanenls_size);
15457 if (!hdd_ctx->channels_5ghz)
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015458 goto mem_fail_5g;
15459
15460 if (QDF_IS_STATUS_ERROR(wlan_hdd_iftype_data_alloc(hdd_ctx)))
15461 goto mem_fail_iftype_data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015462
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015463 /*Initialise the supported cipher suite details */
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080015464 if (ucfg_fwol_get_gcmp_enable(hdd_ctx->psoc)) {
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015465 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites) +
15466 sizeof(hdd_gcmp_cipher_suits));
Min Liu74a1a502018-10-10 19:59:07 +080015467 if (!cipher_suites)
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015468 goto mem_fail_cipher_suites;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015469 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites) +
15470 QDF_ARRAY_SIZE(hdd_gcmp_cipher_suits);
15471 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
15472 sizeof(hdd_cipher_suites));
15473 qdf_mem_copy(cipher_suites + QDF_ARRAY_SIZE(hdd_cipher_suites),
15474 &hdd_gcmp_cipher_suits,
15475 sizeof(hdd_gcmp_cipher_suits));
15476 } else {
15477 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites));
Min Liu74a1a502018-10-10 19:59:07 +080015478 if (!cipher_suites)
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015479 goto mem_fail_cipher_suites;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015480 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites);
15481 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
15482 sizeof(hdd_cipher_suites));
15483 }
15484 wiphy->cipher_suites = cipher_suites;
15485 cipher_suites = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015486 /*signal strength in mBm (100*dBm) */
15487 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
15488 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
15489
Anurag Chouhan6d760662016-02-20 16:05:43 +053015490 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015491 wiphy->n_vendor_commands =
15492 ARRAY_SIZE(hdd_wiphy_vendor_commands);
15493 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
15494
15495 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
15496 wiphy->n_vendor_events =
15497 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
15498 }
15499
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015500#ifdef QCA_HT_2040_COEX
15501 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
15502#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053015503 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080015504
hangtian821d12d2019-06-11 11:53:50 +080015505 wiphy->features |= NL80211_FEATURE_VIF_TXPOWER;
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053015506#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) || \
wadesonga75734c2017-02-07 16:03:25 +080015507 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
15508 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
15509 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
15510 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
15511#endif
15512
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015513 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080015514 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Liangwei Dong3abfe8f2018-09-20 02:25:44 -040015515 wlan_hdd_cfg80211_action_frame_randomization_init(wiphy);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015516
Srinivas Dasarid2ba2612019-12-11 17:27:52 +053015517 wlan_hdd_set_nan_supported_bands(wiphy);
15518
Dustin Browne74003f2018-03-14 12:51:58 -070015519 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015520 return 0;
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015521
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015522mem_fail_cipher_suites:
15523 wlan_hdd_iftype_data_mem_free(hdd_ctx);
15524mem_fail_iftype_data:
15525 qdf_mem_free(hdd_ctx->channels_5ghz);
15526 hdd_ctx->channels_5ghz = NULL;
15527mem_fail_5g:
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015528 hdd_err("Not enough memory to allocate channels");
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015529 qdf_mem_free(hdd_ctx->channels_2ghz);
15530 hdd_ctx->channels_2ghz = NULL;
15531
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015532 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015533}
15534
Abhishek Singhf512bf32016-05-04 16:47:46 +053015535/**
Yingying Tang80e15f32016-09-27 18:23:01 +080015536 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
15537 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053015538 *
15539 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053015540 * memory allocated in wlan_hdd_cfg80211_init also
15541 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053015542 *
15543 * Return: void
15544 */
15545void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
15546{
15547 int i;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015548 const uint32_t *cipher_suites;
Qun Zhang043635a2019-02-27 15:19:29 +080015549 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +053015550
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070015551 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Jeff Johnsond36fa332019-03-18 13:42:25 -070015552 if (wiphy->bands[i] &&
Qun Zhang043635a2019-02-27 15:19:29 +080015553 (wiphy->bands[i]->channels))
Abhishek Singhf512bf32016-05-04 16:47:46 +053015554 wiphy->bands[i]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053015555 }
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015556 wlan_hdd_iftype_data_mem_free(hdd_ctx);
Qun Zhang043635a2019-02-27 15:19:29 +080015557 qdf_mem_free(hdd_ctx->channels_5ghz);
gaurank kathpaliaccfca4a2019-08-13 11:51:27 +053015558 qdf_mem_free(hdd_ctx->channels_2ghz);
Qun Zhang043635a2019-02-27 15:19:29 +080015559 hdd_ctx->channels_2ghz = NULL;
15560 hdd_ctx->channels_5ghz = NULL;
Amar Singhal5cccafe2017-02-15 12:42:58 -080015561
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015562 cipher_suites = wiphy->cipher_suites;
15563 wiphy->cipher_suites = NULL;
15564 wiphy->n_cipher_suites = 0;
15565 qdf_mem_free((uint32_t *)cipher_suites);
15566 cipher_suites = NULL;
Abhishek Singh3e6172f2016-05-04 16:56:48 +053015567 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053015568}
15569
Yingying Tang80e15f32016-09-27 18:23:01 +080015570/**
15571 * wlan_hdd_update_band_cap() - update capabilities for supported bands
15572 * @hdd_ctx: HDD context
15573 *
15574 * this function will update capabilities for supported bands
15575 *
15576 * Return: void
15577 */
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053015578static void wlan_hdd_update_ht_cap(struct hdd_context *hdd_ctx)
Yingying Tang80e15f32016-09-27 18:23:01 +080015579{
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053015580 struct mlme_ht_capabilities_info ht_cap_info = {0};
Yingying Tang80e15f32016-09-27 18:23:01 +080015581 QDF_STATUS status;
Wu Gaoed616a12019-01-16 15:19:21 +080015582 uint32_t channel_bonding_mode;
Rajeev Kumar Sirasanagandla7dee7fe2019-08-05 15:55:19 +053015583 struct ieee80211_supported_band *band_2g;
15584 struct ieee80211_supported_band *band_5g;
Yingying Tang80e15f32016-09-27 18:23:01 +080015585
Dustin Brown76cd2932018-09-11 16:03:05 -070015586 status = ucfg_mlme_get_ht_cap_info(hdd_ctx->psoc, &ht_cap_info);
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053015587 if (QDF_STATUS_SUCCESS != status)
Yingying Tang80e15f32016-09-27 18:23:01 +080015588 hdd_err("could not get HT capability info");
Yingying Tang80e15f32016-09-27 18:23:01 +080015589
Rajeev Kumar Sirasanagandla7dee7fe2019-08-05 15:55:19 +053015590 band_2g = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ];
15591 band_5g = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ];
15592
15593 if (band_2g) {
15594 if (ht_cap_info.tx_stbc)
15595 band_2g->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
15596
15597 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
15598 band_2g->vht_cap.vht_supported = 0;
15599 band_2g->vht_cap.cap = 0;
15600 }
15601
15602 if (!ht_cap_info.short_gi_20_mhz)
15603 band_2g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Yingying Tang80e15f32016-09-27 18:23:01 +080015604 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015605
Rajeev Kumar Sirasanagandla7dee7fe2019-08-05 15:55:19 +053015606 if (band_5g) {
15607 if (ht_cap_info.tx_stbc)
15608 band_5g->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
15609
15610 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
15611 band_5g->vht_cap.vht_supported = 0;
15612 band_5g->vht_cap.cap = 0;
15613 }
15614
15615 if (!ht_cap_info.short_gi_20_mhz)
15616 band_5g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
15617
15618 if (!ht_cap_info.short_gi_40_mhz)
15619 band_5g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
15620
15621 ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc,
15622 &channel_bonding_mode);
15623 if (!channel_bonding_mode)
15624 band_5g->ht_cap.cap &=
15625 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015626 }
Yingying Tang80e15f32016-09-27 18:23:01 +080015627}
15628
Vignesh Viswanathanf97cc112018-10-03 19:17:07 +053015629/**
15630 * wlan_hdd_update_band_cap_in_wiphy() - update channel flags based on band cap
15631 * @hdd_ctx: HDD context
15632 *
15633 * This function updates the channel flags based on the band capability set
15634 * in the MLME CFG
15635 *
15636 * Return: void
15637 */
15638static void wlan_hdd_update_band_cap_in_wiphy(struct hdd_context *hdd_ctx)
15639{
15640 int i, j;
15641 uint8_t band_capability;
15642 QDF_STATUS status;
15643 struct ieee80211_supported_band *band;
15644
15645 status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
15646 if (QDF_IS_STATUS_ERROR(status)) {
15647 hdd_err("Failed to get MLME Band Capability");
15648 return;
15649 }
15650
15651 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Jeff Johnsond36fa332019-03-18 13:42:25 -070015652 if (!hdd_ctx->wiphy->bands[i])
Vignesh Viswanathanf97cc112018-10-03 19:17:07 +053015653 continue;
15654
15655 for (j = 0; j < hdd_ctx->wiphy->bands[i]->n_channels; j++) {
15656 band = hdd_ctx->wiphy->bands[i];
15657
15658 if (HDD_NL80211_BAND_2GHZ == i &&
15659 BAND_5G == band_capability) {
15660 /* 5G only */
15661#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
15662 /* Enable social channels for P2P */
15663 if (WLAN_HDD_IS_SOCIAL_CHANNEL
15664 (band->channels[j].center_freq))
15665 band->channels[j].flags &=
15666 ~IEEE80211_CHAN_DISABLED;
15667 else
15668#endif
15669 band->channels[j].flags |=
15670 IEEE80211_CHAN_DISABLED;
15671 continue;
15672 } else if (HDD_NL80211_BAND_5GHZ == i &&
15673 BAND_2G == band_capability) {
15674 /* 2G only */
15675 band->channels[j].flags |=
15676 IEEE80211_CHAN_DISABLED;
15677 continue;
15678 }
15679 }
15680 }
15681}
15682
Wu Gao1ab05582018-11-08 16:22:49 +080015683#ifdef FEATURE_WLAN_ESE
15684/**
15685 * wlan_hdd_update_lfr_wiphy() - update LFR flag based on configures
15686 * @hdd_ctx: HDD context
15687 *
15688 * This function updates the LFR flag based on LFR configures
15689 *
15690 * Return: void
15691 */
15692static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
15693{
15694 bool fast_transition_enabled;
15695 bool lfr_enabled;
15696 bool ese_enabled;
15697
15698 ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
15699 &fast_transition_enabled);
15700 ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
15701 ucfg_mlme_is_ese_enabled(hdd_ctx->psoc, &ese_enabled);
15702 if (fast_transition_enabled || lfr_enabled || ese_enabled)
15703 hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
15704}
15705#else
15706static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
15707{
15708 bool fast_transition_enabled;
15709 bool lfr_enabled;
15710
15711 ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
15712 &fast_transition_enabled);
15713 ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
15714 if (fast_transition_enabled || lfr_enabled)
15715 hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
15716}
15717#endif
15718
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015719/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053015720 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015721 * initialization. In wlan_hdd_cfg80211_init, only the
15722 * default values will be initialized. The final initialization
15723 * of all required members can be done here.
15724 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015725void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015726{
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053015727 int value;
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053015728 bool fils_enabled, mac_spoofing_enabled;
Srinivas Dasarib264fec2019-05-21 18:56:25 +053015729 bool dfs_master_capable = true, is_oce_sta_enabled = false;
Karthik Kantamneni2231a232018-09-11 15:45:55 +053015730 QDF_STATUS status;
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053015731 struct wiphy *wiphy = hdd_ctx->wiphy;
15732 uint8_t allow_mcc_go_diff_bi = 0, enable_mcc = 0;
Yingying Tang80e15f32016-09-27 18:23:01 +080015733
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053015734 if (!wiphy) {
15735 hdd_err("Invalid wiphy");
15736 return;
15737 }
Dustin Brown05d81302018-09-11 16:49:22 -070015738 ucfg_mlme_get_sap_max_peers(hdd_ctx->psoc, &value);
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053015739 hdd_ctx->wiphy->max_ap_assoc_sta = value;
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053015740 wlan_hdd_update_ht_cap(hdd_ctx);
Vignesh Viswanathanf97cc112018-10-03 19:17:07 +053015741 wlan_hdd_update_band_cap_in_wiphy(hdd_ctx);
Wu Gao1ab05582018-11-08 16:22:49 +080015742 wlan_hdd_update_lfr_wiphy(hdd_ctx);
Karthik Kantamneni2231a232018-09-11 15:45:55 +053015743
15744 fils_enabled = 0;
Dustin Brown05d81302018-09-11 16:49:22 -070015745 status = ucfg_mlme_get_fils_enabled_info(hdd_ctx->psoc,
Karthik Kantamneni2231a232018-09-11 15:45:55 +053015746 &fils_enabled);
15747 if (QDF_IS_STATUS_ERROR(status))
15748 hdd_err("could not get fils enabled info");
15749 if (fils_enabled)
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053015750 wlan_hdd_cfg80211_set_wiphy_fils_feature(wiphy);
Arif Hussain88d1fdd2018-09-26 16:12:24 -070015751
15752 status = ucfg_mlme_get_dfs_master_capability(hdd_ctx->psoc,
15753 &dfs_master_capable);
15754 if (QDF_IS_STATUS_SUCCESS(status) && dfs_master_capable)
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053015755 wlan_hdd_cfg80211_set_dfs_offload_feature(wiphy);
Srinivas Dasarib264fec2019-05-21 18:56:25 +053015756
15757 status = ucfg_mlme_get_oce_sta_enabled_info(hdd_ctx->psoc,
15758 &is_oce_sta_enabled);
15759 if (QDF_IS_STATUS_ERROR(status))
15760 hdd_err("could not get OCE STA enable info");
15761 if (is_oce_sta_enabled)
Ashish Kumar Dhanotiya53d8bb62019-05-29 20:55:13 +053015762 wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(wiphy);
15763
15764 wlan_hdd_cfg80211_set_wiphy_sae_feature(wiphy);
15765
15766 if (QDF_STATUS_SUCCESS !=
15767 ucfg_policy_mgr_get_allow_mcc_go_diff_bi(hdd_ctx->psoc,
15768 &allow_mcc_go_diff_bi))
15769 hdd_err("can't get mcc_go_diff_bi value, use default");
15770
15771 if (QDF_STATUS_SUCCESS !=
15772 ucfg_mlme_get_mcc_feature(hdd_ctx->psoc, &enable_mcc))
15773 hdd_err("can't get enable_mcc value, use default");
15774
15775 if (hdd_ctx->config->advertise_concurrent_operation) {
15776 if (enable_mcc) {
15777 int i;
15778
15779 for (i = 0;
15780 i < ARRAY_SIZE(wlan_hdd_iface_combination);
15781 i++) {
15782 if (!allow_mcc_go_diff_bi)
15783 wlan_hdd_iface_combination[i].
15784 beacon_int_infra_match = true;
15785 }
15786 }
15787 wiphy->n_iface_combinations =
15788 ARRAY_SIZE(wlan_hdd_iface_combination);
15789 wiphy->iface_combinations = wlan_hdd_iface_combination;
15790 }
15791
15792 mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
15793 if (mac_spoofing_enabled)
15794 wlan_hdd_cfg80211_scan_randomization_init(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015795}
15796
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015797/**
15798 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
15799 * @cfg: hdd cfg
15800 *
15801 * this function update 11n mode in hdd cfg
15802 *
15803 * Return: void
15804 */
Sandeep Puligilla34618782019-01-04 17:42:42 -080015805void wlan_hdd_update_11n_mode(struct hdd_context *hdd_ctx)
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015806{
Sandeep Puligilla34618782019-01-04 17:42:42 -080015807 struct hdd_config *cfg = hdd_ctx->config;
15808
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015809 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015810 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015811 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015812 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015813 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
15814 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
15815 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
Sandeep Puligilla34618782019-01-04 17:42:42 -080015816 ucfg_mlme_set_sap_11ac_override(hdd_ctx->psoc, 0);
15817 ucfg_mlme_set_go_11ac_override(hdd_ctx->psoc, 0);
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015818 }
15819 }
15820}
15821
Qun Zhang043635a2019-02-27 15:19:29 +080015822QDF_STATUS wlan_hdd_update_wiphy_supported_band(struct hdd_context *hdd_ctx)
15823{
15824 int len_5g_ch, num_ch;
15825 int num_dsrc_ch, len_dsrc_ch, num_srd_ch, len_srd_ch;
Varuneshwar Petlozu3a18e852019-07-23 15:13:26 +053015826 bool is_vht_for_24ghz = false;
15827 QDF_STATUS status;
Qun Zhang043635a2019-02-27 15:19:29 +080015828 struct hdd_config *cfg = hdd_ctx->config;
15829 struct wiphy *wiphy = hdd_ctx->wiphy;
15830
tinlin5d3721d2019-06-03 16:13:20 +080015831 if (wiphy->registered)
15832 return QDF_STATUS_SUCCESS;
15833
Ashish Kumar Dhanotiya34507e02019-06-12 12:53:59 +053015834 if (hdd_is_2g_supported(hdd_ctx)) {
15835 if (!hdd_ctx->channels_2ghz)
15836 return QDF_STATUS_E_NOMEM;
15837 wiphy->bands[HDD_NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
15838 wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels =
15839 hdd_ctx->channels_2ghz;
15840 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels,
15841 &hdd_channels_2_4_ghz[0],
15842 sizeof(hdd_channels_2_4_ghz));
Varuneshwar Petlozu3a18e852019-07-23 15:13:26 +053015843
15844 status = ucfg_mlme_get_vht_for_24ghz(hdd_ctx->psoc,
15845 &is_vht_for_24ghz);
15846 if (QDF_IS_STATUS_ERROR(status))
15847 hdd_err("could not get VHT capability");
15848
15849 if (is_vht_for_24ghz &&
Sourav Mohapatra92434622020-01-30 09:32:21 +053015850 sme_is_feature_supported_by_fw(DOT11AC) &&
15851 (cfg->dot11Mode == eHDD_DOT11_MODE_AUTO ||
15852 cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY ||
15853 cfg->dot11Mode == eHDD_DOT11_MODE_11ac ||
15854 cfg->dot11Mode == eHDD_DOT11_MODE_11ax ||
15855 cfg->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY))
Varuneshwar Petlozu3a18e852019-07-23 15:13:26 +053015856 wlan_hdd_band_2_4_ghz.vht_cap.vht_supported = 1;
Ashish Kumar Dhanotiya34507e02019-06-12 12:53:59 +053015857 }
Qun Zhang043635a2019-02-27 15:19:29 +080015858 if (!hdd_is_5g_supported(hdd_ctx) ||
15859 (eHDD_DOT11_MODE_11b == cfg->dot11Mode) ||
15860 (eHDD_DOT11_MODE_11g == cfg->dot11Mode) ||
15861 (eHDD_DOT11_MODE_11b_ONLY == cfg->dot11Mode) ||
15862 (eHDD_DOT11_MODE_11g_ONLY == cfg->dot11Mode))
15863 return QDF_STATUS_SUCCESS;
15864
15865 if (!hdd_ctx->channels_5ghz)
15866 return QDF_STATUS_E_NOMEM;
15867 wiphy->bands[HDD_NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
15868 wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels = hdd_ctx->channels_5ghz;
15869 wlan_hdd_get_num_dsrc_ch_and_len(cfg, &num_dsrc_ch, &len_dsrc_ch);
15870 wlan_hdd_get_num_srd_ch_and_len(cfg, &num_srd_ch, &len_srd_ch);
15871 num_ch = QDF_ARRAY_SIZE(hdd_channels_5_ghz) + num_dsrc_ch + num_srd_ch;
15872 len_5g_ch = sizeof(hdd_channels_5_ghz);
15873
15874 wiphy->bands[HDD_NL80211_BAND_5GHZ]->n_channels = num_ch;
15875 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels,
15876 &hdd_channels_5_ghz[0], len_5g_ch);
15877 if (num_dsrc_ch)
15878 wlan_hdd_copy_dsrc_ch((char *)wiphy->bands[
15879 HDD_NL80211_BAND_5GHZ]->channels +
15880 len_5g_ch, len_dsrc_ch);
15881 if (num_srd_ch)
15882 wlan_hdd_copy_srd_ch((char *)wiphy->bands[
15883 HDD_NL80211_BAND_5GHZ]->channels +
15884 len_5g_ch, len_srd_ch);
15885
Sourav Mohapatra92434622020-01-30 09:32:21 +053015886 if (cfg->dot11Mode != eHDD_DOT11_MODE_AUTO &&
15887 cfg->dot11Mode != eHDD_DOT11_MODE_11ac &&
15888 cfg->dot11Mode != eHDD_DOT11_MODE_11ac_ONLY &&
15889 cfg->dot11Mode != eHDD_DOT11_MODE_11ax &&
15890 cfg->dot11Mode != eHDD_DOT11_MODE_11ax_ONLY)
15891 wlan_hdd_band_5_ghz.vht_cap.vht_supported = 0;
15892
Liangwei Dong692455f2019-08-09 17:59:46 +080015893 hdd_init_6ghz(hdd_ctx);
15894
Qun Zhang043635a2019-02-27 15:19:29 +080015895 return QDF_STATUS_SUCCESS;
15896}
15897
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015898/* In this function we are registering wiphy. */
15899int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
15900{
Dustin Brown491d54b2018-03-14 12:39:11 -070015901 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015902 /* Register our wiphy dev with cfg80211 */
15903 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070015904 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015905 return -EIO;
15906 }
15907
Dustin Browne74003f2018-03-14 12:51:58 -070015908 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015909 return 0;
15910}
15911
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015912/* This function registers for all frame which supplicant is interested in */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015913int wlan_hdd_cfg80211_register_frames(struct hdd_adapter *adapter)
Wu Gao84d120c2017-03-24 18:46:00 +080015914{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015915 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
Wu Gao84d120c2017-03-24 18:46:00 +080015916 /* Register for all P2P action, public action etc frames */
15917 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015918 QDF_STATUS status;
Wu Gao84d120c2017-03-24 18:46:00 +080015919
Dustin Brown491d54b2018-03-14 12:39:11 -070015920 hdd_enter();
Sourav Mohapatraa0943922018-11-21 21:26:29 +053015921 if (adapter->device_mode == QDF_FTM_MODE) {
15922 hdd_info("No need to register frames in FTM mode");
15923 return 0;
15924 }
Wu Gao84d120c2017-03-24 18:46:00 +080015925
15926 /* Register frame indication call back */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015927 status = sme_register_mgmt_frame_ind_callback(mac_handle,
15928 hdd_indicate_mgmt_frame);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015929 if (status != QDF_STATUS_SUCCESS) {
15930 hdd_err("Failed to register hdd_indicate_mgmt_frame");
15931 goto ret_status;
15932 }
Wu Gao84d120c2017-03-24 18:46:00 +080015933
Wu Gao84d120c2017-03-24 18:46:00 +080015934 /* Right now we are registering these frame when driver is getting
15935 * initialized. Once we will move to 2.6.37 kernel, in which we have
15936 * frame register ops, we will move this code as a part of that
15937 */
15938
15939 /* GAS Initial Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015940 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15941 (uint8_t *) GAS_INITIAL_REQ,
15942 GAS_INITIAL_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015943 if (status != QDF_STATUS_SUCCESS) {
15944 hdd_err("Failed to register GAS_INITIAL_REQ");
15945 goto ret_status;
15946 }
Wu Gao84d120c2017-03-24 18:46:00 +080015947
15948 /* GAS Initial Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015949 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15950 (uint8_t *) GAS_INITIAL_RSP,
15951 GAS_INITIAL_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015952 if (status != QDF_STATUS_SUCCESS) {
15953 hdd_err("Failed to register GAS_INITIAL_RSP");
15954 goto dereg_gas_initial_req;
15955 }
Wu Gao84d120c2017-03-24 18:46:00 +080015956
15957 /* GAS Comeback Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015958 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15959 (uint8_t *) GAS_COMEBACK_REQ,
15960 GAS_COMEBACK_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015961 if (status != QDF_STATUS_SUCCESS) {
15962 hdd_err("Failed to register GAS_COMEBACK_REQ");
15963 goto dereg_gas_initial_rsp;
15964 }
Wu Gao84d120c2017-03-24 18:46:00 +080015965
15966 /* GAS Comeback Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015967 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15968 (uint8_t *) GAS_COMEBACK_RSP,
15969 GAS_COMEBACK_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015970 if (status != QDF_STATUS_SUCCESS) {
15971 hdd_err("Failed to register GAS_COMEBACK_RSP");
15972 goto dereg_gas_comeback_req;
15973 }
Wu Gao84d120c2017-03-24 18:46:00 +080015974
15975 /* WNM BSS Transition Request frame */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015976 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15977 (uint8_t *) WNM_BSS_ACTION_FRAME,
15978 WNM_BSS_ACTION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015979 if (status != QDF_STATUS_SUCCESS) {
15980 hdd_err("Failed to register WNM_BSS_ACTION_FRAME");
15981 goto dereg_gas_comeback_rsp;
15982 }
Wu Gao84d120c2017-03-24 18:46:00 +080015983
15984 /* WNM-Notification */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080015985 status = sme_register_mgmt_frame(mac_handle, adapter->vdev_id, type,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015986 (uint8_t *) WNM_NOTIFICATION_FRAME,
15987 WNM_NOTIFICATION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015988 if (status != QDF_STATUS_SUCCESS) {
15989 hdd_err("Failed to register WNM_NOTIFICATION_FRAME");
15990 goto dereg_wnm_bss_action_frm;
15991 }
15992
Dustin Brown237baee2018-05-10 13:22:18 -070015993 return 0;
15994
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015995dereg_wnm_bss_action_frm:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015996 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
15997 (uint8_t *) WNM_BSS_ACTION_FRAME,
15998 WNM_BSS_ACTION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015999dereg_gas_comeback_rsp:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016000 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16001 (uint8_t *) GAS_COMEBACK_RSP,
16002 GAS_COMEBACK_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016003dereg_gas_comeback_req:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016004 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16005 (uint8_t *) GAS_COMEBACK_REQ,
16006 GAS_COMEBACK_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016007dereg_gas_initial_rsp:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016008 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16009 (uint8_t *) GAS_INITIAL_RSP,
16010 GAS_INITIAL_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016011dereg_gas_initial_req:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016012 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
16013 (uint8_t *) GAS_INITIAL_REQ,
16014 GAS_INITIAL_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053016015ret_status:
16016 return qdf_status_to_os_return(status);
Wu Gao84d120c2017-03-24 18:46:00 +080016017}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016018
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016019void wlan_hdd_cfg80211_deregister_frames(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016020{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016021 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
16022 /* Deregister for all P2P action, public action etc frames */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016023 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
16024
Dustin Brown491d54b2018-03-14 12:39:11 -070016025 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016026
16027 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016028 * initialized. Once we will move to 2.6.37 kernel, in which we have
16029 * frame register ops, we will move this code as a part of that
16030 */
16031
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016032 /* GAS Initial Request */
16033
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016034 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016035 (uint8_t *) GAS_INITIAL_REQ,
16036 GAS_INITIAL_REQ_SIZE);
16037
16038 /* GAS Initial Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016039 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016040 (uint8_t *) GAS_INITIAL_RSP,
16041 GAS_INITIAL_RSP_SIZE);
16042
16043 /* GAS Comeback Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016044 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016045 (uint8_t *) GAS_COMEBACK_REQ,
16046 GAS_COMEBACK_REQ_SIZE);
16047
16048 /* GAS Comeback Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016049 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016050 (uint8_t *) GAS_COMEBACK_RSP,
16051 GAS_COMEBACK_RSP_SIZE);
16052
16053 /* P2P Public Action */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016054 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016055 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
16056 P2P_PUBLIC_ACTION_FRAME_SIZE);
16057
16058 /* P2P Action */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016059 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016060 (uint8_t *) P2P_ACTION_FRAME,
16061 P2P_ACTION_FRAME_SIZE);
16062
16063 /* WNM-Notification */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016064 sme_deregister_mgmt_frame(mac_handle, adapter->vdev_id, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016065 (uint8_t *) WNM_NOTIFICATION_FRAME,
16066 WNM_NOTIFICATION_FRAME_SIZE);
16067}
16068
Krunal Soni364e0872017-05-10 21:24:34 -070016069bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
16070{
Naveen Rawat08db88f2017-09-08 15:07:48 -070016071 const uint8_t *vendor_ie;
Krunal Soni364e0872017-05-10 21:24:34 -070016072
16073 if (length < 2) {
16074 hdd_debug("bss size is less than expected");
16075 return true;
16076 }
16077 if (!ies) {
16078 hdd_debug("invalid IE pointer");
16079 return true;
16080 }
Naveen Rawat08db88f2017-09-08 15:07:48 -070016081 vendor_ie = wlan_get_vendor_ie_ptr_from_oui(VENDOR1_AP_OUI_TYPE,
Krunal Soni364e0872017-05-10 21:24:34 -070016082 VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
16083 if (vendor_ie) {
16084 hdd_debug("AP can't support immediate powersave. defer it");
16085 return false;
16086 }
16087 return true;
16088}
16089
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016090/*
16091 * FUNCTION: wlan_hdd_validate_operation_channel
16092 * called by wlan_hdd_cfg80211_start_bss() and
16093 * wlan_hdd_set_channel()
16094 * This function validates whether given channel is part of valid
16095 * channel list.
16096 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016097QDF_STATUS wlan_hdd_validate_operation_channel(struct hdd_adapter *adapter,
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016098 uint32_t ch_freq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016099{
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016100 bool value = 0;
16101 uint32_t i;
16102 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16103 struct regulatory_channel *cur_chan_list;
16104 QDF_STATUS status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016105
Dustin Brown05d81302018-09-11 16:49:22 -070016106 status = ucfg_mlme_get_sap_allow_all_channels(hdd_ctx->psoc, &value);
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053016107 if (status != QDF_STATUS_SUCCESS)
16108 hdd_err("Unable to fetch sap allow all channels");
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016109
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053016110 if (value) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016111 /* Validate the channel */
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016112 for (i = CHAN_ENUM_2412; i < NUM_CHANNELS; i++) {
16113 if (ch_freq == WLAN_REG_CH_TO_FREQ(i)) {
16114 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016115 break;
16116 }
16117 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016118 } else {
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016119 cur_chan_list = qdf_mem_malloc(NUM_CHANNELS *
16120 sizeof(struct regulatory_channel));
16121 if (!cur_chan_list)
16122 return QDF_STATUS_E_NOMEM;
16123
16124 if (wlan_reg_get_current_chan_list(
16125 hdd_ctx->pdev, cur_chan_list) != QDF_STATUS_SUCCESS) {
16126 qdf_mem_free(cur_chan_list);
16127 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016128 }
16129
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016130 for (i = 0; i < NUM_CHANNELS; i++) {
16131 if (ch_freq != cur_chan_list[i].center_freq)
16132 continue;
16133 if (cur_chan_list[i].state != CHANNEL_STATE_DISABLE &&
16134 cur_chan_list[i].state != CHANNEL_STATE_INVALID)
16135 status = QDF_STATUS_SUCCESS;
16136 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016137 }
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016138 qdf_mem_free(cur_chan_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016139 }
Manikandan Mohan8773b5c2019-10-04 10:49:17 -070016140
16141 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016142
16143}
16144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016145static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
16146 struct net_device *dev,
16147 struct bss_parameters *params)
16148{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016149 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16150 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016151 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053016152 QDF_STATUS qdf_ret_status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016153 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016154
Dustin Brown491d54b2018-03-14 12:39:11 -070016155 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016156
Anurag Chouhan6d760662016-02-20 16:05:43 +053016157 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070016158 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016159 return -EINVAL;
16160 }
16161
Jeff Johnson48363022019-02-24 16:26:51 -080016162 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016163 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016164
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016165 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
16166 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016167 adapter->vdev_id, params->ap_isolate);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016168
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016169 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Dustin Brown458027c2018-10-19 12:26:27 -070016170 qdf_opmode_str(adapter->device_mode),
16171 adapter->device_mode, params->ap_isolate);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016172
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016173 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016174 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016175 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016176 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016177
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016178 if (!(adapter->device_mode == QDF_SAP_MODE ||
16179 adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016180 return -EOPNOTSUPP;
16181 }
16182
16183 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016184 * want to update this parameter
16185 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016186 if (-1 != params->ap_isolate) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070016187 adapter->session.ap.disable_intrabss_fwd =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016188 !!params->ap_isolate;
16189
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016190 mac_handle = hdd_ctx->mac_handle;
16191 qdf_ret_status = sme_ap_disable_intra_bss_fwd(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016192 adapter->vdev_id,
Jeff Johnsonb9424862017-10-30 08:49:35 -070016193 adapter->session.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016194 ap.
Jeff Johnson82ceb082017-10-27 14:52:42 -070016195 disable_intrabss_fwd);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070016196 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016197 ret = -EINVAL;
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +053016198
Dustin Brown07901ec2018-09-07 11:02:41 -070016199 ucfg_ipa_set_ap_ibss_fwd(hdd_ctx->pdev,
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +053016200 adapter->session.ap.
16201 disable_intrabss_fwd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016202 }
16203
Dustin Browne74003f2018-03-14 12:51:58 -070016204 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016205 return ret;
16206}
16207
Krunal Soni8c37e322016-02-03 16:08:37 -080016208/**
Dustin Brown56377e12018-10-10 17:04:04 -070016209 * hdd_change_adapter_mode() - change @adapter's operating mode to @new_mode
16210 * @adapter: the adapter to change modes on
16211 * @new_mode: the new operating mode to change to
Krunal Soni8c37e322016-02-03 16:08:37 -080016212 *
Dustin Brown56377e12018-10-10 17:04:04 -070016213 * Return: Errno
Krunal Soni8c37e322016-02-03 16:08:37 -080016214 */
Dustin Brown56377e12018-10-10 17:04:04 -070016215static int hdd_change_adapter_mode(struct hdd_adapter *adapter,
16216 enum QDF_OPMODE new_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016217{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070016218 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown56377e12018-10-10 17:04:04 -070016219 struct net_device *netdev = adapter->dev;
Krunal Soni8c37e322016-02-03 16:08:37 -080016220 struct hdd_config *config = hdd_ctx->config;
Jeff Johnson20227a92018-03-13 09:41:05 -070016221 struct csr_roam_profile *roam_profile;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053016222 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016223
Dustin Brown491d54b2018-03-14 12:39:11 -070016224 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016225
Dustin Browndb2a8be2017-12-20 11:49:56 -080016226 hdd_stop_adapter(hdd_ctx, adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080016227 hdd_deinit_adapter(hdd_ctx, adapter, true);
Dustin Brown194aeca2018-10-12 15:37:36 -070016228 adapter->device_mode = new_mode;
Jeff Johnsonb9424862017-10-30 08:49:35 -070016229 memset(&adapter->session, 0, sizeof(adapter->session));
Dustin Brown56377e12018-10-10 17:04:04 -070016230 hdd_set_station_ops(netdev);
Jeff Johnson20227a92018-03-13 09:41:05 -070016231
16232 roam_profile = hdd_roam_profile(adapter);
16233 roam_profile->pAddIEScan = adapter->scan_info.scan_add_ie.addIEdata;
Dustin Brown56377e12018-10-10 17:04:04 -070016234 roam_profile->nAddIEScanLength = adapter->scan_info.scan_add_ie.length;
16235
16236 if (new_mode == QDF_IBSS_MODE) {
Krunal Sonib51eec72017-11-20 21:53:01 -080016237 status = hdd_start_station_adapter(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016238 roam_profile->BSSType = eCSR_BSS_TYPE_START_IBSS;
16239 roam_profile->phyMode =
Krunal Soni8c37e322016-02-03 16:08:37 -080016240 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
16241 }
Dustin Brown56377e12018-10-10 17:04:04 -070016242
Dustin Browne74003f2018-03-14 12:51:58 -070016243 hdd_exit();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070016244
16245 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016246}
16247
16248static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
16249 struct net_device *dev,
16250 struct bss_parameters *params)
16251{
Dustin Brown1d31b082018-11-22 14:41:20 +053016252 int errno;
16253 struct osif_vdev_sync *vdev_sync;
16254
16255 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
16256 if (errno)
16257 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016258
Dustin Brown1d31b082018-11-22 14:41:20 +053016259 errno = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016260
Dustin Brown1d31b082018-11-22 14:41:20 +053016261 osif_vdev_sync_op_stop(vdev_sync);
16262
16263 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016264}
16265
Dustin Brown63fe4922018-10-12 15:02:26 -070016266static bool hdd_is_client_mode(enum QDF_OPMODE mode)
16267{
16268 switch (mode) {
16269 case QDF_STA_MODE:
16270 case QDF_P2P_CLIENT_MODE:
16271 case QDF_P2P_DEVICE_MODE:
16272 case QDF_IBSS_MODE:
16273 return true;
16274 default:
16275 return false;
16276 }
16277}
16278
16279static bool hdd_is_ap_mode(enum QDF_OPMODE mode)
16280{
16281 switch (mode) {
16282 case QDF_SAP_MODE:
16283 case QDF_P2P_GO_MODE:
16284 return true;
16285 default:
16286 return false;
16287 }
16288}
16289
16290/**
Rajeev Kumar98edb772016-01-19 12:42:19 -080016291 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
16292 * @wiphy: Pointer to the wiphy structure
16293 * @ndev: Pointer to the net device
16294 * @type: Interface type
16295 * @flags: Flags for change interface
16296 * @params: Pointer to change interface parameters
16297 *
16298 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016299 */
16300static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16301 struct net_device *ndev,
16302 enum nl80211_iftype type,
16303 u32 *flags,
16304 struct vif_params *params)
16305{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016306 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016307 struct hdd_context *hdd_ctx;
Dustin Brown56377e12018-10-10 17:04:04 -070016308 bool iff_up = ndev->flags & IFF_UP;
16309 enum QDF_OPMODE new_mode;
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053016310 bool ap_random_bssid_enabled;
Dustin Brown56377e12018-10-10 17:04:04 -070016311 QDF_STATUS status;
Dustin Brown63fe4922018-10-12 15:02:26 -070016312 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016313
Dustin Brown491d54b2018-03-14 12:39:11 -070016314 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016315
Dustin Brown63fe4922018-10-12 15:02:26 -070016316 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
Jeff Johnson77848112016-06-29 14:52:06 -070016317 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016318 return -EINVAL;
16319 }
16320
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016321 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown2ab5a972018-10-09 17:19:37 -070016322 errno = wlan_hdd_validate_context(hdd_ctx);
16323 if (errno)
16324 return errno;
Nachiket Kukade08b9f292017-11-17 18:27:37 +053016325
Alok Kumar57305242019-07-23 12:27:18 +053016326 if (wlan_hdd_check_mon_concurrency())
16327 return -EINVAL;
16328
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016329 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
16330 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016331 adapter->vdev_id, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016332
Dustin Brown56377e12018-10-10 17:04:04 -070016333 status = hdd_nl_to_qdf_iface_type(type, &new_mode);
16334 if (QDF_IS_STATUS_ERROR(status))
16335 return qdf_status_to_os_return(status);
16336
Dustin Brown194aeca2018-10-12 15:37:36 -070016337 /* A userspace issue leads to it sending a 'change to station mode'
16338 * request on a "p2p" device, expecting the driver do execute a 'change
16339 * to p2p-device mode' request instead. The (unfortunate) work around
16340 * here is implemented by overriding the new mode if the net_device name
16341 * starts with "p2p" and the requested mode was station.
16342 */
16343 if (strnstr(ndev->name, "p2p", 3) && new_mode == QDF_STA_MODE)
16344 new_mode = QDF_P2P_DEVICE_MODE;
16345
Dustin Brown56377e12018-10-10 17:04:04 -070016346 hdd_debug("Changing mode for '%s' from %s to %s",
16347 ndev->name,
16348 qdf_opmode_str(adapter->device_mode),
16349 qdf_opmode_str(new_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016350
Rajeev Kumar473f9af2019-04-05 14:25:56 -070016351 errno = hdd_trigger_psoc_idle_restart(hdd_ctx);
Dustin Brown2ab5a972018-10-09 17:19:37 -070016352 if (errno) {
Dustin Brown3ecc8782018-09-19 16:37:13 -070016353 hdd_err("Failed to restart psoc; errno:%d", errno);
Arun Khandavallifae92942016-08-01 13:31:08 +053016354 return -EINVAL;
16355 }
16356
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016357 /* Reset the current device mode bit mask */
Dustin Brown2ab5a972018-10-09 17:19:37 -070016358 policy_mgr_clear_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016359
Dustin Brown63fe4922018-10-12 15:02:26 -070016360 if (hdd_is_client_mode(adapter->device_mode)) {
16361 if (hdd_is_client_mode(new_mode)) {
Visweswara Tanukub5a61242019-03-26 12:24:13 +053016362 if (new_mode == QDF_IBSS_MODE) {
16363 hdd_deregister_hl_netdev_fc_timer(adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016364 hdd_deregister_tx_flow_control(adapter);
Visweswara Tanukub5a61242019-03-26 12:24:13 +053016365 }
Dustin Brown56377e12018-10-10 17:04:04 -070016366
16367 errno = hdd_change_adapter_mode(adapter, new_mode);
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016368 if (errno) {
16369 hdd_err("change intf mode fail %d", errno);
16370 goto err;
16371 }
Dustin Brown63fe4922018-10-12 15:02:26 -070016372 } else if (hdd_is_ap_mode(new_mode)) {
16373 if (new_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016374 wlan_hdd_cancel_existing_remain_on_channel
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016375 (adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016376
Dustin Browndb2a8be2017-12-20 11:49:56 -080016377 hdd_stop_adapter(hdd_ctx, adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016378 hdd_deinit_adapter(hdd_ctx, adapter, true);
Dustin Brown2ab5a972018-10-09 17:19:37 -070016379 memset(&adapter->session, 0, sizeof(adapter->session));
Dustin Brown56377e12018-10-10 17:04:04 -070016380 adapter->device_mode = new_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016381
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053016382 status = ucfg_mlme_get_ap_random_bssid_enable(
16383 hdd_ctx->psoc,
16384 &ap_random_bssid_enabled);
16385 if (QDF_IS_STATUS_ERROR(status))
16386 return qdf_status_to_os_return(status);
16387
Dustin Brown2ab5a972018-10-09 17:19:37 -070016388 if (adapter->device_mode == QDF_SAP_MODE &&
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053016389 ap_random_bssid_enabled) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016390 /* To meet Android requirements create
16391 * a randomized MAC address of the
16392 * form 02:1A:11:Fx:xx:xx
16393 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016394 get_random_bytes(&ndev->dev_addr[3], 3);
16395 ndev->dev_addr[0] = 0x02;
16396 ndev->dev_addr[1] = 0x1A;
16397 ndev->dev_addr[2] = 0x11;
16398 ndev->dev_addr[3] |= 0xF0;
Dustin Brown2ab5a972018-10-09 17:19:37 -070016399 memcpy(adapter->mac_addr.bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053016400 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016401 pr_info("wlan: Generated HotSpot BSSID "
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070016402 QDF_MAC_ADDR_STR "\n",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070016403 QDF_MAC_ADDR_ARRAY(ndev->dev_addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016404 }
16405
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016406 hdd_set_ap_ops(adapter->dev);
Dustin Brown63fe4922018-10-12 15:02:26 -070016407 } else {
Dustin Brown56377e12018-10-10 17:04:04 -070016408 hdd_err("Changing to device mode '%s' is not supported",
16409 qdf_opmode_str(new_mode));
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016410 errno = -EOPNOTSUPP;
16411 goto err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016412 }
Dustin Brown63fe4922018-10-12 15:02:26 -070016413 } else if (hdd_is_ap_mode(adapter->device_mode)) {
16414 if (hdd_is_client_mode(new_mode)) {
Dustin Brown56377e12018-10-10 17:04:04 -070016415 errno = hdd_change_adapter_mode(adapter, new_mode);
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016416 if (errno) {
16417 hdd_err("change mode fail %d", errno);
16418 goto err;
16419 }
Dustin Brown63fe4922018-10-12 15:02:26 -070016420 } else if (hdd_is_ap_mode(new_mode)) {
Dustin Brown56377e12018-10-10 17:04:04 -070016421 adapter->device_mode = new_mode;
16422
Dustin Brown63fe4922018-10-12 15:02:26 -070016423 /* avoid starting the adapter, since it never stopped */
16424 iff_up = false;
16425 } else {
Dustin Brown56377e12018-10-10 17:04:04 -070016426 hdd_err("Changing to device mode '%s' is not supported",
16427 qdf_opmode_str(new_mode));
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016428 errno = -EOPNOTSUPP;
16429 goto err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016430 }
16431 } else {
Dustin Brown56377e12018-10-10 17:04:04 -070016432 hdd_err("Changing from device mode '%s' is not supported",
16433 qdf_opmode_str(adapter->device_mode));
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016434 errno = -EOPNOTSUPP;
16435 goto err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016436 }
Dustin Brown56377e12018-10-10 17:04:04 -070016437
Dustin Brown63fe4922018-10-12 15:02:26 -070016438 /* restart the adapter if it was up before the change iface request */
16439 if (iff_up) {
16440 errno = hdd_start_adapter(adapter);
16441 if (errno) {
16442 hdd_err("Failed to start adapter");
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016443 errno = -EINVAL;
16444 goto err;
Dustin Brown63fe4922018-10-12 15:02:26 -070016445 }
16446 }
16447
16448 ndev->ieee80211_ptr->iftype = type;
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016449 hdd_lpass_notify_mode_change(adapter);
16450err:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016451 /* Set bitmask based on updated value */
Dustin Brown2ab5a972018-10-09 17:19:37 -070016452 policy_mgr_set_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016453
Dustin Browne74003f2018-03-14 12:51:58 -070016454 hdd_exit();
Dustin Brown2ab5a972018-10-09 17:19:37 -070016455
Liangwei Dong4d35cad2018-11-02 02:38:50 -040016456 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016457}
16458
Dustin Brown0e1e1622019-01-17 11:00:22 -080016459static int _wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16460 struct net_device *net_dev,
16461 enum nl80211_iftype type,
16462 u32 *flags,
16463 struct vif_params *params)
16464{
16465 int errno;
16466 struct osif_vdev_sync *vdev_sync;
16467
16468 errno = osif_vdev_sync_trans_start(net_dev, &vdev_sync);
16469 if (errno)
16470 return errno;
16471
Dustin Brown0e1e1622019-01-17 11:00:22 -080016472 errno = __wlan_hdd_cfg80211_change_iface(wiphy, net_dev, type,
16473 flags, params);
Dustin Brown0e1e1622019-01-17 11:00:22 -080016474
16475 osif_vdev_sync_trans_stop(vdev_sync);
16476
16477 return errno;
16478}
16479
Dustin Brown9ed30a52017-08-16 13:59:38 -070016480#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
Rajeev Kumar98edb772016-01-19 12:42:19 -080016481/**
16482 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
16483 * @wiphy: Pointer to the wiphy structure
16484 * @ndev: Pointer to the net device
16485 * @type: Interface type
16486 * @flags: Flags for change interface
16487 * @params: Pointer to change interface parameters
16488 *
16489 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016490 */
16491static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16492 struct net_device *ndev,
16493 enum nl80211_iftype type,
16494 u32 *flags,
16495 struct vif_params *params)
16496{
Dustin Brown0e1e1622019-01-17 11:00:22 -080016497 return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
16498 flags, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016499}
Dustin Brown9ed30a52017-08-16 13:59:38 -070016500#else
16501static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16502 struct net_device *ndev,
16503 enum nl80211_iftype type,
16504 struct vif_params *params)
16505{
Dustin Brown0e1e1622019-01-17 11:00:22 -080016506 return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
Dustin Brown9ed30a52017-08-16 13:59:38 -070016507 &params->flags, params);
Dustin Brown9ed30a52017-08-16 13:59:38 -070016508}
16509#endif /* KERNEL_VERSION(4, 12, 0) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016510
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053016511QDF_STATUS wlan_hdd_send_sta_authorized_event(
16512 struct hdd_adapter *adapter,
16513 struct hdd_context *hdd_ctx,
16514 const struct qdf_mac_addr *mac_addr)
16515{
16516 struct sk_buff *vendor_event;
16517 QDF_STATUS status;
16518 struct nl80211_sta_flag_update sta_flags;
16519
16520 hdd_enter();
16521 if (!hdd_ctx) {
16522 hdd_err("HDD context is null");
16523 return QDF_STATUS_E_INVAL;
16524 }
16525
16526 vendor_event =
16527 cfg80211_vendor_event_alloc(
16528 hdd_ctx->wiphy, &adapter->wdev, sizeof(sta_flags) +
16529 QDF_MAC_ADDR_SIZE + NLMSG_HDRLEN,
16530 QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX,
16531 GFP_KERNEL);
16532 if (!vendor_event) {
16533 hdd_err("cfg80211_vendor_event_alloc failed");
16534 return QDF_STATUS_E_FAILURE;
16535 }
16536
Ashish Kumar Dhanotiya0dd9b8b2019-06-04 20:21:06 +053016537 qdf_mem_zero(&sta_flags, sizeof(sta_flags));
16538
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053016539 sta_flags.mask |= BIT(NL80211_STA_FLAG_AUTHORIZED);
16540 sta_flags.set = true;
16541
16542 status = nla_put(vendor_event,
16543 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS,
16544 sizeof(struct nl80211_sta_flag_update),
16545 &sta_flags);
16546 if (status) {
16547 hdd_err("STA flag put fails");
16548 kfree_skb(vendor_event);
16549 return QDF_STATUS_E_FAILURE;
16550 }
16551 status = nla_put(vendor_event,
16552 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR,
16553 QDF_MAC_ADDR_SIZE, mac_addr->bytes);
16554 if (status) {
16555 hdd_err("STA MAC put fails");
16556 kfree_skb(vendor_event);
16557 return QDF_STATUS_E_FAILURE;
16558 }
16559
16560 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
16561
16562 hdd_exit();
16563 return QDF_STATUS_SUCCESS;
16564}
16565
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016566/**
16567 * __wlan_hdd_change_station() - change station
16568 * @wiphy: Pointer to the wiphy structure
16569 * @dev: Pointer to the net device.
16570 * @mac: bssid
16571 * @params: Pointer to station parameters
16572 *
16573 * Return: 0 for success, error number on failure.
16574 */
16575#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
16576static int __wlan_hdd_change_station(struct wiphy *wiphy,
16577 struct net_device *dev,
16578 const uint8_t *mac,
16579 struct station_parameters *params)
16580#else
16581static int __wlan_hdd_change_station(struct wiphy *wiphy,
16582 struct net_device *dev,
16583 uint8_t *mac,
16584 struct station_parameters *params)
16585#endif
16586{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016587 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016588 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016589 struct hdd_context *hdd_ctx;
Jeff Johnsond377dce2017-10-04 10:32:42 -070016590 struct hdd_station_ctx *sta_ctx;
Vignesh Viswanathan597d9012018-07-06 15:26:08 +053016591 struct hdd_ap_ctx *ap_ctx;
Jeff Johnsonf31df632019-03-23 11:53:28 -070016592 struct qdf_mac_addr sta_macaddr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016593 int ret;
16594
Dustin Brown491d54b2018-03-14 12:39:11 -070016595 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016596
Anurag Chouhan6d760662016-02-20 16:05:43 +053016597 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016598 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016599 return -EINVAL;
16600 }
16601
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016602 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
16603 TRACE_CODE_HDD_CHANGE_STATION,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016604 adapter->vdev_id, params->listen_interval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016605
Jeff Johnson48363022019-02-24 16:26:51 -080016606 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016607 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016608
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016609 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016610 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016611 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016612 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016613
Jeff Johnsond377dce2017-10-04 10:32:42 -070016614 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016615
Jeff Johnsonf31df632019-03-23 11:53:28 -070016616 qdf_mem_copy(sta_macaddr.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016617
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016618 if ((adapter->device_mode == QDF_SAP_MODE) ||
16619 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016620 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
Vignesh Viswanathan597d9012018-07-06 15:26:08 +053016621 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
16622 /*
16623 * For Encrypted SAP session, this will be done as
16624 * part of eSAP_STA_SET_KEY_EVENT
16625 */
16626 if (ap_ctx->encryption_type !=
16627 eCSR_ENCRYPT_TYPE_NONE) {
16628 hdd_debug("Encrypt type %d, not setting peer authorized now",
16629 ap_ctx->encryption_type);
16630 return 0;
16631 }
16632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016633 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016634 hdd_softap_change_sta_state(adapter,
Jeff Johnsonf31df632019-03-23 11:53:28 -070016635 &sta_macaddr,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080016636 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016637
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016638 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016639 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016640 return -EINVAL;
16641 }
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053016642 status = wlan_hdd_send_sta_authorized_event(
16643 adapter,
16644 hdd_ctx,
Jeff Johnsonf31df632019-03-23 11:53:28 -070016645 &sta_macaddr);
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053016646 if (status != QDF_STATUS_SUCCESS) {
16647 return -EINVAL;
16648 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016649 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016650 } else if ((adapter->device_mode == QDF_STA_MODE) ||
16651 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016652 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud1a28462017-09-06 22:55:48 +080016653#if defined(FEATURE_WLAN_TDLS)
Min Liu8c5d99e2018-09-10 17:18:44 +080016654 struct wlan_objmgr_vdev *vdev;
16655
16656 vdev = hdd_objmgr_get_vdev(adapter);
16657 if (!vdev)
16658 return -EINVAL;
16659 ret = wlan_cfg80211_tdls_update_peer(vdev, mac, params);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053016660 hdd_objmgr_put_vdev(vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016661#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080016662 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016663 }
Dustin Browne74003f2018-03-14 12:51:58 -070016664 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016665 return ret;
16666}
16667
16668/**
16669 * wlan_hdd_change_station() - cfg80211 change station handler function
16670 * @wiphy: Pointer to the wiphy structure
16671 * @dev: Pointer to the net device.
16672 * @mac: bssid
16673 * @params: Pointer to station parameters
16674 *
16675 * This is the cfg80211 change station handler function which invokes
16676 * the internal function @__wlan_hdd_change_station with
16677 * SSR protection.
16678 *
16679 * Return: 0 for success, error number on failure.
16680 */
16681#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
16682static int wlan_hdd_change_station(struct wiphy *wiphy,
16683 struct net_device *dev,
16684 const u8 *mac,
16685 struct station_parameters *params)
16686#else
16687static int wlan_hdd_change_station(struct wiphy *wiphy,
16688 struct net_device *dev,
16689 u8 *mac,
16690 struct station_parameters *params)
16691#endif
16692{
Dustin Brown1d31b082018-11-22 14:41:20 +053016693 int errno;
16694 struct osif_vdev_sync *vdev_sync;
16695
16696 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
16697 if (errno)
16698 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016699
Dustin Brown1d31b082018-11-22 14:41:20 +053016700 errno = __wlan_hdd_change_station(wiphy, dev, mac, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016701
Dustin Brown1d31b082018-11-22 14:41:20 +053016702 osif_vdev_sync_op_stop(vdev_sync);
16703
16704 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016705}
16706
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016707#ifdef FEATURE_WLAN_ESE
16708static bool hdd_is_krk_enc_type(uint32_t cipher_type)
16709{
16710 if (cipher_type == WLAN_CIPHER_SUITE_KRK)
16711 return true;
16712
16713 return false;
16714}
16715#else
16716static bool hdd_is_krk_enc_type(uint32_t cipher_type)
16717{
16718 return false;
16719}
16720#endif
16721
16722#if defined(FEATURE_WLAN_ESE) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
16723static bool hdd_is_btk_enc_type(uint32_t cipher_type)
16724{
16725 if (cipher_type == WLAN_CIPHER_SUITE_BTK)
16726 return true;
16727
16728 return false;
16729}
16730#else
16731static bool hdd_is_btk_enc_type(uint32_t cipher_type)
16732{
16733 return false;
16734}
16735#endif
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016736
Abhishek Ambure68677462019-09-13 12:44:26 +053016737#ifdef QCA_IBSS_SUPPORT
16738/**
16739 * wlan_hdd_add_key_ibss() - API to add IBSS key
16740 * @adapter: Pointer to adapter
16741 * @pairwise: need to add key pairwise
16742 * @key_index: key index
16743 * @mac_addr: Pointer to mac_addr
16744 * @params: Pointer to key params
16745 * @key_already_installed: pointer to key already installed state
16746 *
16747 * This API will add IBSS key for given mac address.
16748 *
16749 * Return: 0 for success, error number on failure.
16750 */
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016751static int wlan_hdd_add_key_ibss(struct hdd_adapter *adapter,
16752 bool pairwise, u8 key_index,
16753 const u8 *mac_addr, struct key_params *params,
16754 bool *key_already_installed)
16755{
16756 struct wlan_objmgr_vdev *vdev;
16757 int errno;
16758
16759 if (pairwise)
16760 return 0;
16761 /* if a key is already installed, block all subsequent ones */
16762 if (adapter->session.station.ibss_enc_key_installed) {
16763 hdd_debug("IBSS key installed already");
16764 *key_already_installed = true;
16765 return 0;
16766 }
16767 /*Set the group key */
16768 vdev = hdd_objmgr_get_vdev(adapter);
16769 if (!vdev)
16770 return -EINVAL;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016771 errno = wlan_cfg80211_crypto_add_key(vdev, WLAN_CRYPTO_KEY_TYPE_GROUP,
16772 key_index);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016773 if (errno) {
16774 hdd_err("add_ibss_key failed, errno: %d", errno);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053016775 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016776 return errno;
16777 }
16778 /* Save the keys here and call set_key for setting
16779 * the PTK after peer joins the IBSS network
16780 */
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016781 wlan_cfg80211_store_key(vdev, key_index, WLAN_CRYPTO_KEY_TYPE_UNICAST,
16782 mac_addr, params);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053016783 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016784 adapter->session.station.ibss_enc_key_installed = 1;
16785
16786 return 0;
16787}
Abhishek Ambure68677462019-09-13 12:44:26 +053016788#else
16789/**
16790 * wlan_hdd_add_key_ibss() - API to add IBSS key
16791 * @adapter: Pointer to adapter
16792 * @pairwise: need to add key pairwise
16793 * @key_index: key index
16794 * @mac_addr: Pointer to mac_addr
16795 * @params: Pointer to key params
16796 * @key_already_installed: pointer to key already installed state
16797 *
16798 * This function is dummy
16799 *
16800 * Return: 0
16801 */
16802static inline int
16803wlan_hdd_add_key_ibss(struct hdd_adapter *adapter,
16804 bool pairwise, u8 key_index,
16805 const u8 *mac_addr, struct key_params *params,
16806 bool *key_already_installed)
16807{
16808 return 0;
16809}
16810#endif
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016811
16812static int wlan_hdd_add_key_sap(struct hdd_adapter *adapter,
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016813 bool pairwise, u8 key_index,
16814 enum wlan_crypto_cipher_type cipher)
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016815{
16816 struct wlan_objmgr_vdev *vdev;
16817 int errno = 0;
16818 struct hdd_hostapd_state *hostapd_state =
16819 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
16820
16821 vdev = hdd_objmgr_get_vdev(adapter);
16822 if (!vdev)
16823 return -EINVAL;
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016824 if (hostapd_state->bss_state == BSS_START) {
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016825 errno =
16826 wlan_cfg80211_crypto_add_key(vdev, (pairwise ?
16827 WLAN_CRYPTO_KEY_TYPE_UNICAST :
16828 WLAN_CRYPTO_KEY_TYPE_GROUP),
16829 key_index);
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016830 if (!errno)
16831 wma_update_set_key(adapter->vdev_id, pairwise,
16832 key_index, cipher);
16833 }
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053016834 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016835
16836 return errno;
16837}
16838
16839static int wlan_hdd_add_key_sta(struct hdd_adapter *adapter,
16840 bool pairwise, u8 key_index,
16841 mac_handle_t mac_handle, bool *ft_mode)
16842{
16843 struct wlan_objmgr_vdev *vdev;
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016844 int errno;
16845 QDF_STATUS status;
16846
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016847 /* The supplicant may attempt to set the PTK once
16848 * pre-authentication is done. Save the key in the
16849 * UMAC and include it in the ADD BSS request
16850 */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016851 status = sme_check_ft_status(mac_handle, adapter->vdev_id);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016852 if (status == QDF_STATUS_SUCCESS) {
16853 *ft_mode = true;
16854 return 0;
16855 }
16856 vdev = hdd_objmgr_get_vdev(adapter);
16857 if (!vdev)
16858 return -EINVAL;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016859 errno = wlan_cfg80211_crypto_add_key(vdev, (pairwise ?
16860 WLAN_CRYPTO_KEY_TYPE_UNICAST :
16861 WLAN_CRYPTO_KEY_TYPE_GROUP),
16862 key_index);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053016863 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016864 if (!errno && adapter->send_mode_change) {
16865 wlan_hdd_send_mode_change_event();
16866 adapter->send_mode_change = false;
16867 }
16868
16869 return errno;
16870}
16871
16872static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
16873 struct net_device *ndev,
16874 u8 key_index, bool pairwise,
16875 const u8 *mac_addr,
16876 struct key_params *params)
16877{
16878 struct hdd_context *hdd_ctx;
16879 mac_handle_t mac_handle;
16880 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
16881 struct wlan_objmgr_vdev *vdev;
16882 bool key_already_installed = false, ft_mode = false;
16883 enum wlan_crypto_cipher_type cipher;
16884 int errno;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016885 struct qdf_mac_addr mac_address;
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016886
16887 hdd_enter();
16888
16889 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16890 hdd_err("Command not allowed in FTM mode");
16891 return -EINVAL;
16892 }
16893
Jeff Johnson48363022019-02-24 16:26:51 -080016894 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016895 return -EINVAL;
16896
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016897 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
16898 TRACE_CODE_HDD_CFG80211_ADD_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016899 adapter->vdev_id, params->key_len);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053016900
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016901 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16902 errno = wlan_hdd_validate_context(hdd_ctx);
16903 if (errno)
16904 return errno;
16905
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016906 hdd_debug("converged Device_mode %s(%d) index %d, pairwise %d",
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016907 qdf_opmode_str(adapter->device_mode),
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016908 adapter->device_mode, key_index, pairwise);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016909 mac_handle = hdd_ctx->mac_handle;
16910
16911 if (hdd_is_btk_enc_type(params->cipher))
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016912 return sme_add_key_btk(mac_handle, adapter->vdev_id,
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016913 params->key, params->key_len);
16914 if (hdd_is_krk_enc_type(params->cipher))
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016915 return sme_add_key_krk(mac_handle, adapter->vdev_id,
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016916 params->key, params->key_len);
16917
16918 vdev = hdd_objmgr_get_vdev(adapter);
16919 if (!vdev)
16920 return -EINVAL;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016921 if (!pairwise && ((adapter->device_mode == QDF_STA_MODE) ||
16922 (adapter->device_mode == QDF_P2P_CLIENT_MODE))) {
16923 qdf_mem_copy(mac_address.bytes,
Jeff Johnsone04b6992019-02-27 14:06:55 -080016924 adapter->session.station.conn_info.bssid.bytes,
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016925 QDF_MAC_ADDR_SIZE);
16926 } else {
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016927 if (mac_addr)
16928 qdf_mem_copy(mac_address.bytes, mac_addr,
16929 QDF_MAC_ADDR_SIZE);
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080016930 }
16931 errno = wlan_cfg80211_store_key(vdev, key_index,
16932 (pairwise ?
16933 WLAN_CRYPTO_KEY_TYPE_UNICAST :
16934 WLAN_CRYPTO_KEY_TYPE_GROUP),
16935 mac_address.bytes, params);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053016936 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016937 if (errno)
16938 return errno;
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016939 cipher = osif_nl_to_crypto_cipher_type(params->cipher);
Abhishek Singhf880a7d2019-04-29 14:51:11 +053016940 if (pairwise)
16941 wma_set_peer_ucast_cipher(mac_address.bytes, cipher);
16942
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016943 switch (adapter->device_mode) {
16944 case QDF_IBSS_MODE:
16945 errno = wlan_hdd_add_key_ibss(adapter, pairwise, key_index,
16946 mac_addr, params,
16947 &key_already_installed);
16948 if (key_already_installed)
16949 return 0;
16950 break;
16951 case QDF_SAP_MODE:
16952 case QDF_P2P_GO_MODE:
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016953 errno = wlan_hdd_add_key_sap(adapter, pairwise,
16954 key_index, cipher);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016955 break;
16956 case QDF_STA_MODE:
16957 case QDF_P2P_CLIENT_MODE:
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016958 errno = wlan_hdd_add_key_sta(adapter, pairwise, key_index,
16959 mac_handle, &ft_mode);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016960 if (ft_mode)
16961 return 0;
16962 break;
16963 default:
16964 break;
16965 }
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080016966 if (!errno && (adapter->device_mode != QDF_SAP_MODE))
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016967 wma_update_set_key(adapter->vdev_id, pairwise, key_index,
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016968 cipher);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070016969 hdd_exit();
16970
16971 return errno;
16972}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016973
16974static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
16975 struct net_device *ndev,
16976 u8 key_index, bool pairwise,
16977 const u8 *mac_addr,
16978 struct key_params *params)
16979{
Dustin Brown1d31b082018-11-22 14:41:20 +053016980 int errno;
16981 struct osif_vdev_sync *vdev_sync;
16982
16983 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
16984 if (errno)
16985 return errno;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070016986
Dustin Brown1d31b082018-11-22 14:41:20 +053016987 errno = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
16988 mac_addr, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016989
Dustin Brown1d31b082018-11-22 14:41:20 +053016990 osif_vdev_sync_op_stop(vdev_sync);
16991
16992 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016993}
16994
16995/*
16996 * FUNCTION: __wlan_hdd_cfg80211_get_key
16997 * This function is used to get the key information
16998 */
16999static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
17000 struct net_device *ndev,
17001 u8 key_index, bool pairwise,
17002 const u8 *mac_addr, void *cookie,
17003 void (*callback)(void *cookie,
17004 struct key_params *)
17005 )
17006{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017007 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070017008 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017009 struct key_params params;
17010
Dustin Brown491d54b2018-03-14 12:39:11 -070017011 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017012
Anurag Chouhan6d760662016-02-20 16:05:43 +053017013 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017014 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017015 return -EINVAL;
17016 }
17017
Jeff Johnson48363022019-02-24 16:26:51 -080017018 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Jiachao Wud58cfc92017-12-27 14:15:23 +080017019 return -EINVAL;
Jiachao Wud58cfc92017-12-27 14:15:23 +080017020
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017021 hdd_debug("Device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070017022 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017023
17024 memset(&params, 0, sizeof(params));
17025
17026 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017027 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017028 return -EINVAL;
17029 }
17030
Nachiket Kukaded9152832017-10-16 16:18:22 +053017031 if ((adapter->device_mode == QDF_SAP_MODE) ||
17032 (adapter->device_mode == QDF_P2P_GO_MODE)) {
17033 struct hdd_ap_ctx *ap_ctx =
17034 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070017035
Nachiket Kukaded9152832017-10-16 16:18:22 +053017036 roam_profile =
17037 wlan_sap_get_roam_profile(ap_ctx->sap_context);
17038 } else {
Jeff Johnson20227a92018-03-13 09:41:05 -070017039 roam_profile = hdd_roam_profile(adapter);
Nachiket Kukaded9152832017-10-16 16:18:22 +053017040 }
17041
Jeff Johnsond36fa332019-03-18 13:42:25 -070017042 if (!roam_profile) {
Jiachao Wud58cfc92017-12-27 14:15:23 +080017043 hdd_err("Get roam profile failed!");
17044 return -EINVAL;
17045 }
17046
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017047 switch (roam_profile->EncryptionType.encryptionType[0]) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017048 case eCSR_ENCRYPT_TYPE_NONE:
17049 params.cipher = IW_AUTH_CIPHER_NONE;
17050 break;
17051
17052 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
17053 case eCSR_ENCRYPT_TYPE_WEP40:
17054 params.cipher = WLAN_CIPHER_SUITE_WEP40;
17055 break;
17056
17057 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
17058 case eCSR_ENCRYPT_TYPE_WEP104:
17059 params.cipher = WLAN_CIPHER_SUITE_WEP104;
17060 break;
17061
17062 case eCSR_ENCRYPT_TYPE_TKIP:
17063 params.cipher = WLAN_CIPHER_SUITE_TKIP;
17064 break;
17065
17066 case eCSR_ENCRYPT_TYPE_AES:
17067 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
17068 break;
Mukul Sharma05504ac2017-06-08 12:35:53 +053017069 case eCSR_ENCRYPT_TYPE_AES_GCMP:
17070 params.cipher = WLAN_CIPHER_SUITE_GCMP;
17071 break;
17072 case eCSR_ENCRYPT_TYPE_AES_GCMP_256:
17073 params.cipher = WLAN_CIPHER_SUITE_GCMP_256;
17074 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017075 default:
17076 params.cipher = IW_AUTH_CIPHER_NONE;
17077 break;
17078 }
17079
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053017080 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
17081 TRACE_CODE_HDD_CFG80211_GET_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017082 adapter->vdev_id, params.cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017083
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017084 params.key_len = roam_profile->Keys.KeyLength[key_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017085 params.seq_len = 0;
17086 params.seq = NULL;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017087 params.key = &roam_profile->Keys.KeyMaterial[key_index][0];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017088 callback(cookie, &params);
17089
Dustin Browne74003f2018-03-14 12:51:58 -070017090 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017091 return 0;
17092}
17093
17094static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
17095 struct net_device *ndev,
17096 u8 key_index, bool pairwise,
17097 const u8 *mac_addr, void *cookie,
17098 void (*callback)(void *cookie,
17099 struct key_params *)
17100 )
17101{
Dustin Brown1d31b082018-11-22 14:41:20 +053017102 int errno;
17103 struct osif_vdev_sync *vdev_sync;
17104
17105 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
17106 if (errno)
17107 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017108
Dustin Brown1d31b082018-11-22 14:41:20 +053017109 errno = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
17110 mac_addr, cookie, callback);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017111
Dustin Brown1d31b082018-11-22 14:41:20 +053017112 osif_vdev_sync_op_stop(vdev_sync);
17113
17114 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017115}
17116
17117/**
17118 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
17119 * @wiphy: wiphy interface context
17120 * @ndev: pointer to net device
17121 * @key_index: Key index used in 802.11 frames
17122 * @unicast: true if it is unicast key
17123 * @multicast: true if it is multicast key
17124 *
17125 * This function is required for cfg80211_ops API.
17126 * It is used to delete the key information
17127 * Underlying hardware implementation does not have API to delete the
17128 * encryption key. It is automatically deleted when the peer is
17129 * removed. Hence this function currently does nothing.
17130 * Future implementation may interprete delete key operation to
17131 * replacing the key with a random junk value, effectively making it
17132 * useless.
17133 *
17134 * Return: status code, always 0.
17135 */
17136
17137static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
17138 struct net_device *ndev,
17139 u8 key_index,
17140 bool pairwise, const u8 *mac_addr)
17141{
Dustin Browne74003f2018-03-14 12:51:58 -070017142 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017143 return 0;
17144}
17145
17146/**
17147 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
17148 * @wiphy: Pointer to wiphy structure.
17149 * @dev: Pointer to net_device structure.
17150 * @key_index: key index
17151 * @pairwise: pairwise
17152 * @mac_addr: mac address
17153 *
17154 * This is the cfg80211 delete key handler function which invokes
17155 * the internal function @__wlan_hdd_cfg80211_del_key with
17156 * SSR protection.
17157 *
17158 * Return: 0 for success, error number on failure.
17159 */
17160static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
17161 struct net_device *dev,
17162 u8 key_index,
17163 bool pairwise, const u8 *mac_addr)
17164{
Dustin Brown1d31b082018-11-22 14:41:20 +053017165 int errno;
17166 struct osif_vdev_sync *vdev_sync;
17167
17168 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
17169 if (errno)
17170 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017171
Dustin Brown1d31b082018-11-22 14:41:20 +053017172 errno = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
17173 pairwise, mac_addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017174
Dustin Brown1d31b082018-11-22 14:41:20 +053017175 osif_vdev_sync_op_stop(vdev_sync);
17176
17177 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017178}
17179
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017180static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
17181 struct net_device *ndev,
17182 u8 key_index,
17183 bool unicast, bool multicast)
17184{
17185 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
17186 struct hdd_context *hdd_ctx;
17187 struct qdf_mac_addr bssid = QDF_MAC_ADDR_BCAST_INIT;
17188 struct hdd_station_ctx *sta_ctx;
17189 struct wlan_crypto_key *crypto_key;
17190 int ret;
17191 QDF_STATUS status;
17192
17193 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17194 hdd_err("Command not allowed in FTM mode");
17195 return -EINVAL;
17196 }
17197
Jeff Johnson48363022019-02-24 16:26:51 -080017198 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017199 return -EINVAL;
17200
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053017201 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
17202 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017203 adapter->vdev_id, key_index);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017204
17205 hdd_debug("Device_mode %s(%d) key_index = %d",
17206 qdf_opmode_str(adapter->device_mode),
17207 adapter->device_mode, key_index);
17208
17209 if (CSR_MAX_NUM_KEY <= key_index) {
17210 hdd_err("Invalid key index: %d", key_index);
17211 return -EINVAL;
17212 }
17213
17214 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17215 ret = wlan_hdd_validate_context(hdd_ctx);
17216
17217 if (0 != ret)
17218 return ret;
17219 crypto_key = wlan_crypto_get_key(adapter->vdev, key_index);
17220 hdd_debug("unicast %d, cipher %d", unicast, crypto_key->cipher_type);
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017221 if (!IS_WEP_CIPHER(crypto_key->cipher_type))
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017222 return 0;
17223 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17224 if (unicast)
17225 status =
17226 wlan_cfg80211_set_default_key(adapter->vdev, key_index,
Jeff Johnsone04b6992019-02-27 14:06:55 -080017227 &sta_ctx->conn_info.bssid);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017228 else
17229 status = wlan_cfg80211_set_default_key(adapter->vdev, key_index,
17230 &bssid);
17231 if (QDF_STATUS_SUCCESS != status) {
17232 hdd_err("ret fail status %d", ret);
17233 return -EINVAL;
17234 }
17235 if ((adapter->device_mode == QDF_STA_MODE) ||
17236 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080017237 ret =
17238 wlan_cfg80211_crypto_add_key(adapter->vdev, (unicast ?
17239 WLAN_CRYPTO_KEY_TYPE_UNICAST :
17240 WLAN_CRYPTO_KEY_TYPE_GROUP),
17241 key_index);
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017242 wma_update_set_key(adapter->vdev_id, unicast, key_index,
17243 crypto_key->cipher_type);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070017244 }
17245
17246 return ret;
17247}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017248
17249static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
17250 struct net_device *ndev,
17251 u8 key_index,
17252 bool unicast, bool multicast)
17253{
Dustin Brown1d31b082018-11-22 14:41:20 +053017254 int errno;
17255 struct osif_vdev_sync *vdev_sync;
17256
17257 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
17258 if (errno)
17259 return errno;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -070017260
Dustin Brown1d31b082018-11-22 14:41:20 +053017261 errno = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index,
17262 unicast, multicast);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017263
Dustin Brown1d31b082018-11-22 14:41:20 +053017264 osif_vdev_sync_op_stop(vdev_sync);
17265
17266 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017267}
17268
Abhishek Singh85283ae2019-03-08 12:00:51 +053017269void wlan_hdd_cfg80211_unlink_bss(struct hdd_adapter *adapter,
Ashish Kumar Dhanotiya3d8b0ae2019-07-10 20:55:56 +053017270 tSirMacAddr bssid, uint8_t *ssid,
17271 uint8_t ssid_len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017272{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017273 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017274 struct wireless_dev *wdev = dev->ieee80211_ptr;
17275 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017276
Ashish Kumar Dhanotiya3d8b0ae2019-07-10 20:55:56 +053017277 __wlan_cfg80211_unlink_bss_list(wiphy, bssid, ssid, ssid_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017278}
17279
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017280#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017281static inline int
17282wlan_hdd_get_frame_len(struct bss_description *bss_desc)
17283{
17284 return GET_IE_LEN_IN_BSS(bss_desc->length) + sizeof(qcom_ie_age);
17285}
17286
17287static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053017288 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017289{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017290 qcom_ie_age *qie_age = NULL;
Nachiket Kukade348ede72017-04-28 16:34:24 +053017291
17292 /*
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017293 * GPS Requirement: need age ie per entry. Using vendor specific.
17294 * Assuming this is the last IE, copy at the end
Nachiket Kukade348ede72017-04-28 16:34:24 +053017295 */
Abhishek Singhf1c16762018-03-07 10:48:46 +053017296 *ie_length -= sizeof(qcom_ie_age);
17297 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + *ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017298 qie_age->element_id = QCOM_VENDOR_IE_ID;
17299 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
17300 qie_age->oui_1 = QCOM_OUI1;
17301 qie_age->oui_2 = QCOM_OUI2;
17302 qie_age->oui_3 = QCOM_OUI3;
17303 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053017304 /*
17305 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
17306 * all bss related timestamp is in units of ms. Due to this when scan
17307 * results are sent to lowi the scan age is high.To address this,
17308 * send age in units of 1/10 ms.
17309 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017310 qie_age->age = (uint32_t)(qdf_mc_timer_get_system_time() -
17311 bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017312 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070017313 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
17314 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070017315 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
17316 sizeof(qie_age->seq_ctrl));
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017317}
17318#else
17319static inline int
17320wlan_hdd_get_frame_len(struct bss_description *bss_desc)
17321{
17322 return GET_IE_LEN_IN_BSS(bss_desc->length);
17323}
17324static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053017325 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017326{
17327}
17328#endif /* WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017329
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017330
17331struct cfg80211_bss *
17332wlan_hdd_inform_bss_frame(struct hdd_adapter *adapter,
17333 struct bss_description *bss_desc)
17334{
17335 struct wireless_dev *wdev = adapter->dev->ieee80211_ptr;
17336 struct wiphy *wiphy = wdev->wiphy;
Abhishek Singhf1c16762018-03-07 10:48:46 +053017337 uint32_t ie_length = wlan_hdd_get_frame_len(bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017338 const char *ie =
17339 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
Will Huang65d64252019-07-16 17:57:42 +080017340 uint32_t i;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017341 struct cfg80211_bss *bss_status = NULL;
17342 struct hdd_context *hdd_ctx;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017343 struct hdd_config *cfg_param;
17344 struct wlan_cfg80211_inform_bss bss_data = {0};
17345
17346 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17347 /*
17348 * wlan_hdd_validate_context should not be used here, In validate ctx
17349 * start_modules_in_progress or stop_modules_in_progress is validated,
17350 * If the start_modules_in_progress is set to true means the interface
17351 * is not UP yet if the stop_modules_in_progress means that interface
17352 * is already down. So in both the two scenario's driver should not be
17353 * informing bss to kernel. Hence removing the validate context.
17354 */
17355
17356 if (!hdd_ctx || !hdd_ctx->config) {
17357 hdd_debug("HDD context is Null");
17358 return NULL;
17359 }
17360
17361 if (cds_is_driver_recovering() ||
17362 cds_is_load_or_unload_in_progress()) {
17363 hdd_debug("Recovery or load/unload in progress. State: 0x%x",
17364 cds_get_driver_state());
17365 return NULL;
17366 }
17367
17368 cfg_param = hdd_ctx->config;
17369 bss_data.frame_len = ie_length + offsetof(struct ieee80211_mgmt,
17370 u.probe_resp.variable);
17371 bss_data.mgmt = qdf_mem_malloc(bss_data.frame_len);
Min Liu74a1a502018-10-10 19:59:07 +080017372 if (!bss_data.mgmt)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017373 return NULL;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017374
17375 memcpy(bss_data.mgmt->bssid, bss_desc->bssId, ETH_ALEN);
17376
17377 /* Android does not want the timestamp from the frame.
17378 * Instead it wants a monotonic increasing value
17379 */
Alan Chenf1096fd2019-11-11 09:39:06 -080017380 bss_data.mgmt->u.probe_resp.timestamp = qdf_get_monotonic_boottime();
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017381
17382 bss_data.mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
17383 bss_data.mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
17384
Abhishek Singhf1c16762018-03-07 10:48:46 +053017385 wlan_hdd_add_age_ie(bss_data.mgmt, &ie_length, bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017386
17387 memcpy(bss_data.mgmt->u.probe_resp.variable, ie, ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017388 if (bss_desc->fProbeRsp) {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017389 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017390 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
17391 } else {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017392 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017393 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
17394 }
17395
Will Huang65d64252019-07-16 17:57:42 +080017396 bss_data.chan = ieee80211_get_channel(wiphy, bss_desc->chan_freq);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017397 if (!bss_data.chan) {
Will Huang65d64252019-07-16 17:57:42 +080017398 hdd_err("chan pointer is NULL, chan freq: %d",
17399 bss_desc->chan_freq);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017400 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017401 return NULL;
17402 }
17403
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017404 /*
17405 * Based on .ini configuration, raw rssi can be reported for bss.
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070017406 * Raw rssi is typically used for estimating power.
17407 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017408 bss_data.rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070017409 bss_desc->rssi;
17410
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017411 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017412 bss_data.rssi = QDF_MIN(bss_data.rssi, 0) * 100;
17413
17414 bss_data.boottime_ns = bss_desc->scansystimensec;
17415
17416 /* Set all per chain rssi as invalid */
17417 for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++)
Yeshwanth Sriram Guntuka14ab04c2018-09-21 15:06:49 +053017418 bss_data.per_chain_rssi[i] = WLAN_INVALID_PER_CHAIN_RSSI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017419
Ashish Kumar Dhanotiya3d8b0ae2019-07-10 20:55:56 +053017420 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 -070017421 QDF_MAC_ADDR_ARRAY(bss_data.mgmt->bssid),
Abhishek Singhef6f38c2018-12-20 13:51:29 +053017422 bss_data.chan->center_freq, (int)(bss_data.rssi / 100),
17423 bss_desc->timeStamp[0], ((bss_desc->seq_ctrl.seqNumHi <<
Ashish Kumar Dhanotiya3d8b0ae2019-07-10 20:55:56 +053017424 HIGH_SEQ_NUM_OFFSET) | bss_desc->seq_ctrl.seqNumLo),
17425 bss_desc->fProbeRsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017426
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017427 bss_status = wlan_cfg80211_inform_bss_frame_data(wiphy, &bss_data);
Jeff Johnsonb8944722017-09-03 09:03:19 -070017428 hdd_ctx->beacon_probe_rsp_cnt_per_scan++;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017429 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017430 return bss_status;
17431}
17432
17433/**
17434 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017435 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017436 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017437 *
17438 * This function is used to update the BSS data base of CFG8011
17439 *
17440 * Return: struct cfg80211_bss pointer
17441 */
Jeff Johnson172237b2017-11-07 15:32:59 -080017442struct cfg80211_bss *
17443wlan_hdd_cfg80211_update_bss_db(struct hdd_adapter *adapter,
17444 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017445{
17446 tCsrRoamConnectedProfile roamProfile;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017447 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017448 struct cfg80211_bss *bss = NULL;
17449
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017450 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017451 sme_roam_get_connect_profile(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017452 &roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017453
Pragaspathi Thilagaraj96742ae2019-05-29 00:49:33 +053017454 if (roamProfile.bss_desc) {
17455 bss = wlan_hdd_inform_bss_frame(adapter, roamProfile.bss_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017456
Jeff Johnsond36fa332019-03-18 13:42:25 -070017457 if (!bss)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017458 hdd_debug("wlan_hdd_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017459
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080017460 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017461 } else {
Pragaspathi Thilagaraj96742ae2019-05-29 00:49:33 +053017462 hdd_err("roamProfile.bss_desc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017463 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017464 return bss;
17465}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017466
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017467/**
17468 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017469 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017470 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017471 * @index: Index
17472 * @preauth: Preauth flag
17473 *
17474 * This function is used to notify the supplicant of a new PMKSA candidate.
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017475 * PMK value is notified to supplicant whether PMK caching or OKC is enabled
17476 * in firmware or not. Supplicant needs this value becaue it uses PMK caching
17477 * by default.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017478 *
17479 * Return: 0 for success, non-zero for failure
17480 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017481int wlan_hdd_cfg80211_pmksa_candidate_notify(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080017482 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017483 int index, bool preauth)
17484{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017485 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017486
Dustin Brown491d54b2018-03-14 12:39:11 -070017487 hdd_enter();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017488 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017489
Jeff Johnsond36fa332019-03-18 13:42:25 -070017490 if (!roam_info) {
Jeff Johnsonfd060852017-10-04 10:50:51 -070017491 hdd_err("roam_info is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017492 return -EINVAL;
17493 }
17494
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070017495 hdd_info(QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017496 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnsonfd060852017-10-04 10:50:51 -070017497 roam_info->bssid.bytes,
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017498 preauth, GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017499 return 0;
17500}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017501
17502#ifdef FEATURE_WLAN_LFR_METRICS
17503/**
17504 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017505 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017506 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017507 *
17508 * 802.11r/LFR metrics reporting function to report preauth initiation
17509 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017510 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017511 */
17512#define MAX_LFR_METRICS_EVENT_LENGTH 100
Jeff Johnson172237b2017-11-07 15:32:59 -080017513QDF_STATUS
17514wlan_hdd_cfg80211_roam_metrics_preauth(struct hdd_adapter *adapter,
17515 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017516{
17517 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17518 union iwreq_data wrqu;
17519
Dustin Brown491d54b2018-03-14 12:39:11 -070017520 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017521
Jeff Johnsond36fa332019-03-18 13:42:25 -070017522 if (!adapter) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017523 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017524 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017525 }
17526
17527 /* create the event */
17528 memset(&wrqu, 0, sizeof(wrqu));
17529 memset(metrics_notification, 0, sizeof(metrics_notification));
17530
17531 wrqu.data.pointer = metrics_notification;
17532 wrqu.data.length = scnprintf(metrics_notification,
17533 sizeof(metrics_notification),
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070017534 "QCOM: LFR_PREAUTH_INIT " QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070017535 QDF_MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017536
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017537 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017538 metrics_notification);
17539
Dustin Browne74003f2018-03-14 12:51:58 -070017540 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017541
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017542 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017543}
17544
17545/**
17546 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017547 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017548 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017549 * @preauth_status: Preauth status
17550 *
17551 * 802.11r/LFR metrics reporting function to report handover initiation
17552 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017553 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017554 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017555QDF_STATUS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017556wlan_hdd_cfg80211_roam_metrics_preauth_status(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080017557 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017558 bool preauth_status)
17559{
17560 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17561 union iwreq_data wrqu;
17562
Dustin Brown491d54b2018-03-14 12:39:11 -070017563 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017564
Jeff Johnsond36fa332019-03-18 13:42:25 -070017565 if (!adapter) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017566 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017567 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017568 }
17569
17570 /* create the event */
17571 memset(&wrqu, 0, sizeof(wrqu));
17572 memset(metrics_notification, 0, sizeof(metrics_notification));
17573
17574 scnprintf(metrics_notification, sizeof(metrics_notification),
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070017575 "QCOM: LFR_PREAUTH_STATUS " QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070017576 QDF_MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017577
17578 if (1 == preauth_status)
17579 strlcat(metrics_notification, " true",
17580 sizeof(metrics_notification));
17581 else
17582 strlcat(metrics_notification, " false",
17583 sizeof(metrics_notification));
17584
17585 wrqu.data.pointer = metrics_notification;
17586 wrqu.data.length = strlen(metrics_notification);
17587
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017588 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017589 metrics_notification);
17590
Dustin Browne74003f2018-03-14 12:51:58 -070017591 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017592
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017593 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017594}
17595
17596/**
17597 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017598 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017599 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017600 *
17601 * 802.11r/LFR metrics reporting function to report handover initiation
17602 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017603 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017604 */
Jeff Johnson172237b2017-11-07 15:32:59 -080017605QDF_STATUS
17606wlan_hdd_cfg80211_roam_metrics_handover(struct hdd_adapter *adapter,
17607 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017608{
17609 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17610 union iwreq_data wrqu;
17611
Dustin Brown491d54b2018-03-14 12:39:11 -070017612 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017613
Jeff Johnsond36fa332019-03-18 13:42:25 -070017614 if (!adapter) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017615 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017616 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017617 }
17618
17619 /* create the event */
17620 memset(&wrqu, 0, sizeof(wrqu));
17621 memset(metrics_notification, 0, sizeof(metrics_notification));
17622
17623 wrqu.data.pointer = metrics_notification;
17624 wrqu.data.length = scnprintf(metrics_notification,
17625 sizeof(metrics_notification),
17626 "QCOM: LFR_PREAUTH_HANDOVER "
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070017627 QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070017628 QDF_MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017629
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017630 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017631 metrics_notification);
17632
Dustin Browne74003f2018-03-14 12:51:58 -070017633 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017634
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017635 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017636}
17637#endif
17638
Nirav Shah73713f72018-05-17 14:50:41 +053017639#ifdef FEATURE_MONITOR_MODE_SUPPORT
17640static
17641void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
wadesongc48ea292019-08-07 16:40:02 +080017642 uint32_t op_freq,
Nirav Shah73713f72018-05-17 14:50:41 +053017643 struct ch_params *ch_params)
17644{
17645 struct hdd_station_ctx *station_ctx =
17646 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17647 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
17648 enum hdd_dot11_mode hdd_dot11_mode;
17649 uint8_t ini_dot11_mode =
17650 (WLAN_HDD_GET_CTX(adapter))->config->dot11Mode;
17651
17652 hdd_debug("Dot11Mode is %u", ini_dot11_mode);
17653 switch (ini_dot11_mode) {
17654 case eHDD_DOT11_MODE_AUTO:
17655 case eHDD_DOT11_MODE_11ax:
17656 case eHDD_DOT11_MODE_11ax_ONLY:
17657 if (sme_is_feature_supported_by_fw(DOT11AX))
17658 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
17659 else if (sme_is_feature_supported_by_fw(DOT11AC))
17660 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
17661 else
17662 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17663 break;
17664 case eHDD_DOT11_MODE_11ac:
17665 case eHDD_DOT11_MODE_11ac_ONLY:
17666 if (sme_is_feature_supported_by_fw(DOT11AC))
17667 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
17668 else
17669 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17670 break;
17671 case eHDD_DOT11_MODE_11n:
17672 case eHDD_DOT11_MODE_11n_ONLY:
17673 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17674 break;
17675 default:
17676 hdd_dot11_mode = ini_dot11_mode;
17677 break;
17678 }
17679 ch_info->channel_width = ch_params->ch_width;
17680 ch_info->phy_mode =
17681 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
wadesongc48ea292019-08-07 16:40:02 +080017682 ch_info->freq = op_freq;
Nirav Shah73713f72018-05-17 14:50:41 +053017683 ch_info->cb_mode = ch_params->ch_width;
wadesong59e727c2019-07-25 13:52:06 +080017684 hdd_debug("ch_info width %d, phymode %d channel freq %d",
Nirav Shah73713f72018-05-17 14:50:41 +053017685 ch_info->channel_width, ch_info->phy_mode,
wadesong59e727c2019-07-25 13:52:06 +080017686 ch_info->freq);
Nirav Shah73713f72018-05-17 14:50:41 +053017687}
17688#else
17689static
17690void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
wadesongc48ea292019-08-07 16:40:02 +080017691 uint32_t op_freq,
Nirav Shah73713f72018-05-17 14:50:41 +053017692 struct ch_params *ch_params)
17693{
17694}
17695#endif
17696
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017697/**
17698 * hdd_select_cbmode() - select channel bonding mode
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017699 * @adapter: Pointer to adapter
Saket Jhad5c0e022019-11-18 16:53:47 -080017700 * @oper_freq: Operating frequency (MHz)
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017701 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017702 *
17703 * Return: none
17704 */
Saket Jhad5c0e022019-11-18 16:53:47 -080017705void hdd_select_cbmode(struct hdd_adapter *adapter, qdf_freq_t oper_freq,
wadesongc48ea292019-08-07 16:40:02 +080017706 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017707{
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070017708 uint32_t sec_ch_freq = 0;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017709 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017710
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017711 /*
17712 * CDS api expects secondary channel for calculating
17713 * the channel params
17714 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017715 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070017716 (WLAN_REG_IS_24GHZ_CH_FREQ(oper_freq))) {
17717 if (oper_freq >= 2412 && oper_freq <= 2432)
17718 sec_ch_freq = oper_freq + 20;
17719 else if (oper_freq >= 2437 && oper_freq <= 2472)
17720 sec_ch_freq = oper_freq - 20;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017721 }
17722
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017723 /* This call decides required channel bonding mode */
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070017724 wlan_reg_set_channel_params_for_freq(hdd_ctx->pdev, oper_freq,
17725 sec_ch_freq, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017726
Abhishek Singh9fee5182019-11-01 11:39:38 +053017727 if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070017728 hdd_mon_select_cbmode(adapter, oper_freq, ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017729}
17730
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017731/**
17732 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
17733 * @adapter: STA adapter
17734 * @roam_profile: STA roam profile
17735 *
17736 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
17737 *
17738 * Return: false if sta-sap conc is not allowed, else return true
17739 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070017740static
17741bool wlan_hdd_handle_sap_sta_dfs_conc(struct hdd_adapter *adapter,
17742 struct csr_roam_profile *roam_profile)
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017743{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070017744 struct hdd_context *hdd_ctx;
Jeff Johnsone5006672017-08-29 14:39:02 -070017745 struct hdd_adapter *ap_adapter;
Jeff Johnson87251032017-08-29 13:31:11 -070017746 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070017747 struct hdd_hostapd_state *hostapd_state;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017748 QDF_STATUS status;
Tushnim Bhattacharyyafaa9c012019-10-28 15:18:36 -070017749 uint32_t ch_freq = 0;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017750
17751 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17752 if (!hdd_ctx) {
17753 hdd_err("HDD context is NULL");
17754 return true;
17755 }
17756
17757 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
17758 /* probably no sap running, no handling required */
Jeff Johnsond36fa332019-03-18 13:42:25 -070017759 if (!ap_adapter)
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017760 return true;
17761
17762 /*
17763 * sap is not in started state, so it is fine to go ahead with sta.
17764 * if sap is currently doing CAC then don't allow sta to go further.
17765 */
17766 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
17767 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
17768 return true;
17769
17770 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
17771 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
17772 return false;
17773 }
17774
17775 /*
17776 * log and return error, if we allow STA to go through, we don't
17777 * know what is going to happen better stop sta connection
17778 */
17779 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
Jeff Johnsond36fa332019-03-18 13:42:25 -070017780 if (!hdd_ap_ctx) {
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017781 hdd_err("AP context not found");
17782 return false;
17783 }
17784
17785 /* sap is on non-dfs channel, nothing to handle */
Will Huang4b097f52019-08-29 10:51:56 -070017786 if (!wlan_reg_is_dfs_for_freq(hdd_ctx->pdev,
17787 hdd_ap_ctx->operating_chan_freq)) {
Arun Kumar Khandavalliafcb0552020-01-20 11:46:36 +053017788 hdd_debug("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017789 return true;
17790 }
17791 /*
17792 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053017793 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017794 */
Manikandan Mohan282c4b62019-08-14 17:42:22 -070017795 status = policy_mgr_get_channel_from_scan_result(
17796 hdd_ctx->psoc, roam_profile, &ch_freq);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017797
Nitesh Shah59774522016-09-16 15:14:21 +053017798 /*
17799 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
17800 * channels for roaming case.
17801 */
Tushnim Bhattacharyyafaa9c012019-10-28 15:18:36 -070017802 if (WLAN_REG_IS_24GHZ_CH_FREQ(ch_freq)) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017803 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053017804 return true;
17805 }
17806
17807 /*
Jeff Johnsondcf84ce2017-10-05 09:26:24 -070017808 * If channel is 0 or DFS or LTE unsafe then better to call pcl and
Tushnim Bhattacharyya9a929992017-06-18 00:59:09 -070017809 * find out the best channel. If channel is non-dfs 5 GHz then
17810 * better move SAP to STA's channel to make scc, so we have room
17811 * for 3port MCC scenario.
Nitesh Shah59774522016-09-16 15:14:21 +053017812 */
Tushnim Bhattacharyyafaa9c012019-10-28 15:18:36 -070017813 if (!ch_freq || wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, ch_freq) ||
17814 !policy_mgr_is_safe_channel(hdd_ctx->psoc, ch_freq))
17815 ch_freq = policy_mgr_get_nondfs_preferred_channel(
17816 hdd_ctx->psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017817
17818 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
17819 qdf_event_reset(&hostapd_state->qdf_event);
Bala Venkatesh8b9bbde2019-07-03 16:25:16 +053017820 wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, ap_adapter->vdev_id,
17821 CSA_REASON_STA_CONNECT_DFS_TO_NON_DFS);
17822
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017823 status = wlansap_set_channel_change_with_csa(
Tushnim Bhattacharyyafaa9c012019-10-28 15:18:36 -070017824 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), ch_freq,
Jeff Johnson91df29d2017-10-27 19:29:50 -070017825 hdd_ap_ctx->sap_config.ch_width_orig, false);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017826
17827 if (QDF_STATUS_SUCCESS != status) {
17828 hdd_err("Set channel with CSA IE failed, can't allow STA");
17829 return false;
17830 }
17831
17832 /*
17833 * wait here for SAP to finish the channel switch. When channel
17834 * switch happens, SAP sends few beacons with CSA_IE. After
17835 * successfully Transmission of those beacons, it will move its
17836 * state from started to disconnected and move to new channel.
17837 * once it moves to new channel, sap again moves its state
17838 * machine from disconnected to started and set this event.
17839 * wait for 10 secs to finish this.
17840 */
Nachiket Kukade0396b732017-11-14 16:35:16 +053017841 status = qdf_wait_for_event_completion(&hostapd_state->qdf_event, 10000);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017842 if (!QDF_IS_STATUS_SUCCESS(status)) {
17843 hdd_err("wait for qdf_event failed, STA not allowed!!");
17844 return false;
17845 }
17846
17847 return true;
17848}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017849
Abhishek Singhcfb44482017-03-10 12:42:37 +053017850#ifdef WLAN_FEATURE_11W
17851/**
17852 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
17853 * @roam_profile: pointer to roam profile
17854 *
17855 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
17856 * or pmf=2 is an explicit configuration in the supplicant
17857 * configuration, drop the connection request.
17858 *
17859 * Return: 0 if check result is valid, otherwise return error code
17860 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070017861static
17862int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053017863{
17864 if (roam_profile->MFPEnabled &&
Jeff Johnson20227a92018-03-13 09:41:05 -070017865 !(roam_profile->MFPRequired || roam_profile->MFPCapable)) {
Abhishek Singhcfb44482017-03-10 12:42:37 +053017866 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
17867 roam_profile->MFPEnabled,
17868 roam_profile->MFPRequired,
17869 roam_profile->MFPCapable);
17870 return -EINVAL;
17871 }
17872 return 0;
17873}
17874#else
17875static inline
Jeff Johnson61b5e982018-03-15 11:33:31 -070017876int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053017877{
17878 return 0;
17879}
17880#endif
17881
Krunal Soni31949422016-07-29 17:17:53 -070017882/**
17883 * wlan_hdd_cfg80211_connect_start() - to start the association process
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017884 * @adapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070017885 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017886 * @ssid_len: Length of ssid
17887 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070017888 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017889 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017890 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017891 *
17892 * This function is used to start the association process
17893 *
17894 * Return: 0 for success, non-zero for failure
17895 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017896static int wlan_hdd_cfg80211_connect_start(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017897 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070017898 const u8 *bssid, const u8 *bssid_hint,
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070017899 uint32_t oper_freq,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017900 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017901{
17902 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080017903 QDF_STATUS qdf_status;
Jeff Johnsonb8944722017-09-03 09:03:19 -070017904 struct hdd_context *hdd_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070017905 struct hdd_station_ctx *hdd_sta_ctx;
Jeff Johnson29c78672019-02-26 21:05:53 -080017906 uint32_t roam_id = INVALID_ROAM_ID;
Jeff Johnson61b5e982018-03-15 11:33:31 -070017907 struct csr_roam_profile *roam_profile;
Pragaspathi Thilagaraj7a1a08e2019-05-29 01:20:29 +053017908 enum csr_akm_type rsn_auth_type;
Jeff Johnson46b4f0e2019-03-08 10:48:35 -080017909 struct sme_config_params *sme_config;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017910 mac_handle_t mac_handle;
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +053017911 uint8_t wmm_mode = 0;
17912 uint8_t value = 0;
Min Liu8c5d99e2018-09-10 17:18:44 +080017913 struct wlan_objmgr_vdev *vdev;
Wu Gaoed616a12019-01-16 15:19:21 +080017914 uint32_t channel_bonding_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017915
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017916 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17917 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017918
Jeff Johnsonb8944722017-09-03 09:03:19 -070017919 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053017920 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017921 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017922
Srinivas Girigowdab8fdc642019-03-19 15:33:03 -070017923 if (WLAN_SSID_MAX_LEN < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017924 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017925 status = -EINVAL;
17926 goto ret_status;
17927 }
17928
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017929 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017930 hdd_err("Connection refused: conn in progress");
17931 status = -EINVAL;
17932 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017933 }
17934
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053017935 /* Disable roaming on all other adapters before connect start */
Abhinav Kumar523ca372019-08-30 16:28:19 +053017936 wlan_hdd_disable_roaming(adapter, RSO_CONNECT_START);
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053017937
Bala Venkatesh9bb9c052019-05-27 14:16:40 +053017938 hdd_notify_teardown_tdls_links(hdd_ctx->psoc);
Nitesh Shah273e4e52017-04-03 12:53:36 +053017939
Anurag Chouhand939d3d2016-07-20 17:45:48 +053017940 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
17941 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017942
Srinivas Dasariff782fb2019-10-10 18:37:24 +053017943 /*
17944 * Reset the ptk, gtk status flags to avoid using old/previous
17945 * connection status.
17946 */
17947 hdd_sta_ctx->conn_info.gtk_installed = false;
17948 hdd_sta_ctx->conn_info.ptk_installed = false;
Srinivas Dasari3b661522020-02-15 18:34:57 +053017949 adapter->last_disconnect_reason = 0;
Srinivas Dasariff782fb2019-10-10 18:37:24 +053017950
Jeff Johnson20227a92018-03-13 09:41:05 -070017951 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017952 if (roam_profile) {
Jeff Johnsond377dce2017-10-04 10:32:42 -070017953 struct hdd_station_ctx *sta_ctx;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070017954
Jeff Johnsond377dce2017-10-04 10:32:42 -070017955 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017956
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017957 /* Restart the opportunistic timer
17958 *
17959 * If hw_mode_change_in_progress is true, then wait
17960 * till firmware sends the callback for hw_mode change.
17961 *
17962 * Else set connect_in_progress as true and proceed.
17963 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017964 policy_mgr_restart_opportunistic_timer(
Dustin Brown76cd2932018-09-11 16:03:05 -070017965 hdd_ctx->psoc, false);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017966 if (policy_mgr_is_hw_mode_change_in_progress(
Dustin Brown76cd2932018-09-11 16:03:05 -070017967 hdd_ctx->psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053017968 qdf_status = policy_mgr_wait_for_connection_update(
Dustin Brown76cd2932018-09-11 16:03:05 -070017969 hdd_ctx->psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053017970 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017971 hdd_err("qdf wait for event failed!!");
17972 status = -EINVAL;
17973 goto ret_status;
17974 }
17975 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017976 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017977
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +053017978 status = ucfg_mlme_get_wmm_mode(hdd_ctx->psoc, &wmm_mode);
17979 if (!QDF_IS_STATUS_SUCCESS(status)) {
17980 hdd_err("Get wmm_mode failed");
17981 status = -EINVAL;
17982 goto ret_status;
17983 }
17984 if (HDD_WMM_USER_MODE_NO_QOS == wmm_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017985 /*QoS not enabled in cfg file */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017986 roam_profile->uapsd_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017987 } else {
17988 /*QoS enabled, update uapsd mask from cfg file */
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +053017989 status = ucfg_mlme_get_wmm_uapsd_mask(hdd_ctx->psoc,
17990 &value);
17991 if (!QDF_IS_STATUS_SUCCESS(status)) {
17992 hdd_err("Get uapsd_mask failed");
17993 status = -EINVAL;
17994 goto ret_status;
17995 }
17996 roam_profile->uapsd_mask = value;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017997 }
17998
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017999 roam_profile->SSIDs.numOfSSIDs = 1;
18000 roam_profile->SSIDs.SSIDList->SSID.length = ssid_len;
18001 qdf_mem_zero(roam_profile->SSIDs.SSIDList->SSID.ssId,
18002 sizeof(roam_profile->SSIDs.SSIDList->SSID.ssId));
18003 qdf_mem_copy((void *)(roam_profile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018004 ssid, ssid_len);
18005
Abhishek Singh3c9910e2017-01-06 17:56:47 +053018006 /* cleanup bssid hint */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018007 qdf_mem_zero(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053018008 QDF_MAC_ADDR_SIZE);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018009 qdf_mem_zero((void *)(roam_profile->BSSIDs.bssid),
Abhishek Singh3c9910e2017-01-06 17:56:47 +053018010 QDF_MAC_ADDR_SIZE);
18011
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018012 if (bssid) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018013 roam_profile->BSSIDs.numOfBSSIDs = 1;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018014 qdf_mem_copy((void *)(roam_profile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053018015 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070018016 /*
Jeff Johnsonfa7d9602018-05-06 11:25:31 -070018017 * Save BSSID in separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018018 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070018019 * association process. In case of join failure
18020 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018021 */
Jeff Johnson731bc322017-10-14 19:53:44 -070018022 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
18023 bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018024 } else if (bssid_hint) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018025 qdf_mem_copy(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053018026 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070018027 /*
18028 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018029 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070018030 * association process. In case of join failure
18031 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018032 */
Jeff Johnson731bc322017-10-14 19:53:44 -070018033 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053018034 bssid_hint, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018035 }
18036
Jeff Johnsonce4a8342017-10-14 13:12:22 -070018037 if (hdd_sta_ctx->wpa_versions) {
Jeff Johnson784efe22019-03-09 18:31:13 -080018038 hdd_set_genie_to_csr(adapter, &rsn_auth_type);
18039 hdd_set_csr_auth_type(adapter, rsn_auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018040 }
18041#ifdef FEATURE_WLAN_WAPI
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018042 if (adapter->wapi_info.wapi_mode) {
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018043 switch (adapter->wapi_info.wapi_auth_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018044 case WAPI_AUTH_MODE_PSK:
18045 {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018046 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018047 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
18048 break;
18049 }
18050 case WAPI_AUTH_MODE_CERT:
18051 {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018052 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018053 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
18054 break;
18055 }
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018056 default:
18057 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018058 } /* End of switch */
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018059 if (adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018060 WAPI_AUTH_MODE_PSK
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018061 || adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018062 WAPI_AUTH_MODE_CERT) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018063 roam_profile->AuthType.numEntries = 1;
18064 roam_profile->EncryptionType.numEntries = 1;
18065 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018066 eCSR_ENCRYPT_TYPE_WPI;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018067 roam_profile->mcEncryptionType.numEntries = 1;
18068 roam_profile->mcEncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018069 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
18070 }
18071 }
Krunal Soni31949422016-07-29 17:17:53 -070018072#endif
Min Liu8c5d99e2018-09-10 17:18:44 +080018073 vdev = hdd_objmgr_get_vdev(adapter);
18074 if (!vdev) {
18075 status = -EINVAL;
18076 goto conn_failure;
18077 }
18078 ucfg_pmo_flush_gtk_offload_req(vdev);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053018079 hdd_objmgr_put_vdev(vdev);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018080 roam_profile->csrPersona = adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018081
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070018082 if (oper_freq) {
wadesong24c869a2019-07-19 17:38:59 +080018083 roam_profile->ChannelInfo.freq_list = &oper_freq;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018084 roam_profile->ChannelInfo.numOfChannels = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018085 } else {
wadesong24c869a2019-07-19 17:38:59 +080018086 roam_profile->ChannelInfo.freq_list = NULL;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018087 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018088 }
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070018089 if (QDF_IBSS_MODE == adapter->device_mode && oper_freq) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018090 /*
18091 * Need to post the IBSS power save parameters
18092 * to WMA. WMA will configure this parameters
18093 * to firmware if power save is enabled by the
18094 * firmware.
18095 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018096 qdf_status = hdd_set_ibss_power_save_params(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018097
Abhishek Singh471652b2017-04-14 12:28:32 +053018098 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018099 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018100 status = -EINVAL;
18101 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018102 }
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018103 roam_profile->ch_params.ch_width =
Naveen Rawatc77e6e72016-08-05 15:19:03 -070018104 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053018105 /*
18106 * In IBSS mode while operating in 2.4 GHz,
18107 * the device supports only 20 MHz.
18108 */
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070018109 if (WLAN_REG_IS_24GHZ_CH_FREQ(oper_freq))
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018110 roam_profile->ch_params.ch_width =
Nitesh Shah87335a52016-09-05 15:47:32 +053018111 CH_WIDTH_20MHZ;
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070018112 hdd_select_cbmode(adapter, oper_freq,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018113 &roam_profile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018114 }
18115
Jeff Johnson20227a92018-03-13 09:41:05 -070018116 if (wlan_hdd_cfg80211_check_pmf_valid(roam_profile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018117 status = -EINVAL;
18118 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018119 }
18120
Krunal Soni31949422016-07-29 17:17:53 -070018121 /*
18122 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018123 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070018124 * enhancements, the supplicant is not issuing the scan command
18125 * now. So the unicast frames which are sent from the host are
18126 * not having the additional IEs. If it is P2P CLIENT and there
18127 * is no additional IE present in roamProfile, then use the
18128 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018129 */
18130
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018131 if ((adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018132 (!roam_profile->pAddIEScan)) {
18133 roam_profile->pAddIEScan =
Jeff Johnson37fa0402017-10-28 12:42:29 -070018134 &adapter->scan_info.scan_add_ie.addIEdata[0];
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018135 roam_profile->nAddIEScanLength =
Jeff Johnson37fa0402017-10-28 12:42:29 -070018136 adapter->scan_info.scan_add_ie.length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018137 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018138
Pragaspathi Thilagarajea0a7e12020-02-21 17:38:38 +053018139 /*
18140 * When connecting between two profiles there could be scenario
18141 * when the vdev create and vdev destroy clears the additional
18142 * scan IEs in roam profile and when the supplicant doesn't
18143 * issue scan request. So the unicast frames that are sent from
18144 * the STA doesn't have the additional MBO IE.
18145 */
18146 if (adapter->device_mode == QDF_STA_MODE &&
18147 (adapter->scan_info.default_scan_ies ||
18148 adapter->scan_info.scan_add_ie.length) &&
18149 !roam_profile->nAddIEScanLength) {
18150 if (adapter->scan_info.default_scan_ies) {
18151 roam_profile->pAddIEScan =
18152 adapter->scan_info.default_scan_ies;
18153 roam_profile->nAddIEScanLength =
18154 adapter->scan_info.default_scan_ies_len;
18155 } else if (adapter->scan_info.scan_add_ie.length) {
18156 roam_profile->pAddIEScan =
18157 adapter->scan_info.scan_add_ie.addIEdata;
18158 roam_profile->nAddIEScanLength =
18159 adapter->scan_info.scan_add_ie.length;
18160 }
18161 }
18162
Dustin Brown76cd2932018-09-11 16:03:05 -070018163 if ((policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) == true)
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018164 && (false == wlan_hdd_handle_sap_sta_dfs_conc(adapter,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018165 roam_profile))) {
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018166 hdd_err("sap-sta conc will fail, can't allow sta");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018167 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018168 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018169 status = -ENOMEM;
18170 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018171 }
18172
Anurag Chouhan600c3a02016-03-01 10:33:54 +053018173 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018174 if (!sme_config) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018175 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018176 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018177 status = -ENOMEM;
18178 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018179 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018180
18181 mac_handle = hdd_ctx->mac_handle;
18182 sme_get_config_param(mac_handle, sme_config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018183 /* These values are not sessionized. So, any change in these SME
18184 * configs on an older or parallel interface will affect the
18185 * cb mode. So, restoring the default INI params before starting
18186 * interfaces such as sta, cli etc.,
18187 */
Wu Gaoed616a12019-01-16 15:19:21 +080018188 ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc,
18189 &channel_bonding_mode);
Jeff Johnsone94ccd02019-04-02 15:02:56 -070018190 sme_config->csr_config.channelBondingMode5GHz =
Wu Gaoed616a12019-01-16 15:19:21 +080018191 channel_bonding_mode;
18192 ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
18193 &channel_bonding_mode);
Jeff Johnsone94ccd02019-04-02 15:02:56 -070018194 sme_config->csr_config.channelBondingMode24GHz =
Wu Gaoed616a12019-01-16 15:19:21 +080018195 channel_bonding_mode;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018196 sme_update_config(mac_handle, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053018197 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053018198 /*
18199 * Change conn_state to connecting before sme_roam_connect(),
18200 * because sme_roam_connect() has a direct path to call
18201 * hdd_sme_roam_callback(), which will change the conn_state
18202 * If direct path, conn_state will be accordingly changed to
18203 * NotConnected or Associated by either
18204 * hdd_association_completion_handler() or
18205 * hdd_dis_connect_handler() in sme_RoamCallback()if
18206 * sme_RomConnect is to be queued,
18207 * Connecting state will remain until it is completed.
18208 *
18209 * If connection state is not changed, connection state will
18210 * remain in eConnectionState_NotConnected state.
18211 * In hdd_association_completion_handler, "hddDisconInProgress"
18212 * is set to true if conn state is
18213 * eConnectionState_NotConnected.
18214 * If "hddDisconInProgress" is set to true then cfg80211 layer
18215 * is not informed of connect result indication which
18216 * is an issue.
18217 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018218 if (QDF_STA_MODE == adapter->device_mode ||
18219 QDF_P2P_CLIENT_MODE == adapter->device_mode)
18220 hdd_conn_set_connection_state(adapter,
Agrawal Ashish6b015762016-05-05 11:22:18 +053018221 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018222
Alok Kumarb64650c2018-03-23 17:05:11 +053018223 hdd_set_disconnect_status(adapter, false);
18224
Jingxiang Geb49aa302018-01-17 20:54:15 +080018225 qdf_runtime_pm_prevent_suspend(
18226 &hdd_ctx->runtime_context.connect);
Padma, Santhosh Kumarc88de482018-04-09 16:17:04 +053018227 hdd_prevent_suspend_timeout(HDD_WAKELOCK_CONNECT_COMPLETE,
Dustin Brownceed67e2017-05-26 11:57:31 -070018228 WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018229 qdf_status = sme_roam_connect(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018230 adapter->vdev_id, roam_profile,
Jeff Johnson29c78672019-02-26 21:05:53 -080018231 &roam_id);
Abhishek Singh471652b2017-04-14 12:28:32 +053018232 if (QDF_IS_STATUS_ERROR(qdf_status))
18233 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018234
Rajeev Kumard31e1542017-01-13 14:37:42 -080018235 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018236 (QDF_STA_MODE == adapter->device_mode ||
18237 QDF_P2P_CLIENT_MODE == adapter->device_mode)) {
Abhishek Singh4ec44a72020-02-03 15:07:34 +053018238 hdd_err("Vdev %d connect failed with status %d",
18239 adapter->vdev_id, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018240 /* change back to NotAssociated */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018241 hdd_conn_set_connection_state(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018242 eConnectionState_NotConnected);
Jingxiang Geb49aa302018-01-17 20:54:15 +080018243 qdf_runtime_pm_allow_suspend(
18244 &hdd_ctx->runtime_context.connect);
Dustin Brownceed67e2017-05-26 11:57:31 -070018245 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018246 }
18247
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018248 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018249 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018250
wadesong24c869a2019-07-19 17:38:59 +080018251 roam_profile->ChannelInfo.freq_list = NULL;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018252 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018253 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018254 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018255 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018256 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018257 goto ret_status;
18258
18259conn_failure:
18260 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018261 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018262
18263ret_status:
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053018264 /*
18265 * Enable roaming on other STA adapter for failure case.
18266 * For success case, it is enabled in assoc completion handler
18267 */
18268 if (status)
Abhinav Kumar523ca372019-08-30 16:28:19 +053018269 wlan_hdd_enable_roaming(adapter, RSO_CONNECT_START);
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053018270
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018271 return status;
18272}
18273
18274/**
18275 * wlan_hdd_cfg80211_set_auth_type() - set auth type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018276 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018277 * @auth_type: Auth type
18278 *
18279 * This function is used to set the authentication type (OPEN/SHARED).
18280 *
18281 * Return: 0 for success, non-zero for failure
18282 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018283static int wlan_hdd_cfg80211_set_auth_type(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018284 enum nl80211_auth_type auth_type)
18285{
Jeff Johnsond377dce2017-10-04 10:32:42 -070018286 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018287 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070018288 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018289
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018290 /*set authentication type */
18291 switch (auth_type) {
18292 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnson96e33512019-02-27 15:10:21 -080018293 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_AUTOSWITCH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018294 break;
18295
18296 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018297 case NL80211_AUTHTYPE_FT:
Jeff Johnson96e33512019-02-27 15:10:21 -080018298 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018299 break;
18300
18301 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnson96e33512019-02-27 15:10:21 -080018302 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_SHARED_KEY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018303 break;
18304#ifdef FEATURE_WLAN_ESE
18305 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnson96e33512019-02-27 15:10:21 -080018306 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_CCKM_WPA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018307 break;
18308#endif
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053018309#if defined(WLAN_FEATURE_FILS_SK) && \
18310 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
18311 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018312 case NL80211_AUTHTYPE_FILS_SK:
Jeff Johnson96e33512019-02-27 15:10:21 -080018313 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018314 break;
18315#endif
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018316 case NL80211_AUTHTYPE_SAE:
Jeff Johnson96e33512019-02-27 15:10:21 -080018317 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_SAE;
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018318 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018319 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018320 hdd_err("Unsupported authentication type: %d", auth_type);
Jeff Johnson96e33512019-02-27 15:10:21 -080018321 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_UNKNOWN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018322 return -EINVAL;
18323 }
18324
Jeff Johnson20227a92018-03-13 09:41:05 -070018325 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson96e33512019-02-27 15:10:21 -080018326 roam_profile->AuthType.authType[0] = sta_ctx->conn_info.auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018327 return 0;
18328}
18329
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053018330#if defined(WLAN_FEATURE_FILS_SK) && \
18331 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
18332 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Jeff Johnson20227a92018-03-13 09:41:05 -070018333static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018334{
18335 struct cds_fils_connection_info *fils_con_info;
18336
Jeff Johnson20227a92018-03-13 09:41:05 -070018337 fils_con_info = roam_profile->fils_con_info;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018338 if (!fils_con_info) {
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018339 hdd_err("No valid Roam profile");
18340 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018341 }
18342
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018343 return true;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018344}
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018345
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018346static enum eAniAuthType wlan_hdd_get_fils_auth_type(
18347 enum nl80211_auth_type auth)
18348{
18349 switch (auth) {
18350 case NL80211_AUTHTYPE_FILS_SK:
18351 return SIR_FILS_SK_WITHOUT_PFS;
18352 case NL80211_AUTHTYPE_FILS_SK_PFS:
18353 return SIR_FILS_SK_WITH_PFS;
18354 case NL80211_AUTHTYPE_FILS_PK:
18355 return SIR_FILS_PK_AUTH;
18356 default:
18357 return eSIR_DONOT_USE_AUTH_TYPE;
18358 }
18359}
18360
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018361static bool wlan_hdd_fils_data_in_limits(struct cfg80211_connect_params *req)
18362{
18363 hdd_debug("seq=%d auth=%d lengths: user=%zu rrk=%zu realm=%zu",
18364 req->fils_erp_next_seq_num, req->auth_type,
18365 req->fils_erp_username_len, req->fils_erp_rrk_len,
18366 req->fils_erp_realm_len);
18367 if (!req->fils_erp_rrk_len || !req->fils_erp_realm_len ||
18368 !req->fils_erp_username_len ||
18369 req->fils_erp_rrk_len > FILS_MAX_RRK_LENGTH ||
18370 req->fils_erp_realm_len > FILS_MAX_REALM_LEN ||
18371 req->fils_erp_username_len > FILS_MAX_KEYNAME_NAI_LENGTH) {
18372 hdd_err("length incorrect, user=%zu rrk=%zu realm=%zu",
18373 req->fils_erp_username_len, req->fils_erp_rrk_len,
18374 req->fils_erp_realm_len);
18375 return false;
18376 }
18377
bings77a35ac2018-06-01 15:10:44 +080018378 if (!req->fils_erp_rrk || !req->fils_erp_realm ||
18379 !req->fils_erp_username) {
18380 hdd_err("buffer incorrect, user=%pK rrk=%pK realm=%pK",
18381 req->fils_erp_username, req->fils_erp_rrk,
18382 req->fils_erp_realm);
18383 return false;
18384 }
18385
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018386 return true;
18387}
18388
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018389/**
18390 * wlan_hdd_cfg80211_set_fils_config() - set fils config params during connect
18391 * @adapter: Pointer to adapter
18392 * @req: Pointer to fils parameters
18393 *
18394 * Return: 0 for success, non-zero for failure
18395 */
18396static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
18397 struct cfg80211_connect_params *req)
18398{
Jeff Johnson61b5e982018-03-15 11:33:31 -070018399 struct csr_roam_profile *roam_profile;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018400 enum eAniAuthType auth_type;
18401 uint8_t *buf;
Karthik Kantamneni2231a232018-09-11 15:45:55 +053018402 bool value;
18403 QDF_STATUS status;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018404 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
18405
Jeff Johnson20227a92018-03-13 09:41:05 -070018406 roam_profile = hdd_roam_profile(adapter);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018407
Karthik Kantamneni2231a232018-09-11 15:45:55 +053018408 value = 0;
Dustin Brown05d81302018-09-11 16:49:22 -070018409 status = ucfg_mlme_get_fils_enabled_info(hdd_ctx->psoc, &value);
Karthik Kantamneni2231a232018-09-11 15:45:55 +053018410 if (QDF_IS_STATUS_ERROR(status) || !value) {
18411 hdd_err("get_fils_enabled status: %d fils_enabled: %d",
18412 status, value);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018413 return -EINVAL;
18414 }
Karthik Kantamneni2231a232018-09-11 15:45:55 +053018415
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018416 hdd_clear_fils_connection_info(adapter);
18417 roam_profile->fils_con_info =
18418 qdf_mem_malloc(sizeof(*roam_profile->fils_con_info));
18419
Min Liu74a1a502018-10-10 19:59:07 +080018420 if (!roam_profile->fils_con_info)
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018421 return -EINVAL;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018422 /*
18423 * The initial connection for FILS may happen with an OPEN
18424 * auth type. Hence we need to allow the connection to go
18425 * through in that case as well. Below is_fils_connection
18426 * flag is propagated down to CSR and PE sessions through
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018427 * the JOIN request. As the flag is used, do not free the
18428 * memory allocated to fils_con_info and return success.
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018429 */
18430 if (req->auth_type != NL80211_AUTHTYPE_FILS_SK) {
18431 roam_profile->fils_con_info->is_fils_connection = false;
18432 return 0;
18433 }
18434
18435 /*
18436 * Once above check is done, then we can check for valid FILS
18437 * auth types. Currently only NL80211_AUTHTYPE_FILS_SK is
18438 * supported. Once all auth types are supported, then we can
18439 * merge these 2 conditions into one.
18440 */
18441 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
18442 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
18443 hdd_err("invalid auth type for fils %d", req->auth_type);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018444 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018445 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018446 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080018447 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018448
18449 roam_profile->fils_con_info->is_fils_connection = true;
18450 roam_profile->fils_con_info->sequence_number =
Pragaspathi Thilagaraj87a60af2019-02-20 20:42:47 +053018451 (req->fils_erp_next_seq_num + 1);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018452 roam_profile->fils_con_info->auth_type = auth_type;
18453
18454 roam_profile->fils_con_info->r_rk_length =
18455 req->fils_erp_rrk_len;
18456 if (req->fils_erp_rrk_len)
18457 qdf_mem_copy(roam_profile->fils_con_info->r_rk,
18458 req->fils_erp_rrk,
18459 roam_profile->fils_con_info->r_rk_length);
18460
18461 roam_profile->fils_con_info->realm_len = req->fils_erp_realm_len;
18462 if (req->fils_erp_realm_len)
18463 qdf_mem_copy(roam_profile->fils_con_info->realm,
18464 req->fils_erp_realm,
18465 roam_profile->fils_con_info->realm_len);
18466
18467 roam_profile->fils_con_info->key_nai_length =
18468 req->fils_erp_username_len + sizeof(char) +
18469 req->fils_erp_realm_len;
18470 hdd_debug("key_nai_length = %d",
18471 roam_profile->fils_con_info->key_nai_length);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018472 if (roam_profile->fils_con_info->key_nai_length >
18473 FILS_MAX_KEYNAME_NAI_LENGTH) {
18474 hdd_err("Do not allow FILS conn due to excess NAI Length %d",
18475 roam_profile->fils_con_info->key_nai_length);
18476 goto fils_conn_fail;
18477 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018478 buf = roam_profile->fils_con_info->keyname_nai;
18479 qdf_mem_copy(buf, req->fils_erp_username, req->fils_erp_username_len);
18480 buf += req->fils_erp_username_len;
18481 *buf++ = '@';
18482 qdf_mem_copy(buf, req->fils_erp_realm, req->fils_erp_realm_len);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018483
18484 return 0;
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018485
18486fils_conn_fail:
18487 if (roam_profile->fils_con_info) {
18488 qdf_mem_free(roam_profile->fils_con_info);
18489 roam_profile->fils_con_info = NULL;
18490 }
18491 return -EINVAL;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018492}
18493
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018494static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
18495{
18496 switch (key_mgmt) {
18497 case WLAN_AKM_SUITE_FILS_SHA256:
18498 case WLAN_AKM_SUITE_FILS_SHA384:
18499 case WLAN_AKM_SUITE_FT_FILS_SHA256:
18500 case WLAN_AKM_SUITE_FT_FILS_SHA384:
18501 return true;
18502 default:
18503 return false;
18504 }
18505}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018506
18507static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
18508{
18509 enum nl80211_auth_type auth_type = req->auth_type;
18510 /*
18511 * Below n_akm_suites is defined as int in the kernel, even though it
18512 * is supposed to be unsigned.
18513 */
18514 int num_akm_suites = req->crypto.n_akm_suites;
18515 uint32_t key_mgmt = req->crypto.akm_suites[0];
18516 enum eAniAuthType fils_auth_type =
18517 wlan_hdd_get_fils_auth_type(req->auth_type);
18518
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018519 if (num_akm_suites <= 0)
18520 return false;
18521
18522 /*
18523 * Auth type will be either be OPEN or FILS type for a FILS connection
18524 */
18525 if ((auth_type != NL80211_AUTHTYPE_OPEN_SYSTEM) &&
Abhishek Singh4ec44a72020-02-03 15:07:34 +053018526 (fils_auth_type == eSIR_DONOT_USE_AUTH_TYPE))
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018527 return false;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018528
Abhishek Singh4ec44a72020-02-03 15:07:34 +053018529 if (!wlan_hdd_is_akm_suite_fils(key_mgmt))
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018530 return false;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053018531
18532 hdd_debug("Fils Auth %d AKM %d", fils_auth_type, key_mgmt);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018533
18534 return true;
18535}
18536
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018537#else
Jeff Johnson20227a92018-03-13 09:41:05 -070018538static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018539{
18540 return true;
18541}
18542
18543static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
18544 struct cfg80211_connect_params *req)
18545{
18546 return 0;
18547}
18548
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018549static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
18550{
18551 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018552}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018553
18554static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
18555{
18556 return false;
18557}
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018558#endif
18559
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018560/**
18561 * wlan_hdd_set_akm_suite() - set key management type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018562 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018563 * @key_mgmt: Key management type
18564 *
18565 * This function is used to set the key mgmt type(PSK/8021x).
18566 *
18567 * Return: 0 for success, non-zero for failure
18568 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018569static int wlan_hdd_set_akm_suite(struct hdd_adapter *adapter, u32 key_mgmt)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018570{
Jeff Johnson37ecea42018-03-18 17:54:40 -070018571 struct hdd_station_ctx *sta_ctx;
Jeff Johnson61b5e982018-03-15 11:33:31 -070018572 struct csr_roam_profile *roam_profile;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018573
Jeff Johnson20227a92018-03-13 09:41:05 -070018574 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018575
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018576 if (wlan_hdd_is_akm_suite_fils(key_mgmt) &&
Jeff Johnson20227a92018-03-13 09:41:05 -070018577 !hdd_validate_fils_info_ptr(roam_profile))
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018578 return -EINVAL;
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018579#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018580#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018581#endif
18582#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018583#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018584#endif
Jeff Johnson37ecea42018-03-18 17:54:40 -070018585
18586 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
18587
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018588 /*set key mgmt type */
18589 switch (key_mgmt) {
18590 case WLAN_AKM_SUITE_PSK:
18591 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018592 case WLAN_AKM_SUITE_FT_PSK:
Abhishek Singh02cb9e02017-08-30 17:39:50 +053018593 case WLAN_AKM_SUITE_DPP_RSN:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018594 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_PSK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018595 break;
18596
18597 case WLAN_AKM_SUITE_8021X_SHA256:
18598 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018599 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018600 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018601 break;
18602#ifdef FEATURE_WLAN_ESE
18603#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018604 case WLAN_AKM_SUITE_CCKM:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018605 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_CCKM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018606 break;
18607#endif
18608#ifndef WLAN_AKM_SUITE_OSEN
18609#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
18610#endif
18611 case WLAN_AKM_SUITE_OSEN:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018612 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018613 break;
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053018614#if defined(WLAN_FEATURE_FILS_SK) && \
18615 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
18616 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053018617 case WLAN_AKM_SUITE_FILS_SHA256:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018618 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018619 roam_profile->fils_con_info->akm_type =
18620 eCSR_AUTH_TYPE_FILS_SHA256;
18621 break;
18622
18623 case WLAN_AKM_SUITE_FILS_SHA384:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018624 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018625 roam_profile->fils_con_info->akm_type =
18626 eCSR_AUTH_TYPE_FILS_SHA384;
18627 break;
18628
18629 case WLAN_AKM_SUITE_FT_FILS_SHA256:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018630 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018631 roam_profile->fils_con_info->akm_type =
18632 eCSR_AUTH_TYPE_FT_FILS_SHA256;
18633 break;
18634
18635 case WLAN_AKM_SUITE_FT_FILS_SHA384:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018636 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018637 roam_profile->fils_con_info->akm_type =
18638 eCSR_AUTH_TYPE_FT_FILS_SHA384;
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053018639 break;
18640#endif
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053018641
18642 case WLAN_AKM_SUITE_OWE:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018643 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053018644 break;
18645
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018646 case WLAN_AKM_SUITE_EAP_SHA256:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018647 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018648 break;
18649 case WLAN_AKM_SUITE_EAP_SHA384:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018650 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018651 break;
18652
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018653 case WLAN_AKM_SUITE_SAE:
Jeff Johnson37ecea42018-03-18 17:54:40 -070018654 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018655 break;
18656
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +053018657 case WLAN_AKM_SUITE_FT_SAE:
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +053018658 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
18659 break;
18660
18661 case WLAN_AKM_SUITE_FT_EAP_SHA_384:
Pragaspathi Thilagarajeb367282019-02-19 00:42:28 +053018662 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
18663 break;
18664
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018665 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018666 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018667 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018668 }
18669 return 0;
18670}
18671
18672/**
18673 * wlan_hdd_cfg80211_set_cipher() - set encryption type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018674 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018675 * @cipher: Cipher type
18676 * @ucast: Unicast flag
18677 *
18678 * This function is used to set the encryption type
18679 * (NONE/WEP40/WEP104/TKIP/CCMP).
18680 *
18681 * Return: 0 for success, non-zero for failure
18682 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018683static int wlan_hdd_cfg80211_set_cipher(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018684 u32 cipher, bool ucast)
18685{
18686 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Jeff Johnsond377dce2017-10-04 10:32:42 -070018687 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018688 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070018689 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018690
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018691 if (!cipher) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018692 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
18693 } else {
18694
18695 /*set encryption method */
18696 switch (cipher) {
18697 case IW_AUTH_CIPHER_NONE:
18698 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
18699 break;
18700
18701 case WLAN_CIPHER_SUITE_WEP40:
18702 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
18703 break;
18704
18705 case WLAN_CIPHER_SUITE_WEP104:
18706 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
18707 break;
18708
18709 case WLAN_CIPHER_SUITE_TKIP:
18710 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
18711 break;
18712
18713 case WLAN_CIPHER_SUITE_CCMP:
18714 encryptionType = eCSR_ENCRYPT_TYPE_AES;
18715 break;
18716#ifdef FEATURE_WLAN_WAPI
18717 case WLAN_CIPHER_SUITE_SMS4:
18718 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
18719 break;
18720#endif
18721
18722#ifdef FEATURE_WLAN_ESE
18723 case WLAN_CIPHER_SUITE_KRK:
18724 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
18725 break;
18726#ifdef WLAN_FEATURE_ROAM_OFFLOAD
18727 case WLAN_CIPHER_SUITE_BTK:
18728 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
18729 break;
18730#endif
18731#endif
Mukul Sharma05504ac2017-06-08 12:35:53 +053018732 case WLAN_CIPHER_SUITE_GCMP:
18733 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP;
18734 break;
18735 case WLAN_CIPHER_SUITE_GCMP_256:
18736 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP_256;
18737 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018738 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018739 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018740 return -EOPNOTSUPP;
18741 }
18742 }
18743
Jeff Johnson20227a92018-03-13 09:41:05 -070018744 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018745 if (ucast) {
Jeff Johnsonb1959842019-02-27 13:04:04 -080018746 sta_ctx->conn_info.uc_encrypt_type = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070018747 roam_profile->EncryptionType.numEntries = 1;
18748 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018749 encryptionType;
18750 } else {
Jeff Johnsonb1959842019-02-27 13:04:04 -080018751 sta_ctx->conn_info.mc_encrypt_type = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070018752 roam_profile->mcEncryptionType.numEntries = 1;
18753 roam_profile->mcEncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018754 encryptionType;
18755 }
18756
18757 return 0;
18758}
18759
18760/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018761 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
Jeff Johnson20227a92018-03-13 09:41:05 -070018762 * @adapter: Pointer to adapter
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018763 * @gen_ie: Pointer to IE data
18764 * @len: length of IE data
18765 *
18766 * Return: 0 for success, non-zero for failure
18767 */
Jeff Johnson20227a92018-03-13 09:41:05 -070018768static int wlan_hdd_add_assoc_ie(struct hdd_adapter *adapter,
18769 const uint8_t *gen_ie, uint16_t len)
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018770{
Jeff Johnson20227a92018-03-13 09:41:05 -070018771 struct csr_roam_profile *roam_profile;
18772 tSirAddie *assoc_add_ie;
18773 uint16_t cur_add_ie_len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018774
Jeff Johnson20227a92018-03-13 09:41:05 -070018775 assoc_add_ie = hdd_assoc_additional_ie(adapter);
18776 cur_add_ie_len = assoc_add_ie->length;
18777 if (SIR_MAC_MAX_ADD_IE_LENGTH < (cur_add_ie_len + len)) {
18778 hdd_err("current len %u, new ie of len %u will overflow",
18779 cur_add_ie_len, len);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018780 return -ENOMEM;
18781 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018782 memcpy(assoc_add_ie->addIEdata + cur_add_ie_len, gen_ie, len);
18783 assoc_add_ie->length += len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018784
Jeff Johnson20227a92018-03-13 09:41:05 -070018785 roam_profile = hdd_roam_profile(adapter);
18786 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
18787 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
18788
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018789 return 0;
18790}
18791
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018792#ifdef WLAN_FEATURE_FILS_SK
18793/**
18794 * wlan_hdd_save_hlp_ie - API to save HLP IE
18795 * @roam_profile: Pointer to roam profile
18796 * @gen_ie: IE buffer to store
18797 * @len: length of the IE buffer @gen_ie
18798 * @flush: Flush the older saved HLP if any
18799 *
18800 * Return: None
18801 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070018802static void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070018803 const uint8_t *gen_ie, uint16_t len,
18804 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018805{
18806 uint8_t *hlp_ie = roam_profile->hlp_ie;
18807
18808 if (flush) {
18809 roam_profile->hlp_ie_len = 0;
18810 if (hlp_ie) {
18811 qdf_mem_free(hlp_ie);
18812 roam_profile->hlp_ie = NULL;
18813 }
18814 }
18815
18816 if ((roam_profile->hlp_ie_len +
18817 len) > FILS_MAX_HLP_DATA_LEN) {
18818 hdd_err("HLP len exceeds: hlp_ie_len %d len %d",
18819 roam_profile->hlp_ie_len, len);
18820 return;
18821 }
18822
18823 if (!roam_profile->hlp_ie) {
18824 roam_profile->hlp_ie =
18825 qdf_mem_malloc(FILS_MAX_HLP_DATA_LEN);
18826 hlp_ie = roam_profile->hlp_ie;
Min Liu74a1a502018-10-10 19:59:07 +080018827 if (!hlp_ie)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018828 return;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018829 }
18830
18831 qdf_mem_copy(hlp_ie + roam_profile->hlp_ie_len, gen_ie, len);
18832 roam_profile->hlp_ie_len += len;
18833}
18834#else
Jeff Johnson61b5e982018-03-15 11:33:31 -070018835static inline void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070018836 const uint8_t *gen_ie, uint16_t len,
18837 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018838{}
18839#endif
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080018840
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080018841/**
18842 * hdd_populate_crypto_auth_type() - populate auth type for crypto
18843 * @vdev: pointed to vdev obmgr
18844 * @auth_type: legacy auth_type
18845 *
18846 * set the crypto auth type for corresponding auth type received
18847 * from NL
18848 *
18849 * Return: None
18850 */
18851static void hdd_populate_crypto_auth_type(struct wlan_objmgr_vdev *vdev,
18852 enum nl80211_auth_type auth_type)
18853{
18854 QDF_STATUS status;
18855 uint32_t set_val = 0;
18856 wlan_crypto_auth_mode crypto_auth_type =
18857 osif_nl_to_crypto_auth_type(auth_type);
18858
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080018859 HDD_SET_BIT(set_val, crypto_auth_type);
18860 status = wlan_crypto_set_vdev_param(vdev,
18861 WLAN_CRYPTO_PARAM_AUTH_MODE,
18862 set_val);
18863 if (QDF_IS_STATUS_ERROR(status))
18864 hdd_err("Failed to set auth type %0X to crypto component",
18865 set_val);
18866}
18867
18868/**
18869 * hdd_populate_crypto_akm_type() - populate akm type for crypto
18870 * @vdev: pointed to vdev obmgr
18871 * @akm_type: legacy akm_type
18872 *
18873 * set the crypto akm type for corresponding akm type received
18874 * from NL
18875 *
18876 * Return: None
18877 */
18878static void hdd_populate_crypto_akm_type(struct wlan_objmgr_vdev *vdev,
18879 u32 key_mgmt)
18880{
18881 QDF_STATUS status;
18882 uint32_t set_val = 0;
18883 wlan_crypto_key_mgmt crypto_akm_type =
18884 osif_nl_to_crypto_akm_type(key_mgmt);
18885
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080018886 HDD_SET_BIT(set_val, crypto_akm_type);
18887
18888 status = wlan_crypto_set_vdev_param(vdev,
18889 WLAN_CRYPTO_PARAM_KEY_MGMT,
18890 set_val);
18891 if (QDF_IS_STATUS_ERROR(status))
18892 hdd_err("Failed to set akm type %0x to crypto component",
18893 set_val);
18894}
18895
18896/**
18897 * hdd_populate_crypto_cipher_type() - populate cipher type for crypto
18898 * @cipher: legacy cipher type
18899 * @vdev: pointed to vdev obmgr
18900 * @cipher_param_type: param type, UCST/MCAST
18901 *
18902 * set the crypto cipher type for corresponding cipher type received
18903 * from NL
18904 *
18905 * Return: None
18906 */
18907static void hdd_populate_crypto_cipher_type(u32 cipher,
18908 struct wlan_objmgr_vdev *vdev,
18909 wlan_crypto_param_type
18910 cipher_param_type)
18911{
18912 QDF_STATUS status;
18913 uint32_t set_val = 0;
18914 wlan_crypto_cipher_type crypto_cipher_type =
18915 osif_nl_to_crypto_cipher_type(cipher);
18916
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080018917 HDD_SET_BIT(set_val, crypto_cipher_type);
18918 status = wlan_crypto_set_vdev_param(vdev, cipher_param_type, set_val);
18919 if (QDF_IS_STATUS_ERROR(status))
Arun Kumar Khandavalliafcb0552020-01-20 11:46:36 +053018920 hdd_debug("Failed to set cipher params %d type %0x to crypto",
18921 cipher_param_type, set_val);
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080018922}
18923
18924/**
18925 * hdd_populate_crypto_params() - set crypto params
18926 * @vdev: Pointer to vdev obh mgr
18927 * @req: Pointer to security parameters
18928 *
18929 * Set Auth, Akm and Cipher type for crypto
18930 *
18931 * Return: None
18932 */
18933static void hdd_populate_crypto_params(struct wlan_objmgr_vdev *vdev,
18934 struct cfg80211_connect_params *req)
18935{
18936 hdd_populate_crypto_auth_type(vdev, req->auth_type);
18937
18938 if (req->crypto.n_akm_suites)
18939 hdd_populate_crypto_akm_type(vdev, req->crypto.akm_suites[0]);
18940
Abhishek Singh4ec44a72020-02-03 15:07:34 +053018941 if (req->crypto.n_ciphers_pairwise)
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080018942 hdd_populate_crypto_cipher_type(req->crypto.ciphers_pairwise[0],
18943 vdev,
18944 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080018945
Abhishek Singh4ec44a72020-02-03 15:07:34 +053018946 if (req->crypto.cipher_group)
18947 hdd_populate_crypto_cipher_type(req->crypto.cipher_group,
18948 vdev,
18949 WLAN_CRYPTO_PARAM_MCAST_CIPHER);
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080018950}
18951
18952/**
18953 * hdd_set_crypto_key_mgmt_param() - Set key mgmt param.
18954 * @adapter: Pointer to adapter.
18955 *
18956 * Return: None
18957 */
18958static void hdd_set_crypto_key_mgmt_param(struct hdd_adapter *adapter)
18959{
18960 uint32_t key_mgmt = 0;
18961 struct wlan_objmgr_vdev *vdev;
18962
18963 if (!adapter) {
18964 hdd_err("adapter is null");
18965 return;
18966 }
18967
18968 vdev = hdd_objmgr_get_vdev(adapter);
18969 if (!vdev)
18970 return;
18971
18972 if (adapter->wapi_info.wapi_auth_mode == WAPI_AUTH_MODE_PSK)
18973 HDD_SET_BIT(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK);
18974 if (adapter->wapi_info.wapi_auth_mode == WAPI_AUTH_MODE_CERT)
18975 HDD_SET_BIT(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT);
18976
18977 wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT, key_mgmt);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053018978 hdd_objmgr_put_vdev(vdev);
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080018979}
18980
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018981/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018982 * wlan_hdd_cfg80211_set_ie() - set IEs
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018983 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018984 * @ie: Pointer ot ie
18985 * @ie: IE length
18986 *
18987 * Return: 0 for success, non-zero for failure
18988 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018989static int wlan_hdd_cfg80211_set_ie(struct hdd_adapter *adapter,
Jeff Johnson2a722002017-09-30 20:02:35 -070018990 const uint8_t *ie,
18991 size_t ie_len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018992{
Jeff Johnson20227a92018-03-13 09:41:05 -070018993 struct csr_roam_profile *roam_profile;
18994 tSirAddie *assoc_add_ie;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018995 const uint8_t *genie = ie;
18996 uint16_t remLen = ie_len;
18997#ifdef FEATURE_WLAN_WAPI
18998 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
tinlin8a44b642018-04-25 13:56:06 +080018999 uint8_t *tmp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019000 uint16_t akmsuiteCount;
tinlin8a44b642018-04-25 13:56:06 +080019001 uint32_t *akmlist;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019002#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019003 int status;
Jeff Johnson20227a92018-03-13 09:41:05 -070019004 uint8_t *security_ie;
19005
19006 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019007
19008 /* clear previous assocAddIE */
Jeff Johnson20227a92018-03-13 09:41:05 -070019009 assoc_add_ie = hdd_assoc_additional_ie(adapter);
19010 assoc_add_ie->length = 0;
19011 roam_profile->bWPSAssociation = false;
19012 roam_profile->bOSENAssociation = false;
19013 security_ie = hdd_security_ie(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019014
19015 while (remLen >= 2) {
19016 uint16_t eLen = 0;
19017 uint8_t elementId;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019018
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019019 elementId = *genie++;
19020 eLen = *genie++;
19021 remLen -= 2;
19022
Nachiket Kukade4bea8b42017-06-13 11:53:19 +053019023 /* Sanity check on eLen */
19024 if (eLen > remLen) {
19025 hdd_err("%s: Invalid IE length[%d] for IE[0x%X]",
19026 __func__, eLen, elementId);
19027 QDF_ASSERT(0);
19028 return -EINVAL;
19029 }
19030
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019031 switch (elementId) {
19032 case DOT11F_EID_WPA:
19033 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 +053019034 hdd_err("Invalid vendor ie");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019035 return -EINVAL;
19036 } else if (0 ==
19037 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
Jeff Johnson20227a92018-03-13 09:41:05 -070019038 uint16_t curAddIELen = assoc_add_ie->length;
19039
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019040 hdd_debug("WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019041
19042 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019043 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070019044 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019045 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019046 return -ENOMEM;
19047 }
19048 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070019049 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019050 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019051 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019052
Jeff Johnson20227a92018-03-13 09:41:05 -070019053 roam_profile->bWPSAssociation = true;
19054 roam_profile->pAddIEAssoc =
19055 assoc_add_ie->addIEdata;
19056 roam_profile->nAddIEAssocLength =
19057 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019058 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowdacf161402019-03-14 11:37:33 -070019059 if (eLen > (WLAN_MAX_IE_LEN - 2)) {
Nachiket Kukade2f6509f2017-06-13 17:45:46 +053019060 hdd_err("%s: Invalid WPA IE length[%d]",
19061 __func__, eLen);
19062 QDF_ASSERT(0);
19063 return -EINVAL;
19064 }
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019065 hdd_debug("WPA IE (len %d)", eLen + 2);
Srinivas Girigowdacf161402019-03-14 11:37:33 -070019066 memset(security_ie, 0, WLAN_MAX_IE_LEN);
Jeff Johnson20227a92018-03-13 09:41:05 -070019067 memcpy(security_ie, genie - 2, (eLen + 2));
19068 roam_profile->pWPAReqIE = security_ie;
19069 roam_profile->nWPAReqIELength = eLen + 2; /* ie_len; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019070 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
19071 P2P_OUI_TYPE_SIZE))) {
19072 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070019073 assoc_add_ie->length;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019074 hdd_debug("P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019075
19076 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019077 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070019078 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019079 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019080 return -ENOMEM;
19081 }
19082 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070019083 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019084 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019085 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019086
Jeff Johnson20227a92018-03-13 09:41:05 -070019087 roam_profile->pAddIEAssoc =
19088 assoc_add_ie->addIEdata;
19089 roam_profile->nAddIEAssocLength =
19090 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019091 }
19092#ifdef WLAN_FEATURE_WFD
19093 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
19094 WFD_OUI_TYPE_SIZE)) &&
19095 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080019096 (QDF_P2P_CLIENT_MODE ==
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019097 adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019098 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070019099 assoc_add_ie->length;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019100 hdd_debug("WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019101
19102 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019103 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070019104 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019105 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019106 return -ENOMEM;
19107 }
19108 /* WFD IE is saved to Additional IE ; it should
19109 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080019110 * WFD IE
19111 */
Jeff Johnson20227a92018-03-13 09:41:05 -070019112 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019113 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019114 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019115
Jeff Johnson20227a92018-03-13 09:41:05 -070019116 roam_profile->pAddIEAssoc =
19117 assoc_add_ie->addIEdata;
19118 roam_profile->nAddIEAssocLength =
19119 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019120 }
19121#endif
19122 /* Appending HS 2.0 Indication Element in Assiciation Request */
19123 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
19124 HS20_OUI_TYPE_SIZE))) {
19125 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070019126 assoc_add_ie->length;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019127 hdd_debug("HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019128
19129 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019130 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070019131 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019132 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019133 return -ENOMEM;
19134 }
Jeff Johnson20227a92018-03-13 09:41:05 -070019135 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019136 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019137 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019138
Jeff Johnson20227a92018-03-13 09:41:05 -070019139 roam_profile->pAddIEAssoc =
19140 assoc_add_ie->addIEdata;
19141 roam_profile->nAddIEAssocLength =
19142 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019143 }
19144 /* Appending OSEN Information Element in Assiciation Request */
19145 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
19146 OSEN_OUI_TYPE_SIZE))) {
19147 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070019148 assoc_add_ie->length;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019149 hdd_debug("OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019150
19151 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019152 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070019153 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019154 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019155 return -ENOMEM;
19156 }
Jeff Johnson20227a92018-03-13 09:41:05 -070019157 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019158 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019159 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019160
Jeff Johnson20227a92018-03-13 09:41:05 -070019161 roam_profile->bOSENAssociation = true;
19162 roam_profile->pAddIEAssoc =
19163 assoc_add_ie->addIEdata;
19164 roam_profile->nAddIEAssocLength =
19165 assoc_add_ie->length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019166 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
19167 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019168 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019169 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019170 genie - 2, eLen + 2);
19171 if (status)
19172 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019173 } else {
19174 uint16_t add_ie_len =
Jeff Johnson20227a92018-03-13 09:41:05 -070019175 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019176
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019177 hdd_debug("Additional IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019178
19179 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019180 (assoc_add_ie->length + eLen)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019181 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019182 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019183 return -ENOMEM;
19184 }
19185
Jeff Johnson20227a92018-03-13 09:41:05 -070019186 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019187 add_ie_len, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019188 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019189
Jeff Johnson20227a92018-03-13 09:41:05 -070019190 roam_profile->pAddIEAssoc =
19191 assoc_add_ie->addIEdata;
19192 roam_profile->nAddIEAssocLength =
19193 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019194 }
19195 break;
19196 case DOT11F_EID_RSN:
tinlin8a44b642018-04-25 13:56:06 +080019197 if (eLen > DOT11F_IE_RSN_MAX_LEN) {
Vignesh Viswanathan96e0e702017-12-05 19:42:46 +053019198 hdd_err("%s: Invalid WPA RSN IE length[%d]",
tinlin8a44b642018-04-25 13:56:06 +080019199 __func__, eLen);
Vignesh Viswanathan96e0e702017-12-05 19:42:46 +053019200 return -EINVAL;
19201 }
Srinivas Girigowdacf161402019-03-14 11:37:33 -070019202 memset(security_ie, 0, WLAN_MAX_IE_LEN);
Jeff Johnson20227a92018-03-13 09:41:05 -070019203 memcpy(security_ie, genie - 2, (eLen + 2));
19204 roam_profile->pRSNReqIE = security_ie;
19205 roam_profile->nRSNReqIELength = eLen + 2; /* ie_len; */
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019206 hdd_debug("RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019207 break;
19208 /*
19209 * Appending Extended Capabilities with Interworking bit set
19210 * in Assoc Req.
19211 *
19212 * In assoc req this EXT Cap will only be taken into account if
19213 * interworkingService bit is set to 1. Currently
19214 * driver is only interested in interworkingService capability
19215 * from supplicant. If in future any other EXT Cap info is
19216 * required from supplicat, it needs to be handled while
19217 * sending Assoc Req in LIM.
19218 */
19219 case DOT11F_EID_EXTCAP:
19220 {
19221 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070019222 assoc_add_ie->length;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019223 hdd_debug("Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019224
19225 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070019226 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070019227 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019228 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019229 return -ENOMEM;
19230 }
Jeff Johnson20227a92018-03-13 09:41:05 -070019231 memcpy(assoc_add_ie->addIEdata + curAddIELen, genie - 2, eLen + 2);
19232 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019233
Jeff Johnson20227a92018-03-13 09:41:05 -070019234 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
19235 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019236 break;
19237 }
19238#ifdef FEATURE_WLAN_WAPI
Srinivas Girigowda61771262019-04-01 11:55:19 -070019239 case WLAN_ELEMID_WAPI:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019240 /* Setting WAPI Mode to ON=1 */
tinlin8a44b642018-04-25 13:56:06 +080019241 adapter->wapi_info.wapi_mode = 1;
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070019242 hdd_debug("WAPI MODE IS %u", adapter->wapi_info.wapi_mode);
Abhinav Kumarf56c81f2018-06-06 16:07:01 +053019243 /* genie is pointing to data field of WAPI IE's buffer */
19244 tmp = (uint8_t *)genie;
19245 /* Validate length for Version(2 bytes) and Number
19246 * of AKM suite (2 bytes) in WAPI IE buffer, coming from
19247 * supplicant*/
19248 if (eLen < 4) {
19249 hdd_err("Invalid IE Len: %u", eLen);
19250 return -EINVAL;
19251 }
19252 tmp = tmp + 2; /* Skip Version */
tinlin8a44b642018-04-25 13:56:06 +080019253 /* Get the number of AKM suite */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019254 akmsuiteCount = WPA_GET_LE16(tmp);
tinlin8a44b642018-04-25 13:56:06 +080019255 /* Skip the number of AKM suite */
19256 tmp = tmp + 2;
Abhinav Kumarf56c81f2018-06-06 16:07:01 +053019257 /* Validate total length for WAPI IE's buffer */
19258 if (eLen < (4 + (akmsuiteCount * sizeof(uint32_t)))) {
19259 hdd_err("Invalid IE Len: %u", eLen);
19260 return -EINVAL;
19261 }
tinlin8a44b642018-04-25 13:56:06 +080019262 /* AKM suite list, each OUI contains 4 bytes */
19263 akmlist = (uint32_t *)(tmp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019264 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
Vignesh Viswanathan845bd472018-06-11 18:45:45 +053019265 qdf_mem_copy(akmsuite, akmlist,
19266 sizeof(uint32_t) * akmsuiteCount);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019267 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019268 hdd_err("Invalid akmSuite count: %u",
19269 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019270 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019271 return -EINVAL;
19272 }
19273
19274 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019275 hdd_debug("WAPI AUTH MODE SET TO PSK");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070019276 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019277 WAPI_AUTH_MODE_PSK;
19278 }
19279 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019280 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070019281 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019282 WAPI_AUTH_MODE_CERT;
19283 }
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080019284
19285 hdd_set_crypto_key_mgmt_param(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019286 break;
19287#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019288 case DOT11F_EID_SUPPOPERATINGCLASSES:
19289 {
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019290 hdd_debug("Supported Operating Classes IE(len %d)",
19291 eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019292 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019293 genie - 2, eLen + 2);
19294 if (status)
19295 return status;
19296 break;
19297 }
Srinivas Girigowda61771262019-04-01 11:55:19 -070019298 case WLAN_REQUEST_IE_MAX_LEN:
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019299 {
19300 if (genie[0] == SIR_FILS_HLP_EXT_EID) {
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019301 hdd_debug("HLP EXT IE(len %d)",
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019302 eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019303 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019304 genie - 2, eLen + 2,
19305 true);
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019306 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070019307 adapter, genie - 2,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019308 eLen + 2);
19309 if (status)
19310 return status;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053019311 } else if (genie[0] ==
19312 SIR_DH_PARAMETER_ELEMENT_EXT_EID) {
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019313 hdd_debug("DH EXT IE(len %d)",
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053019314 eLen + 2);
19315 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070019316 adapter, genie - 2,
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053019317 eLen + 2);
19318 if (status)
19319 return status;
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019320 } else {
19321 hdd_err("UNKNOWN EID: %X", genie[0]);
19322 }
19323 break;
19324 }
19325 case DOT11F_EID_FRAGMENT_IE:
19326 {
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019327 hdd_debug("Fragment IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019328 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019329 genie - 2, eLen + 2,
19330 false);
Jeff Johnson20227a92018-03-13 09:41:05 -070019331 status = wlan_hdd_add_assoc_ie(adapter,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019332 genie - 2, eLen + 2);
19333 if (status)
19334 return status;
19335 break;
19336 }
Pragaspathi Thilagarajc0515882019-10-24 02:59:11 +053019337 case WLAN_ELEMID_RSNXE:
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019338 hdd_debug("RSNXE(len %d)", eLen + 2);
Pragaspathi Thilagarajc0515882019-10-24 02:59:11 +053019339 status = wlan_hdd_add_assoc_ie(adapter, genie - 2,
19340 eLen + 2);
19341 if (status)
19342 return status;
19343 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019344 default:
Abhishek Singh4ec44a72020-02-03 15:07:34 +053019345 hdd_err("UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080019346 /* when Unknown IE is received we break
19347 * and continue to the next IE in the buffer
19348 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019349 break;
19350 }
19351 genie += eLen;
19352 remLen -= eLen;
19353 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019354 return 0;
19355}
19356
Abhishek Ambure68677462019-09-13 12:44:26 +053019357#ifdef QCA_IBSS_SUPPORT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019358/**
19359 * hdd_is_wpaie_present() - check for WPA ie
19360 * @ie: Pointer to ie
19361 * @ie_len: Ie length
19362 *
19363 * Parse the received IE to find the WPA IE
19364 *
19365 * Return: true if wpa ie is found else false
19366 */
19367static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
19368{
19369 uint8_t eLen = 0;
19370 uint16_t remLen = ie_len;
19371 uint8_t elementId = 0;
19372
19373 while (remLen >= 2) {
19374 elementId = *ie++;
19375 eLen = *ie++;
19376 remLen -= 2;
19377 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019378 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019379 return false;
19380 }
19381 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
19382 /* OUI - 0x00 0X50 0XF2
19383 * WPA Information Element - 0x01
19384 * WPA version - 0x01
19385 */
19386 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
19387 return true;
19388 }
19389 ie += eLen;
19390 remLen -= eLen;
19391 }
19392 return false;
19393}
19394
Abhishek Ambure68677462019-09-13 12:44:26 +053019395/**
19396 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
19397 * @adapter: Pointer to adapter
19398 * @param: Pointer to IBSS parameters
19399 *
19400 * This function is used to initialize the security settings in IBSS mode
19401 *
19402 * Return: 0 for success, non-zero for failure
19403 */
19404static int wlan_hdd_cfg80211_set_privacy_ibss(struct hdd_adapter *adapter,
19405 struct cfg80211_ibss_params
19406 *params)
19407{
19408 uint32_t ret;
19409 int status = 0;
19410 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
19411 struct hdd_station_ctx *sta_ctx =
19412 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19413 struct csr_roam_profile *roam_profile;
19414
19415 hdd_enter();
19416
19417 sta_ctx->wpa_versions = 0;
19418 qdf_mem_zero(&sta_ctx->ibss_enc_key, sizeof(tCsrRoamSetKey));
19419 sta_ctx->ibss_enc_key_installed = 0;
19420
19421 if (params->ie_len && (params->ie)) {
19422 if (wlan_get_ie_ptr_from_eid(WLAN_EID_RSN, params->ie,
19423 params->ie_len)) {
19424 sta_ctx->wpa_versions = NL80211_WPA_VERSION_2;
19425 encryptionType = eCSR_ENCRYPT_TYPE_AES;
19426 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
19427 tDot11fIEWPA dot11_wpa_ie;
19428 mac_handle_t mac_handle =
19429 hdd_adapter_get_mac_handle(adapter);
19430 const u8 *ie;
19431
19432 memset(&dot11_wpa_ie, 0, sizeof(dot11_wpa_ie));
19433 ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_WPA,
19434 params->ie, params->ie_len);
19435 if (ie) {
19436 sta_ctx->wpa_versions = NL80211_WPA_VERSION_1;
19437 /* Unpack the WPA IE
19438 * Skip past the EID byte and length byte
19439 * and four byte WiFi OUI
19440 */
19441 if (ie[1] < DOT11F_IE_WPA_MIN_LEN ||
19442 ie[1] > DOT11F_IE_WPA_MAX_LEN) {
19443 hdd_err("invalid ie len:%d", ie[1]);
19444 return -EINVAL;
19445 }
19446 ret = dot11f_unpack_ie_wpa(
19447 MAC_CONTEXT(mac_handle),
19448 (uint8_t *)&ie[2 + 4],
19449 ie[1] - 4, &dot11_wpa_ie, false);
19450 if (DOT11F_FAILED(ret)) {
19451 hdd_err("unpack failed ret: 0x%x", ret);
19452 return -EINVAL;
19453 }
19454 /*
19455 * Extract the multicast cipher, the
19456 * encType for unicast cipher for
19457 * wpa-none is none
19458 */
19459 encryptionType =
19460 hdd_translate_wpa_to_csr_encryption_type
19461 (dot11_wpa_ie.multicast_cipher);
19462 }
19463 }
19464
19465 status =
19466 wlan_hdd_cfg80211_set_ie(adapter, params->ie,
19467 params->ie_len);
19468
19469 if (0 > status) {
19470 hdd_err("Failed to parse WPA/RSN IE");
19471 return status;
19472 }
19473 }
19474
19475 roam_profile = hdd_roam_profile(adapter);
19476 roam_profile->AuthType.authType[0] =
19477 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM;
19478
19479 if (params->privacy) {
19480 /* Security enabled IBSS, At this time there is no information
19481 * available about the security parameters, so initialise the
19482 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
19483 * The correct security parameters will be updated later in
19484 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
19485 * set inorder enable privacy bit in beacons
19486 */
19487
19488 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
19489 }
19490 hdd_debug("encryptionType=%d", encryptionType);
19491 sta_ctx->conn_info.uc_encrypt_type = encryptionType;
19492 roam_profile->EncryptionType.numEntries = 1;
19493 roam_profile->EncryptionType.encryptionType[0] =
19494 encryptionType;
19495 return status;
19496}
19497
19498/**
19499 * __wlan_hdd_cfg80211_join_ibss() - join ibss
19500 * @wiphy: Pointer to wiphy
19501 * @dev: Pointer to network device
19502 * @param: Pointer to IBSS join parameters
19503 *
19504 * This function is used to create/join an IBSS network
19505 *
19506 * Return: 0 for success, non-zero for failure
19507 */
19508static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
19509 struct net_device *dev,
19510 struct cfg80211_ibss_params *params)
19511{
19512 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19513 struct csr_roam_profile *roam_profile;
19514 int status;
19515 struct hdd_station_ctx *sta_ctx =
19516 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19517 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
19518 struct qdf_mac_addr bssid;
19519 uint8_t channelNum = 0;
19520 mac_handle_t mac_handle;
19521 struct wlan_mlme_ibss_cfg ibss_cfg = {0};
19522 uint8_t conn_info_channel;
19523
19524 hdd_enter();
19525
19526 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19527 hdd_err("Command not allowed in FTM mode");
19528 return -EINVAL;
19529 }
19530
19531 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
19532 return -EINVAL;
19533
19534 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
19535 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
19536 adapter->vdev_id, adapter->device_mode);
19537
19538 hdd_debug("Device_mode %s(%d)",
19539 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
19540
19541 status = wlan_hdd_validate_context(hdd_ctx);
19542
19543 if (0 != status)
19544 return status;
19545
19546 if (QDF_IS_STATUS_ERROR(ucfg_mlme_get_ibss_cfg(hdd_ctx->psoc,
19547 &ibss_cfg))) {
19548 return -EINVAL;
19549 }
19550
19551 mac_handle = hdd_ctx->mac_handle;
19552 if (NULL !=
19553 params->chandef.chan) {
19554 uint32_t numChans = CFG_VALID_CHANNEL_LIST_LEN;
19555 uint32_t validChan[CFG_VALID_CHANNEL_LIST_LEN];
19556 int indx;
19557
19558 /* Get channel number */
19559 channelNum = ieee80211_frequency_to_channel(
19560 params->
19561 chandef.
19562 chan->
19563 center_freq);
19564 ucfg_mlme_get_valid_channel_freq_list(hdd_ctx->psoc, validChan,
19565 &numChans);
19566
19567 for (indx = 0; indx < numChans; indx++) {
19568 if (channelNum ==
19569 wlan_reg_freq_to_chan(hdd_ctx->pdev, validChan[indx]))
19570 break;
19571 }
19572 if (indx >= numChans) {
19573 hdd_err("Not valid Channel: %d", channelNum);
19574 return -EINVAL;
19575 }
19576 }
19577
19578 /* Disable NAN Discovery if enabled */
19579 ucfg_nan_disable_concurrency(hdd_ctx->psoc);
19580
Manikandan Mohan282c4b62019-08-14 17:42:22 -070019581 if (!policy_mgr_allow_concurrency(
19582 hdd_ctx->psoc, PM_IBSS_MODE,
19583 wlan_reg_chan_to_freq(hdd_ctx->pdev, channelNum),
19584 HW_MODE_20_MHZ)) {
Abhishek Ambure68677462019-09-13 12:44:26 +053019585 hdd_err("This concurrency combination is not allowed");
19586 return -ECONNREFUSED;
19587 }
19588
19589 status = policy_mgr_reset_connection_update(hdd_ctx->psoc);
19590 if (!QDF_IS_STATUS_SUCCESS(status))
19591 hdd_err("qdf_reset_connection_update failed status: %d", status);
19592
Manikandan Mohan282c4b62019-08-14 17:42:22 -070019593 status = policy_mgr_current_connections_update(
19594 hdd_ctx->psoc, adapter->vdev_id,
19595 wlan_reg_chan_to_freq(hdd_ctx->pdev, channelNum),
19596 POLICY_MGR_UPDATE_REASON_JOIN_IBSS);
Abhishek Ambure68677462019-09-13 12:44:26 +053019597 if (QDF_STATUS_E_FAILURE == status) {
19598 hdd_err("connections update failed!!");
19599 return -EINVAL;
19600 }
19601
19602 if (QDF_STATUS_SUCCESS == status) {
19603 status = policy_mgr_wait_for_connection_update(
19604 hdd_ctx->psoc);
19605 if (!QDF_IS_STATUS_SUCCESS(status)) {
19606 hdd_err("qdf wait for event failed!!");
19607 return -EINVAL;
19608 }
19609 }
19610
19611 /*Try disconnecting if already in connected state */
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053019612 status = wlan_hdd_try_disconnect(adapter,
19613 eSIR_MAC_UNSPEC_FAILURE_REASON);
Abhishek Ambure68677462019-09-13 12:44:26 +053019614 if (0 > status) {
19615 hdd_err("Failed to disconnect the existing IBSS connection");
19616 return -EALREADY;
19617 }
19618
19619 roam_profile = hdd_roam_profile(adapter);
19620
19621 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
19622 hdd_err("Interface type is not set to IBSS");
19623 return -EINVAL;
19624 }
19625
19626 /* enable selected protection checks in IBSS mode */
19627 roam_profile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
19628
19629 /* BSSID is provided by upper layers hence no need to AUTO generate */
19630 if (params->bssid) {
19631 if (ucfg_mlme_set_ibss_auto_bssid(hdd_ctx->psoc, 0)
19632 == QDF_STATUS_E_FAILURE) {
19633 hdd_err("Unable to update MLME IBSS Auto BSSID config");
19634 return -EIO;
19635 }
19636 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
19637 } else if (ibss_cfg.coalesing_enable == 0) {
19638 if (ucfg_mlme_set_ibss_auto_bssid(hdd_ctx->psoc, 0)
19639 == QDF_STATUS_E_FAILURE) {
19640 hdd_err("Unable to update MLME IBSS Auto BSSID config");
19641 return -EIO;
19642 }
19643 qdf_copy_macaddr(&bssid, &ibss_cfg.bssid);
19644 }
19645
19646 if (cfg_in_range(CFG_BEACON_INTERVAL, params->beacon_interval))
19647 roam_profile->beaconInterval = params->beacon_interval;
19648 else
19649 roam_profile->beaconInterval = cfg_get(hdd_ctx->psoc,
19650 CFG_BEACON_INTERVAL);
19651
19652 /* Set Channel */
19653 if (channelNum) {
19654 /* Set the Operational Channel */
19655 hdd_debug("set channel %d", channelNum);
19656 roam_profile->ChannelInfo.numOfChannels = 1;
19657 sta_ctx->conn_info.chan_freq =
19658 wlan_reg_chan_to_freq(hdd_ctx->pdev,
19659 channelNum);
19660 roam_profile->ChannelInfo.freq_list =
19661 &sta_ctx->conn_info.chan_freq;
19662 }
19663
19664 /* Initialize security parameters */
19665 status = wlan_hdd_cfg80211_set_privacy_ibss(adapter, params);
19666 if (status < 0) {
19667 hdd_err("failed to set security parameters");
19668 return status;
19669 }
19670
19671 conn_info_channel =
19672 wlan_reg_freq_to_chan(
19673 hdd_ctx->pdev,
19674 sta_ctx->conn_info.chan_freq);
19675 /* Issue connect start */
19676 status = wlan_hdd_cfg80211_connect_start(adapter, params->ssid,
19677 params->ssid_len,
19678 bssid.bytes, NULL,
19679 conn_info_channel,
19680 params->chandef.width);
19681
19682 if (0 > status) {
19683 hdd_err("connect failed");
19684 return status;
19685 }
19686 hdd_exit();
19687 return 0;
19688}
19689
19690/**
19691 * wlan_hdd_cfg80211_join_ibss() - join ibss
19692 * @wiphy: Pointer to wiphy
19693 * @dev: Pointer to network device
19694 * @param: Pointer to IBSS join parameters
19695 *
19696 * This function is used to create/join an IBSS network
19697 *
19698 * Return: 0 for success, non-zero for failure
19699 */
19700static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
19701 struct net_device *dev,
19702 struct cfg80211_ibss_params *params)
19703{
19704 int errno;
19705 struct osif_vdev_sync *vdev_sync;
19706
19707 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
19708 if (errno)
19709 return errno;
19710
19711 errno = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
19712
19713 osif_vdev_sync_op_stop(vdev_sync);
19714
19715 return errno;
19716}
19717
19718/**
19719 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
19720 * @wiphy: Pointer to wiphy
19721 * @dev: Pointer to network device
19722 *
19723 * This function is used to leave an IBSS network
19724 *
19725 * Return: 0 for success, non-zero for failure
19726 */
19727static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
19728 struct net_device *dev)
19729{
19730 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19731 struct csr_roam_profile *roam_profile;
19732 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
19733 int status;
19734 mac_handle_t mac_handle;
19735 unsigned long rc;
19736 tSirUpdateIE update_ie;
19737
19738 hdd_enter();
19739
19740 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19741 hdd_err("Command not allowed in FTM mode");
19742 return -EINVAL;
19743 }
19744
19745 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
19746 return -EINVAL;
19747
19748 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
19749 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
19750 adapter->vdev_id, eCSR_DISCONNECT_REASON_IBSS_LEAVE);
19751
19752 status = wlan_hdd_validate_context(hdd_ctx);
19753 if (0 != status)
19754 return status;
19755
19756 hdd_debug("Device_mode %s(%d)",
19757 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
19758
19759 roam_profile = hdd_roam_profile(adapter);
19760
19761 /* Issue disconnect only if interface type is set to IBSS */
19762 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
19763 hdd_err("BSS Type is not set to IBSS");
19764 return -EINVAL;
19765 }
19766 /* Clearing add IE of beacon */
19767 qdf_mem_copy(update_ie.bssid.bytes, adapter->mac_addr.bytes,
19768 sizeof(tSirMacAddr));
Abhishek Singh5a2c42f2019-11-19 11:39:23 +053019769 update_ie.vdev_id = adapter->vdev_id;
Abhishek Ambure68677462019-09-13 12:44:26 +053019770 update_ie.ieBufferlength = 0;
19771 update_ie.pAdditionIEBuffer = NULL;
19772 update_ie.append = true;
19773 update_ie.notify = true;
19774 mac_handle = hdd_ctx->mac_handle;
19775 if (sme_update_add_ie(mac_handle,
19776 &update_ie,
19777 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
19778 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
19779 }
19780
19781 /* Reset WNI_CFG_PROBE_RSP Flags */
19782 wlan_hdd_reset_prob_rspies(adapter);
19783
19784 /* Issue Disconnect request */
19785 INIT_COMPLETION(adapter->disconnect_comp_var);
19786 status = sme_roam_disconnect(mac_handle,
19787 adapter->vdev_id,
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053019788 eCSR_DISCONNECT_REASON_IBSS_LEAVE,
19789 eSIR_MAC_UNSPEC_FAILURE_REASON);
Abhishek Ambure68677462019-09-13 12:44:26 +053019790 if (!QDF_IS_STATUS_SUCCESS(status)) {
19791 hdd_err("sme_roam_disconnect failed status: %d",
19792 status);
19793 return -EAGAIN;
19794 }
19795
19796 /* wait for mc thread to cleanup and then return to upper stack
19797 * so by the time upper layer calls the change interface, we are
19798 * all set to proceed further
19799 */
19800 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
19801 msecs_to_jiffies(SME_DISCONNECT_TIMEOUT));
19802 if (!rc) {
19803 hdd_err("Failed to disconnect, timed out");
19804 return -ETIMEDOUT;
19805 }
19806
19807 hdd_exit();
19808 return 0;
19809}
19810
19811/**
19812 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
19813 * @wiphy: Pointer to wiphy
19814 * @dev: Pointer to network device
19815 *
19816 * This function is used to leave an IBSS network
19817 *
19818 * Return: 0 for success, non-zero for failure
19819 */
19820static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
19821 struct net_device *dev)
19822{
19823 int errno;
19824 struct osif_vdev_sync *vdev_sync;
19825
19826 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
19827 if (errno)
19828 return errno;
19829
19830 errno = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
19831
19832 osif_vdev_sync_op_stop(vdev_sync);
19833
19834 return errno;
19835}
19836#else
19837/**
19838 * wlan_hdd_cfg80211_join_ibss() - join ibss
19839 * @wiphy: Pointer to wiphy
19840 * @dev: Pointer to network device
19841 * @param: Pointer to IBSS join parameters
19842 *
19843 * This function is dummy
19844 *
19845 * Return: 0
19846 */
19847static inline int
19848wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
19849 struct net_device *dev,
19850 struct cfg80211_ibss_params *params)
19851{
19852 return 0;
19853}
19854
19855/**
19856 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
19857 * @wiphy: Pointer to wiphy
19858 * @dev: Pointer to network device
19859 *
19860 * This function is dummy
19861 *
19862 * Return: 0
19863 */
19864static inline int
19865wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
19866 struct net_device *dev)
19867{
19868 return 0;
19869}
19870#endif
19871
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019872static void wlan_hdd_cfg80211_store_wep_key(struct hdd_adapter *adapter,
19873 struct wlan_objmgr_vdev *vdev,
19874 struct cfg80211_connect_params *req)
19875{
19876 struct key_params params;
19877
19878 qdf_mem_zero(&params, sizeof(params));
19879 params.cipher = req->crypto.ciphers_pairwise[0];
19880 params.key_len = req->key_len;
19881 params.key = req->key;
19882 wlan_cfg80211_store_key(vdev, req->key_idx,
19883 WLAN_CRYPTO_KEY_TYPE_UNICAST,
19884 NULL, &params);
19885}
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019886
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070019887/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019888 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019889 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019890 * @req: Pointer to security parameters
19891 *
19892 * Return: 0 for success, non-zero for failure
19893 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019894static int wlan_hdd_cfg80211_set_privacy(struct hdd_adapter *adapter,
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070019895 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019896{
19897 int status = 0;
Jeff Johnsonce4a8342017-10-14 13:12:22 -070019898 struct hdd_station_ctx *sta_ctx;
Jeff Johnson20227a92018-03-13 09:41:05 -070019899 struct csr_roam_profile *roam_profile;
Min Liu8c5d99e2018-09-10 17:18:44 +080019900 struct wlan_objmgr_vdev *vdev;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019901
Jeff Johnsonce4a8342017-10-14 13:12:22 -070019902 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19903 sta_ctx->wpa_versions = req->crypto.wpa_versions;
Jeff Johnson20227a92018-03-13 09:41:05 -070019904 roam_profile = hdd_roam_profile(adapter);
19905
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070019906 /* populate auth,akm and cipher params for crypto */
Min Liu8c5d99e2018-09-10 17:18:44 +080019907 vdev = hdd_objmgr_get_vdev(adapter);
19908 if (!vdev)
19909 return -EINVAL;
19910 hdd_populate_crypto_params(vdev, req);
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070019911
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019912 /*set authentication type */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019913 status = wlan_hdd_cfg80211_set_auth_type(adapter, req->auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019914
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070019915 if (wlan_hdd_is_conn_type_fils(req)) {
19916 status = wlan_hdd_cfg80211_set_fils_config(adapter, req);
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053019917
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070019918 if (0 > status) {
19919 hdd_err("Failed to set fils config");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019920 goto release_vdev_ref;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070019921 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019922 }
19923
19924 /*set key mgmt type */
19925 if (req->crypto.n_akm_suites) {
19926 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019927 wlan_hdd_set_akm_suite(adapter, req->crypto.akm_suites[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019928 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019929 hdd_err("Failed to set akm suite");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019930 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019931 }
19932 }
19933
19934 /*set pairwise cipher type */
19935 if (req->crypto.n_ciphers_pairwise) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019936 status = wlan_hdd_cfg80211_set_cipher(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019937 req->crypto.
19938 ciphers_pairwise[0],
19939 true);
19940 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019941 hdd_err("Failed to set unicast cipher type");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019942 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019943 }
19944 } else {
19945 /*Reset previous cipher suite to none */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019946 status = wlan_hdd_cfg80211_set_cipher(adapter, 0, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019947 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019948 hdd_err("Failed to set unicast cipher type");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019949 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019950 }
19951 }
19952
19953 /*set group cipher type */
19954 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019955 wlan_hdd_cfg80211_set_cipher(adapter, req->crypto.cipher_group,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019956 false);
19957
19958 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019959 hdd_err("Failed to set mcast cipher type");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019960 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019961 }
19962#ifdef WLAN_FEATURE_11W
Jeff Johnson20227a92018-03-13 09:41:05 -070019963 roam_profile->MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019964#endif
19965
19966 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
19967 if (req->ie_len) {
19968 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019969 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019970 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019971 hdd_err("Failed to parse the WPA/RSN IE");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019972 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019973 }
19974 }
19975
19976 /*incase of WEP set default key information */
19977 if (req->key && req->key_len) {
Jeff Johnson37ecea42018-03-18 17:54:40 -070019978 u32 cipher = req->crypto.ciphers_pairwise[0];
Jeff Johnson68755312017-02-10 11:46:55 -080019979
Jeff Johnson37ecea42018-03-18 17:54:40 -070019980 if ((WLAN_CIPHER_SUITE_WEP40 == cipher) ||
19981 (WLAN_CIPHER_SUITE_WEP104 == cipher)) {
19982 enum hdd_auth_key_mgmt key_mgmt =
19983 sta_ctx->auth_key_mgmt;
19984
19985 if (key_mgmt & HDD_AUTH_KEY_MGMT_802_1X) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019986 hdd_err("Dynamic WEP not supported");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019987 status = -EOPNOTSUPP;
19988 goto release_vdev_ref;
Jeff Johnson68755312017-02-10 11:46:55 -080019989 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019990
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019991 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
19992 req->key_len) && (CSR_MAX_NUM_KEY > req->key_idx))
19993 wlan_hdd_cfg80211_store_wep_key(adapter,
19994 vdev, req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019995 }
19996 }
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080019997release_vdev_ref:
19998 hdd_objmgr_put_vdev(vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019999
20000 return status;
20001}
20002
wadesongcaad7c72018-08-06 13:26:27 +080020003/**
20004 * wlan_hdd_clear_wapi_privacy() - reset WAPI settings in HDD layer
20005 * @adapter: pointer to HDD adapter object
20006 *
20007 * This function resets all WAPI related parameters imposed before STA
20008 * connection starts. It's invoked when privacy checking against concurrency
20009 * fails, to make sure no improper WAPI settings are still populated before
20010 * returning an error to the upper layer requester.
20011 *
20012 * Return: none
20013 */
20014#ifdef FEATURE_WLAN_WAPI
20015static inline void wlan_hdd_clear_wapi_privacy(struct hdd_adapter *adapter)
20016{
20017 adapter->wapi_info.wapi_mode = 0;
20018 adapter->wapi_info.wapi_auth_mode = WAPI_AUTH_MODE_OPEN;
20019}
20020#else
20021static inline void wlan_hdd_clear_wapi_privacy(struct hdd_adapter *adapter)
20022{
20023}
20024#endif
20025
20026/**
20027 * wlan_hdd_cfg80211_clear_privacy() - reset STA security parameters
20028 * @adapter: pointer to HDD adapter object
20029 *
20030 * This function resets all privacy related parameters imposed
20031 * before STA connection starts. It's invoked when privacy checking
20032 * against concurrency fails, to make sure no improper settings are
20033 * still populated before returning an error to the upper layer requester.
20034 *
20035 * Return: none
20036 */
20037static void wlan_hdd_cfg80211_clear_privacy(struct hdd_adapter *adapter)
20038{
20039 struct hdd_station_ctx *hdd_sta_ctx =
20040 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
20041
20042 hdd_debug("resetting all privacy configurations");
20043
20044 hdd_sta_ctx->wpa_versions = 0;
20045
Jeff Johnson96e33512019-02-27 15:10:21 -080020046 hdd_sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_NONE;
wadesongcaad7c72018-08-06 13:26:27 +080020047 hdd_sta_ctx->roam_profile.AuthType.authType[0] = eCSR_AUTH_TYPE_NONE;
20048
Jeff Johnsonb1959842019-02-27 13:04:04 -080020049 hdd_sta_ctx->conn_info.uc_encrypt_type = eCSR_ENCRYPT_TYPE_NONE;
wadesongcaad7c72018-08-06 13:26:27 +080020050 hdd_sta_ctx->roam_profile.EncryptionType.numEntries = 0;
Jeff Johnsonb1959842019-02-27 13:04:04 -080020051 hdd_sta_ctx->conn_info.mc_encrypt_type = eCSR_ENCRYPT_TYPE_NONE;
wadesongcaad7c72018-08-06 13:26:27 +080020052 hdd_sta_ctx->roam_profile.mcEncryptionType.numEntries = 0;
20053
20054 wlan_hdd_clear_wapi_privacy(adapter);
20055}
20056
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020057static int wlan_hdd_wait_for_disconnect(mac_handle_t mac_handle,
20058 struct hdd_adapter *adapter,
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020059 uint16_t reason,
20060 tSirMacReasonCodes mac_reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020061{
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020062 eConnectionState prev_conn_state;
20063 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
20064 QDF_STATUS status = QDF_STATUS_SUCCESS;
20065 int ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020066 unsigned long rc;
Abhishek Singhd1f21c72019-01-21 15:16:34 +053020067 uint32_t wait_time = SME_DISCONNECT_TIMEOUT;
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020068
Abhishek Singh30769a32020-01-24 09:59:11 +053020069 /* Return if already disconnected */
20070 if (sta_ctx->conn_info.conn_state == eConnectionState_NotConnected ||
20071 sta_ctx->conn_info.conn_state == eConnectionState_IbssDisconnected)
20072 return 0;
20073
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020074 /* If already in disconnecting state just wait for its completion */
20075 if (sta_ctx->conn_info.conn_state == eConnectionState_Disconnecting)
20076 goto wait_for_disconnect;
20077
20078 INIT_COMPLETION(adapter->disconnect_comp_var);
20079 prev_conn_state = sta_ctx->conn_info.conn_state;
20080 hdd_conn_set_connection_state(adapter, eConnectionState_Disconnecting);
20081
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020082 status = sme_roam_disconnect(mac_handle, adapter->vdev_id, reason,
20083 mac_reason);
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020084 if (status == QDF_STATUS_CMD_NOT_QUEUED &&
20085 prev_conn_state == eConnectionState_Connecting) {
20086 /*
20087 * Wait here instead of returning directly, this will block the
20088 * next connect command and allow processing of the scan for
20089 * ssid and the previous connect command in CSR.
20090 */
20091 hdd_debug("CSR not connected but scan for SSID is in progress, wait for scan to be aborted or completed.");
20092 } else if (QDF_IS_STATUS_ERROR(status)) {
20093 hdd_debug("SB Disconnect in progress/SME is disconencted/Connect removed from pending queue: status = %d",
20094 status);
20095 /*
20096 * Wait here instead of returning directly. This will block the
20097 * next connect command and allow processing of the disconnect
20098 * in SME. As disconnect is already in progress, wait here for
20099 * WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS instead of
20100 * SME_DISCONNECT_TIMEOUT.
20101 */
20102 wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS;
20103 }
20104
20105wait_for_disconnect:
20106 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
20107 msecs_to_jiffies(wait_time));
20108
20109 if (!rc && QDF_IS_STATUS_SUCCESS(status)) {
20110 hdd_err("Disconnect timed out!!!");
20111 ret = -ETIMEDOUT;
20112 }
20113
20114 hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
20115
20116 return ret;
20117}
20118
20119static void wlan_hdd_wait_for_roaming(mac_handle_t mac_handle,
20120 struct hdd_adapter *adapter)
20121{
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053020122 struct hdd_context *hdd_ctx;
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020123 unsigned long rc;
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020124 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020125
Abhishek Singh30769a32020-01-24 09:59:11 +053020126 if (adapter->device_mode != QDF_STA_MODE)
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020127 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020128
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053020129 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020130
20131 /* Return if not in connected state */
20132 if (sta_ctx->conn_info.conn_state != eConnectionState_Associated)
20133 return;
20134
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020135 sme_stop_roaming(mac_handle, adapter->vdev_id,
20136 REASON_DRIVER_DISABLED,
20137 RSO_INVALID_REQUESTOR);
20138 /*
20139 * If firmware has already started roaming process, driver
20140 * needs to wait for processing of this disconnect request.
20141 *
20142 */
20143 INIT_COMPLETION(adapter->roaming_comp_var);
20144 if (hdd_is_roaming_in_progress(hdd_ctx) ||
20145 sme_neighbor_middle_of_roaming(mac_handle,
20146 adapter->vdev_id)) {
20147 rc = wait_for_completion_timeout(&adapter->roaming_comp_var,
Abhishek Singh533c9da2017-05-04 10:23:34 +053020148 msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020149 if (!rc) {
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020150 hdd_err("roaming_comp_var time out vdev id: %d",
20151 adapter->vdev_id);
20152 /* Clear roaming in progress flag */
20153 hdd_set_roaming_in_progress(false);
20154 }
20155 if (adapter->roam_ho_fail) {
20156 INIT_COMPLETION(adapter->disconnect_comp_var);
20157 hdd_conn_set_connection_state(adapter,
20158 eConnectionState_Disconnecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020159 }
20160 }
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020161}
20162
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020163int wlan_hdd_try_disconnect(struct hdd_adapter *adapter,
20164 enum eSirMacReasonCodes reason)
Abhishek Singhf68ceb12020-01-23 09:47:09 +053020165{
20166 mac_handle_t mac_handle;
20167
20168 mac_handle = hdd_adapter_get_mac_handle(adapter);
20169 wlan_hdd_wait_for_roaming(mac_handle, adapter);
20170
20171 return wlan_hdd_wait_for_disconnect(mac_handle, adapter,
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020172 eCSR_DISCONNECT_REASON_UNSPECIFIED,
20173 reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020174}
20175
20176/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020177 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
20178 * @adapter: Pointer to the HDD adapter
20179 * @req: Pointer to the structure cfg_connect_params receieved from user space
20180 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053020181 * This function will start reassociation if prev_bssid is set and bssid/
20182 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020183 *
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020184 * Return: 0 if connect was for ReAssociation, non-zero error code otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020185 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053020186#if defined(CFG80211_CONNECT_PREV_BSSID) || \
20187 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020188static int wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
20189 struct cfg80211_connect_params *req)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020190{
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020191 int status = -EINVAL;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053020192 const uint8_t *bssid = NULL;
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020193 uint32_t ch_freq = 0;
Jeff Johnson731bc322017-10-14 19:53:44 -070020194 struct hdd_station_ctx *sta_ctx;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053020195
20196 if (req->bssid)
20197 bssid = req->bssid;
20198 else if (req->bssid_hint)
20199 bssid = req->bssid_hint;
20200
20201 if (req->channel)
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020202 ch_freq = req->channel->center_freq;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053020203 else if (req->channel_hint)
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020204 ch_freq = req->channel_hint->center_freq;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053020205
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020206 if (bssid && ch_freq && req->prev_bssid) {
20207 hdd_debug("REASSOC Attempt on ch freq %d to " QDF_MAC_ADDR_STR,
20208 ch_freq, QDF_MAC_ADDR_ARRAY(bssid));
Arif Hussain43354e62017-05-24 11:24:25 -070020209 /*
20210 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020211 * roam_profile's BSSID is getting zeroed out in the
Arif Hussain43354e62017-05-24 11:24:25 -070020212 * association process. In case of join failure
20213 * we should send valid BSSID to supplicant
20214 */
Jeff Johnson731bc322017-10-14 19:53:44 -070020215 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
20216 qdf_mem_copy(sta_ctx->requested_bssid.bytes, bssid,
Arif Hussain43354e62017-05-24 11:24:25 -070020217 QDF_MAC_ADDR_SIZE);
20218
Abhinav Kumarc0716d42020-01-23 18:19:36 +053020219 hdd_set_roaming_in_progress(true);
20220
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020221 status = hdd_reassoc(adapter, bssid, ch_freq,
20222 CONNECT_CMD_USERSPACE);
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020223 if (QDF_IS_STATUS_ERROR(status)) {
Abhinav Kumarc0716d42020-01-23 18:19:36 +053020224 hdd_set_roaming_in_progress(false);
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020225 hdd_debug("Failed with status: %d", status);
20226 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020227 }
Abhinav Kumarc0716d42020-01-23 18:19:36 +053020228
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020229 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020230}
20231#else
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020232static int wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
20233 struct cfg80211_connect_params *req)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020234{
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020235 return -ENOTSUPP;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020236}
20237#endif
20238
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020239
20240/**
20241 * wlan_hdd_check_ht20_ht40_ind() - check if Supplicant has indicated to
20242 * connect in HT20 mode
20243 * @hdd_ctx: hdd context
20244 * @adapter: Pointer to the HDD adapter
20245 * @req: Pointer to the structure cfg_connect_params receieved from user space
20246 *
20247 * This function will check if supplicant has indicated to to connect in HT20
20248 * mode. this is currently applicable only for 2.4Ghz mode only.
20249 * if feature is enabled and supplicant indicate HT20 set
20250 * force_24ghz_in_ht20 to true to force 2.4Ghz in HT20 else set it to false.
20251 *
20252 * Return: void
20253 */
20254#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
Jeff Johnson20227a92018-03-13 09:41:05 -070020255static void
20256wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
20257 struct hdd_adapter *adapter,
20258 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020259{
Jeff Johnson61b5e982018-03-15 11:33:31 -070020260 struct csr_roam_profile *roam_profile;
Wu Gaofc81ecf2018-11-22 11:38:41 +080020261 bool is_override_ht20_40_24g;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020262
Jeff Johnson20227a92018-03-13 09:41:05 -070020263 roam_profile = hdd_roam_profile(adapter);
20264
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020265 roam_profile->force_24ghz_in_ht20 = false;
20266
Wu Gaofc81ecf2018-11-22 11:38:41 +080020267 ucfg_mlme_is_override_ht20_40_24g(hdd_ctx->psoc,
20268 &is_override_ht20_40_24g);
20269 if (is_override_ht20_40_24g &&
Jeff Johnson20227a92018-03-13 09:41:05 -070020270 !(req->ht_capa.cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020271 roam_profile->force_24ghz_in_ht20 = true;
20272
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020273 if (is_override_ht20_40_24g)
20274 hdd_nofl_debug("HT cap %x", req->ht_capa.cap_info);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020275}
20276#else
Jeff Johnson20227a92018-03-13 09:41:05 -070020277static inline void
20278wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
20279 struct hdd_adapter *adapter,
20280 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020281{
Jeff Johnson61b5e982018-03-15 11:33:31 -070020282 struct csr_roam_profile *roam_profile;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020283
Jeff Johnson20227a92018-03-13 09:41:05 -070020284 roam_profile = hdd_roam_profile(adapter);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020285
20286 roam_profile->force_24ghz_in_ht20 = false;
20287}
20288#endif
20289
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020290static inline void hdd_dump_connect_req(struct hdd_adapter *adapter,
20291 struct net_device *ndev,
20292 struct cfg80211_connect_params *req)
20293{
20294 uint32_t i;
20295
20296 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",
20297 ndev->name, adapter->vdev_id, adapter->device_mode,
20298 req->channel ? req->channel->center_freq : 0,
20299 (int)req->ssid_len, req->ssid, req->auth_type,
20300 req->crypto.wpa_versions,
20301 req->crypto.n_akm_suites, req->crypto.n_ciphers_pairwise,
20302 req->crypto.cipher_group, req->mfp,
20303 req->channel_hint ? req->channel_hint->center_freq : 0);
20304 if (req->bssid)
20305 hdd_nofl_debug("BSSID %pM", req->bssid);
20306 if (req->bssid_hint)
20307 hdd_nofl_debug("BSSID hint %pM", req->bssid_hint);
20308 if (req->prev_bssid)
20309 hdd_nofl_debug("prev BSSID %pM", req->prev_bssid);
20310
20311 for (i = 0; i < req->crypto.n_akm_suites; i++)
20312 hdd_nofl_debug("akm[%d] = %x", i, req->crypto.akm_suites[i]);
20313
20314 for (i = 0; i < req->crypto.n_ciphers_pairwise; i++)
20315 hdd_nofl_debug("cipher_pairwise[%d] = %x", i,
20316 req->crypto.ciphers_pairwise[i]);
20317}
20318
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020319/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020320 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
20321 * @wiphy: Pointer to wiphy
20322 * @dev: Pointer to network device
20323 * @req: Pointer to cfg80211 connect request
20324 *
20325 * This function is used to start the association process
20326 *
20327 * Return: 0 for success, non-zero for failure
20328 */
20329static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
20330 struct net_device *ndev,
20331 struct cfg80211_connect_params *req)
20332{
20333 int status;
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020334 uint32_t ch_freq, sap_cnt, sta_cnt;
Arif Hussainee677012017-01-26 17:50:13 -080020335 const u8 *bssid = NULL;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053020336#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
20337 const u8 *bssid_hint = req->bssid_hint;
20338#else
20339 const u8 *bssid_hint = NULL;
20340#endif
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020341 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020342 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020343
Dustin Brown491d54b2018-03-14 12:39:11 -070020344 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020345
Anurag Chouhan6d760662016-02-20 16:05:43 +053020346 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020347 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020348 return -EINVAL;
20349 }
20350
Jeff Johnson48363022019-02-24 16:26:51 -080020351 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020352 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020353
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020354 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
20355 TRACE_CODE_HDD_CFG80211_CONNECT,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020356 adapter->vdev_id, adapter->device_mode);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020357
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020358 if (adapter->device_mode != QDF_STA_MODE &&
Dustin Brown458027c2018-10-19 12:26:27 -070020359 adapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020360 hdd_err("Device_mode %s(%d) is not supported",
Dustin Brown458027c2018-10-19 12:26:27 -070020361 qdf_opmode_str(adapter->device_mode),
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020362 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020363 return -EINVAL;
20364 }
20365
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020366 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020367 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020368 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020369 return -EINVAL;
20370 }
20371
Jeff Johnsonb8944722017-09-03 09:03:19 -070020372 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020373 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020374 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020375
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020376 if (req->bssid)
20377 bssid = req->bssid;
20378 else if (bssid_hint)
20379 bssid = bssid_hint;
20380
20381 if (bssid && hdd_get_adapter_by_macaddr(hdd_ctx, (uint8_t *)bssid)) {
20382 hdd_err("adapter exist with same mac address " QDF_MAC_ADDR_STR,
20383 QDF_MAC_ADDR_ARRAY(bssid));
20384 return -EINVAL;
20385 }
20386
20387 hdd_dump_connect_req(adapter, ndev, req);
20388
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020389 /*
20390 * Disable NAN Discovery if incoming connection is P2P or if a STA
Manikandan Mohan956b69e2019-02-14 13:08:14 -080020391 * connection already exists and if this is a case of STA+STA
20392 * or SAP+STA concurrency
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020393 */
Manikandan Mohan956b69e2019-02-14 13:08:14 -080020394 sta_cnt = policy_mgr_mode_specific_connection_count(hdd_ctx->psoc,
20395 PM_STA_MODE, NULL);
20396 sap_cnt = policy_mgr_mode_specific_connection_count(hdd_ctx->psoc,
20397 PM_SAP_MODE, NULL);
Nachiket Kukade089b9832018-12-12 16:38:17 +053020398
Manikandan Mohan956b69e2019-02-14 13:08:14 -080020399 if (adapter->device_mode == QDF_P2P_CLIENT_MODE || sap_cnt || sta_cnt) {
20400 hdd_debug("Invalid NAN concurrency. SAP: %d STA: %d P2P: %d",
20401 sap_cnt, sta_cnt,
20402 (adapter->device_mode == QDF_P2P_CLIENT_MODE));
20403 ucfg_nan_disable_concurrency(hdd_ctx->psoc);
20404 }
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020405 /*
20406 * STA+NDI concurrency gets preference over NDI+NDI. Disable
gaurank kathpalia7fd92d92020-02-27 00:02:54 +053020407 * first NDI in case an NDI+NDI concurrency exists if FW does
20408 * not support 4 port concurrency of two NDI + NAN with STA.
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020409 */
gaurank kathpalia7fd92d92020-02-27 00:02:54 +053020410 if (!ucfg_nan_is_sta_nan_ndi_4_port_allowed(hdd_ctx->psoc))
20411 ucfg_nan_check_and_disable_unsupported_ndi(hdd_ctx->psoc,
20412 false);
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053020413
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020414 /*
Pragaspathi Thilagaraj76d0e252019-10-01 15:45:21 +053020415 * In STA + STA roaming scenario, connection to same ssid but different
20416 * bssid is allowed on both vdevs. So there could be a race where the
20417 * STA1 connectes to a bssid when roaming is in progress on STA2 for
20418 * the same bssid. Here the firwmare would have already created peer for
20419 * the roam candidate and host would have created peer on the other
20420 * vdev. When roam synch indication is received, then peer create fails
20421 * at host for the roaming vdev due to duplicate peer detection logic.
20422 * Still roam synch confirm is sent to the firmware.
20423 * When disconnection is received for STA1, then del bss is sent for
20424 * this vdev and firmware asserts as the peer was not created for this
20425 * vdev.
20426 */
20427 if (hdd_is_roaming_in_progress(hdd_ctx) ||
20428 sme_is_any_session_in_middle_of_roaming(hdd_ctx->mac_handle)) {
20429 hdd_err("Roaming in progress. Defer connect");
20430 return -EBUSY;
20431 }
20432
20433 /*
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053020434 * Check if this is reassoc to same bssid, if reassoc is success, return
20435 */
20436 status = wlan_hdd_reassoc_bssid_hint(adapter, req);
Abhinav Kumarc0716d42020-01-23 18:19:36 +053020437 if (!status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070020438 return status;
20439
Agrawal Ashishf156e942016-08-04 14:54:47 +053020440 /* Try disconnecting if already in connected state */
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020441 status = wlan_hdd_try_disconnect(adapter,
20442 eSIR_MAC_UNSPEC_FAILURE_REASON);
Agrawal Ashishf156e942016-08-04 14:54:47 +053020443 if (0 > status) {
20444 hdd_err("Failed to disconnect the existing connection");
20445 return -EALREADY;
20446 }
20447
Liangwei Dong3fa5cba2018-07-16 06:41:55 -040020448 /*initialise security parameters */
20449 status = wlan_hdd_cfg80211_set_privacy(adapter, req);
Liangwei Dong3fa5cba2018-07-16 06:41:55 -040020450 if (status < 0) {
20451 hdd_err("Failed to set security params");
20452 return status;
20453 }
20454
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053020455 if (req->channel)
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020456 ch_freq = req->channel->center_freq;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053020457 else
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020458 ch_freq = 0;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020459
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020460 wlan_hdd_check_ht20_ht40_ind(hdd_ctx, adapter, req);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053020461
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020462 status = wlan_hdd_cfg80211_connect_start(adapter, req->ssid,
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053020463 req->ssid_len, req->bssid,
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070020464 bssid_hint, ch_freq, 0);
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020465 if (status) {
20466 wlan_hdd_cfg80211_clear_privacy(adapter);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020467 hdd_err("connect failed");
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020468 }
Srinivas Girigowdad2412882018-09-07 15:42:04 -070020469
Dustin Browne74003f2018-03-14 12:51:58 -070020470 hdd_exit();
Abhishek Singh4ec44a72020-02-03 15:07:34 +053020471
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020472 return status;
20473}
20474
20475/**
20476 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
20477 * @wiphy: Pointer to wiphy
20478 * @dev: Pointer to network device
20479 * @req: Pointer to cfg80211 connect request
20480 *
20481 * Return: 0 for success, non-zero for failure
20482 */
20483static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
20484 struct net_device *ndev,
20485 struct cfg80211_connect_params *req)
20486{
Dustin Brown1d31b082018-11-22 14:41:20 +053020487 int errno;
20488 struct osif_vdev_sync *vdev_sync;
20489
20490 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
20491 if (errno)
20492 return errno;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020493
Dustin Brown1d31b082018-11-22 14:41:20 +053020494 errno = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020495
Dustin Brown1d31b082018-11-22 14:41:20 +053020496 osif_vdev_sync_op_stop(vdev_sync);
20497
20498 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020499}
20500
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020501/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080020502 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
20503 * @reason: ieee80211 reason code.
20504 *
20505 * This utility function helps log string conversion of reason code.
20506 *
20507 * Return: string conversion of reason code, if match found;
20508 * "Unknown" otherwise.
20509 */
20510static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
20511{
20512 switch (reason) {
20513 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
20514 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
20515 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
20516 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
20517 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
20518 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
20519 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
20520 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
20521 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
20522 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
20523 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
20524 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
20525 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
20526 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
20527 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
20528 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
20529 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
20530 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
20531 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
20532 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
20533 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
20534 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
20535 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
20536 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
20537 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
20538 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
20539 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
20540 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
20541 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
20542 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
20543 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
20544 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
20545 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
20546 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
20547 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
20548 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
20549 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
20550 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
20551 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
20552 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
20553 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
20554 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
20555 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
20556 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
20557 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
20558 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
20559 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
20560 default:
20561 return "Unknown";
20562 }
20563}
20564
20565/**
Srinivas Dasariaa1b8c22020-02-26 14:33:27 +053020566 * hdd_qca_reason_to_str() - return string conversion of qca reason code
20567 * @reason: enum qca_disconnect_reason_codes
20568 *
20569 * This utility function helps log string conversion of qca reason code.
20570 *
20571 * Return: string conversion of reason code, if match found;
20572 * "Unknown" otherwise.
20573 */
20574static const char *
20575hdd_qca_reason_to_str(enum qca_disconnect_reason_codes reason)
20576{
20577 switch (reason) {
20578 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_INTERNAL_ROAM_FAILURE);
20579 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_EXTERNAL_ROAM_FAILURE);
20580 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_GATEWAY_REACHABILITY_FAILURE);
20581 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_UNSUPPORTED_CHANNEL_CSA);
20582 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_OPER_CHANNEL_DISABLED_INDOOR);
20583 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_OPER_CHANNEL_USER_DISABLED);
20584 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_DEVICE_RECOVERY);
20585 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_KEY_TIMEOUT);
20586 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_OPER_CHANNEL_BAND_CHANGE);
20587 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_IFACE_DOWN);
20588 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_PEER_XRETRY_FAIL);
20589 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_PEER_INACTIVITY);
20590 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_SA_QUERY_TIMEOUT);
20591 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_BEACON_MISS_FAILURE);
20592 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_CHANNEL_SWITCH_FAILURE);
20593 CASE_RETURN_STRING(QCA_DISCONNECT_REASON_USER_TRIGGERED);
20594 case QCA_DISCONNECT_REASON_UNSPECIFIED:
20595 return "";
20596 default:
20597 return "Unknown";
20598 }
20599}
20600
20601/**
20602 * wlan_hdd_sir_mac_to_qca_reason() - Convert to qca internal disconnect reason
20603 * @internal_reason: Mac reason code of type @enum eSirMacReasonCodes
20604 *
20605 * Check if it is internal reason code and convert it to the
20606 * enum qca_disconnect_reason_codes.
20607 *
20608 * Return: Reason code of type enum qca_disconnect_reason_codes
20609 */
20610static enum qca_disconnect_reason_codes
20611wlan_hdd_sir_mac_to_qca_reason(enum eSirMacReasonCodes internal_reason)
20612{
20613 enum qca_disconnect_reason_codes reason =
20614 QCA_DISCONNECT_REASON_UNSPECIFIED;
20615 switch (internal_reason) {
20616 case eSIR_MAC_HOST_TRIGGERED_ROAM_FAILURE:
20617 reason = QCA_DISCONNECT_REASON_INTERNAL_ROAM_FAILURE;
20618 break;
20619 case eSIR_MAC_FW_TRIGGERED_ROAM_FAILURE:
20620 reason = QCA_DISCONNECT_REASON_EXTERNAL_ROAM_FAILURE;
20621 break;
20622 case eSIR_MAC_GATEWAY_REACHABILITY_FAILURE:
20623 reason =
20624 QCA_DISCONNECT_REASON_GATEWAY_REACHABILITY_FAILURE;
20625 break;
20626 case eSIR_MAC_UNSUPPORTED_CHANNEL_CSA:
20627 reason = QCA_DISCONNECT_REASON_UNSUPPORTED_CHANNEL_CSA;
20628 break;
20629 case eSIR_MAC_OPER_CHANNEL_DISABLED_INDOOR:
20630 reason =
20631 QCA_DISCONNECT_REASON_OPER_CHANNEL_DISABLED_INDOOR;
20632 break;
20633 case eSIR_MAC_OPER_CHANNEL_USER_DISABLED:
20634 reason =
20635 QCA_DISCONNECT_REASON_OPER_CHANNEL_USER_DISABLED;
20636 break;
20637 case eSIR_MAC_DEVICE_RECOVERY:
20638 reason = QCA_DISCONNECT_REASON_DEVICE_RECOVERY;
20639 break;
20640 case eSIR_MAC_KEY_TIMEOUT:
20641 reason = QCA_DISCONNECT_REASON_KEY_TIMEOUT;
20642 break;
20643 case eSIR_MAC_OPER_CHANNEL_BAND_CHANGE:
20644 reason = QCA_DISCONNECT_REASON_OPER_CHANNEL_BAND_CHANGE;
20645 break;
20646 case eSIR_MAC_IFACE_DOWN:
20647 reason = QCA_DISCONNECT_REASON_IFACE_DOWN;
20648 break;
20649 case eSIR_MAC_PEER_XRETRY_FAIL:
20650 reason = QCA_DISCONNECT_REASON_PEER_XRETRY_FAIL;
20651 break;
20652 case eSIR_MAC_PEER_INACTIVITY:
20653 reason = QCA_DISCONNECT_REASON_PEER_INACTIVITY;
20654 break;
20655 case eSIR_MAC_SA_QUERY_TIMEOUT:
20656 reason = QCA_DISCONNECT_REASON_SA_QUERY_TIMEOUT;
20657 break;
20658 case eSIR_MAC_CHANNEL_SWITCH_FAILED:
20659 reason = QCA_DISCONNECT_REASON_CHANNEL_SWITCH_FAILURE;
20660 break;
20661 case eSIR_MAC_BEACON_MISSED:
20662 reason = QCA_DISCONNECT_REASON_BEACON_MISS_FAILURE;
20663 break;
20664 case eSIR_MAC_USER_TRIGGERED_ROAM_FAILURE:
20665 reason = QCA_DISCONNECT_REASON_USER_TRIGGERED;
20666 break;
20667 default:
20668 hdd_debug("No QCA reason code for mac reason: %u",
20669 internal_reason);
20670 /* Unspecified reason by default */
20671 }
20672
20673 return reason;
20674}
20675
20676/**
20677 * wlan_hdd_get_ieee80211_disconnect_reason() - Get ieee80211 disconnect reason
20678 * @adapter: pointer to adapter structure
20679 * @reason: Mac Disconnect reason code as per @enum eSirMacReasonCodes
20680 *
20681 * Reason codes that are greater than eSIR_MAC_REASON_PROP_START are internal
20682 * reason codes. Convert them to qca reason code format and cache in adapter
20683 * and return UNSPECIFIED.
20684 * Rest of the reason codes are valid ieee80211 reason codes.
20685 *
20686 * Return: Reason code of type ieee80211_reasoncode.
20687 */
20688static enum ieee80211_reasoncode
20689wlan_hdd_get_cfg80211_disconnect_reason(struct hdd_adapter *adapter,
20690 enum eSirMacReasonCodes reason)
20691{
20692 enum ieee80211_reasoncode ieee80211_reason = WLAN_REASON_UNSPECIFIED;
20693
20694 /*
20695 * Convert and cache internal reason code in adapter. This can be
20696 * sent to userspace with a vendor event.
20697 */
20698 if (reason >= eSIR_MAC_REASON_PROP_START) {
20699 adapter->last_disconnect_reason =
20700 wlan_hdd_sir_mac_to_qca_reason(reason);
20701 } else {
20702 ieee80211_reason = (enum ieee80211_reasoncode)reason;
20703 adapter->last_disconnect_reason =
20704 QCA_DISCONNECT_REASON_UNSPECIFIED;
20705 }
20706
20707 return ieee80211_reason;
20708}
20709
20710#if defined(CFG80211_DISCONNECTED_V2) || \
20711(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
20712void
20713wlan_hdd_cfg80211_indicate_disconnect(struct hdd_adapter *adapter,
20714 bool locally_generated,
20715 enum eSirMacReasonCodes reason,
20716 uint8_t *disconnect_ies,
20717 uint16_t disconnect_ies_len)
20718{
20719 enum ieee80211_reasoncode ieee80211_reason;
20720
20721 ieee80211_reason = wlan_hdd_get_cfg80211_disconnect_reason(adapter,
20722 reason);
20723 hdd_nofl_info("Disconnect reason: %u %s vendor: %u %s LG: %u",
20724 ieee80211_reason,
20725 hdd_ieee80211_reason_code_to_str(ieee80211_reason),
20726 adapter->last_disconnect_reason,
20727 hdd_qca_reason_to_str(adapter->last_disconnect_reason),
20728 locally_generated);
20729 cfg80211_disconnected(adapter->dev, ieee80211_reason, disconnect_ies,
20730 disconnect_ies_len, locally_generated,
20731 GFP_KERNEL);
20732}
20733#else
20734void
20735wlan_hdd_cfg80211_indicate_disconnect(struct hdd_adapter *adapter,
20736 bool locally_generated,
20737 enum eSirMacReasonCodes reason,
20738 uint8_t *disconnect_ies,
20739 uint16_t disconnect_ies_len)
20740{
20741 enum ieee80211_reasoncode ieee80211_reason;
20742
20743 ieee80211_reason = wlan_hdd_get_cfg80211_disconnect_reason(adapter,
20744 reason);
20745 hdd_nofl_info("Disconnect reason: %u %s vendor: %u %s LG: %u",
20746 ieee80211_reason,
20747 hdd_ieee80211_reason_code_to_str(ieee80211_reason),
20748 adapter->last_disconnect_reason,
20749 hdd_qca_reason_to_str(adapter->last_disconnect_reason),
20750 locally_generated);
20751 cfg80211_disconnected(adapter->dev, ieee80211_reason, disconnect_ies,
20752 disconnect_ies_len, GFP_KERNEL);
20753}
20754#endif
20755
20756int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason,
20757 tSirMacReasonCodes mac_reason)
20758{
20759 int ret;
20760 mac_handle_t mac_handle;
20761
20762 mac_handle = hdd_adapter_get_mac_handle(adapter);
20763 wlan_hdd_wait_for_roaming(mac_handle, adapter);
20764
20765 /*stop tx queues */
20766 hdd_debug("Disabling queues");
20767 wlan_hdd_netif_queue_control(adapter,
20768 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
20769
20770 ret = wlan_hdd_wait_for_disconnect(mac_handle, adapter, reason,
20771 mac_reason);
20772
20773#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
20774 /* Sending disconnect event to userspace for kernel version < 3.11
20775 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
20776 */
20777 wlan_hdd_cfg80211_indicate_disconnect(adapter, true,
20778 mac_reason, NULL, 0);
20779#endif
20780
20781 return ret;
20782}
20783
20784/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020785 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
20786 * @wiphy: Pointer to wiphy
20787 * @dev: Pointer to network device
20788 * @reason: Disconnect reason code
20789 *
20790 * This function is used to issue a disconnect request to SME
20791 *
20792 * Return: 0 for success, non-zero for failure
20793 */
20794static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
20795 struct net_device *dev, u16 reason)
20796{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020797 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020798 int status;
Jeff Johnsond377dce2017-10-04 10:32:42 -070020799 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020800 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
20801 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Min Liu8c5d99e2018-09-10 17:18:44 +080020802 struct wlan_objmgr_vdev *vdev;
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053020803 bool enable_deauth_to_disassoc_map;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020804
Anurag Chouhan6d760662016-02-20 16:05:43 +053020805 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020806 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020807 return -EINVAL;
20808 }
20809
Jeff Johnson48363022019-02-24 16:26:51 -080020810 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020811 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020812
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020813 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
20814 TRACE_CODE_HDD_CFG80211_DISCONNECT,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020815 adapter->vdev_id, reason);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020816
Srinivas Girigowda44cff5c2018-04-16 15:49:30 -070020817 hdd_print_netdev_txq_status(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020818 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020819
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020820 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020821 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020822
Alok Kumarb64650c2018-03-23 17:05:11 +053020823 qdf_mutex_acquire(&adapter->disconnection_status_lock);
20824 if (adapter->disconnection_in_progress) {
20825 qdf_mutex_release(&adapter->disconnection_status_lock);
20826 hdd_debug("Disconnect is already in progress");
20827 return 0;
20828 }
20829 adapter->disconnection_in_progress = true;
20830 qdf_mutex_release(&adapter->disconnection_status_lock);
20831
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020832 /* Issue disconnect request to SME, if station is in connected state */
Jeff Johnsone7951512019-02-27 10:02:51 -080020833 if ((sta_ctx->conn_info.conn_state == eConnectionState_Associated) ||
20834 (sta_ctx->conn_info.conn_state == eConnectionState_Connecting)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020835 eCsrRoamDisconnectReason reasonCode =
20836 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020837
20838 switch (reason) {
20839 case WLAN_REASON_MIC_FAILURE:
20840 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
20841 break;
20842
20843 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
20844 case WLAN_REASON_DISASSOC_AP_BUSY:
20845 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
20846 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
20847 break;
20848
20849 case WLAN_REASON_PREV_AUTH_NOT_VALID:
20850 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
20851 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
20852 break;
20853
20854 case WLAN_REASON_DEAUTH_LEAVING:
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053020855 status = ucfg_mlme_get_enable_deauth_to_disassoc_map(
20856 hdd_ctx->psoc,
20857 &enable_deauth_to_disassoc_map);
20858 if (QDF_IS_STATUS_ERROR(status))
20859 return -EINVAL;
20860
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020861 reasonCode =
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053020862 enable_deauth_to_disassoc_map ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020863 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
20864 eCSR_DISCONNECT_REASON_DEAUTH;
Mohit Khannaceb97782017-04-05 16:27:08 -070020865 qdf_dp_trace_dump_all(
20866 WLAN_DEAUTH_DPTRACE_DUMP_COUNT,
20867 QDF_TRACE_DEFAULT_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020868 break;
20869 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
20870 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
20871 break;
20872 default:
20873 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
20874 break;
20875 }
Min Liu8c5d99e2018-09-10 17:18:44 +080020876
20877 vdev = hdd_objmgr_get_vdev(adapter);
20878 if (!vdev)
20879 return -EINVAL;
Abhishek Singh29405dc2020-02-17 13:08:32 +053020880 if (ucfg_scan_get_vdev_status(vdev) != SCAN_NOT_IN_PROGRESS)
Dustin Brown07901ec2018-09-07 11:02:41 -070020881 wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020882 adapter->vdev_id, INVALID_SCAN_ID,
Dustin Brown07901ec2018-09-07 11:02:41 -070020883 false);
Abhishek Singh29405dc2020-02-17 13:08:32 +053020884
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020885 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020886 /* First clean up the tdls peers if any */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020887 hdd_notify_sta_disconnect(adapter->vdev_id,
Min Liu8c5d99e2018-09-10 17:18:44 +080020888 false, true, vdev);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053020889 hdd_objmgr_put_vdev(vdev);
Kabilan Kannanb6153b12017-07-13 17:54:02 -070020890
Srinivas Dasariaa1b8c22020-02-26 14:33:27 +053020891 hdd_nofl_info("%s(vdevid-%d): Received Disconnect reason:%d %s",
20892 dev->name, adapter->vdev_id, reason,
20893 hdd_ieee80211_reason_code_to_str(reason));
Srinivas Dasarie2495dc2020-02-13 09:49:24 +053020894 status = wlan_hdd_disconnect(adapter, reasonCode, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020895 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020896 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Alok Kumarb64650c2018-03-23 17:05:11 +053020897 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020898 return -EINVAL;
20899 }
20900 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020901 hdd_err("Unexpected cfg disconnect called while in state: %d",
Jeff Johnsone7951512019-02-27 10:02:51 -080020902 sta_ctx->conn_info.conn_state);
Alok Kumarb64650c2018-03-23 17:05:11 +053020903 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020904 }
20905
20906 return status;
20907}
20908
20909/**
20910 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
20911 * @wiphy: Pointer to wiphy
20912 * @dev: Pointer to network device
20913 * @reason: Disconnect reason code
20914 *
20915 * Return: 0 for success, non-zero for failure
20916 */
20917static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
20918 struct net_device *dev, u16 reason)
20919{
Dustin Brown1d31b082018-11-22 14:41:20 +053020920 int errno;
20921 struct osif_vdev_sync *vdev_sync;
20922
20923 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
20924 if (errno)
20925 return errno;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020926
Dustin Brown1d31b082018-11-22 14:41:20 +053020927 errno = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020928
Dustin Brown1d31b082018-11-22 14:41:20 +053020929 osif_vdev_sync_op_stop(vdev_sync);
20930
20931 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020932}
20933
20934/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020935 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
20936 * @wiphy: Pointer to wiphy
20937 * @changed: Parameters changed
20938 *
20939 * This function is used to set the phy parameters. RTS Threshold/FRAG
20940 * Threshold/Retry Count etc.
20941 *
20942 * Return: 0 for success, non-zero for failure
20943 */
20944static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
20945 u32 changed)
20946{
Jeff Johnsonb8944722017-09-03 09:03:19 -070020947 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020948 int status;
20949
Dustin Brown491d54b2018-03-14 12:39:11 -070020950 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020951
Anurag Chouhan6d760662016-02-20 16:05:43 +053020952 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020953 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020954 return -EINVAL;
20955 }
20956
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020957 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
20958 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
20959 NO_SESSION, wiphy->rts_threshold);
20960
Jeff Johnsonb8944722017-09-03 09:03:19 -070020961 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020962
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020963 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020964 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020965
20966 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
20967 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
Harprit Chhabadabec6de42018-09-10 10:21:15 -070020968 cfg_max(CFG_RTS_THRESHOLD) :
20969 wiphy->rts_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020970
Harprit Chhabadabec6de42018-09-10 10:21:15 -070020971 if ((cfg_min(CFG_RTS_THRESHOLD) > rts_threshold) ||
20972 (cfg_max(CFG_RTS_THRESHOLD) < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020973 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020974 rts_threshold);
20975 return -EINVAL;
20976 }
20977
Harprit Chhabadabec6de42018-09-10 10:21:15 -070020978 if (0 != ucfg_mlme_set_rts_threshold(hdd_ctx->psoc,
20979 rts_threshold)) {
20980 hdd_err("mlme_set_rts_threshold failed for val %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020981 rts_threshold);
20982 return -EIO;
20983 }
20984
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020985 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020986 }
20987
20988 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
20989 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
Harprit Chhabadabec6de42018-09-10 10:21:15 -070020990 cfg_max(CFG_FRAG_THRESHOLD) :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020991 wiphy->frag_threshold;
20992
Harprit Chhabadabec6de42018-09-10 10:21:15 -070020993 if ((cfg_min(CFG_FRAG_THRESHOLD) > frag_threshold) ||
20994 (cfg_max(CFG_FRAG_THRESHOLD) < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020995 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020996 frag_threshold);
20997 return -EINVAL;
20998 }
20999
Harprit Chhabadabec6de42018-09-10 10:21:15 -070021000 if (0 != ucfg_mlme_set_frag_threshold(hdd_ctx->psoc,
21001 frag_threshold)) {
21002 hdd_err("mlme_set_frag_threshold failed for val %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021003 frag_threshold);
21004 return -EIO;
21005 }
21006
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021007 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021008 }
21009
Dustin Browne74003f2018-03-14 12:51:58 -070021010 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021011 return 0;
21012}
21013
21014/**
21015 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
21016 * @wiphy: Pointer to wiphy
21017 * @changed: Parameters changed
21018 *
21019 * Return: 0 for success, non-zero for failure
21020 */
21021static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
21022{
Dustin Brown363b4792019-02-05 16:11:55 -080021023 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080021024 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +053021025
Dustin Brown363b4792019-02-05 16:11:55 -080021026 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080021027 if (errno)
21028 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021029
Dustin Brownf0f00612019-01-31 16:02:24 -080021030 errno = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021031
Dustin Brown363b4792019-02-05 16:11:55 -080021032 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080021033
21034 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021035}
21036
21037/**
21038 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
21039 * key
21040 * @wiphy: Pointer to wiphy
21041 * @dev: Pointer to network device
21042 * @key_index: Key index
21043 *
21044 * Return: 0
21045 */
21046static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
21047 struct net_device *netdev,
21048 u8 key_index)
21049{
Dustin Brown491d54b2018-03-14 12:39:11 -070021050 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021051 return 0;
21052}
21053
21054/**
21055 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
21056 * wlan_hdd_set_default_mgmt_key
21057 * @wiphy: pointer to wiphy
21058 * @netdev: pointer to net_device structure
21059 * @key_index: key index
21060 *
21061 * Return: 0 on success, error number on failure
21062 */
21063static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
21064 struct net_device *netdev,
21065 u8 key_index)
21066{
Dustin Brown1d31b082018-11-22 14:41:20 +053021067 int errno;
21068 struct osif_vdev_sync *vdev_sync;
21069
21070 errno = osif_vdev_sync_op_start(netdev, &vdev_sync);
21071 if (errno)
21072 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021073
Dustin Brown1d31b082018-11-22 14:41:20 +053021074 errno = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021075
Dustin Brown1d31b082018-11-22 14:41:20 +053021076 osif_vdev_sync_op_stop(vdev_sync);
21077
21078 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021079}
21080
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021081/**
21082 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
21083 * @wiphy: Pointer to wiphy
21084 * @dev: Pointer to network device
21085 * @params: Pointer to tx queue parameters
21086 *
21087 * Return: 0
21088 */
21089static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
21090 struct net_device *dev,
21091 struct ieee80211_txq_params *params)
21092{
Dustin Brown491d54b2018-03-14 12:39:11 -070021093 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021094 return 0;
21095}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021096
21097/**
21098 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
21099 * @wiphy: pointer to wiphy
21100 * @netdev: pointer to net_device structure
21101 * @params: pointer to ieee80211_txq_params
21102 *
21103 * Return: 0 on success, error number on failure
21104 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021105static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
21106 struct net_device *dev,
21107 struct ieee80211_txq_params *params)
21108{
Dustin Brown1d31b082018-11-22 14:41:20 +053021109 int errno;
21110 struct osif_vdev_sync *vdev_sync;
21111
21112 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21113 if (errno)
21114 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021115
Dustin Brown1d31b082018-11-22 14:41:20 +053021116 errno = __wlan_hdd_set_txq_params(wiphy, dev, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021117
Dustin Brown1d31b082018-11-22 14:41:20 +053021118 osif_vdev_sync_op_stop(vdev_sync);
21119
21120 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021121}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021122
21123/**
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021124 * hdd_softap_deauth_current_sta() - Deauth current sta
21125 * @sta_info: pointer to the current station info structure
21126 * @adapter: pointer to adapter structure
21127 * @hdd_ctx: pointer to hdd context
21128 * @hapd_state: pointer to hostapd state structure
21129 * @param: pointer to del sta params
21130 *
21131 * Return: QDF_STATUS on success, corresponding QDF failure status on failure
21132 */
21133static
21134QDF_STATUS hdd_softap_deauth_current_sta(struct hdd_adapter *adapter,
21135 struct hdd_station_info *sta_info,
21136 struct hdd_hostapd_state *hapd_state,
21137 struct csr_del_sta_params *param)
21138{
21139 qdf_event_t *disassoc_event = &hapd_state->qdf_sta_disassoc_event;
21140 struct hdd_context *hdd_ctx;
21141 QDF_STATUS qdf_status;
21142
21143 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21144 if (!hdd_ctx) {
21145 hdd_err("hdd_ctx is NULL");
21146 return QDF_STATUS_E_INVAL;
21147 }
21148
21149 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
21150 return QDF_STATUS_E_INVAL;
21151
21152 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
21153
21154 if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac))
21155 sme_send_disassoc_req_frame(hdd_ctx->mac_handle,
21156 adapter->vdev_id,
21157 (uint8_t *)&param->peerMacAddr,
21158 param->reason_code, 0);
21159
21160 qdf_status = hdd_softap_sta_deauth(adapter, param);
21161
21162 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
21163 sta_info->is_deauth_in_progress = true;
21164 qdf_status = qdf_wait_for_event_completion(
21165 disassoc_event,
21166 SME_PEER_DISCONNECT_TIMEOUT);
21167 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
21168 hdd_warn("Deauth time expired");
21169 } else {
21170 sta_info->is_deauth_in_progress = false;
21171 hdd_debug("STA removal failed for ::" QDF_MAC_ADDR_STR,
21172 QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
21173 return QDF_STATUS_E_NOENT;
21174 }
21175 return QDF_STATUS_SUCCESS;
21176}
21177
21178/**
21179 * hdd_softap_deauth_all_sta() - Deauth all sta in the sta list
21180 * @hdd_ctx: pointer to hdd context
21181 * @adapter: pointer to adapter structure
21182 * @hapd_state: pointer to hostapd state structure
21183 * @param: pointer to del sta params
21184 *
21185 * Return: QDF_STATUS on success, corresponding QDF failure status on failure
21186 */
21187static
21188QDF_STATUS hdd_softap_deauth_all_sta(struct hdd_adapter *adapter,
21189 struct hdd_hostapd_state *hapd_state,
21190 struct csr_del_sta_params *param)
21191{
21192 uint8_t index = 0;
21193 QDF_STATUS status;
21194 bool is_sap_bcast_deauth_enabled = false;
21195 struct hdd_context *hdd_ctx;
21196 struct hdd_station_info *sta_info;
21197
21198 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21199 if (!hdd_ctx) {
21200 hdd_err("hdd_ctx is NULL");
21201 return QDF_STATUS_E_INVAL;
21202 }
21203
21204 ucfg_mlme_get_sap_bcast_deauth_enabled(hdd_ctx->psoc,
21205 &is_sap_bcast_deauth_enabled);
21206
21207 hdd_debug("sap_bcast_deauth_enabled %d", is_sap_bcast_deauth_enabled);
21208
21209 if (is_sap_bcast_deauth_enabled)
21210 return QDF_STATUS_E_INVAL;
21211
21212 hdd_for_each_station(adapter->sta_info_list, sta_info, index) {
21213 if (!sta_info->is_deauth_in_progress) {
21214 hdd_debug("Delete STA with MAC:" QDF_MAC_ADDR_STR,
21215 QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
21216 status =
21217 hdd_softap_deauth_current_sta(adapter, sta_info,
21218 hapd_state, param);
21219 if (QDF_IS_STATUS_ERROR(status))
21220 return status;
21221 }
21222 }
21223
21224 return QDF_STATUS_SUCCESS;
21225}
21226
21227/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021228 * __wlan_hdd_cfg80211_del_station() - delete station v2
21229 * @wiphy: Pointer to wiphy
Jeff Johnson50e37e92019-03-08 11:32:25 -080021230 * @dev: Underlying net device
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021231 * @param: Pointer to delete station parameter
21232 *
21233 * Return: 0 for success, non-zero for failure
21234 */
21235static
21236int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
21237 struct net_device *dev,
Jeff Johnson50e37e92019-03-08 11:32:25 -080021238 struct csr_del_sta_params *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021239{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021240 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021241 struct hdd_context *hdd_ctx;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070021242 struct hdd_hostapd_state *hapd_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021243 uint8_t *mac;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021244 mac_handle_t mac_handle;
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021245 struct hdd_station_info *sta_info;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021246
Dustin Brown491d54b2018-03-14 12:39:11 -070021247 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021248
Anurag Chouhan6d760662016-02-20 16:05:43 +053021249 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021250 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021251 return -EINVAL;
21252 }
21253
Jeff Johnson48363022019-02-24 16:26:51 -080021254 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021255 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021256
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021257 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21258 TRACE_CODE_HDD_CFG80211_DEL_STA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021259 adapter->vdev_id, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021260
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021261 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Abhishek Singh97e8a712019-03-29 12:14:04 +053021262 if (!hdd_ctx) {
21263 hdd_err("hdd_ctx is NULL");
21264 return -EINVAL;
21265 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021266
Jeff Johnson50e37e92019-03-08 11:32:25 -080021267 mac = (uint8_t *) param->peerMacAddr.bytes;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021268 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021269
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021270 if (QDF_SAP_MODE != adapter->device_mode &&
21271 QDF_P2P_GO_MODE != adapter->device_mode)
21272 goto fn_end;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021273
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021274 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
21275 if (!hapd_state) {
21276 hdd_err("Hostapd State is Null");
21277 return 0;
21278 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021279
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021280 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac)) {
21281 if (!QDF_IS_STATUS_SUCCESS(hdd_softap_deauth_all_sta(adapter,
21282 hapd_state,
21283 param)))
21284 goto fn_end;
21285 } else {
21286 sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
21287 mac);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070021288
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021289 if (!sta_info) {
21290 hdd_debug("Skip DEL STA as this is not used::"
21291 QDF_MAC_ADDR_STR,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021292 QDF_MAC_ADDR_ARRAY(mac));
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021293 return -ENOENT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021294 }
Sourav Mohapatra43e6dea2019-08-18 11:39:23 +053021295
21296 if (sta_info->is_deauth_in_progress) {
21297 hdd_debug("Skip DEL STA as deauth is in progress::"
21298 QDF_MAC_ADDR_STR,
21299 QDF_MAC_ADDR_ARRAY(mac));
21300 return -ENOENT;
21301 }
21302
21303 hdd_debug("ucast, Delete STA with MAC:" QDF_MAC_ADDR_STR,
21304 QDF_MAC_ADDR_ARRAY(mac));
21305 hdd_softap_deauth_current_sta(adapter, sta_info, hapd_state,
21306 param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021307 }
21308
21309fn_end:
Dustin Browne74003f2018-03-14 12:51:58 -070021310 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021311 return 0;
21312}
21313
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080021314#if defined(USE_CFG80211_DEL_STA_V2)
21315/**
21316 * wlan_hdd_del_station() - delete station wrapper
21317 * @adapter: pointer to the hdd adapter
21318 *
21319 * Return: None
21320 */
Jeff Johnsone5006672017-08-29 14:39:02 -070021321void wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080021322{
21323 struct station_del_parameters del_sta;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070021324
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080021325 del_sta.mac = NULL;
21326 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
21327 del_sta.reason_code = eCsrForcedDeauthSta;
21328
21329 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
21330 &del_sta);
21331}
21332#else
Jeff Johnsone5006672017-08-29 14:39:02 -070021333void wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080021334{
21335 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
21336}
21337#endif
21338
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021339/**
Dustin Brown1d31b082018-11-22 14:41:20 +053021340 * wlan_hdd_cfg80211_del_station() - delete station entry handler
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021341 * @wiphy: Pointer to wiphy
Dustin Brown1d31b082018-11-22 14:41:20 +053021342 * @dev: net_device to operate against
21343 * @mac: binary mac address
21344 * @reason_code: reason for the deauthorization/disassociation
21345 * @subtype: management frame subtype to indicate removal
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021346 *
Dustin Brown1d31b082018-11-22 14:41:20 +053021347 * Return: Errno
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021348 */
Dustin Brown1d31b082018-11-22 14:41:20 +053021349static int _wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
21350 struct net_device *dev,
21351 const uint8_t *mac,
21352 uint16_t reason_code,
21353 uint8_t subtype)
21354{
21355 int errno;
21356 struct csr_del_sta_params delStaParams;
21357 struct osif_vdev_sync *vdev_sync;
21358
21359 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21360 if (errno)
21361 return errno;
21362
Dustin Brown1d31b082018-11-22 14:41:20 +053021363 wlansap_populate_del_sta_params(mac, reason_code, subtype,
21364 &delStaParams);
21365 errno = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
Dustin Brown1d31b082018-11-22 14:41:20 +053021366
21367 osif_vdev_sync_op_stop(vdev_sync);
21368
21369 return errno;
21370}
21371
21372#ifdef USE_CFG80211_DEL_STA_V2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021373int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
21374 struct net_device *dev,
21375 struct station_del_parameters *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021376{
Dustin Brown1d31b082018-11-22 14:41:20 +053021377 if (!param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021378 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021379
Dustin Brown1d31b082018-11-22 14:41:20 +053021380 return _wlan_hdd_cfg80211_del_station(wiphy, dev, param->mac,
21381 param->reason_code,
21382 param->subtype);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021383}
Dustin Brown1d31b082018-11-22 14:41:20 +053021384#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
21385int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
21386 const uint8_t *mac)
21387{
21388 uint16_t reason = eSIR_MAC_DEAUTH_LEAVING_BSS_REASON;
21389 uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
21390
21391 return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
21392}
21393#else
21394int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
21395 uint8_t *mac)
21396{
21397 uint16_t reason = eSIR_MAC_DEAUTH_LEAVING_BSS_REASON;
21398 uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
21399
21400 return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
21401}
21402#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021403
21404/**
21405 * __wlan_hdd_cfg80211_add_station() - add station
21406 * @wiphy: Pointer to wiphy
21407 * @mac: Pointer to station mac address
21408 * @pmksa: Pointer to add station parameter
21409 *
21410 * Return: 0 for success, non-zero for failure
21411 */
21412static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
21413 struct net_device *dev,
21414 const uint8_t *mac,
21415 struct station_parameters *params)
21416{
21417 int status = -EPERM;
21418#ifdef FEATURE_WLAN_TDLS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021419 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021420 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021421 u32 mask, set;
21422
Dustin Brown491d54b2018-03-14 12:39:11 -070021423 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021424
Anurag Chouhan6d760662016-02-20 16:05:43 +053021425 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021426 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021427 return -EINVAL;
21428 }
21429
Jeff Johnson48363022019-02-24 16:26:51 -080021430 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021431 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021432
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021433 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21434 TRACE_CODE_HDD_CFG80211_ADD_STA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021435 adapter->vdev_id, params->listen_interval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021436
Jeff Johnsonb8944722017-09-03 09:03:19 -070021437 if (0 != wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021438 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021439
21440 mask = params->sta_flags_mask;
21441
21442 set = params->sta_flags_set;
21443
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070021444 hdd_debug("mask 0x%x set 0x%x " QDF_MAC_ADDR_STR, mask, set,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021445 QDF_MAC_ADDR_ARRAY(mac));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021446
21447 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Min Liu8c5d99e2018-09-10 17:18:44 +080021448 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
21449 struct wlan_objmgr_vdev *vdev;
21450
21451 vdev = hdd_objmgr_get_vdev(adapter);
21452 if (vdev) {
21453 status = wlan_cfg80211_tdls_add_peer(vdev,
21454 mac);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053021455 hdd_objmgr_put_vdev(vdev);
Min Liu8c5d99e2018-09-10 17:18:44 +080021456 }
21457 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021458 }
21459#endif
Dustin Browne74003f2018-03-14 12:51:58 -070021460 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021461 return status;
21462}
21463
21464/**
21465 * wlan_hdd_cfg80211_add_station() - add station
21466 * @wiphy: Pointer to wiphy
21467 * @mac: Pointer to station mac address
21468 * @pmksa: Pointer to add station parameter
21469 *
21470 * Return: 0 for success, non-zero for failure
21471 */
21472#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
21473static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
21474 struct net_device *dev,
21475 const uint8_t *mac,
21476 struct station_parameters *params)
21477#else
21478static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
21479 struct net_device *dev, uint8_t *mac,
21480 struct station_parameters *params)
21481#endif
21482{
Dustin Brown1d31b082018-11-22 14:41:20 +053021483 int errno;
21484 struct osif_vdev_sync *vdev_sync;
21485
21486 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21487 if (errno)
21488 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021489
Dustin Brown1d31b082018-11-22 14:41:20 +053021490 errno = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021491
Dustin Brown1d31b082018-11-22 14:41:20 +053021492 osif_vdev_sync_op_stop(vdev_sync);
21493
21494 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021495}
21496
Abhinav Kumar243b43b2020-02-21 14:23:07 +053021497#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
21498/**
21499 * wlan_update_sae_single_pmk_info() - Update a separate pmk information
21500 * structure to support sae roaming using same pmk
21501 * @vdev: vdev common object
21502 * @pmk_cache: Pointer to pmk cache info
21503 *
21504 * Return: None
21505 */
21506static void wlan_update_sae_single_pmk_info(struct wlan_objmgr_vdev *vdev,
21507 tPmkidCacheInfo *pmk_cache)
21508{
21509 struct mlme_pmk_info *pmk_info;
21510
21511 pmk_info = qdf_mem_malloc(sizeof(*pmk_info));
21512 if (!pmk_info)
21513 return;
21514
21515 qdf_mem_copy(pmk_info->pmk, pmk_cache->pmk, pmk_cache->pmk_len);
21516 pmk_info->pmk_len = pmk_cache->pmk_len;
21517
21518 ucfg_mlme_update_sae_single_pmk_info(vdev, pmk_info);
21519
21520 qdf_mem_zero(pmk_info, sizeof(*pmk_info));
21521 qdf_mem_free(pmk_info);
21522
21523}
21524#else
21525static void wlan_update_sae_single_pmk_info(struct wlan_objmgr_vdev *vdev,
21526 tPmkidCacheInfo *pmk_cache)
21527{
21528}
21529#endif
Liangwei Donga44d55b2019-03-20 03:22:08 -040021530static QDF_STATUS wlan_hdd_set_pmksa_cache(struct hdd_adapter *adapter,
21531 tPmkidCacheInfo *pmk_cache)
21532{
21533 QDF_STATUS result;
21534 struct wlan_crypto_pmksa *pmksa;
21535 struct wlan_objmgr_vdev *vdev;
Liangwei Dongd4ea8ea2020-02-05 14:10:36 +080021536 mac_handle_t mac_handle;
21537 struct hdd_context *hdd_ctx;
21538
21539 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21540 if (!hdd_ctx) {
21541 hdd_err("HDD context is null");
21542 return QDF_STATUS_E_INVAL;
21543 }
21544
21545 if (wlan_hdd_validate_context(hdd_ctx))
21546 return QDF_STATUS_E_INVAL;
21547 mac_handle = hdd_ctx->mac_handle;
Liangwei Donga44d55b2019-03-20 03:22:08 -040021548
21549 vdev = hdd_objmgr_get_vdev(adapter);
21550 if (!vdev)
21551 return QDF_STATUS_E_FAILURE;
21552
21553 pmksa = qdf_mem_malloc(sizeof(*pmksa));
21554 if (!pmksa) {
21555 hdd_objmgr_put_vdev(vdev);
21556 return QDF_STATUS_E_NOMEM;
21557 }
Liangwei Dongd4ea8ea2020-02-05 14:10:36 +080021558
21559 if (!pmk_cache->ssid_len) {
21560 qdf_copy_macaddr(&pmksa->bssid, &pmk_cache->BSSID);
21561 } else {
21562 qdf_mem_copy(pmksa->ssid, pmk_cache->ssid, pmk_cache->ssid_len);
21563 qdf_mem_copy(pmksa->cache_id, pmk_cache->cache_id,
21564 WLAN_CACHE_ID_LEN);
21565 pmksa->ssid_len = pmk_cache->ssid_len;
21566 }
Liangwei Donga44d55b2019-03-20 03:22:08 -040021567 qdf_mem_copy(pmksa->pmkid, pmk_cache->PMKID, PMKID_LEN);
21568 qdf_mem_copy(pmksa->pmk, pmk_cache->pmk, pmk_cache->pmk_len);
21569 pmksa->pmk_len = pmk_cache->pmk_len;
21570
21571 result = wlan_crypto_set_del_pmksa(vdev, pmksa, true);
21572 if (result != QDF_STATUS_SUCCESS) {
21573 qdf_mem_zero(pmksa, sizeof(*pmksa));
21574 qdf_mem_free(pmksa);
21575 }
Liangwei Dongd4ea8ea2020-02-05 14:10:36 +080021576
Abhinav Kumar243b43b2020-02-21 14:23:07 +053021577 wlan_update_sae_single_pmk_info(vdev, pmk_cache);
21578
Liangwei Dongd4ea8ea2020-02-05 14:10:36 +080021579 if (result == QDF_STATUS_SUCCESS && pmk_cache->pmk_len)
21580 sme_roam_set_psk_pmk(mac_handle, adapter->vdev_id,
21581 pmk_cache->pmk, pmk_cache->pmk_len);
Abhinav Kumar243b43b2020-02-21 14:23:07 +053021582
Liangwei Donga44d55b2019-03-20 03:22:08 -040021583 hdd_objmgr_put_vdev(vdev);
21584
21585 return result;
21586}
21587
21588static QDF_STATUS wlan_hdd_del_pmksa_cache(struct hdd_adapter *adapter,
21589 tPmkidCacheInfo *pmk_cache)
21590{
21591 QDF_STATUS result;
21592 struct wlan_crypto_pmksa pmksa;
21593 struct wlan_objmgr_vdev *vdev;
21594
21595 vdev = hdd_objmgr_get_vdev(adapter);
21596 if (!vdev)
21597 return QDF_STATUS_E_FAILURE;
21598
21599 qdf_copy_macaddr(&pmksa.bssid, &pmk_cache->BSSID);
21600 result = wlan_crypto_set_del_pmksa(adapter->vdev, &pmksa, false);
21601 hdd_objmgr_put_vdev(vdev);
21602
21603 return result;
21604}
21605
21606QDF_STATUS wlan_hdd_flush_pmksa_cache(struct hdd_adapter *adapter)
21607{
21608 QDF_STATUS result;
21609 struct wlan_objmgr_vdev *vdev;
21610
21611 vdev = hdd_objmgr_get_vdev(adapter);
21612 if (!vdev)
21613 return QDF_STATUS_E_FAILURE;
21614
21615 result = wlan_crypto_set_del_pmksa(adapter->vdev, NULL, false);
21616 hdd_objmgr_put_vdev(vdev);
21617
21618 return result;
21619}
Liangwei Donga44d55b2019-03-20 03:22:08 -040021620
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053021621#if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
21622 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021623/*
21624 * wlan_hdd_is_pmksa_valid: API to validate pmksa
21625 * @pmksa: pointer to cfg80211_pmksa structure
21626 *
21627 * Return: True if valid else false
21628 */
21629static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
21630{
21631 if (!pmksa->bssid) {
Liangwei Dongd4ea8ea2020-02-05 14:10:36 +080021632 hdd_warn("bssid is NULL");
Vignesh Viswanathanfa90d622017-12-22 13:13:26 +053021633 if (!pmksa->ssid || !pmksa->cache_id) {
Liangwei Dongd4ea8ea2020-02-05 14:10:36 +080021634 hdd_err("either ssid or cache_id are NULL");
Vignesh Viswanathanfa90d622017-12-22 13:13:26 +053021635 return false;
21636 }
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021637 }
21638 return true;
21639}
21640
21641/*
21642 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021643 * @adapter: Pointer to hdd adapter
21644 * @pmk_cache: pmk that needs to be udated
21645 * @pmksa: pmk from supplicant
21646 * @is_delete: Bool to decide set or delete PMK
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021647 * Return: None
21648 */
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021649static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
21650 tPmkidCacheInfo *pmk_cache,
21651 struct cfg80211_pmksa *pmksa, bool is_delete)
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021652{
21653 if (pmksa->bssid) {
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070021654 hdd_debug("%s PMKSA for " QDF_MAC_ADDR_STR,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021655 is_delete ? "Delete" : "Set",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021656 QDF_MAC_ADDR_ARRAY(pmksa->bssid));
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021657 qdf_mem_copy(pmk_cache->BSSID.bytes,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021658 pmksa->bssid, QDF_MAC_ADDR_SIZE);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021659 } else {
Jeff Johnson9c749db2018-05-07 12:50:46 -070021660 qdf_mem_copy(pmk_cache->ssid, pmksa->ssid, pmksa->ssid_len);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021661 qdf_mem_copy(pmk_cache->cache_id, pmksa->cache_id,
21662 CACHE_ID_LEN);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021663 pmk_cache->ssid_len = pmksa->ssid_len;
21664 hdd_debug("%s PMKSA for ssid %*.*s cache_id %x %x",
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021665 is_delete ? "Delete" : "Set",
21666 pmk_cache->ssid_len, pmk_cache->ssid_len,
21667 pmk_cache->ssid, pmk_cache->cache_id[0],
21668 pmk_cache->cache_id[1]);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021669 }
21670
21671 if (is_delete)
21672 return;
21673
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -070021674 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, PMKID_LEN);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021675 if (pmksa->pmk_len && (pmksa->pmk_len <= CSR_RSN_MAX_PMK_LEN)) {
21676 qdf_mem_copy(pmk_cache->pmk, pmksa->pmk, pmksa->pmk_len);
21677 pmk_cache->pmk_len = pmksa->pmk_len;
21678 } else
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053021679 hdd_debug("pmk len is %zu", pmksa->pmk_len);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021680}
21681#else
21682/*
21683 * wlan_hdd_is_pmksa_valid: API to validate pmksa
21684 * @pmksa: pointer to cfg80211_pmksa structure
21685 *
21686 * Return: True if valid else false
21687 */
21688static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
21689{
21690 if (!pmksa->bssid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070021691 hdd_err("both bssid is NULL %pK", pmksa->bssid);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021692 return false;
21693 }
21694 return true;
21695}
21696
21697/*
21698 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021699 * @adapter: Pointer to hdd adapter
21700 * @pmk_cache: pmk which needs to be updated
21701 * @pmksa: pmk from supplicant
21702 * @is_delete: Bool to decide whether to set or delete PMK
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021703 *
21704 * Return: None
21705 */
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021706static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
21707 tPmkidCacheInfo *pmk_cache,
21708 struct cfg80211_pmksa *pmksa, bool is_delete)
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021709{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021710 mac_handle_t mac_handle;
Srinivas Girigowda50335342018-09-07 15:21:01 -070021711
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070021712 hdd_debug("%s PMKSA for " QDF_MAC_ADDR_STR, is_delete ? "Delete" : "Set",
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070021713 QDF_MAC_ADDR_ARRAY(pmksa->bssid));
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021714 qdf_mem_copy(pmk_cache->BSSID.bytes,
21715 pmksa->bssid, QDF_MAC_ADDR_SIZE);
21716
21717 if (is_delete)
21718 return;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021719 mac_handle = hdd_adapter_get_mac_handle(adapter);
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021720 sme_get_pmk_info(mac_handle, adapter->vdev_id, pmk_cache);
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -070021721 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, PMKID_LEN);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021722}
21723#endif
21724
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021725/**
21726 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
21727 * @wiphy: Pointer to wiphy
21728 * @dev: Pointer to network device
21729 * @pmksa: Pointer to set pmksa parameter
21730 *
21731 * Return: 0 for success, non-zero for failure
21732 */
21733static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
21734 struct net_device *dev,
21735 struct cfg80211_pmksa *pmksa)
21736{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021737 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21738 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021739 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021740 int status;
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053021741 tPmkidCacheInfo *pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021742
Dustin Brown491d54b2018-03-14 12:39:11 -070021743 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021744
Anurag Chouhan6d760662016-02-20 16:05:43 +053021745 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021746 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021747 return -EINVAL;
21748 }
21749
Jeff Johnson48363022019-02-24 16:26:51 -080021750 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021751 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021752
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021753 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021754 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021755 return -EINVAL;
21756 }
21757
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021758 if (!pmksa->pmkid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070021759 hdd_err("pmksa->pmkid(%pK) is NULL",
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021760 pmksa->pmkid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021761 return -EINVAL;
21762 }
21763
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021764 if (!wlan_hdd_is_pmksa_valid(pmksa))
21765 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021766
Jeff Johnsonb8944722017-09-03 09:03:19 -070021767 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021768
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021769 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021770 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021771
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053021772 pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
21773 if (!pmk_cache)
21774 return -ENOMEM;
21775
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053021776 hdd_fill_pmksa_info(adapter, pmk_cache, pmksa, false);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021777
21778 /*
21779 * Add to the PMKSA Cache in CSR
21780 * PMKSA cache will be having following
21781 * 1. pmkid id
21782 * 2. pmk
21783 * 3. bssid or cache identifier
21784 */
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053021785 result = wlan_hdd_set_pmksa_cache(adapter, pmk_cache);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021786
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021787 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21788 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021789 adapter->vdev_id, result);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021790
Abhinav Kumard9edfba2020-02-24 22:11:15 +053021791 sme_set_del_pmkid_cache(hdd_ctx->psoc, adapter->vdev_id,
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053021792 pmk_cache, true);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021793
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053021794 qdf_mem_zero(pmk_cache, sizeof(pmk_cache));
21795
21796 qdf_mem_free(pmk_cache);
Dustin Browne74003f2018-03-14 12:51:58 -070021797 hdd_exit();
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +053021798
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021799 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021800}
21801
21802/**
21803 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
21804 * @wiphy: Pointer to wiphy
21805 * @dev: Pointer to network device
21806 * @pmksa: Pointer to set pmksa parameter
21807 *
21808 * Return: 0 for success, non-zero for failure
21809 */
21810static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
21811 struct net_device *dev,
21812 struct cfg80211_pmksa *pmksa)
21813{
Dustin Brown1d31b082018-11-22 14:41:20 +053021814 int errno;
21815 struct osif_vdev_sync *vdev_sync;
21816
21817 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21818 if (errno)
21819 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021820
Dustin Brown1d31b082018-11-22 14:41:20 +053021821 errno = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021822
Dustin Brown1d31b082018-11-22 14:41:20 +053021823 osif_vdev_sync_op_stop(vdev_sync);
21824
21825 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021826}
21827
21828/**
21829 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
21830 * @wiphy: Pointer to wiphy
21831 * @dev: Pointer to network device
21832 * @pmksa: Pointer to pmksa parameter
21833 *
21834 * Return: 0 for success, non-zero for failure
21835 */
21836static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
21837 struct net_device *dev,
21838 struct cfg80211_pmksa *pmksa)
21839{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021840 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21841 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021842 int status = 0;
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053021843 tPmkidCacheInfo *pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021844
Dustin Brown491d54b2018-03-14 12:39:11 -070021845 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021846
Anurag Chouhan6d760662016-02-20 16:05:43 +053021847 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021848 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021849 return -EINVAL;
21850 }
21851
Jeff Johnson48363022019-02-24 16:26:51 -080021852 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021853 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021854
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021855 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021856 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021857 return -EINVAL;
21858 }
21859
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021860 if (!wlan_hdd_is_pmksa_valid(pmksa))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021861 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021862
Jeff Johnsonb8944722017-09-03 09:03:19 -070021863 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021864
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021865 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021866 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021867
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053021868 pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
21869 if (!pmk_cache)
21870 return -ENOMEM;
21871
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053021872 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
21873 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021874 adapter->vdev_id, 0);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021875
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053021876 hdd_fill_pmksa_info(adapter, pmk_cache, pmksa, true);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021877
Abhinav Kumard9edfba2020-02-24 22:11:15 +053021878 /* clear single_pmk_info information */
21879 sme_clear_sae_single_pmk_info(hdd_ctx->psoc, adapter->vdev_id,
21880 pmk_cache);
21881
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021882 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021883 if (QDF_STATUS_SUCCESS !=
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053021884 wlan_hdd_del_pmksa_cache(adapter, pmk_cache)) {
Alan Chen159cd452020-02-13 11:09:23 -080021885 if (!pmksa->bssid)
21886 hdd_err("Failed to delete PMKSA for null bssid");
21887 else
21888 hdd_err("Failed to delete PMKSA for " QDF_MAC_ADDR_STR,
21889 QDF_MAC_ADDR_ARRAY(pmksa->bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021890 status = -EINVAL;
21891 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021892
Abhinav Kumard9edfba2020-02-24 22:11:15 +053021893 sme_set_del_pmkid_cache(hdd_ctx->psoc, adapter->vdev_id, pmk_cache,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021894 false);
Abhinav Kumard9edfba2020-02-24 22:11:15 +053021895
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053021896 qdf_mem_zero(pmk_cache, sizeof(*pmk_cache));
21897 qdf_mem_free(pmk_cache);
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +053021898
Dustin Browne74003f2018-03-14 12:51:58 -070021899 hdd_exit();
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053021900
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021901 return status;
21902}
21903
21904/**
21905 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
21906 * @wiphy: Pointer to wiphy
21907 * @dev: Pointer to network device
21908 * @pmksa: Pointer to pmksa parameter
21909 *
21910 * Return: 0 for success, non-zero for failure
21911 */
21912static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
21913 struct net_device *dev,
21914 struct cfg80211_pmksa *pmksa)
21915{
Dustin Brown1d31b082018-11-22 14:41:20 +053021916 int errno;
21917 struct osif_vdev_sync *vdev_sync;
21918
21919 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21920 if (errno)
21921 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021922
Dustin Brown1d31b082018-11-22 14:41:20 +053021923 errno = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021924
Dustin Brown1d31b082018-11-22 14:41:20 +053021925 osif_vdev_sync_op_stop(vdev_sync);
21926
21927 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021928
21929}
21930
21931/**
21932 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
21933 * @wiphy: Pointer to wiphy
21934 * @dev: Pointer to network device
21935 *
21936 * Return: 0 for success, non-zero for failure
21937 */
21938static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
21939 struct net_device *dev)
21940{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021941 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21942 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021943 int errno;
21944 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021945
Dustin Brown491d54b2018-03-14 12:39:11 -070021946 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021947
Anurag Chouhan6d760662016-02-20 16:05:43 +053021948 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021949 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021950 return -EINVAL;
21951 }
21952
Jeff Johnson48363022019-02-24 16:26:51 -080021953 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021954 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021955
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021956 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021957
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021958 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021959 errno = wlan_hdd_validate_context(hdd_ctx);
21960 if (errno)
21961 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021962
Liangwei Donga44d55b2019-03-20 03:22:08 -040021963 status = wlan_hdd_flush_pmksa_cache(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021964 if (QDF_IS_STATUS_ERROR(status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021965 hdd_err("Cannot flush PMKIDCache");
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021966 errno = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021967 }
Vignesh Viswanathane8a26b22017-10-11 20:38:47 +053021968
Abhinav Kumard9edfba2020-02-24 22:11:15 +053021969 sme_set_del_pmkid_cache(hdd_ctx->psoc, adapter->vdev_id, NULL, false);
Dustin Browne74003f2018-03-14 12:51:58 -070021970 hdd_exit();
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021971 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021972}
21973
21974/**
21975 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
21976 * @wiphy: Pointer to wiphy
21977 * @dev: Pointer to network device
21978 *
21979 * Return: 0 for success, non-zero for failure
21980 */
21981static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
21982 struct net_device *dev)
21983{
Dustin Brown1d31b082018-11-22 14:41:20 +053021984 int errno;
21985 struct osif_vdev_sync *vdev_sync;
21986
21987 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21988 if (errno)
21989 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021990
Dustin Brown1d31b082018-11-22 14:41:20 +053021991 errno = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021992
Dustin Brown1d31b082018-11-22 14:41:20 +053021993 osif_vdev_sync_op_stop(vdev_sync);
21994
21995 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021996}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021997
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080021998#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021999/**
22000 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
22001 * @wiphy: Pointer to wiphy
22002 * @dev: Pointer to network device
22003 * @ftie: Pointer to fast transition ie parameter
22004 *
22005 * Return: 0 for success, non-zero for failure
22006 */
22007static int
22008__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
22009 struct net_device *dev,
22010 struct cfg80211_update_ft_ies_params *ftie)
22011{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022012 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022013 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsond377dce2017-10-04 10:32:42 -070022014 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022015 int status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022016 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022017
Dustin Brown491d54b2018-03-14 12:39:11 -070022018 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022019
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022020 status = wlan_hdd_validate_context(hdd_ctx);
22021 if (status)
22022 return status;
22023
Anurag Chouhan6d760662016-02-20 16:05:43 +053022024 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022025 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022026 return -EINVAL;
22027 }
22028
Jeff Johnson48363022019-02-24 16:26:51 -080022029 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022030 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022031
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022032 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22033 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
Jeff Johnsone7951512019-02-27 10:02:51 -080022034 adapter->vdev_id, sta_ctx->conn_info.conn_state);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022035
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022036 /* Added for debug on reception of Re-assoc Req. */
Jeff Johnsone7951512019-02-27 10:02:51 -080022037 if (eConnectionState_Associated != sta_ctx->conn_info.conn_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022038 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022039 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022040 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022041 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022042 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022043 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022044
22045 /* Pass the received FT IEs to SME */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022046 mac_handle = hdd_ctx->mac_handle;
Jeff Johnsoncf07c312019-02-04 13:53:29 -080022047 sme_set_ft_ies(mac_handle, adapter->vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022048 (const u8 *)ftie->ie, ftie->ie_len);
Dustin Browne74003f2018-03-14 12:51:58 -070022049 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022050 return 0;
22051}
22052
22053/**
22054 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
22055 * @wiphy: Pointer to wiphy
22056 * @dev: Pointer to network device
22057 * @ftie: Pointer to fast transition ie parameter
22058 *
22059 * Return: 0 for success, non-zero for failure
22060 */
22061static int
22062wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
22063 struct net_device *dev,
22064 struct cfg80211_update_ft_ies_params *ftie)
22065{
Dustin Brown1d31b082018-11-22 14:41:20 +053022066 int errno;
22067 struct osif_vdev_sync *vdev_sync;
22068
22069 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22070 if (errno)
22071 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022072
Dustin Brown1d31b082018-11-22 14:41:20 +053022073 errno = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022074
Dustin Brown1d31b082018-11-22 14:41:20 +053022075 osif_vdev_sync_op_stop(vdev_sync);
22076
22077 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022078}
22079#endif
22080
Min Liu0daa0982019-02-01 17:50:44 +080022081#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
22082/**
22083 * __wlan_hdd_cfg80211_update_owe_info() - update OWE info
22084 * @wiphy: Pointer to wiphy
22085 * @dev: Pointer to network device
22086 * @owe_info: Pointer to OWE info
22087 *
22088 * Return: 0 for success, non-zero for failure
22089 */
22090static int
22091__wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
22092 struct net_device *dev,
22093 struct cfg80211_update_owe_info *owe_info)
22094{
22095 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
22096 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
22097 QDF_STATUS status;
Dustin Brown96b98dd2019-03-06 12:39:37 -080022098 int errno;
Min Liu0daa0982019-02-01 17:50:44 +080022099
22100 hdd_enter_dev(dev);
22101
22102 errno = wlan_hdd_validate_context(hdd_ctx);
22103 if (errno)
22104 return errno;
22105
22106 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
22107 hdd_err("Command not allowed in FTM mode");
22108 return -EINVAL;
22109 }
22110
Jeff Johnsona6b398d2019-02-24 16:26:51 -080022111 if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) {
22112 hdd_err("invalid vdev id: %d", adapter->vdev_id);
Min Liu0daa0982019-02-01 17:50:44 +080022113 return -EINVAL;
22114 }
22115
22116 hdd_debug("owe_status %d", owe_info->status);
22117
22118 status = wlansap_update_owe_info(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Min Liue2b469f2019-04-10 19:13:42 +080022119 owe_info->peer, owe_info->ie,
Min Liu0daa0982019-02-01 17:50:44 +080022120 owe_info->ie_len, owe_info->status);
22121 if (QDF_IS_STATUS_ERROR(status)) {
22122 hdd_err("Failed to update OWE info");
22123 errno = qdf_status_to_os_return(status);
22124 }
22125
22126 hdd_exit();
22127 return errno;
22128}
22129
22130/**
22131 * wlan_hdd_cfg80211_update_owe_info() - update OWE info
22132 * @wiphy: Pointer to wiphy
22133 * @dev: Pointer to network device
22134 * @owe_info: Pointer to OWE info
22135 *
22136 * Return: 0 for success, non-zero for failure
22137 */
22138static int
22139wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
Dustin Brown96b98dd2019-03-06 12:39:37 -080022140 struct net_device *net_dev,
Min Liu0daa0982019-02-01 17:50:44 +080022141 struct cfg80211_update_owe_info *owe_info)
22142{
Dustin Brown96b98dd2019-03-06 12:39:37 -080022143 struct osif_vdev_sync *vdev_sync;
22144 int errno;
Min Liu0daa0982019-02-01 17:50:44 +080022145
Dustin Brown96b98dd2019-03-06 12:39:37 -080022146 errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
22147 if (errno)
22148 return errno;
Min Liu0daa0982019-02-01 17:50:44 +080022149
Dustin Brown96b98dd2019-03-06 12:39:37 -080022150 errno = __wlan_hdd_cfg80211_update_owe_info(wiphy, net_dev, owe_info);
22151
22152 osif_vdev_sync_op_stop(vdev_sync);
22153
22154 return errno;
Min Liu0daa0982019-02-01 17:50:44 +080022155}
22156#endif
22157
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +053022158void wlan_hdd_cfg80211_update_replay_counter_cb(
Mukul Sharma3d36c392017-01-18 18:39:12 +053022159 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
22160
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022161{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022162 struct hdd_adapter *adapter = (struct hdd_adapter *)cb_ctx;
Mukul Sharma3d36c392017-01-18 18:39:12 +053022163 uint8_t temp_replay_counter[8];
22164 int i;
22165 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022166
Dustin Brown491d54b2018-03-14 12:39:11 -070022167 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022168
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022169 if (!adapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022170 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053022171 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022172 }
22173
Mukul Sharma3d36c392017-01-18 18:39:12 +053022174 if (!gtk_rsp_param) {
22175 hdd_err("gtk_rsp_param is Null");
22176 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022177 }
22178
Mukul Sharma3d36c392017-01-18 18:39:12 +053022179 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022180 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053022181 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022182 }
22183
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022184 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053022185 gtk_rsp_param->replay_counter);
22186 /* convert little to big endian since supplicant works on big endian */
22187 p = (uint8_t *)&gtk_rsp_param->replay_counter;
22188 for (i = 0; i < 8; i++)
22189 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022190
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022191 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022192 /* Update replay counter to NL */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022193 cfg80211_gtk_rekey_notify(adapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053022194 gtk_rsp_param->bssid.bytes,
22195 temp_replay_counter, GFP_KERNEL);
22196out:
Dustin Browne74003f2018-03-14 12:51:58 -070022197 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053022198
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022199}
22200
Wu Gaoa9d336b2018-05-30 14:48:04 +080022201#ifdef WLAN_FEATURE_GTK_OFFLOAD
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022202/**
22203 * wlan_hdd_copy_gtk_kek - Copy the KEK from GTK rekey data to GTK request
22204 * @gtk_req: Pointer to GTK request
22205 * @data: Pointer to rekey data
22206 *
22207 * Return: none
22208 */
22209#ifdef CFG80211_REKEY_DATA_KEK_LEN
22210static
22211void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
22212 struct cfg80211_gtk_rekey_data *data)
22213{
22214 qdf_mem_copy(gtk_req->kek, data->kek, data->kek_len);
22215 gtk_req->kek_len = data->kek_len;
22216}
22217#else
22218static
22219void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
22220 struct cfg80211_gtk_rekey_data *data)
22221{
22222 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
22223 gtk_req->kek_len = NL80211_KEK_LEN;
22224}
22225#endif
22226
22227/**
22228 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
22229 * @wiphy: Pointer to wiphy
22230 * @dev: Pointer to network device
22231 * @data: Pointer to rekey data
22232 *
22233 * This function is used to offload GTK rekeying job to the firmware.
22234 *
22235 * Return: 0 for success, non-zero for failure
22236 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070022237static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022238int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053022239 struct net_device *dev,
22240 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022241{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022242 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053022243 int result, i;
22244 struct pmo_gtk_req *gtk_req = NULL;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022245 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharma3d36c392017-01-18 18:39:12 +053022246 uint8_t *buf;
Min Liu8c5d99e2018-09-10 17:18:44 +080022247 struct wlan_objmgr_vdev *vdev;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022248 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022249
Dustin Brown491d54b2018-03-14 12:39:11 -070022250 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022251
Anurag Chouhan6d760662016-02-20 16:05:43 +053022252 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022253 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053022254 result = -EINVAL;
22255 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022256 }
22257
Jeff Johnson48363022019-02-24 16:26:51 -080022258 if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) {
Mukul Sharma3d36c392017-01-18 18:39:12 +053022259 result = -EINVAL;
22260 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022261 }
22262
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022263 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22264 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080022265 adapter->vdev_id, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022266
Mukul Sharma3d36c392017-01-18 18:39:12 +053022267 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022268 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053022269 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022270
Mukul Sharma3d36c392017-01-18 18:39:12 +053022271 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
22272 if (!gtk_req) {
Mukul Sharma3d36c392017-01-18 18:39:12 +053022273 result = -ENOMEM;
22274 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022275 }
22276
Mukul Sharma3d36c392017-01-18 18:39:12 +053022277 /* convert big to little endian since driver work on little endian */
22278 buf = (uint8_t *)&gtk_req->replay_counter;
22279 for (i = 0; i < 8; i++)
22280 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022281
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022282 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053022283 gtk_req->replay_counter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022284
22285 wlan_hdd_copy_gtk_kek(gtk_req, data);
Yeshwanth Sriram Guntukae6313412019-08-06 14:18:33 +053022286 if (data->kck) {
nakul kachhwahaa580cc32019-03-15 17:45:17 +053022287 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
Yeshwanth Sriram Guntukae6313412019-08-06 14:18:33 +053022288 gtk_req->kck_len = NL80211_KCK_LEN;
22289 }
gaurank kathpalia82a1b2b2018-07-10 16:49:10 +053022290 gtk_req->is_fils_connection = hdd_is_fils_connection(adapter);
Min Liu8c5d99e2018-09-10 17:18:44 +080022291 vdev = hdd_objmgr_get_vdev(adapter);
22292 if (!vdev) {
22293 result = -EINVAL;
22294 goto out;
22295 }
22296 status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053022297 hdd_objmgr_put_vdev(vdev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053022298 if (status != QDF_STATUS_SUCCESS) {
22299 hdd_err("Failed to cache GTK Offload");
22300 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022301 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053022302out:
22303 if (gtk_req)
22304 qdf_mem_free(gtk_req);
Dustin Browne74003f2018-03-14 12:51:58 -070022305 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053022306
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022307 return result;
22308}
22309
22310/**
22311 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
22312 * @wiphy: Pointer to wiphy
22313 * @dev: Pointer to network device
22314 * @data: Pointer to rekey data
22315 *
22316 * This function is used to offload GTK rekeying job to the firmware.
22317 *
22318 * Return: 0 for success, non-zero for failure
22319 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070022320static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022321int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
22322 struct net_device *dev,
22323 struct cfg80211_gtk_rekey_data *data)
22324{
Dustin Brown1d31b082018-11-22 14:41:20 +053022325 int errno;
22326 struct osif_vdev_sync *vdev_sync;
22327
22328 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22329 if (errno)
22330 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022331
Dustin Brown1d31b082018-11-22 14:41:20 +053022332 errno = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022333
Dustin Brown1d31b082018-11-22 14:41:20 +053022334 osif_vdev_sync_op_stop(vdev_sync);
22335
22336 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022337}
Wu Gaoa9d336b2018-05-30 14:48:04 +080022338#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022339
22340/**
22341 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
22342 * @wiphy: Pointer to wiphy
22343 * @dev: Pointer to network device
22344 * @param: Pointer to access control parameter
22345 *
22346 * Return: 0 for success, non-zero for failure
22347 */
22348static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
22349 struct net_device *dev,
22350 const struct cfg80211_acl_data *params)
22351{
22352 int i;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022353 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson5c19ade2017-10-04 09:52:12 -070022354 struct hdd_hostapd_state *hostapd_state;
Jeff Johnson8f8ceb92019-03-24 08:16:55 -070022355 struct sap_config *config;
Jeff Johnsonb8944722017-09-03 09:03:19 -070022356 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022357 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022358 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022359
Dustin Brown491d54b2018-03-14 12:39:11 -070022360 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022361
Anurag Chouhan6d760662016-02-20 16:05:43 +053022362 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022363 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022364 return -EINVAL;
22365 }
22366
Jeff Johnsond36fa332019-03-18 13:42:25 -070022367 if (!params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022368 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022369 return -EINVAL;
22370 }
22371
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022372 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070022373 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022374
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022375 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022376 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022377
Jeff Johnson5c19ade2017-10-04 09:52:12 -070022378 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022379
Jeff Johnsond36fa332019-03-18 13:42:25 -070022380 if (!hostapd_state) {
Jeff Johnson5c19ade2017-10-04 09:52:12 -070022381 hdd_err("hostapd_state is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022382 return -EINVAL;
22383 }
22384
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022385 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022386 params->n_acl_entries);
22387
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022388 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22389 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080022390 adapter->vdev_id, adapter->device_mode);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022391
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022392 if (QDF_SAP_MODE == adapter->device_mode) {
Jeff Johnson954903d2019-03-07 20:41:27 -080022393 config = &adapter->session.ap.sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022394
22395 /* default value */
Jeff Johnson954903d2019-03-07 20:41:27 -080022396 config->num_accept_mac = 0;
22397 config->num_deny_mac = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022398
22399 /**
22400 * access control policy
22401 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
22402 * listed in hostapd.deny file.
22403 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
22404 * listed in hostapd.accept file.
22405 */
22406 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
Jeff Johnson954903d2019-03-07 20:41:27 -080022407 config->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022408 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
22409 params->acl_policy) {
Jeff Johnson954903d2019-03-07 20:41:27 -080022410 config->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022411 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022412 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022413 params->acl_policy);
22414 return -ENOTSUPP;
22415 }
22416
Jeff Johnson954903d2019-03-07 20:41:27 -080022417 if (eSAP_DENY_UNLESS_ACCEPTED == config->SapMacaddr_acl) {
22418 config->num_accept_mac = params->n_acl_entries;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022419 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022420 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070022421 QDF_MAC_ADDR_STR, i,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070022422 QDF_MAC_ADDR_ARRAY(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022423 params->mac_addrs[i].addr));
22424
Jeff Johnson954903d2019-03-07 20:41:27 -080022425 qdf_mem_copy(&config->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022426 params->mac_addrs[i].addr,
Srinivas Girigowdaa47b45f2019-02-27 12:29:02 -080022427 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022428 }
Jeff Johnson954903d2019-03-07 20:41:27 -080022429 } else if (eSAP_ACCEPT_UNLESS_DENIED == config->SapMacaddr_acl) {
22430 config->num_deny_mac = params->n_acl_entries;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022431 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022432 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Srinivas Girigowdacb7b8b82019-04-10 14:27:47 -070022433 QDF_MAC_ADDR_STR, i,
Srinivas Girigowda34fbba02019-04-08 12:07:44 -070022434 QDF_MAC_ADDR_ARRAY(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022435 params->mac_addrs[i].addr));
22436
Jeff Johnson954903d2019-03-07 20:41:27 -080022437 qdf_mem_copy(&config->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022438 params->mac_addrs[i].addr,
Srinivas Girigowdaa47b45f2019-02-27 12:29:02 -080022439 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022440 }
22441 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070022442 qdf_status = wlansap_set_mac_acl(
Jeff Johnson954903d2019-03-07 20:41:27 -080022443 WLAN_HDD_GET_SAP_CTX_PTR(adapter), config);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022444 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022445 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022446 return -EINVAL;
22447 }
22448 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022449 hdd_debug("Invalid device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070022450 qdf_opmode_str(adapter->device_mode),
22451 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022452 return -EINVAL;
22453 }
Dustin Browne74003f2018-03-14 12:51:58 -070022454 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022455 return 0;
22456}
22457
22458/**
22459 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
22460 * __wlan_hdd_cfg80211_set_mac_acl
22461 * @wiphy: pointer to wiphy structure
22462 * @dev: pointer to net_device
22463 * @params: pointer to cfg80211_acl_data
22464 *
22465 * Return; 0 on success, error number otherwise
22466 */
22467static int
22468wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
22469 struct net_device *dev,
22470 const struct cfg80211_acl_data *params)
22471{
Dustin Brown1d31b082018-11-22 14:41:20 +053022472 int errno;
22473 struct osif_vdev_sync *vdev_sync;
22474
22475 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22476 if (errno)
22477 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022478
Dustin Brown1d31b082018-11-22 14:41:20 +053022479 errno = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022480
Dustin Brown1d31b082018-11-22 14:41:20 +053022481 osif_vdev_sync_op_stop(vdev_sync);
22482
22483 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022484}
22485
22486#ifdef WLAN_NL80211_TESTMODE
22487#ifdef FEATURE_WLAN_LPHB
22488/**
22489 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
Jeff Johnsonb8944722017-09-03 09:03:19 -070022490 * @hdd_ctx: Pointer to hdd context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022491 * @lphbInd: Pointer to low power heart beat indication parameter
22492 *
22493 * Return: none
22494 */
Jeff Johnsonb8944722017-09-03 09:03:19 -070022495static void wlan_hdd_cfg80211_lphb_ind_handler(void *hdd_ctx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022496 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022497{
22498 struct sk_buff *skb;
22499
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022500 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022501
Jeff Johnsonb8944722017-09-03 09:03:19 -070022502 if (0 != wlan_hdd_validate_context((struct hdd_context *) hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022503 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022504
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022505 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022506 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022507 return;
22508 }
22509
Jeff Johnsonb8944722017-09-03 09:03:19 -070022510 skb = cfg80211_testmode_alloc_event_skb(((struct hdd_context *) hdd_ctx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022511 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022512 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022513 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022514 return;
22515 }
22516
22517 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022518 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022519 goto nla_put_failure;
22520 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022521 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022522 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022523 goto nla_put_failure;
22524 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022525 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
22526 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022527 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022528 goto nla_put_failure;
22529 }
22530 cfg80211_testmode_event(skb, GFP_ATOMIC);
22531 return;
22532
22533nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022534 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022535 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022536}
22537#endif /* FEATURE_WLAN_LPHB */
22538
22539/**
22540 * __wlan_hdd_cfg80211_testmode() - test mode
22541 * @wiphy: Pointer to wiphy
22542 * @data: Data pointer
22543 * @len: Data length
22544 *
22545 * Return: 0 for success, non-zero for failure
22546 */
22547static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
22548 void *data, int len)
22549{
22550 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
22551 int err;
Jeff Johnsonb8944722017-09-03 09:03:19 -070022552 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022553
Dustin Brown491d54b2018-03-14 12:39:11 -070022554 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053022555
Jeff Johnsonb8944722017-09-03 09:03:19 -070022556 err = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022557 if (err)
22558 return err;
22559
Ryan Hsu4df41382018-06-15 15:45:22 -070022560 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
22561 hdd_err("Driver Modules are closed");
22562 return -EINVAL;
22563 }
22564
Dustin Brown4ea21db2018-01-05 14:13:17 -080022565 err = wlan_cfg80211_nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
22566 len, wlan_hdd_tm_policy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022567 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022568 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022569 return err;
22570 }
22571
22572 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022573 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022574 return -EINVAL;
22575 }
22576
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053022577 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22578 TRACE_CODE_HDD_CFG80211_TESTMODE,
22579 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
22580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022581 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
22582#ifdef FEATURE_WLAN_LPHB
22583 /* Low Power Heartbeat configuration request */
22584 case WLAN_HDD_TM_CMD_WLAN_HB:
22585 {
22586 int buf_len;
22587 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022588 struct pmo_lphb_req *hb_params = NULL;
22589 struct pmo_lphb_req *hb_params_temp = NULL;
22590 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022591
22592 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022593 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022594 return -EINVAL;
22595 }
22596
22597 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
22598 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
Rajeev Kumar Sirasanagandla012e7b72019-03-14 21:54:43 +053022599 if (buf_len < sizeof(*hb_params_temp)) {
22600 hdd_err("Invalid buffer length for TM_ATTR_DATA");
22601 return -EINVAL;
22602 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022603
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022604 hb_params_temp = (struct pmo_lphb_req *) buf;
22605 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
22606 && (hb_params_temp->params.lphb_tcp_params.
22607 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022608 return -EINVAL;
22609
Manjeet Singh00b2a562017-01-03 12:08:10 +053022610 if (buf_len > sizeof(*hb_params)) {
22611 hdd_err("buf_len=%d exceeded hb_params size limit",
22612 buf_len);
22613 return -ERANGE;
22614 }
22615
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022616 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
22617 sizeof(*hb_params));
Min Liu74a1a502018-10-10 19:59:07 +080022618 if (!hb_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022619 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022620
Ashish Kumar Dhanotiya0fa8ee02017-07-13 14:04:31 +053022621 qdf_mem_zero(hb_params, sizeof(*hb_params));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053022622 qdf_mem_copy(hb_params, buf, buf_len);
Wu Gaod7dd6e42018-10-16 17:22:56 +080022623 status = ucfg_pmo_lphb_config_req(
22624 hdd_ctx->psoc,
Jeff Johnsonb8944722017-09-03 09:03:19 -070022625 hb_params, (void *)hdd_ctx,
Wu Gaod7dd6e42018-10-16 17:22:56 +080022626 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022627 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022628 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053022629
22630 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022631 return 0;
22632 }
22633#endif /* FEATURE_WLAN_LPHB */
22634
22635#if defined(QCA_WIFI_FTM)
22636 case WLAN_HDD_TM_CMD_WLAN_FTM:
22637 {
Ryan Hsu4df41382018-06-15 15:45:22 -070022638 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam()) {
22639 hdd_err("Command not allowed in FTM mode, mode %d",
22640 hdd_get_conparam());
22641 return -EINVAL;
22642 }
22643
Dustin Brown07901ec2018-09-07 11:02:41 -070022644 err = wlan_cfg80211_ftm_testmode_cmd(hdd_ctx->pdev,
Ryan Hsuc8b27a42018-01-02 13:57:56 -080022645 data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022646 break;
22647 }
22648#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022649 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022650 hdd_err("command: %d not supported",
Ryan Hsuc8b27a42018-01-02 13:57:56 -080022651 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022652 return -EOPNOTSUPP;
22653 }
Ryan Hsuc8b27a42018-01-02 13:57:56 -080022654
Dustin Browne74003f2018-03-14 12:51:58 -070022655 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022656 return err;
22657}
22658
22659/**
22660 * wlan_hdd_cfg80211_testmode() - test mode
22661 * @wiphy: Pointer to wiphy
22662 * @dev: Pointer to network device
22663 * @data: Data pointer
22664 * @len: Data length
22665 *
22666 * Return: 0 for success, non-zero for failure
22667 */
22668static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
22669#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
22670 struct wireless_dev *wdev,
22671#endif
22672 void *data, int len)
22673{
Dustin Brown363b4792019-02-05 16:11:55 -080022674 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080022675 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +053022676
Dustin Brown363b4792019-02-05 16:11:55 -080022677 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080022678 if (errno)
22679 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022680
Dustin Brownf0f00612019-01-31 16:02:24 -080022681 errno = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022682
Dustin Brown363b4792019-02-05 16:11:55 -080022683 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080022684
22685 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022686}
22687
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022688#endif /* CONFIG_NL80211_TESTMODE */
22689
22690#ifdef QCA_HT_2040_COEX
22691/**
22692 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
22693 * @wiphy: Pointer to wiphy
22694 * @dev: Pointer to network device
22695 * @chandef: Pointer to channel definition parameter
22696 *
22697 * Return: 0 for success, non-zero for failure
22698 */
22699static int
22700__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
22701 struct net_device *dev,
22702 struct cfg80211_chan_def *chandef)
22703{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022704 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070022705 struct hdd_context *hdd_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022706 QDF_STATUS status;
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053022707 int retval = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022708
Anurag Chouhan6d760662016-02-20 16:05:43 +053022709 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070022710 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022711 return -EINVAL;
22712 }
22713
Jeff Johnson48363022019-02-24 16:26:51 -080022714 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022715 return -EINVAL;
Dustin Brown63500612018-08-07 11:36:09 -070022716
Abhishek Singh9d5f4582017-10-11 17:59:48 +053022717 if (!(adapter->device_mode == QDF_SAP_MODE ||
22718 adapter->device_mode == QDF_P2P_GO_MODE))
22719 return -EOPNOTSUPP;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022720
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022721 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070022722 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053022723 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022724 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022725
Abhishek Singh9d5f4582017-10-11 17:59:48 +053022726 hdd_debug("Channel width changed to %d ",
22727 cfg80211_get_chandef_type(chandef));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022728
22729 /* Change SAP ht2040 mode */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070022730 status = hdd_set_sap_ht2040_mode(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022731 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053022732 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022733 hdd_err("Cannot set SAP HT20/40 mode!");
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053022734 retval = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022735 }
22736
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053022737 return retval;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022738}
22739
22740/**
22741 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
22742 * @wiphy: Pointer to wiphy
22743 * @dev: Pointer to network device
22744 * @chandef: Pointer to channel definition parameter
22745 *
22746 * Return: 0 for success, non-zero for failure
22747 */
22748static int
22749wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
22750 struct net_device *dev,
22751 struct cfg80211_chan_def *chandef)
22752{
Dustin Brown1d31b082018-11-22 14:41:20 +053022753 int errno;
22754 struct osif_vdev_sync *vdev_sync;
22755
22756 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22757 if (errno)
22758 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022759
Dustin Brown1d31b082018-11-22 14:41:20 +053022760 errno = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022761
Dustin Brown1d31b082018-11-22 14:41:20 +053022762 osif_vdev_sync_op_stop(vdev_sync);
22763
22764 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022765}
22766#endif
22767
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022768#ifdef CHANNEL_SWITCH_SUPPORTED
22769/**
22770 * __wlan_hdd_cfg80211_channel_switch()- function to switch
22771 * channel in SAP/GO
22772 * @wiphy: wiphy pointer
22773 * @dev: dev pointer.
22774 * @csa_params: Change channel params
22775 *
22776 * This function is called to switch channel in SAP/GO
22777 *
22778 * Return: 0 if success else return non zero
22779 */
22780static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
22781 struct net_device *dev,
22782 struct cfg80211_csa_settings *csa_params)
22783{
Jeff Johnsone5006672017-08-29 14:39:02 -070022784 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022785 struct hdd_context *hdd_ctx;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022786 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080022787 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022788
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022789 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022790 csa_params->chandef.chan->center_freq);
22791
Jeff Johnson48363022019-02-24 16:26:51 -080022792 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022793 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053022794
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022795 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22796 ret = wlan_hdd_validate_context(hdd_ctx);
22797
22798 if (0 != ret)
22799 return ret;
22800
Krunal Sonib4326f22016-03-10 13:05:51 -080022801 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
22802 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022803 return -ENOTSUPP;
Bala Venkatesh8b9bbde2019-07-03 16:25:16 +053022804 wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->vdev_id,
22805 CSA_REASON_USER_INITIATED);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022806
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053022807 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
22808
Tushnim Bhattacharyya6c40b112019-10-30 11:39:25 -070022809 ret =
22810 hdd_softap_set_channel_change(dev,
22811 csa_params->chandef.chan->center_freq,
22812 ch_width, false);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022813 return ret;
22814}
22815
22816/**
22817 * wlan_hdd_cfg80211_channel_switch()- function to switch
22818 * channel in SAP/GO
22819 * @wiphy: wiphy pointer
22820 * @dev: dev pointer.
22821 * @csa_params: Change channel params
22822 *
22823 * This function is called to switch channel in SAP/GO
22824 *
22825 * Return: 0 if success else return non zero
22826 */
22827static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
22828 struct net_device *dev,
22829 struct cfg80211_csa_settings *csa_params)
22830{
Dustin Brown1d31b082018-11-22 14:41:20 +053022831 int errno;
22832 struct osif_vdev_sync *vdev_sync;
22833
22834 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22835 if (errno)
22836 return errno;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022837
Dustin Brown1d31b082018-11-22 14:41:20 +053022838 errno = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
Dustin Brown1d31b082018-11-22 14:41:20 +053022839
22840 osif_vdev_sync_op_stop(vdev_sync);
22841
22842 return errno;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022843}
22844#endif
22845
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022846int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter,
Tushnim Bhattacharyyac682bfb2019-12-11 17:11:10 -080022847 uint32_t chan_freq,
22848 enum policy_mgr_conn_update_reason reason)
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022849{
22850 QDF_STATUS status;
22851 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22852
Dustin Brown491d54b2018-03-14 12:39:11 -070022853 hdd_enter();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022854
Dustin Brown76cd2932018-09-11 16:03:05 -070022855 status = policy_mgr_reset_connection_update(hdd_ctx->psoc);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022856 if (!QDF_IS_STATUS_SUCCESS(status))
22857 hdd_err("clearing event failed");
22858
Manikandan Mohan282c4b62019-08-14 17:42:22 -070022859 status = policy_mgr_current_connections_update(
22860 hdd_ctx->psoc, adapter->vdev_id,
Tushnim Bhattacharyyac682bfb2019-12-11 17:11:10 -080022861 chan_freq, reason);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022862 switch (status) {
22863 case QDF_STATUS_E_FAILURE:
22864 /*
Jeff Johnson11d7c9d2018-05-06 15:44:09 -070022865 * QDF_STATUS_E_FAILURE indicates that some error has occurred
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022866 * while changing the hw mode
22867 */
22868 hdd_err("ERROR: connections update failed!!");
22869 return -EINVAL;
22870
22871 case QDF_STATUS_SUCCESS:
22872 /*
22873 * QDF_STATUS_SUCCESS indicates that HW mode change has been
22874 * triggered and wait for it to finish.
22875 */
22876 status = policy_mgr_wait_for_connection_update(
Dustin Brown76cd2932018-09-11 16:03:05 -070022877 hdd_ctx->psoc);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022878 if (!QDF_IS_STATUS_SUCCESS(status)) {
22879 hdd_err("ERROR: qdf wait for event failed!!");
22880 return -EINVAL;
22881 }
22882 if (QDF_MONITOR_MODE == adapter->device_mode)
Tushnim Bhattacharyyac682bfb2019-12-11 17:11:10 -080022883 hdd_info("Monitor mode:channel freq:%d (SMM->DBS)", chan_freq);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022884 break;
22885
22886 default:
22887 /*
22888 * QDF_STATUS_E_NOSUPPORT indicates that no HW mode change is
22889 * required, so caller can proceed further.
22890 */
22891 break;
22892
22893 }
Dustin Browne74003f2018-03-14 12:51:58 -070022894 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022895
22896 return 0;
22897}
22898
Nirav Shah73713f72018-05-17 14:50:41 +053022899#ifdef FEATURE_MONITOR_MODE_SUPPORT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022900/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022901 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
22902 * @wiphy: Handle to struct wiphy to get handle to module context.
22903 * @chandef: Contains information about the capture channel to be set.
22904 *
22905 * This interface is called if and only if monitor mode interface alone is
22906 * active.
22907 *
22908 * Return: 0 success or error code on failure.
22909 */
22910static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
22911 struct cfg80211_chan_def *chandef)
22912{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022913 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsone5006672017-08-29 14:39:02 -070022914 struct hdd_adapter *adapter;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070022915 struct hdd_station_ctx *sta_ctx;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022916 struct hdd_mon_set_ch_info *ch_info;
22917 QDF_STATUS status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022918 mac_handle_t mac_handle;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022919 struct qdf_mac_addr bssid;
Jeff Johnson61b5e982018-03-15 11:33:31 -070022920 struct csr_roam_profile roam_profile;
Saket Jhad5c0e022019-11-18 16:53:47 -080022921 struct ch_params ch_params;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022922 int ret;
gaurank kathpalia31800672019-11-22 13:50:11 +053022923 enum channel_state chan_freq_state;
22924 uint8_t max_fw_bw;
22925 enum phy_ch_width ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022926
Dustin Brown491d54b2018-03-14 12:39:11 -070022927 hdd_enter();
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022928
22929 ret = wlan_hdd_validate_context(hdd_ctx);
22930 if (ret)
22931 return ret;
22932
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022933 mac_handle = hdd_ctx->mac_handle;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022934
22935 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
22936 if (!adapter)
22937 return -EIO;
22938
Saket Jhad5c0e022019-11-18 16:53:47 -080022939 hdd_debug("%s: set monitor mode freq %d",
22940 adapter->dev->name, chandef->chan->center_freq);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022941
gaurank kathpalia31800672019-11-22 13:50:11 +053022942 /* Verify channel state before accepting this request */
22943 chan_freq_state =
22944 wlan_reg_get_channel_state_for_freq(hdd_ctx->pdev,
22945 chandef->chan->center_freq);
22946 if (chan_freq_state == CHANNEL_STATE_DISABLE ||
22947 chan_freq_state == CHANNEL_STATE_INVALID) {
22948 hdd_err("Invalid chan freq received for monitor mode aborting");
22949 return -EINVAL;
22950 }
22951
22952 /* Verify the BW before accepting this request */
22953 ch_width = hdd_map_nl_chan_width(chandef->width);
22954
gaurank kathpaliab3b21942020-01-10 15:09:33 +053022955 if (ch_width > CH_WIDTH_10MHZ ||
22956 (!cds_is_sub_20_mhz_enabled() && ch_width > CH_WIDTH_160MHZ)) {
22957 hdd_err("invalid BW received %d", ch_width);
22958 return -EINVAL;
22959 }
22960
gaurank kathpalia31800672019-11-22 13:50:11 +053022961 max_fw_bw = sme_get_vht_ch_width();
22962
22963 if ((ch_width == CH_WIDTH_160MHZ &&
22964 max_fw_bw <= WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) ||
22965 (ch_width == CH_WIDTH_80P80MHZ &&
22966 max_fw_bw <= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)) {
22967 hdd_err("FW does not support this BW %d max BW supported %d",
22968 ch_width, max_fw_bw);
22969 return -EINVAL;
22970 }
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022971 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
22972 ch_info = &sta_ctx->ch_info;
wadesong24c869a2019-07-19 17:38:59 +080022973 roam_profile.ChannelInfo.freq_list = &ch_info->freq;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022974 roam_profile.ChannelInfo.numOfChannels = 1;
22975 roam_profile.phyMode = ch_info->phy_mode;
gaurank kathpalia31800672019-11-22 13:50:11 +053022976 roam_profile.ch_params.ch_width = ch_width;
Manikandan Mohan5c1e9ae2019-10-23 15:45:35 -070022977 hdd_select_cbmode(adapter, chandef->chan->center_freq,
22978 &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022979
Jeff Johnson1e851a12017-10-28 14:36:12 -070022980 qdf_mem_copy(bssid.bytes, adapter->mac_addr.bytes,
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022981 QDF_MAC_ADDR_SIZE);
22982
Saket Jhad5c0e022019-11-18 16:53:47 -080022983 ch_params.ch_width = ch_width;
22984 wlan_reg_set_channel_params_for_freq(hdd_ctx->pdev,
22985 chandef->chan->center_freq,
22986 0, &ch_params);
22987
22988 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter,
22989 chandef->chan->center_freq,
22990 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022991 hdd_err("Failed to change hw mode");
22992 return -EINVAL;
22993 }
gaurank kathpaliab3b21942020-01-10 15:09:33 +053022994 status = sme_roam_channel_change_req(mac_handle, bssid,
22995 &roam_profile.ch_params,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070022996 &roam_profile);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022997 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022998 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022999 status);
23000 ret = qdf_status_to_os_return(status);
23001 return ret;
23002 }
Dustin Browne74003f2018-03-14 12:51:58 -070023003 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080023004
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023005 return 0;
23006}
23007
23008/**
23009 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
23010 * @wiphy: Handle to struct wiphy to get handle to module context.
23011 * @chandef: Contains information about the capture channel to be set.
23012 *
23013 * This interface is called if and only if monitor mode interface alone is
23014 * active.
23015 *
23016 * Return: 0 success or error code on failure.
23017 */
23018static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
23019 struct cfg80211_chan_def *chandef)
23020{
Dustin Brown363b4792019-02-05 16:11:55 -080023021 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080023022 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +053023023
Dustin Brown363b4792019-02-05 16:11:55 -080023024 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080023025 if (errno)
23026 return errno;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023027
Dustin Brownf0f00612019-01-31 16:02:24 -080023028 errno = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
Arunk Khandavalli447837f2018-11-08 14:32:53 +053023029
Dustin Brown363b4792019-02-05 16:11:55 -080023030 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080023031
23032 return errno;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023033}
Nirav Shah73713f72018-05-17 14:50:41 +053023034#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023035
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023036#define CNT_DIFF(cur, prev) \
23037 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
23038#define MAX_COUNT 0xffffffff
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070023039static void hdd_update_chan_info(struct hdd_context *hdd_ctx,
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023040 struct scan_chan_info *chan,
23041 struct scan_chan_info *info, uint32_t cmd_flag)
23042{
23043 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
23044 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
23045 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
23046
23047 mutex_lock(&hdd_ctx->chan_info_lock);
23048
23049 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
23050 qdf_mem_zero(chan, sizeof(*chan));
23051
23052 chan->freq = info->freq;
23053 chan->noise_floor = info->noise_floor;
23054 chan->clock_freq = info->clock_freq;
23055 chan->cmd_flag = info->cmd_flag;
23056 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
23057
23058 chan->rx_clear_count =
23059 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
23060
23061 chan->tx_frame_count =
23062 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
23063
23064 mutex_unlock(&hdd_ctx->chan_info_lock);
23065
23066}
23067#undef CNT_DIFF
23068#undef MAX_COUNT
23069
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023070#ifndef UPDATE_ASSOC_IE
23071#define UPDATE_ASSOC_IE BIT(0)
23072#endif
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023073
23074#ifndef UPDATE_FILS_ERP_INFO
23075#define UPDATE_FILS_ERP_INFO BIT(1)
23076#endif
23077
23078#ifndef UPDATE_FILS_AUTH_TYPE
23079#define UPDATE_FILS_AUTH_TYPE BIT(2)
23080#endif
23081
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023082#if defined(WLAN_FEATURE_FILS_SK) &&\
23083 defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) &&\
23084 (defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
23085 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
23086
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023087/**
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023088 * hdd_update_connect_params_fils_info() - Update fils parameters based on
23089 * the update_connect_params received from userspace
23090 * @adapter: Pointer to hdd_adapter
23091 * @hdd_ctx: Pointer to hdd_context
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023092 * @req: Pointer to connect params
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023093 * @changed: bitmap indicating which parameters have changed
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023094 *
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023095 * Return 0 on SUCCESS or error code on FAILURE
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023096 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023097static int
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023098hdd_update_connect_params_fils_info(struct hdd_adapter *adapter,
23099 struct hdd_context *hdd_ctx,
23100 struct cfg80211_connect_params *req,
23101 uint32_t changed)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023102{
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023103 uint8_t *buf;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023104 QDF_STATUS status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023105 mac_handle_t mac_handle;
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023106 struct csr_roam_profile *roam_profile;
23107 struct cds_fils_connection_info *fils_info;
23108 enum eAniAuthType auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023109
Jeff Johnson20227a92018-03-13 09:41:05 -070023110 roam_profile = hdd_roam_profile(adapter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023111 fils_info = roam_profile->fils_con_info;
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023112 mac_handle = hdd_ctx->mac_handle;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023113 if (!fils_info) {
23114 hdd_err("No valid FILS conn info");
23115 return -EINVAL;
23116 }
23117
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023118 fils_info->is_fils_connection = true;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023119 if (changed & UPDATE_FILS_ERP_INFO) {
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080023120 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080023121 return -EINVAL;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023122 fils_info->key_nai_length = req->fils_erp_username_len +
23123 sizeof(char) +
23124 req->fils_erp_realm_len;
Dundi Raviteja170d2872018-03-23 15:49:54 +053023125 if (fils_info->key_nai_length >
23126 FILS_MAX_KEYNAME_NAI_LENGTH) {
23127 hdd_err("Key NAI Length %d",
23128 fils_info->key_nai_length);
23129 return -EINVAL;
23130 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023131 if (req->fils_erp_username_len && req->fils_erp_username) {
23132 buf = fils_info->keyname_nai;
23133 qdf_mem_copy(buf, req->fils_erp_username,
23134 req->fils_erp_username_len);
23135 buf += req->fils_erp_username_len;
23136 *buf++ = '@';
23137 qdf_mem_copy(buf, req->fils_erp_realm,
23138 req->fils_erp_realm_len);
23139 }
23140
Pragaspathi Thilagaraj87a60af2019-02-20 20:42:47 +053023141 fils_info->sequence_number = req->fils_erp_next_seq_num + 1;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023142 fils_info->r_rk_length = req->fils_erp_rrk_len;
23143
Alan Chendc26e042019-12-10 16:44:56 -080023144 if (fils_info->r_rk_length > FILS_MAX_RRK_LENGTH) {
23145 hdd_err("r_rk_length is invalid");
23146 return -EINVAL;
23147 }
23148
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023149 if (req->fils_erp_rrk_len && req->fils_erp_rrk)
23150 qdf_mem_copy(fils_info->r_rk, req->fils_erp_rrk,
23151 fils_info->r_rk_length);
23152
23153 fils_info->realm_len = req->fils_erp_realm_len;
23154 if (req->fils_erp_realm_len && req->fils_erp_realm)
23155 qdf_mem_copy(fils_info->realm, req->fils_erp_realm,
23156 fils_info->realm_len);
23157 }
23158
23159 if (changed & UPDATE_FILS_AUTH_TYPE) {
23160 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070023161 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023162 hdd_err("invalid auth type for fils %d",
23163 req->auth_type);
23164 return -EINVAL;
23165 }
23166
23167 roam_profile->fils_con_info->auth_type = auth_type;
23168 }
23169
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080023170 hdd_debug("fils conn update: changed %x is_fils %d keyname nai len %d",
23171 changed, roam_profile->fils_con_info->is_fils_connection,
23172 roam_profile->fils_con_info->key_nai_length);
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023173 /*
23174 * Update the FILS config from adapter->roam_profile to
23175 * csr_session
23176 */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080023177 status = sme_update_fils_config(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023178 roam_profile);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023179 if (QDF_IS_STATUS_ERROR(status))
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023180 hdd_err("Update FILS connect params to csr failed %d", status);
23181
23182 return 0;
23183}
23184#else
23185
Lin Bai9dc616c2019-04-10 10:08:49 +080023186static inline int
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023187hdd_update_connect_params_fils_info(struct hdd_adapter *adapter,
23188 struct hdd_context *hdd_ctx,
23189 struct cfg80211_connect_params *req,
23190 uint32_t changed)
23191{
23192 return -EINVAL;
23193}
23194
23195#endif
23196
23197#if defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
23198 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
23199
23200/**
23201 * __wlan_hdd_cfg80211_update_connect_params - update connect params
23202 * @wiphy: Handle to struct wiphy to get handle to module context.
23203 * @dev: Pointer to network device
23204 * @req: Pointer to connect params
23205 * @changed: Bitmap used to indicate the changed params
23206 *
23207 * Update the connect parameters while connected to a BSS. The updated
23208 * parameters can be used by driver/firmware for subsequent BSS selection
23209 * (roaming) decisions and to form the Authentication/(Re)Association
23210 * Request frames. This call does not request an immediate disassociation
23211 * or reassociation with the current BSS, i.e., this impacts only
23212 * subsequent (re)associations. The bits in changed are defined in enum
23213 * cfg80211_connect_params_changed
23214 *
23215 * Return: zero for success, non-zero for failure
23216 */
23217static int
23218__wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
23219 struct net_device *dev,
23220 struct cfg80211_connect_params *req,
23221 uint32_t changed)
23222{
23223 struct csr_roam_profile *roam_profile;
23224 int ret;
23225 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
23226 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
23227 QDF_STATUS status;
23228 mac_handle_t mac_handle;
23229
23230 hdd_enter_dev(dev);
23231
23232 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
23233 return -EINVAL;
23234
23235 ret = wlan_hdd_validate_context(hdd_ctx);
23236 if (ret)
23237 return -EINVAL;
23238
23239 mac_handle = hdd_ctx->mac_handle;
23240 roam_profile = hdd_roam_profile(adapter);
23241
23242 if (changed & UPDATE_ASSOC_IE) {
23243 /*
23244 * Validate the elements of the IE and copy it to
23245 * roam_profile in adapter
23246 */
23247 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
23248
23249 /*
23250 * Update this assoc IE received from user space to
23251 * csr_session. RSO command will pick up the assoc
23252 * IEs to be sent to firmware from the csr_session.
23253 */
23254 sme_update_session_assoc_ie(mac_handle, adapter->vdev_id,
23255 roam_profile);
23256 }
23257
23258 if ((changed & UPDATE_FILS_ERP_INFO) ||
23259 (changed & UPDATE_FILS_AUTH_TYPE)) {
23260 ret = hdd_update_connect_params_fils_info(adapter, hdd_ctx,
23261 req, changed);
23262 if (ret)
23263 return -EINVAL;
23264
23265 if (!hdd_ctx->is_fils_roaming_supported) {
23266 hdd_debug("FILS roaming support %d",
23267 hdd_ctx->is_fils_roaming_supported);
23268 return 0;
23269 }
23270 }
23271
23272 if (changed) {
23273 status = sme_send_rso_connect_params(mac_handle,
23274 adapter->vdev_id,
23275 roam_profile);
23276 if (QDF_IS_STATUS_ERROR(status))
23277 hdd_err("Update connect params to fw failed %d",
23278 status);
23279 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023280
23281 return 0;
23282}
23283
23284/**
23285 * wlan_hdd_cfg80211_update_connect_params - SSR wrapper for
23286 * __wlan_hdd_cfg80211_update_connect_params
23287 * @wiphy: Pointer to wiphy structure
23288 * @dev: Pointer to net_device
23289 * @req: Pointer to connect params
23290 * @changed: flags used to indicate the changed params
23291 *
23292 * Return: zero for success, non-zero for failure
23293 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023294static int
23295wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
23296 struct net_device *dev,
23297 struct cfg80211_connect_params *req,
23298 uint32_t changed)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023299{
Dustin Brown1d31b082018-11-22 14:41:20 +053023300 int errno;
23301 struct osif_vdev_sync *vdev_sync;
23302
23303 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
23304 if (errno)
23305 return errno;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023306
Dustin Brown1d31b082018-11-22 14:41:20 +053023307 errno = __wlan_hdd_cfg80211_update_connect_params(wiphy, dev,
23308 req, changed);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023309
Dustin Brown1d31b082018-11-22 14:41:20 +053023310 osif_vdev_sync_op_stop(vdev_sync);
23311
23312 return errno;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023313}
23314#endif
23315
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023316#if defined(WLAN_FEATURE_SAE) && \
23317 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023318#if defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT)
23319/**
23320 * wlan_hdd_extauth_cache_pmkid() - Extract and cache pmkid
23321 * @adapter: hdd vdev/net_device context
23322 * @mac_handle: Handle to the MAC
23323 * @params: Pointer to external auth params.
23324 *
23325 * Extract the PMKID and BSS from external auth params and add to the
23326 * PMKSA Cache in CSR.
23327 */
23328static void
23329wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
23330 mac_handle_t mac_handle,
23331 struct cfg80211_external_auth_params *params)
23332{
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023333 tPmkidCacheInfo *pmk_cache;
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023334 QDF_STATUS result;
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023335
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023336 if (params->pmkid) {
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023337 pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
23338 if (!pmk_cache)
23339 return;
23340
23341 qdf_mem_copy(pmk_cache->BSSID.bytes, params->bssid,
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023342 QDF_MAC_ADDR_SIZE);
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023343 qdf_mem_copy(pmk_cache->PMKID, params->pmkid,
Srinivas Girigowdaff8f5ef2019-03-26 17:20:55 -070023344 PMKID_LEN);
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023345 result = wlan_hdd_set_pmksa_cache(adapter, pmk_cache);
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023346 if (!QDF_IS_STATUS_SUCCESS(result))
23347 hdd_debug("external_auth: Failed to cache PMKID");
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023348
23349 qdf_mem_free(pmk_cache);
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023350 }
Pragaspathi Thilagaraj8a4ffcc2020-01-30 23:10:51 +053023351
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023352}
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053023353
23354/**
23355 * wlan_hdd_extauth_copy_pmkid() - Copy the pmkid received from the
23356 * external authentication command received from the userspace.
23357 * @params: pointer to auth params
23358 * @pmkid: Pointer to destination pmkid buffer to be filled
23359 *
23360 * The caller should ensure that destination pmkid buffer is not NULL.
23361 *
23362 * Return: None
23363 */
23364static void
23365wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params *params,
23366 uint8_t *pmkid)
23367{
Pragaspathi Thilagarajaf840592019-08-14 11:45:32 +053023368 if (params->pmkid)
23369 qdf_mem_copy(pmkid, params->pmkid, PMKID_LEN);
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053023370}
23371
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023372#else
23373static void
23374wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
23375 mac_handle_t mac_handle,
23376 struct cfg80211_external_auth_params *params)
23377{}
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053023378
23379static void
23380wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params *params,
23381 uint8_t *pmkid)
23382{}
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023383#endif
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023384/**
23385 * __wlan_hdd_cfg80211_external_auth() - Handle external auth
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023386 *
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023387 * @wiphy: Pointer to wireless phy
23388 * @dev: net device
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023389 * @params: Pointer to external auth params.
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023390 * Return: 0 on success, negative errno on failure
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023391 *
23392 * Userspace sends status of the external authentication(e.g., SAE) with a peer.
23393 * The message carries BSSID of the peer and auth status (WLAN_STATUS_SUCCESS/
23394 * WLAN_STATUS_UNSPECIFIED_FAILURE) in params.
23395 * Userspace may send PMKID in params, which can be used for
23396 * further connections.
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023397 */
23398static int
23399__wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
23400 struct net_device *dev,
23401 struct cfg80211_external_auth_params *params)
23402{
23403 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
23404 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
23405 int ret;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023406 mac_handle_t mac_handle;
Srinivas Dasarie854ff02019-02-11 17:24:48 +053023407 struct qdf_mac_addr peer_mac_addr;
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053023408 uint8_t pmkid[PMKID_LEN] = {0};
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023409
23410 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
23411 hdd_err("Command not allowed in FTM mode");
23412 return -EPERM;
23413 }
23414
Jeff Johnson48363022019-02-24 16:26:51 -080023415 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023416 return -EINVAL;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023417
23418 ret = wlan_hdd_validate_context(hdd_ctx);
23419 if (ret)
23420 return ret;
23421
Srinivas Dasarie854ff02019-02-11 17:24:48 +053023422 hdd_debug("external_auth status: %d peer mac: " QDF_MAC_ADDR_STR,
23423 params->status, QDF_MAC_ADDR_ARRAY(params->bssid));
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023424 mac_handle = hdd_ctx->mac_handle;
Srinivas Dasarie854ff02019-02-11 17:24:48 +053023425 qdf_mem_copy(peer_mac_addr.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Srinivas Dasari29186ca2019-02-11 18:45:48 +053023426
23427 wlan_hdd_extauth_cache_pmkid(adapter, mac_handle, params);
23428
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053023429 wlan_hdd_extauth_copy_pmkid(params, pmkid);
Srinivas Dasarie854ff02019-02-11 17:24:48 +053023430 sme_handle_sae_msg(mac_handle, adapter->vdev_id, params->status,
Pragaspathi Thilagaraja97d4982019-07-18 01:18:44 +053023431 peer_mac_addr, pmkid);
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023432
23433 return ret;
23434}
23435
23436/**
23437 * wlan_hdd_cfg80211_external_auth() - Handle external auth
23438 * @wiphy: Pointer to wireless phy
23439 * @dev: net device
23440 * @params: Pointer to external auth params
23441 *
23442 * Return: 0 on success, negative errno on failure
23443 */
23444static int
23445wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
23446 struct net_device *dev,
23447 struct cfg80211_external_auth_params *params)
23448{
Dustin Brown1d31b082018-11-22 14:41:20 +053023449 int errno;
23450 struct osif_vdev_sync *vdev_sync;
23451
23452 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
23453 if (errno)
23454 return errno;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023455
Dustin Brown1d31b082018-11-22 14:41:20 +053023456 errno = __wlan_hdd_cfg80211_external_auth(wiphy, dev, params);
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023457
Dustin Brown1d31b082018-11-22 14:41:20 +053023458 osif_vdev_sync_op_stop(vdev_sync);
23459
23460 return errno;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023461}
23462#endif
23463
Srinivas Dasarid2ba2612019-12-11 17:27:52 +053023464#if defined(WLAN_FEATURE_NAN) && \
23465 (KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE)
23466static int
23467wlan_hdd_cfg80211_start_nan(struct wiphy *wiphy, struct wireless_dev *wdev,
23468 struct cfg80211_nan_conf *conf)
23469{
23470 return -EOPNOTSUPP;
23471}
23472
23473static void
23474wlan_hdd_cfg80211_stop_nan(struct wiphy *wiphy, struct wireless_dev *wdev)
23475{
23476}
23477
23478static int wlan_hdd_cfg80211_add_nan_func(struct wiphy *wiphy,
23479 struct wireless_dev *wdev,
23480 struct cfg80211_nan_func *nan_func)
23481{
23482 return -EOPNOTSUPP;
23483}
23484
23485static void wlan_hdd_cfg80211_del_nan_func(struct wiphy *wiphy,
23486 struct wireless_dev *wdev,
23487 u64 cookie)
23488{
23489}
23490
23491static int wlan_hdd_cfg80211_nan_change_conf(struct wiphy *wiphy,
23492 struct wireless_dev *wdev,
23493 struct cfg80211_nan_conf *conf,
23494 u32 changes)
23495{
23496 return -EOPNOTSUPP;
23497}
23498#endif
23499
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023500/**
23501 * wlan_hdd_chan_info_cb() - channel info callback
23502 * @chan_info: struct scan_chan_info
23503 *
23504 * Store channel info into HDD context
23505 *
23506 * Return: None.
23507 */
23508static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
23509{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070023510 struct hdd_context *hdd_ctx;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023511 struct scan_chan_info *chan;
23512 uint8_t idx;
23513
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023514 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
23515 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
23516 hdd_err("hdd_ctx is invalid");
23517 return;
23518 }
23519
23520 if (!hdd_ctx->chan_info) {
23521 hdd_err("chan_info is NULL");
23522 return;
23523 }
23524
23525 chan = hdd_ctx->chan_info;
23526 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
23527 if (chan[idx].freq == info->freq) {
23528 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
23529 info->cmd_flag);
Rajeev Kumareb6ec172018-09-26 20:45:36 -070023530 hdd_debug("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
23531 chan[idx].cmd_flag, chan[idx].freq,
23532 chan[idx].noise_floor,
23533 chan[idx].cycle_count,
23534 chan[idx].rx_clear_count,
23535 chan[idx].clock_freq, chan[idx].cmd_flag,
23536 chan[idx].tx_frame_count, idx);
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023537 if (chan[idx].freq == 0)
23538 break;
23539
23540 }
23541 }
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023542}
23543
23544/**
23545 * wlan_hdd_init_chan_info() - init chan info in hdd context
23546 * @hdd_ctx: HDD context pointer
23547 *
23548 * Return: none
23549 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070023550void wlan_hdd_init_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023551{
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053023552 uint32_t num_2g, num_5g, index = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023553 mac_handle_t mac_handle;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023554
Kapil Gupta63e75282017-05-18 20:55:10 +053023555 hdd_ctx->chan_info = NULL;
hqud109f762019-12-18 14:26:17 +080023556 if (!ucfg_scan_is_snr_monitor_enabled(hdd_ctx->psoc)) {
Dustin Brown31116772018-08-15 14:59:21 -070023557 hdd_debug("SNR monitoring is disabled");
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023558 return;
23559 }
23560
23561 hdd_ctx->chan_info =
23562 qdf_mem_malloc(sizeof(struct scan_chan_info)
23563 * QDF_MAX_NUM_CHAN);
Min Liu74a1a502018-10-10 19:59:07 +080023564 if (!hdd_ctx->chan_info)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023565 return;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023566 mutex_init(&hdd_ctx->chan_info_lock);
23567
23568 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
23569 for (; index < num_2g; index++) {
23570 hdd_ctx->chan_info[index].freq =
23571 hdd_channels_2_4_ghz[index].center_freq;
23572 }
23573
23574 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
23575 for (; (index - num_2g) < num_5g; index++) {
Dustin Brown07901ec2018-09-07 11:02:41 -070023576 if (wlan_reg_is_dsrc_chan(hdd_ctx->pdev,
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070023577 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023578 continue;
23579 hdd_ctx->chan_info[index].freq =
23580 hdd_channels_5_ghz[index - num_2g].center_freq;
23581 }
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053023582
23583 index = num_2g + num_5g;
23584 index = wlan_hdd_populate_srd_chan_info(hdd_ctx, index);
23585
Jeff Johnson34fc63a2018-06-14 10:10:02 -070023586 mac_handle = hdd_ctx->mac_handle;
23587 sme_set_chan_info_callback(mac_handle,
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023588 &wlan_hdd_chan_info_cb);
23589}
23590
23591/**
23592 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
23593 * @hdd_ctx: hdd context pointer
23594 *
23595 * Return: none
23596 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070023597void wlan_hdd_deinit_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053023598{
23599 struct scan_chan_info *chan;
23600
23601 chan = hdd_ctx->chan_info;
23602 hdd_ctx->chan_info = NULL;
23603 if (chan)
23604 qdf_mem_free(chan);
23605}
23606
Dustin Brown32cb4792017-06-15 15:33:42 -070023607#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
23608static enum rate_info_bw hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
23609{
23610 switch (hdd_bw) {
23611 case HDD_RATE_BW_5:
23612 return RATE_INFO_BW_5;
23613 case HDD_RATE_BW_10:
23614 return RATE_INFO_BW_10;
23615 case HDD_RATE_BW_20:
23616 return RATE_INFO_BW_20;
23617 case HDD_RATE_BW_40:
23618 return RATE_INFO_BW_40;
23619 case HDD_RATE_BW_80:
23620 return RATE_INFO_BW_80;
23621 case HDD_RATE_BW_160:
23622 return RATE_INFO_BW_160;
23623 }
23624
23625 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
23626
23627 return RATE_INFO_BW_20;
23628}
23629
23630void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
23631{
23632 info->bw = hdd_map_hdd_bw_to_os(hdd_bw);
23633}
23634#else
23635static enum rate_info_flags hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
23636{
23637 switch (hdd_bw) {
23638 case HDD_RATE_BW_5:
23639 case HDD_RATE_BW_10:
23640 case HDD_RATE_BW_20:
23641 return (enum rate_info_flags)0;
23642 case HDD_RATE_BW_40:
23643 return RATE_INFO_FLAGS_40_MHZ_WIDTH;
23644 case HDD_RATE_BW_80:
23645 return RATE_INFO_FLAGS_80_MHZ_WIDTH;
23646 case HDD_RATE_BW_160:
23647 return RATE_INFO_FLAGS_160_MHZ_WIDTH;
23648 }
23649
23650 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
23651
23652 return (enum rate_info_flags)0;
23653}
23654
23655void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
23656{
23657 const enum rate_info_flags all_bws =
23658 RATE_INFO_FLAGS_40_MHZ_WIDTH |
23659 RATE_INFO_FLAGS_80_MHZ_WIDTH |
23660 RATE_INFO_FLAGS_80P80_MHZ_WIDTH |
23661 RATE_INFO_FLAGS_160_MHZ_WIDTH;
23662
23663 info->flags &= ~all_bws;
23664 info->flags |= hdd_map_hdd_bw_to_os(hdd_bw);
23665}
23666#endif
23667
Min Liue34708a2019-02-01 15:00:34 +080023668#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
23669void hdd_send_update_owe_info_event(struct hdd_adapter *adapter,
23670 uint8_t sta_addr[],
23671 uint8_t *owe_ie,
23672 uint32_t owe_ie_len)
23673{
23674 struct cfg80211_update_owe_info owe_info;
23675 struct net_device *dev = adapter->dev;
23676
23677 hdd_enter_dev(dev);
23678
Min Liue2b469f2019-04-10 19:13:42 +080023679 qdf_mem_copy(owe_info.peer, sta_addr, ETH_ALEN);
Min Liue34708a2019-02-01 15:00:34 +080023680 owe_info.ie = owe_ie;
23681 owe_info.ie_len = owe_ie_len;
23682
23683 cfg80211_update_owe_info_event(dev, &owe_info, GFP_KERNEL);
23684
23685 hdd_exit();
23686}
23687#endif
23688
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053023689/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023690 * struct cfg80211_ops - cfg80211_ops
23691 *
23692 * @add_virtual_intf: Add virtual interface
23693 * @del_virtual_intf: Delete virtual interface
23694 * @change_virtual_intf: Change virtual interface
23695 * @change_station: Change station
23696 * @add_beacon: Add beacon in sap mode
23697 * @del_beacon: Delete beacon in sap mode
23698 * @set_beacon: Set beacon in sap mode
23699 * @start_ap: Start ap
23700 * @change_beacon: Change beacon
23701 * @stop_ap: Stop ap
23702 * @change_bss: Change bss
23703 * @add_key: Add key
23704 * @get_key: Get key
23705 * @del_key: Delete key
23706 * @set_default_key: Set default key
23707 * @set_channel: Set channel
23708 * @scan: Scan
23709 * @connect: Connect
23710 * @disconnect: Disconnect
23711 * @join_ibss = Join ibss
23712 * @leave_ibss = Leave ibss
23713 * @set_wiphy_params = Set wiphy params
23714 * @set_tx_power = Set tx power
23715 * @get_tx_power = get tx power
23716 * @remain_on_channel = Remain on channel
23717 * @cancel_remain_on_channel = Cancel remain on channel
23718 * @mgmt_tx = Tx management frame
23719 * @mgmt_tx_cancel_wait = Cancel management tx wait
23720 * @set_default_mgmt_key = Set default management key
23721 * @set_txq_params = Set tx queue parameters
23722 * @get_station = Get station
23723 * @set_power_mgmt = Set power management
23724 * @del_station = Delete station
23725 * @add_station = Add station
23726 * @set_pmksa = Set pmksa
23727 * @del_pmksa = Delete pmksa
23728 * @flush_pmksa = Flush pmksa
23729 * @update_ft_ies = Update FT IEs
23730 * @tdls_mgmt = Tdls management
23731 * @tdls_oper = Tdls operation
23732 * @set_rekey_data = Set rekey data
23733 * @sched_scan_start = Scheduled scan start
23734 * @sched_scan_stop = Scheduled scan stop
23735 * @resume = Resume wlan
23736 * @suspend = Suspend wlan
23737 * @set_mac_acl = Set mac acl
23738 * @testmode_cmd = Test mode command
23739 * @set_ap_chanwidth = Set AP channel bandwidth
23740 * @dump_survey = Dump survey
23741 * @key_mgmt_set_pmk = Set pmk key management
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023742 * @update_connect_params = Update connect params
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023743 */
23744static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
23745 .add_virtual_intf = wlan_hdd_add_virtual_intf,
23746 .del_virtual_intf = wlan_hdd_del_virtual_intf,
23747 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
23748 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023749 .start_ap = wlan_hdd_cfg80211_start_ap,
23750 .change_beacon = wlan_hdd_cfg80211_change_beacon,
23751 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023752 .change_bss = wlan_hdd_cfg80211_change_bss,
23753 .add_key = wlan_hdd_cfg80211_add_key,
23754 .get_key = wlan_hdd_cfg80211_get_key,
23755 .del_key = wlan_hdd_cfg80211_del_key,
23756 .set_default_key = wlan_hdd_cfg80211_set_default_key,
23757 .scan = wlan_hdd_cfg80211_scan,
23758 .connect = wlan_hdd_cfg80211_connect,
23759 .disconnect = wlan_hdd_cfg80211_disconnect,
23760 .join_ibss = wlan_hdd_cfg80211_join_ibss,
23761 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
23762 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
23763 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
23764 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
23765 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
23766 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
23767 .mgmt_tx = wlan_hdd_mgmt_tx,
23768 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
23769 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
23770 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053023771 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023772 .get_station = wlan_hdd_cfg80211_get_station,
23773 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
23774 .del_station = wlan_hdd_cfg80211_del_station,
23775 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023776 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
23777 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
23778 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080023779#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023780 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
23781#endif
Min Liu0daa0982019-02-01 17:50:44 +080023782#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
23783 .update_owe_info = wlan_hdd_cfg80211_update_owe_info,
23784#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023785#ifdef FEATURE_WLAN_TDLS
23786 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
23787 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
23788#endif
23789#ifdef WLAN_FEATURE_GTK_OFFLOAD
23790 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
23791#endif /* WLAN_FEATURE_GTK_OFFLOAD */
23792#ifdef FEATURE_WLAN_SCAN_PNO
23793 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
23794 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
23795#endif /*FEATURE_WLAN_SCAN_PNO */
23796 .resume = wlan_hdd_cfg80211_resume_wlan,
23797 .suspend = wlan_hdd_cfg80211_suspend_wlan,
23798 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
23799#ifdef WLAN_NL80211_TESTMODE
23800 .testmode_cmd = wlan_hdd_cfg80211_testmode,
23801#endif
23802#ifdef QCA_HT_2040_COEX
23803 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
23804#endif
23805 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053023806#ifdef CHANNEL_SWITCH_SUPPORTED
23807 .channel_switch = wlan_hdd_cfg80211_channel_switch,
23808#endif
Nirav Shah73713f72018-05-17 14:50:41 +053023809#ifdef FEATURE_MONITOR_MODE_SUPPORT
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070023810 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Nirav Shah73713f72018-05-17 14:50:41 +053023811#endif
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053023812#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
Srinivas Girigowda576b2352017-08-25 14:44:26 -070023813 defined(CFG80211_ABORT_SCAN)
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053023814 .abort_scan = wlan_hdd_cfg80211_abort_scan,
23815#endif
Pragaspathi Thilagaraj6695ba92019-04-04 17:59:47 +053023816#if defined(CFG80211_UPDATE_CONNECT_PARAMS) || \
23817 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053023818 .update_connect_params = wlan_hdd_cfg80211_update_connect_params,
23819#endif
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053023820#if defined(WLAN_FEATURE_SAE) && \
23821 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
23822 .external_auth = wlan_hdd_cfg80211_external_auth,
23823#endif
Srinivas Dasarid2ba2612019-12-11 17:27:52 +053023824#if defined(WLAN_FEATURE_NAN) && \
23825 (KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE)
23826 .start_nan = wlan_hdd_cfg80211_start_nan,
23827 .stop_nan = wlan_hdd_cfg80211_stop_nan,
23828 .add_nan_func = wlan_hdd_cfg80211_add_nan_func,
23829 .del_nan_func = wlan_hdd_cfg80211_del_nan_func,
23830 .nan_change_conf = wlan_hdd_cfg80211_nan_change_conf,
23831#endif
23832
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080023833};