blob: fc4c4b39f0037bc3a4179857f9669babfac871ce [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Abhishek Singhef6f38c2018-12-20 13:51:29 +05302 * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019/**
20 * DOC: wlan_hdd_cfg80211.c
21 *
22 * WLAN Host Device Driver cfg80211 APIs implementation
23 *
24 */
25
26#include <linux/version.h>
27#include <linux/module.h>
28#include <linux/kernel.h>
29#include <linux/init.h>
30#include <linux/etherdevice.h>
31#include <linux/wireless.h>
Dustin Browna09acf42018-11-08 12:32:26 +053032#include "osif_sync.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080033#include <wlan_hdd_includes.h>
34#include <net/arp.h>
35#include <net/cfg80211.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080036#include <wlan_hdd_wowl.h>
37#include <ani_global.h>
38#include "sir_params.h"
39#include "dot11f.h"
40#include "wlan_hdd_assoc.h"
41#include "wlan_hdd_wext.h"
42#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070043#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080044#include "wlan_hdd_p2p.h"
45#include "wlan_hdd_cfg80211.h"
46#include "wlan_hdd_hostapd.h"
47#include "wlan_hdd_softap_tx_rx.h"
48#include "wlan_hdd_main.h"
49#include "wlan_hdd_power.h"
50#include "wlan_hdd_trace.h"
Dustin Brownd4241942018-02-26 12:51:37 -080051#include "qdf_str.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053052#include "qdf_trace.h"
Dustin Brownd4241942018-02-26 12:51:37 -080053#include "qdf_types.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080054#include "cds_utils.h"
55#include "cds_sched.h"
56#include "wlan_hdd_scan.h"
57#include <qc_sap_ioctl.h>
58#include "wlan_hdd_tdls.h"
59#include "wlan_hdd_wmm.h"
60#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053061#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "wlan_hdd_misc.h"
63#include "wlan_hdd_nan.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080064#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053065#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053066#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053067#include "pld_common.h"
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070068#include "wmi_unified_param.h"
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070069
Paul Zhang3a210c52016-12-08 10:18:12 +080070#ifdef WLAN_UMAC_CONVERGENCE
71#include "wlan_cfg80211.h"
72#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080073#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080074#include <wlan_cfg80211_scan.h>
Ryan Hsuc8b27a42018-01-02 13:57:56 -080075#include <wlan_cfg80211_ftm.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080076
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077#include "wlan_hdd_ext_scan.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080078
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080079#include "wlan_hdd_stats.h"
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080080#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080081#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080082#include "qwlan_version.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083
84#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070085#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080086
Ravi Joshideb5a8d2015-11-09 19:11:43 -080087#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053088#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070089#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070090#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053091#include "wlan_hdd_disa.h"
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070092#include "wlan_osif_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080093#include "wlan_hdd_he.h"
Nachiket Kukade177b5b02018-05-22 20:52:17 +053094#ifdef FEATURE_WLAN_APF
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053095#include "wlan_hdd_apf.h"
Nachiket Kukade177b5b02018-05-22 20:52:17 +053096#endif
Qun Zhangef655622019-02-25 10:48:10 +080097#include "wlan_hdd_fw_state.h"
stonez2d686482019-03-12 14:54:26 +080098#include "wlan_hdd_mpta_helper.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -080099
Leo Changfdb45c32016-10-28 11:09:23 -0700100#include <cdp_txrx_cmn.h>
101#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800102#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530103#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800104#include "os_if_wifi_pos.h"
Ajit Pal Singh90a45a42017-04-18 18:53:46 +0530105#include "wlan_utility.h"
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -0700106#include "wlan_reg_ucfg_api.h"
Naveen Rawatd2657be2017-10-10 14:31:23 -0700107#include "wifi_pos_api.h"
Sandeep Puligilla063a4342018-01-10 02:50:14 -0800108#include "wlan_hdd_spectralscan.h"
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +0530109#include "wlan_ipa_ucfg_api.h"
Naveen Rawate8b1b822018-01-30 09:46:16 -0800110#include <wlan_cfg80211_mc_cp_stats.h>
Yu Wang157d1472018-03-09 16:05:01 +0800111#include <wlan_cp_stats_mc_ucfg_api.h>
Wu Gaobdb7f272018-07-05 19:33:26 +0800112#include "wlan_tdls_cfg_api.h"
Qiwei Caie689a262018-07-26 15:50:22 +0800113#include <wlan_hdd_bss_transition.h>
114#include <wlan_hdd_concurrency_matrix.h>
115#include <wlan_hdd_p2p_listen_offload.h>
116#include <wlan_hdd_rssi_monitor.h>
117#include <wlan_hdd_sap_cond_chan_switch.h>
118#include <wlan_hdd_station_info.h>
119#include <wlan_hdd_tx_power.h>
120#include <wlan_hdd_active_tos.h>
121#include <wlan_hdd_sar_limits.h>
122#include <wlan_hdd_ota_test.h>
Krunal Soni5e3f9622018-09-26 16:35:50 -0700123#include "wlan_policy_mgr_ucfg.h"
Arunk Khandavalli99716d12018-11-14 15:02:02 +0530124#include "wlan_mlme_ucfg_api.h"
125#include "wlan_mlme_public_struct.h"
Harprit Chhabadae8155d32018-08-22 16:19:34 -0700126#include "wlan_extscan_ucfg_api.h"
Wu Gao93816212018-08-31 16:49:54 +0800127#include "wlan_mlme_ucfg_api.h"
Wu Gao66454f12018-09-26 19:55:41 +0800128#include "wlan_pmo_cfg.h"
129#include "cfg_ucfg_api.h"
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +0530130
Harprit Chhabada6c641ba2018-06-28 14:45:10 -0700131#include "wlan_crypto_global_api.h"
132#include "wlan_nl_to_crypto_params.h"
133#include "wlan_crypto_global_def.h"
jitiphil377bcc12018-10-05 19:46:08 +0530134#include "cdp_txrx_cfg.h"
Min Liu8c5d99e2018-09-10 17:18:44 +0800135#include "wlan_hdd_object_manager.h"
Nachiket Kukade089b9832018-12-12 16:38:17 +0530136#include "nan_ucfg_api.h"
Manikandan Mohand350c192018-11-29 14:01:12 -0800137#include "wlan_fwol_ucfg_api.h"
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -0700138#include "wlan_cfg80211_crypto.h"
gaurank kathpalia97c070b2019-01-07 17:23:06 +0530139#include "wlan_scan_ucfg_api.h"
Jiani Liua5f17222019-03-04 16:22:33 +0800140#include "wlan_hdd_coex_config.h"
Harprit Chhabada6c641ba2018-06-28 14:45:10 -0700141
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800142#define g_mode_rates_size (12)
143#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800144
145/*
146 * Android CTS verifier needs atleast this much wait time (in msec)
147 */
148#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
149
150/*
151 * Refer @tCfgProtection structure for definition of the bit map.
152 * below value is obtained by setting the following bit-fields.
153 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
154 */
155#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
156
157#define HDD2GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700158 .band = HDD_NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159 .center_freq = (freq), \
160 .hw_value = (chan), \
161 .flags = (flag), \
162 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800163 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800164}
165
166#define HDD5GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700167 .band = HDD_NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168 .center_freq = (freq), \
169 .hw_value = (chan), \
170 .flags = (flag), \
171 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800172 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800173}
174
175#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
176 { \
177 .bitrate = rate, \
178 .hw_value = rate_id, \
179 .flags = flag, \
180 }
181
Agrawal Ashish65634612016-08-18 13:24:32 +0530182#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
183 mode <= DFS_MODE_DEPRIORITIZE))
Mohit Khannaceb97782017-04-05 16:27:08 -0700184/*
185 * Number of DPTRACE records to dump when a cfg80211 disconnect with reason
186 * WLAN_REASON_DEAUTH_LEAVING DEAUTH is received from user-space.
187 */
188#define WLAN_DEAUTH_DPTRACE_DUMP_COUNT 100
Mukul Sharma05504ac2017-06-08 12:35:53 +0530189#ifndef WLAN_CIPHER_SUITE_GCMP
190#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
191#endif
192#ifndef WLAN_CIPHER_SUITE_GCMP_256
193#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09
194#endif
Mohit Khannaceb97782017-04-05 16:27:08 -0700195
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +0530196static const u32 hdd_gcmp_cipher_suits[] = {
197 WLAN_CIPHER_SUITE_GCMP,
198 WLAN_CIPHER_SUITE_GCMP_256,
199};
200
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800201static const u32 hdd_cipher_suites[] = {
202 WLAN_CIPHER_SUITE_WEP40,
203 WLAN_CIPHER_SUITE_WEP104,
204 WLAN_CIPHER_SUITE_TKIP,
205#ifdef FEATURE_WLAN_ESE
206#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
207#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
208 WLAN_CIPHER_SUITE_BTK,
209 WLAN_CIPHER_SUITE_KRK,
210 WLAN_CIPHER_SUITE_CCMP,
211#else
212 WLAN_CIPHER_SUITE_CCMP,
213#endif
214#ifdef FEATURE_WLAN_WAPI
215 WLAN_CIPHER_SUITE_SMS4,
216#endif
217#ifdef WLAN_FEATURE_11W
218 WLAN_CIPHER_SUITE_AES_CMAC,
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +0530219#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
220 WLAN_CIPHER_SUITE_BIP_GMAC_128,
221 WLAN_CIPHER_SUITE_BIP_GMAC_256,
222#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800223#endif
224};
225
Abhishek Singhf512bf32016-05-04 16:47:46 +0530226static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800227 HDD2GHZCHAN(2412, 1, 0),
228 HDD2GHZCHAN(2417, 2, 0),
229 HDD2GHZCHAN(2422, 3, 0),
230 HDD2GHZCHAN(2427, 4, 0),
231 HDD2GHZCHAN(2432, 5, 0),
232 HDD2GHZCHAN(2437, 6, 0),
233 HDD2GHZCHAN(2442, 7, 0),
234 HDD2GHZCHAN(2447, 8, 0),
235 HDD2GHZCHAN(2452, 9, 0),
236 HDD2GHZCHAN(2457, 10, 0),
237 HDD2GHZCHAN(2462, 11, 0),
238 HDD2GHZCHAN(2467, 12, 0),
239 HDD2GHZCHAN(2472, 13, 0),
240 HDD2GHZCHAN(2484, 14, 0),
241};
242
Abhishek Singhf512bf32016-05-04 16:47:46 +0530243static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800244 HDD5GHZCHAN(5180, 36, 0),
245 HDD5GHZCHAN(5200, 40, 0),
246 HDD5GHZCHAN(5220, 44, 0),
247 HDD5GHZCHAN(5240, 48, 0),
248 HDD5GHZCHAN(5260, 52, 0),
249 HDD5GHZCHAN(5280, 56, 0),
250 HDD5GHZCHAN(5300, 60, 0),
251 HDD5GHZCHAN(5320, 64, 0),
252 HDD5GHZCHAN(5500, 100, 0),
253 HDD5GHZCHAN(5520, 104, 0),
254 HDD5GHZCHAN(5540, 108, 0),
255 HDD5GHZCHAN(5560, 112, 0),
256 HDD5GHZCHAN(5580, 116, 0),
257 HDD5GHZCHAN(5600, 120, 0),
258 HDD5GHZCHAN(5620, 124, 0),
259 HDD5GHZCHAN(5640, 128, 0),
260 HDD5GHZCHAN(5660, 132, 0),
261 HDD5GHZCHAN(5680, 136, 0),
262 HDD5GHZCHAN(5700, 140, 0),
263 HDD5GHZCHAN(5720, 144, 0),
264 HDD5GHZCHAN(5745, 149, 0),
265 HDD5GHZCHAN(5765, 153, 0),
266 HDD5GHZCHAN(5785, 157, 0),
267 HDD5GHZCHAN(5805, 161, 0),
268 HDD5GHZCHAN(5825, 165, 0),
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +0530269};
270
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -0700271#ifdef WLAN_FEATURE_DSRC
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +0530272static const struct ieee80211_channel hdd_channels_dot11p[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800273 HDD5GHZCHAN(5852, 170, 0),
274 HDD5GHZCHAN(5855, 171, 0),
275 HDD5GHZCHAN(5860, 172, 0),
276 HDD5GHZCHAN(5865, 173, 0),
277 HDD5GHZCHAN(5870, 174, 0),
278 HDD5GHZCHAN(5875, 175, 0),
279 HDD5GHZCHAN(5880, 176, 0),
280 HDD5GHZCHAN(5885, 177, 0),
281 HDD5GHZCHAN(5890, 178, 0),
282 HDD5GHZCHAN(5895, 179, 0),
283 HDD5GHZCHAN(5900, 180, 0),
284 HDD5GHZCHAN(5905, 181, 0),
285 HDD5GHZCHAN(5910, 182, 0),
286 HDD5GHZCHAN(5915, 183, 0),
287 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288};
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -0700289#else
290static const struct ieee80211_channel hdd_etsi13_srd_ch[] = {
291 HDD5GHZCHAN(5845, 169, 0),
292 HDD5GHZCHAN(5865, 173, 0),
293};
294#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800295
296static struct ieee80211_rate g_mode_rates[] = {
297 HDD_G_MODE_RATETAB(10, 0x1, 0),
298 HDD_G_MODE_RATETAB(20, 0x2, 0),
299 HDD_G_MODE_RATETAB(55, 0x4, 0),
300 HDD_G_MODE_RATETAB(110, 0x8, 0),
301 HDD_G_MODE_RATETAB(60, 0x10, 0),
302 HDD_G_MODE_RATETAB(90, 0x20, 0),
303 HDD_G_MODE_RATETAB(120, 0x40, 0),
304 HDD_G_MODE_RATETAB(180, 0x80, 0),
305 HDD_G_MODE_RATETAB(240, 0x100, 0),
306 HDD_G_MODE_RATETAB(360, 0x200, 0),
307 HDD_G_MODE_RATETAB(480, 0x400, 0),
308 HDD_G_MODE_RATETAB(540, 0x800, 0),
309};
310
311static struct ieee80211_rate a_mode_rates[] = {
312 HDD_G_MODE_RATETAB(60, 0x10, 0),
313 HDD_G_MODE_RATETAB(90, 0x20, 0),
314 HDD_G_MODE_RATETAB(120, 0x40, 0),
315 HDD_G_MODE_RATETAB(180, 0x80, 0),
316 HDD_G_MODE_RATETAB(240, 0x100, 0),
317 HDD_G_MODE_RATETAB(360, 0x200, 0),
318 HDD_G_MODE_RATETAB(480, 0x400, 0),
319 HDD_G_MODE_RATETAB(540, 0x800, 0),
320};
321
322static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530323 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800324 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700325 .band = HDD_NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800326 .bitrates = g_mode_rates,
327 .n_bitrates = g_mode_rates_size,
328 .ht_cap.ht_supported = 1,
329 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
330 | IEEE80211_HT_CAP_GRN_FLD
331 | IEEE80211_HT_CAP_DSSSCCK40
332 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
333 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
334 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
335 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
336 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
337 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
338 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
339};
340
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800341static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530342 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800343 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700344 .band = HDD_NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800345 .bitrates = a_mode_rates,
346 .n_bitrates = a_mode_rates_size,
347 .ht_cap.ht_supported = 1,
348 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
349 | IEEE80211_HT_CAP_GRN_FLD
350 | IEEE80211_HT_CAP_DSSSCCK40
351 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
352 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
353 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
354 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
355 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
356 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
357 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
358 .vht_cap.vht_supported = 1,
359};
360
361/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800362 * TX/RX direction for each kind of interface
363 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800364static const struct ieee80211_txrx_stypes
365 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
366 [NL80211_IFTYPE_STATION] = {
367 .tx = 0xffff,
368 .rx = BIT(SIR_MAC_MGMT_ACTION) |
Padma, Santhosh Kumar1ccc1332017-09-13 17:39:01 +0530369 BIT(SIR_MAC_MGMT_PROBE_REQ) |
370 BIT(SIR_MAC_MGMT_AUTH),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800371 },
372 [NL80211_IFTYPE_AP] = {
373 .tx = 0xffff,
374 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
375 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
376 BIT(SIR_MAC_MGMT_PROBE_REQ) |
377 BIT(SIR_MAC_MGMT_DISASSOC) |
378 BIT(SIR_MAC_MGMT_AUTH) |
379 BIT(SIR_MAC_MGMT_DEAUTH) |
380 BIT(SIR_MAC_MGMT_ACTION),
381 },
382 [NL80211_IFTYPE_ADHOC] = {
383 .tx = 0xffff,
384 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
385 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
386 BIT(SIR_MAC_MGMT_PROBE_REQ) |
387 BIT(SIR_MAC_MGMT_DISASSOC) |
388 BIT(SIR_MAC_MGMT_AUTH) |
389 BIT(SIR_MAC_MGMT_DEAUTH) |
390 BIT(SIR_MAC_MGMT_ACTION),
391 },
392 [NL80211_IFTYPE_P2P_CLIENT] = {
393 .tx = 0xffff,
394 .rx = BIT(SIR_MAC_MGMT_ACTION) |
395 BIT(SIR_MAC_MGMT_PROBE_REQ),
396 },
397 [NL80211_IFTYPE_P2P_GO] = {
398 /* This is also same as for SoftAP */
399 .tx = 0xffff,
400 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
401 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
402 BIT(SIR_MAC_MGMT_PROBE_REQ) |
403 BIT(SIR_MAC_MGMT_DISASSOC) |
404 BIT(SIR_MAC_MGMT_AUTH) |
405 BIT(SIR_MAC_MGMT_DEAUTH) |
406 BIT(SIR_MAC_MGMT_ACTION),
407 },
408};
409
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800410/* Interface limits and combinations registered by the driver */
411
412/* STA ( + STA ) combination */
413static const struct ieee80211_iface_limit
414 wlan_hdd_sta_iface_limit[] = {
415 {
416 .max = 3, /* p2p0 is a STA as well */
417 .types = BIT(NL80211_IFTYPE_STATION),
418 },
419};
420
421/* ADHOC (IBSS) limit */
422static const struct ieee80211_iface_limit
423 wlan_hdd_adhoc_iface_limit[] = {
424 {
425 .max = 1,
426 .types = BIT(NL80211_IFTYPE_STATION),
427 },
428 {
429 .max = 1,
430 .types = BIT(NL80211_IFTYPE_ADHOC),
431 },
432};
433
434/* AP ( + AP ) combination */
435static const struct ieee80211_iface_limit
436 wlan_hdd_ap_iface_limit[] = {
437 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530438 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800439 .types = BIT(NL80211_IFTYPE_AP),
440 },
441};
442
443/* P2P limit */
444static const struct ieee80211_iface_limit
445 wlan_hdd_p2p_iface_limit[] = {
446 {
447 .max = 1,
448 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
449 },
450 {
451 .max = 1,
452 .types = BIT(NL80211_IFTYPE_P2P_GO),
453 },
454};
455
456static const struct ieee80211_iface_limit
457 wlan_hdd_sta_ap_iface_limit[] = {
458 {
459 /* We need 1 extra STA interface for OBSS scan when SAP starts
460 * with HT40 in STA+SAP concurrency mode
461 */
462 .max = (1 + SAP_MAX_OBSS_STA_CNT),
463 .types = BIT(NL80211_IFTYPE_STATION),
464 },
465 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530466 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800467 .types = BIT(NL80211_IFTYPE_AP),
468 },
469};
470
471/* STA + P2P combination */
472static const struct ieee80211_iface_limit
473 wlan_hdd_sta_p2p_iface_limit[] = {
474 {
475 /* One reserved for dedicated P2PDEV usage */
476 .max = 2,
477 .types = BIT(NL80211_IFTYPE_STATION)
478 },
479 {
480 /* Support for two identical (GO + GO or CLI + CLI)
481 * or dissimilar (GO + CLI) P2P interfaces
482 */
483 .max = 2,
484 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
485 },
486};
487
488/* STA + AP + P2PGO combination */
489static const struct ieee80211_iface_limit
490wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
491 /* Support for AP+P2PGO interfaces */
492 {
493 .max = 2,
494 .types = BIT(NL80211_IFTYPE_STATION)
495 },
496 {
497 .max = 1,
498 .types = BIT(NL80211_IFTYPE_P2P_GO)
499 },
500 {
501 .max = 1,
502 .types = BIT(NL80211_IFTYPE_AP)
503 }
504};
505
506/* SAP + P2P combination */
507static const struct ieee80211_iface_limit
508wlan_hdd_sap_p2p_iface_limit[] = {
509 {
510 /* 1 dedicated for p2p0 which is a STA type */
511 .max = 1,
512 .types = BIT(NL80211_IFTYPE_STATION)
513 },
514 {
515 /* The p2p interface in SAP+P2P can be GO/CLI.
516 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
517 */
518 .max = 1,
519 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
520 },
521 {
522 /* SAP+GO to support only one SAP interface */
523 .max = 1,
524 .types = BIT(NL80211_IFTYPE_AP)
525 }
526};
527
528/* P2P + P2P combination */
529static const struct ieee80211_iface_limit
530wlan_hdd_p2p_p2p_iface_limit[] = {
531 {
532 /* 1 dedicated for p2p0 which is a STA type */
533 .max = 1,
534 .types = BIT(NL80211_IFTYPE_STATION)
535 },
536 {
537 /* The p2p interface in P2P+P2P can be GO/CLI.
538 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
539 */
540 .max = 2,
541 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
542 },
543};
544
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700545static const struct ieee80211_iface_limit
546 wlan_hdd_mon_iface_limit[] = {
547 {
548 .max = 3, /* Monitor interface */
549 .types = BIT(NL80211_IFTYPE_MONITOR),
550 },
551};
552
553static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800554 wlan_hdd_iface_combination[] = {
555 /* STA */
556 {
557 .limits = wlan_hdd_sta_iface_limit,
558 .num_different_channels = 2,
559 .max_interfaces = 3,
560 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
561 },
562 /* ADHOC */
563 {
564 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700565 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800566 .max_interfaces = 2,
567 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
568 },
569 /* AP */
570 {
571 .limits = wlan_hdd_ap_iface_limit,
572 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530573 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800574 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
hqu3c4ed3d2017-09-19 11:42:35 +0800575#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
576 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
577 .beacon_int_min_gcd = 1,
578#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800579 },
580 /* P2P */
581 {
582 .limits = wlan_hdd_p2p_iface_limit,
583 .num_different_channels = 2,
584 .max_interfaces = 2,
585 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
586 },
587 /* STA + AP */
588 {
589 .limits = wlan_hdd_sta_ap_iface_limit,
590 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530591 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
593 .beacon_int_infra_match = true,
hqu3c4ed3d2017-09-19 11:42:35 +0800594#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
595 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
596 .beacon_int_min_gcd = 1,
597#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800598 },
599 /* STA + P2P */
600 {
601 .limits = wlan_hdd_sta_p2p_iface_limit,
602 .num_different_channels = 2,
603 /* one interface reserved for P2PDEV dedicated usage */
604 .max_interfaces = 4,
605 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
606 .beacon_int_infra_match = true,
607 },
608 /* STA + P2P GO + SAP */
609 {
610 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
611 /* we can allow 3 channels for three different persona
612 * but due to firmware limitation, allow max 2 concrnt channels.
613 */
614 .num_different_channels = 2,
615 /* one interface reserved for P2PDEV dedicated usage */
616 .max_interfaces = 4,
617 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
618 .beacon_int_infra_match = true,
619 },
620 /* SAP + P2P */
621 {
622 .limits = wlan_hdd_sap_p2p_iface_limit,
623 .num_different_channels = 2,
624 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
625 .max_interfaces = 3,
626 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
627 .beacon_int_infra_match = true,
628 },
629 /* P2P + P2P */
630 {
631 .limits = wlan_hdd_p2p_p2p_iface_limit,
632 .num_different_channels = 2,
633 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
634 .max_interfaces = 3,
635 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
636 .beacon_int_infra_match = true,
637 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530638 /* Monitor */
639 {
640 .limits = wlan_hdd_mon_iface_limit,
641 .max_interfaces = 3,
642 .num_different_channels = 2,
643 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
644 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800645};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800646
647static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800648
649#ifdef WLAN_NL80211_TESTMODE
650enum wlan_hdd_tm_attr {
651 WLAN_HDD_TM_ATTR_INVALID = 0,
652 WLAN_HDD_TM_ATTR_CMD = 1,
653 WLAN_HDD_TM_ATTR_DATA = 2,
654 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
655 WLAN_HDD_TM_ATTR_TYPE = 4,
656 /* keep last */
657 WLAN_HDD_TM_ATTR_AFTER_LAST,
658 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
659};
660
661enum wlan_hdd_tm_cmd {
662 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
663 WLAN_HDD_TM_CMD_WLAN_HB = 1,
664};
665
666#define WLAN_HDD_TM_DATA_MAX_LEN 5000
667
668static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
669 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
670 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
671 .len = WLAN_HDD_TM_DATA_MAX_LEN},
672};
673#endif /* WLAN_NL80211_TESTMODE */
674
Lin Baia016e9a2017-08-29 19:10:42 +0800675enum wlan_hdd_vendor_ie_access_policy {
676 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
677 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
678};
679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
681static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
682 .flags = WIPHY_WOWLAN_MAGIC_PKT,
683 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
684 .pattern_min_len = 1,
685 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
686};
687#endif
688
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800689/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530690 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
691 * @flags: Pointer to the flags to Add channel switch flag.
692 *
693 * This Function adds Channel Switch support flag, if channel switch is
694 * supported by kernel.
695 * Return: void.
696 */
697#ifdef CHANNEL_SWITCH_SUPPORTED
698static inline void hdd_add_channel_switch_support(uint32_t *flags)
699{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800700 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530701}
702#else
703static inline void hdd_add_channel_switch_support(uint32_t *flags)
704{
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530705}
706#endif
707
Manikandan Mohan22b83722015-12-15 15:03:23 -0800708#ifdef FEATURE_WLAN_TDLS
709
710/* TDLS capabilities params */
711#define PARAM_MAX_TDLS_SESSION \
712 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
713#define PARAM_TDLS_FEATURE_SUPPORT \
714 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
715
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530716/**
Jeff Johnson118a4a02018-05-06 00:14:15 -0700717 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800718 * @wiphy: WIPHY structure pointer
719 * @wdev: Wireless device structure pointer
720 * @data: Pointer to the data received
721 * @data_len: Length of the data received
722 *
723 * This function provides TDLS capabilities
724 *
725 * Return: 0 on success and errno on failure
726 */
727static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
728 struct wireless_dev *wdev,
729 const void *data,
730 int data_len)
731{
732 int status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -0700733 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800734 struct sk_buff *skb;
735 uint32_t set = 0;
Frank Liu5c63dc82017-09-07 14:49:05 +0800736 uint32_t max_num_tdls_sta = 0;
Wu Gaobdb7f272018-07-05 19:33:26 +0800737 bool tdls_support;
738 bool tdls_external_control;
739 bool tdls_sleep_sta_enable;
740 bool tdls_buffer_sta;
741 bool tdls_off_channel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800742
Dustin Brownfdf17c12018-03-14 12:55:34 -0700743 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -0800744
Anurag Chouhan6d760662016-02-20 16:05:43 +0530745 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800746 hdd_err("Command not allowed in FTM mode");
747 return -EPERM;
748 }
749
750 status = wlan_hdd_validate_context(hdd_ctx);
751 if (status)
752 return status;
753
754 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
755 NLMSG_HDRLEN);
756 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700757 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800758 goto fail;
759 }
760
Dustin Brown76cd2932018-09-11 16:03:05 -0700761 if ((cfg_tdls_get_support_enable(hdd_ctx->psoc, &tdls_support) ==
Wu Gaobdb7f272018-07-05 19:33:26 +0800762 QDF_STATUS_SUCCESS) && tdls_support) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800763 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
765 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700766 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 goto fail;
768 }
769 } else {
Dustin Brown76cd2932018-09-11 16:03:05 -0700770 cfg_tdls_get_external_control(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800771 &tdls_external_control);
Dustin Brown76cd2932018-09-11 16:03:05 -0700772 cfg_tdls_get_sleep_sta_enable(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800773 &tdls_sleep_sta_enable);
Dustin Brown76cd2932018-09-11 16:03:05 -0700774 cfg_tdls_get_buffer_sta_enable(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800775 &tdls_buffer_sta);
Dustin Brown76cd2932018-09-11 16:03:05 -0700776 cfg_tdls_get_off_channel_enable(hdd_ctx->psoc,
Wu Gaobdb7f272018-07-05 19:33:26 +0800777 &tdls_off_channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800778 set = set | WIFI_TDLS_SUPPORT;
Wu Gaobdb7f272018-07-05 19:33:26 +0800779 set = set | (tdls_external_control ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800780 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
Wu Gaobdb7f272018-07-05 19:33:26 +0800781 set = set | (tdls_off_channel ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Wu Gaobdb7f272018-07-05 19:33:26 +0800783 if (tdls_sleep_sta_enable || tdls_buffer_sta ||
784 tdls_off_channel)
Frank Liu5c63dc82017-09-07 14:49:05 +0800785 max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA_P_UAPSD_OFFCHAN;
786 else
787 max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA;
788
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800789 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
Frank Liu5c63dc82017-09-07 14:49:05 +0800791 max_num_tdls_sta) ||
792 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700793 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800794 goto fail;
795 }
796 }
797 return cfg80211_vendor_cmd_reply(skb);
798fail:
799 if (skb)
800 kfree_skb(skb);
801 return -EINVAL;
802}
803
804/**
Jeff Johnson118a4a02018-05-06 00:14:15 -0700805 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800806 * @wiphy: WIPHY structure pointer
807 * @wdev: Wireless device structure pointer
808 * @data: Pointer to the data received
809 * @data_len: Length of the data received
810 *
811 * This function provides TDLS capabilities
812 *
813 * Return: 0 on success and errno on failure
814 */
815static int
816wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
817 struct wireless_dev *wdev,
818 const void *data,
819 int data_len)
820{
Dustin Brown363b4792019-02-05 16:11:55 -0800821 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -0800822 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +0530823
Dustin Brown363b4792019-02-05 16:11:55 -0800824 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -0800825 if (errno)
826 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800827
Dustin Brownf0f00612019-01-31 16:02:24 -0800828 errno = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
829 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800830
Dustin Brown363b4792019-02-05 16:11:55 -0800831 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -0800832
833 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800834}
jiad7b8a5e02018-11-26 16:37:57 +0800835
836static uint8_t hdd_get_bw_offset(uint32_t ch_width)
837{
838 uint8_t bw_offset = 0;
839
840 if (ch_width == CH_WIDTH_40MHZ)
841 bw_offset = 1 << BW_40_OFFSET_BIT;
842 else if (ch_width == CH_WIDTH_20MHZ)
843 bw_offset = 1 << BW_20_OFFSET_BIT;
844
845 return bw_offset;
846}
847
848#else /* !FEATURE_WLAN_TDLS */
849
850static inline uint8_t hdd_get_bw_offset(uint32_t ch_width)
851{
852 return 0;
853}
854
855#endif /* FEATURE_WLAN_TDLS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800856
857#ifdef QCA_HT_2040_COEX
858static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
859#endif
860
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700861int wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type *destFreqList,
862 struct ch_avoid_ind_type *srcFreqList)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530863{
864 int i;
Jeff Johnson62f28992019-03-05 14:48:42 -0800865 uint32_t room;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700866 struct ch_avoid_freq_type *avoid_range =
867 &destFreqList->avoid_freq_range[destFreqList->ch_avoid_range_cnt];
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530868
Jeff Johnson62f28992019-03-05 14:48:42 -0800869 room = CH_AVOID_MAX_RANGE - destFreqList->ch_avoid_range_cnt;
870 if (srcFreqList->ch_avoid_range_cnt > room) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530871 hdd_err("avoid freq overflow");
872 return -EINVAL;
873 }
Jeff Johnson62f28992019-03-05 14:48:42 -0800874 destFreqList->ch_avoid_range_cnt += srcFreqList->ch_avoid_range_cnt;
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530875
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700876 for (i = 0; i < srcFreqList->ch_avoid_range_cnt; i++) {
877 avoid_range->start_freq =
878 srcFreqList->avoid_freq_range[i].start_freq;
879 avoid_range->end_freq =
880 srcFreqList->avoid_freq_range[i].end_freq;
881 avoid_range++;
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530882 }
883 return 0;
884}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800885/*
886 * FUNCTION: wlan_hdd_send_avoid_freq_event
887 * This is called when wlan driver needs to send vendor specific
888 * avoid frequency range event to userspace
889 */
Jeff Johnsonb8944722017-09-03 09:03:19 -0700890int wlan_hdd_send_avoid_freq_event(struct hdd_context *hdd_ctx,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700891 struct ch_avoid_ind_type *avoid_freq_list)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800892{
893 struct sk_buff *vendor_event;
894
Dustin Brown491d54b2018-03-14 12:39:11 -0700895 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800896
Jeff Johnsonb8944722017-09-03 09:03:19 -0700897 if (!hdd_ctx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700898 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800899 return -EINVAL;
900 }
901
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700902 if (!avoid_freq_list) {
903 hdd_err("avoid_freq_list is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800904 return -EINVAL;
905 }
906
Jeff Johnsonb8944722017-09-03 09:03:19 -0700907 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700908 NULL, sizeof(struct ch_avoid_ind_type),
909 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
910 GFP_KERNEL);
911
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800912 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700913 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914 return -EINVAL;
915 }
916
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700917 memcpy(skb_put(vendor_event, sizeof(struct ch_avoid_ind_type)),
918 (void *)avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800919
920 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
921
Dustin Browne74003f2018-03-14 12:51:58 -0700922 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923 return 0;
924}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800925
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530926/*
927 * define short names for the global vendor params
928 * used by QCA_NL80211_VENDOR_SUBCMD_HANG
929 */
930#define HANG_REASON_INDEX QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX
931
932/**
933 * hdd_convert_hang_reason() - Convert cds recovery reason to vendor specific
934 * hang reason
935 * @reason: cds recovery reason
936 *
937 * Return: Vendor specific reason code
938 */
939static enum qca_wlan_vendor_hang_reason
940hdd_convert_hang_reason(enum qdf_hang_reason reason)
941{
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -0700942 u32 ret_val;
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530943
944 switch (reason) {
945 case QDF_RX_HASH_NO_ENTRY_FOUND:
946 ret_val = QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND;
947 break;
948 case QDF_PEER_DELETION_TIMEDOUT:
949 ret_val = QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT;
950 break;
951 case QDF_PEER_UNMAP_TIMEDOUT:
952 ret_val = QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT;
953 break;
954 case QDF_SCAN_REQ_EXPIRED:
955 ret_val = QCA_WLAN_HANG_SCAN_REQ_EXPIRED;
956 break;
957 case QDF_SCAN_ATTEMPT_FAILURES:
958 ret_val = QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES;
959 break;
960 case QDF_GET_MSG_BUFF_FAILURE:
961 ret_val = QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE;
962 break;
963 case QDF_ACTIVE_LIST_TIMEOUT:
964 ret_val = QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT;
965 break;
966 case QDF_SUSPEND_TIMEOUT:
967 ret_val = QCA_WLAN_HANG_SUSPEND_TIMEOUT;
968 break;
969 case QDF_RESUME_TIMEOUT:
970 ret_val = QCA_WLAN_HANG_RESUME_TIMEOUT;
971 break;
972 case QDF_REASON_UNSPECIFIED:
973 default:
974 ret_val = QCA_WLAN_HANG_REASON_UNSPECIFIED;
975 }
976 return ret_val;
977}
978
979/**
980 * wlan_hdd_send_hang_reason_event() - Send hang reason to the userspace
981 * @hdd_ctx: Pointer to hdd context
982 * @reason: cds recovery reason
983 *
984 * Return: 0 on success or failure reason
985 */
986int wlan_hdd_send_hang_reason_event(struct hdd_context *hdd_ctx,
987 enum qdf_hang_reason reason)
988{
989 struct sk_buff *vendor_event;
990 enum qca_wlan_vendor_hang_reason hang_reason;
991
Dustin Brown491d54b2018-03-14 12:39:11 -0700992 hdd_enter();
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530993
994 if (!hdd_ctx) {
995 hdd_err("HDD context is null");
996 return -EINVAL;
997 }
998
999 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1000 NULL,
1001 sizeof(uint32_t),
1002 HANG_REASON_INDEX,
1003 GFP_KERNEL);
1004 if (!vendor_event) {
1005 hdd_err("cfg80211_vendor_event_alloc failed");
1006 return -ENOMEM;
1007 }
1008
1009 hang_reason = hdd_convert_hang_reason(reason);
1010
1011 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON,
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -07001012 (uint32_t)hang_reason)) {
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301013 hdd_err("QCA_WLAN_VENDOR_ATTR_HANG_REASON put fail");
1014 kfree_skb(vendor_event);
1015 return -EINVAL;
1016 }
1017
1018 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1019
Dustin Browne74003f2018-03-14 12:51:58 -07001020 hdd_exit();
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301021 return 0;
1022}
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -07001023
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301024#undef HANG_REASON_INDEX
1025
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301026/**
1027 * wlan_hdd_get_adjacent_chan(): Gets next/previous channel
1028 * with respect to the channel passed.
1029 * @chan: Channel
1030 * @upper: If "true" then next channel is returned or else
1031 * previous channel is returned.
1032 *
1033 * This function returns the next/previous adjacent-channel to
1034 * the channel passed. If "upper = true" then next channel is
1035 * returned else previous is returned.
1036 */
1037int wlan_hdd_get_adjacent_chan(uint8_t chan, bool upper)
1038{
Ashish Kumar Dhanotiyaaa9fdbb2018-12-14 15:29:14 +05301039 enum channel_enum ch_idx = wlan_reg_get_chan_enum(chan);
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301040
1041 if (ch_idx == INVALID_CHANNEL)
1042 return -EINVAL;
1043
1044 if (upper && (ch_idx < (NUM_CHANNELS - 1)))
1045 ch_idx++;
1046 else if (!upper && (ch_idx > CHAN_ENUM_1))
1047 ch_idx--;
1048 else
1049 return -EINVAL;
1050
1051 return WLAN_REG_CH_NUM(ch_idx);
1052}
1053
1054/**
1055 * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
1056 * avoided when Do_Not_Break_Stream is active.
Jeff Johnsonb8944722017-09-03 09:03:19 -07001057 * @hdd_ctx: HDD Context
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301058 * @op_chan: AP/P2P-GO operating channel
1059 *
1060 * This function sends list of frequencies to be avoided when
1061 * Do_Not_Break_Stream is active.
1062 * To clear the avoid_frequency_list in the application,
1063 * op_chan = 0 can be passed.
1064 *
1065 * Return: 0 on success and errno on failure
1066 */
Jeff Johnsonb8944722017-09-03 09:03:19 -07001067int wlan_hdd_send_avoid_freq_for_dnbs(struct hdd_context *hdd_ctx, uint8_t op_chan)
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301068{
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001069 struct ch_avoid_ind_type p2p_avoid_freq_list;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301070 uint8_t min_chan, max_chan;
1071 int ret;
1072 int chan;
1073
Dustin Brown491d54b2018-03-14 12:39:11 -07001074 hdd_enter();
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301075
Jeff Johnsonb8944722017-09-03 09:03:19 -07001076 if (!hdd_ctx) {
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301077 hdd_err("invalid param");
1078 return -EINVAL;
1079 }
1080
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001081 qdf_mem_zero(&p2p_avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301082 /*
1083 * If channel passed is zero, clear the avoid_freq list in application.
1084 */
1085 if (!op_chan) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301086#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001087 mutex_lock(&hdd_ctx->avoid_freq_lock);
1088 qdf_mem_zero(&hdd_ctx->dnbs_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001089 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001090 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301091 memcpy(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001092 &hdd_ctx->coex_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001093 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001094 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301095#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001096 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx,
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301097 &p2p_avoid_freq_list);
1098 if (ret)
1099 hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
1100 ret);
1101
1102 return ret;
1103 }
1104
1105 if (WLAN_REG_IS_24GHZ_CH(op_chan)) {
Ashish Kumar Dhanotiyaaa9fdbb2018-12-14 15:29:14 +05301106 min_chan = WLAN_REG_MIN_24GHZ_CH_NUM;
1107 max_chan = WLAN_REG_MAX_24GHZ_CH_NUM;
1108 } else if (WLAN_REG_IS_5GHZ_CH(op_chan)) {
1109 min_chan = WLAN_REG_MIN_5GHZ_CH_NUM;
1110 max_chan = WLAN_REG_MAX_5GHZ_CH_NUM;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301111 } else {
1112 hdd_err("invalid channel:%d", op_chan);
1113 return -EINVAL;
1114 }
1115
1116 if ((op_chan > min_chan) && (op_chan < max_chan)) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001117 p2p_avoid_freq_list.ch_avoid_range_cnt = 2;
1118 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301119 wlan_chan_to_freq(min_chan);
1120
1121 /* Get channel before the op_chan */
1122 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1123 if (chan < 0)
1124 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001125 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301126 wlan_chan_to_freq(chan);
1127
1128 /* Get channel next to the op_chan */
1129 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1130 if (chan < 0)
1131 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001132 p2p_avoid_freq_list.avoid_freq_range[1].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301133 wlan_chan_to_freq(chan);
1134
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001135 p2p_avoid_freq_list.avoid_freq_range[1].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301136 wlan_chan_to_freq(max_chan);
1137 } else if (op_chan == min_chan) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001138 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301139
1140 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1141 if (chan < 0)
1142 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001143 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301144 wlan_chan_to_freq(chan);
1145
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001146 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301147 wlan_chan_to_freq(max_chan);
1148 } else {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001149 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
1150 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301151 wlan_chan_to_freq(min_chan);
1152
1153 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1154 if (chan < 0)
1155 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001156 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301157 wlan_chan_to_freq(chan);
1158 }
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301159#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001160 mutex_lock(&hdd_ctx->avoid_freq_lock);
1161 hdd_ctx->dnbs_avoid_freq_list = p2p_avoid_freq_list;
1162 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301163 ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001164 &hdd_ctx->coex_avoid_freq_list);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301165 if (ret) {
Jeff Johnsonb8944722017-09-03 09:03:19 -07001166 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301167 hdd_err("avoid freq merge failed");
1168 return ret;
1169 }
1170 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07001171 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301172#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001173 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx, &p2p_avoid_freq_list);
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301174 if (ret)
1175 hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
1176
1177 return ret;
1178}
1179
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001180/* vendor specific events */
1181static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001182 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
1183 .vendor_id =
1184 QCA_NL80211_VENDOR_ID,
1185 .subcmd =
1186 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
1187 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001188
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001189 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
1190 .vendor_id =
1191 QCA_NL80211_VENDOR_ID,
1192 .subcmd =
1193 QCA_NL80211_VENDOR_SUBCMD_NAN
1194 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001195
1196#ifdef WLAN_FEATURE_STATS_EXT
1197 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
1198 .vendor_id =
1199 QCA_NL80211_VENDOR_ID,
1200 .subcmd =
1201 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
1202 },
1203#endif /* WLAN_FEATURE_STATS_EXT */
1204#ifdef FEATURE_WLAN_EXTSCAN
1205 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
1206 .vendor_id =
1207 QCA_NL80211_VENDOR_ID,
1208 .subcmd =
1209 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
1210 },
1211 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
1212 .vendor_id =
1213 QCA_NL80211_VENDOR_ID,
1214 .subcmd =
1215 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
1216 },
1217 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
1218 .
1219 vendor_id
1220 =
1221 QCA_NL80211_VENDOR_ID,
1222 .subcmd =
1223 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
1224 },
1225 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
1226 .
1227 vendor_id
1228 =
1229 QCA_NL80211_VENDOR_ID,
1230 .
1231 subcmd =
1232 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
1233 },
1234 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
1235 .
1236 vendor_id
1237 =
1238 QCA_NL80211_VENDOR_ID,
1239 .
1240 subcmd
1241 =
1242 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1243 },
1244 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1245 .
1246 vendor_id
1247 =
1248 QCA_NL80211_VENDOR_ID,
1249 .subcmd =
1250 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1251 },
1252 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1253 .vendor_id =
1254 QCA_NL80211_VENDOR_ID,
1255 .subcmd =
1256 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1257 },
1258 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1259 .
1260 vendor_id
1261 =
1262 QCA_NL80211_VENDOR_ID,
1263 .subcmd =
1264 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1265 },
1266 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1267 .
1268 vendor_id
1269 =
1270 QCA_NL80211_VENDOR_ID,
1271 .subcmd =
1272 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1273 },
1274 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1275 .
1276 vendor_id
1277 =
1278 QCA_NL80211_VENDOR_ID,
1279 .
1280 subcmd
1281 =
1282 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1283 },
1284 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1285 .
1286 vendor_id
1287 =
1288 QCA_NL80211_VENDOR_ID,
1289 .
1290 subcmd =
1291 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1292 },
1293 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1294 .
1295 vendor_id
1296 =
1297 QCA_NL80211_VENDOR_ID,
1298 .
1299 subcmd
1300 =
1301 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
1302 },
1303 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
1304 .
1305 vendor_id
1306 =
1307 QCA_NL80211_VENDOR_ID,
1308 .
1309 subcmd
1310 =
1311 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
1312 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001313#endif /* FEATURE_WLAN_EXTSCAN */
1314
1315#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1316 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
1317 .vendor_id =
1318 QCA_NL80211_VENDOR_ID,
1319 .subcmd =
1320 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
1321 },
1322 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
1323 .vendor_id =
1324 QCA_NL80211_VENDOR_ID,
1325 .subcmd =
1326 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
1327 },
1328 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
1329 .vendor_id =
1330 QCA_NL80211_VENDOR_ID,
1331 .subcmd =
1332 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
1333 },
1334 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
1335 .vendor_id =
1336 QCA_NL80211_VENDOR_ID,
1337 .subcmd =
1338 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
1339 },
1340 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
1341 .vendor_id =
1342 QCA_NL80211_VENDOR_ID,
1343 .subcmd =
1344 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
1345 },
1346 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
1347 .vendor_id =
1348 QCA_NL80211_VENDOR_ID,
1349 .subcmd =
1350 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
1351 },
Zhang Qianca38fb12016-12-23 11:10:48 +08001352 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
1353 .vendor_id =
1354 QCA_NL80211_VENDOR_ID,
1355 .subcmd =
1356 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
1357 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001358#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1359 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1360 .vendor_id =
1361 QCA_NL80211_VENDOR_ID,
1362 .subcmd =
1363 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1364 },
1365 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1366 .vendor_id = QCA_NL80211_VENDOR_ID,
1367 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1368 },
1369#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1370 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1371 .vendor_id =
1372 QCA_NL80211_VENDOR_ID,
1373 .subcmd =
1374 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1375 },
1376#endif
1377 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1378 .vendor_id =
1379 QCA_NL80211_VENDOR_ID,
1380 .subcmd =
1381 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1382 },
1383 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1384 .vendor_id =
1385 QCA_NL80211_VENDOR_ID,
1386 .subcmd =
1387 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1388 },
1389 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1390 .vendor_id =
1391 QCA_NL80211_VENDOR_ID,
1392 .subcmd =
1393 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1394 },
1395 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1396 .vendor_id =
1397 QCA_NL80211_VENDOR_ID,
1398 .subcmd =
1399 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1400 },
1401 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1402 .vendor_id =
1403 QCA_NL80211_VENDOR_ID,
1404 .subcmd =
1405 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1406 },
1407#ifdef FEATURE_WLAN_EXTSCAN
1408 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1409 .vendor_id = QCA_NL80211_VENDOR_ID,
1410 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1411 },
1412 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1413 .vendor_id = QCA_NL80211_VENDOR_ID,
1414 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1415 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001416 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1417 .vendor_id = QCA_NL80211_VENDOR_ID,
1418 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1419 },
1420#endif /* FEATURE_WLAN_EXTSCAN */
Qiwei Caie689a262018-07-26 15:50:22 +08001421
1422 FEATURE_RSSI_MONITOR_VENDOR_EVENTS
1423
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001424#ifdef WLAN_FEATURE_TSF
1425 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1426 .vendor_id = QCA_NL80211_VENDOR_ID,
1427 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1428 },
1429#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001430 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1431 .vendor_id = QCA_NL80211_VENDOR_ID,
1432 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1433 },
1434 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1435 .vendor_id = QCA_NL80211_VENDOR_ID,
1436 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1437 },
1438 /* OCB events */
1439 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1440 .vendor_id = QCA_NL80211_VENDOR_ID,
1441 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1442 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001443#ifdef FEATURE_LFR_SUBNET_DETECTION
1444 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1445 .vendor_id = QCA_NL80211_VENDOR_ID,
1446 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1447 },
1448#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001449
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001450 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1451 .vendor_id = QCA_NL80211_VENDOR_ID,
1452 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1453 },
Peng Xu8fdaa492016-06-22 10:20:47 -07001454
1455 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1456 .vendor_id = QCA_NL80211_VENDOR_ID,
1457 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1458 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301459 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1460 .vendor_id = QCA_NL80211_VENDOR_ID,
1461 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1462 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301463 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1464 .vendor_id = QCA_NL80211_VENDOR_ID,
1465 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1466 },
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05301467 [QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX] = {
1468 .vendor_id = QCA_NL80211_VENDOR_ID,
1469 .subcmd = QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE
Anurag Chouhan3920c0f2017-09-11 17:10:56 +05301470 },
1471 [QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX] = {
1472 .vendor_id = QCA_NL80211_VENDOR_ID,
1473 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
1474 },
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301475 [QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX] = {
1476 .vendor_id = QCA_NL80211_VENDOR_ID,
1477 .subcmd = QCA_NL80211_VENDOR_SUBCMD_HANG,
1478 },
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +05301479 [QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX] = {
1480 .vendor_id = QCA_NL80211_VENDOR_ID,
1481 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO,
1482 },
Alok Kumar2fad6442018-11-08 19:19:28 +05301483 [QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT_INDEX] = {
1484 .vendor_id = QCA_NL80211_VENDOR_ID,
1485 .subcmd = QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT,
1486 },
Nachiket Kukadea6a70a92018-10-09 20:07:21 +05301487 [QCA_NL80211_VENDOR_SUBCMD_NAN_EXT_INDEX] = {
1488 .vendor_id = QCA_NL80211_VENDOR_ID,
1489 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN_EXT
1490 },
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +05301491 [QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX] = {
1492 .vendor_id = QCA_NL80211_VENDOR_ID,
1493 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
1494 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001495#ifdef WLAN_UMAC_CONVERGENCE
1496 COMMON_VENDOR_EVENTS
1497#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001498};
1499
1500/**
1501 * __is_driver_dfs_capable() - get driver DFS capability
1502 * @wiphy: pointer to wireless wiphy structure.
1503 * @wdev: pointer to wireless_dev structure.
1504 * @data: Pointer to the data to be passed via vendor interface
1505 * @data_len:Length of the data to be passed
1506 *
1507 * This function is called by userspace to indicate whether or not
1508 * the driver supports DFS offload.
1509 *
1510 * Return: 0 on success, negative errno on failure
1511 */
1512static int __is_driver_dfs_capable(struct wiphy *wiphy,
1513 struct wireless_dev *wdev,
1514 const void *data,
1515 int data_len)
1516{
1517 u32 dfs_capability = 0;
1518 struct sk_buff *temp_skbuff;
1519 int ret_val;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001520 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001521
Dustin Brownfdf17c12018-03-14 12:55:34 -07001522 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001523
1524 ret_val = wlan_hdd_validate_context(hdd_ctx);
1525 if (ret_val)
1526 return ret_val;
1527
Anurag Chouhan6d760662016-02-20 16:05:43 +05301528 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001529 hdd_err("Command not allowed in FTM mode");
1530 return -EPERM;
1531 }
1532
Peng Xu8e8b0392018-04-30 11:32:34 -07001533#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
1534 defined(CFG80211_DFS_OFFLOAD_BACKPORT)
1535 dfs_capability =
1536 wiphy_ext_feature_isset(wiphy,
1537 NL80211_EXT_FEATURE_DFS_OFFLOAD);
1538#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001539 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Peng Xu8e8b0392018-04-30 11:32:34 -07001540#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541
1542 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1543 NLMSG_HDRLEN);
1544
1545 if (temp_skbuff != NULL) {
1546 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1547 dfs_capability);
1548 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001549 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001550 kfree_skb(temp_skbuff);
1551
1552 return ret_val;
1553 }
1554
1555 return cfg80211_vendor_cmd_reply(temp_skbuff);
1556 }
1557
Jeff Johnson020db452016-06-29 14:37:26 -07001558 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001559 return -ENOMEM;
1560}
1561
1562/**
1563 * is_driver_dfs_capable() - get driver DFS capability
1564 * @wiphy: pointer to wireless wiphy structure.
1565 * @wdev: pointer to wireless_dev structure.
1566 * @data: Pointer to the data to be passed via vendor interface
1567 * @data_len:Length of the data to be passed
1568 *
1569 * This function is called by userspace to indicate whether or not
1570 * the driver supports DFS offload. This is an SSR-protected
1571 * wrapper function.
1572 *
1573 * Return: 0 on success, negative errno on failure
1574 */
1575static int is_driver_dfs_capable(struct wiphy *wiphy,
1576 struct wireless_dev *wdev,
1577 const void *data,
1578 int data_len)
1579{
Dustin Brown363b4792019-02-05 16:11:55 -08001580 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08001581 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05301582
Dustin Brown363b4792019-02-05 16:11:55 -08001583 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001584 if (errno)
1585 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001586
Dustin Brownf0f00612019-01-31 16:02:24 -08001587 errno = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001588
Dustin Brown363b4792019-02-05 16:11:55 -08001589 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001590
1591 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001592}
1593
1594/**
1595 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1596 *
1597 * @adapter: SAP adapter pointer
1598 *
1599 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1600 * radio. So in case of DFS MCC scenario override current SAP given config
1601 * to follow concurrent SAP DFS config
1602 *
1603 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1604 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001605int wlan_hdd_sap_cfg_dfs_override(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001606{
Jeff Johnsone5006672017-08-29 14:39:02 -07001607 struct hdd_adapter *con_sap_adapter;
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001608 tsap_config_t *sap_config, *con_sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001609 int con_ch;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001610 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001611
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001612 if (!hdd_ctx) {
1613 hdd_err("hdd context is NULL");
1614 return 0;
1615 }
1616
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001617 /*
1618 * Check if AP+AP case, once primary AP chooses a DFS
1619 * channel secondary AP should always follow primary APs channel
1620 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001621 if (!policy_mgr_concurrent_beaconing_sessions_running(
Dustin Brown76cd2932018-09-11 16:03:05 -07001622 hdd_ctx->psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001623 return 0;
1624
1625 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1626 if (!con_sap_adapter)
1627 return 0;
1628
Jeff Johnsonb9424862017-10-30 08:49:35 -07001629 sap_config = &adapter->session.ap.sap_config;
1630 con_sap_config = &con_sap_adapter->session.ap.sap_config;
1631 con_ch = con_sap_adapter->session.ap.operating_channel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001632
Dustin Brown07901ec2018-09-07 11:02:41 -07001633 if (!wlan_reg_is_dfs_ch(hdd_ctx->pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001634 return 0;
1635
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001636 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001637 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001638 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001639 sap_config->channel = con_ch;
1640
1641 if (con_sap_config->acs_cfg.acs_mode == true) {
1642 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1643 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001644 hdd_err("Primary AP channel config error");
1645 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001646 con_ch, con_sap_config->acs_cfg.pri_ch,
1647 con_sap_config->acs_cfg.ht_sec_ch);
1648 return -EINVAL;
1649 }
1650 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1651 * MCC restriction. So free ch list allocated in do_acs
1652 * func for Sec AP and realloc for Pri AP ch list size
1653 */
1654 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301655 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001656
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301657 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001658 &con_sap_config->acs_cfg,
1659 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301660 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001661 sizeof(uint8_t) *
1662 con_sap_config->acs_cfg.ch_list_count);
Min Liu74a1a502018-10-10 19:59:07 +08001663 if (!sap_config->acs_cfg.ch_list)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001664 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001665
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301666 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001667 con_sap_config->acs_cfg.ch_list,
1668 con_sap_config->acs_cfg.ch_list_count);
1669
1670 } else {
1671 sap_config->acs_cfg.pri_ch = con_ch;
1672 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1673 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1674 }
1675
1676 return con_ch;
1677}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001678
1679/**
wadesong1795e142018-01-05 11:13:07 +08001680 * wlan_hdd_set_acs_ch_range : Populate ACS hw mode and channel range values
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001681 * @sap_cfg: pointer to SAP config struct
wadesong1795e142018-01-05 11:13:07 +08001682 * @hw_mode: hw mode retrieved from vendor command buffer
1683 * @ht_enabled: whether HT phy mode is enabled
1684 * @vht_enabled: whether VHT phy mode is enabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001685 *
wadesong1795e142018-01-05 11:13:07 +08001686 * This function populates the ACS hw mode based on the configuration retrieved
1687 * from the vendor command buffer; and sets ACS start and end channel for the
1688 * given band.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001689 *
wadesong1795e142018-01-05 11:13:07 +08001690 * Return: 0 if success; -EINVAL if ACS channel list is NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001691 */
wadesong1795e142018-01-05 11:13:07 +08001692static int wlan_hdd_set_acs_ch_range(
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001693 tsap_config_t *sap_cfg, enum qca_wlan_vendor_acs_hw_mode hw_mode,
wadesong1795e142018-01-05 11:13:07 +08001694 bool ht_enabled, bool vht_enabled)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001695{
1696 int i;
Srinivas Girigowda576b2352017-08-25 14:44:26 -07001697
wadesong1795e142018-01-05 11:13:07 +08001698 if (hw_mode == QCA_ACS_MODE_IEEE80211B) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001699 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001700 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1701 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
wadesong1795e142018-01-05 11:13:07 +08001702 } else if (hw_mode == QCA_ACS_MODE_IEEE80211G) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001703 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001704 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1705 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
wadesong1795e142018-01-05 11:13:07 +08001706 } else if (hw_mode == QCA_ACS_MODE_IEEE80211A) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001707 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001708 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07001709 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_173);
wadesong1795e142018-01-05 11:13:07 +08001710 } else if (hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001711 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001712 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07001713 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_173);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001714 }
1715
1716 if (ht_enabled)
1717 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1718
1719 if (vht_enabled)
1720 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1721
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001722 /* Parse ACS Chan list from hostapd */
1723 if (!sap_cfg->acs_cfg.ch_list)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301724 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001725
1726 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1727 sap_cfg->acs_cfg.end_ch =
1728 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1729 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301730 /* avoid channel as start channel */
1731 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1732 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001733 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1734 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1735 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1736 }
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301737
1738 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001739}
1740
1741
1742static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1743
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301744
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001745static void hdd_update_acs_channel_list(tsap_config_t *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001746 enum band_info band)
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301747{
1748 int i, temp_count = 0;
1749 int acs_list_count = sap_config->acs_cfg.ch_list_count;
1750
1751 for (i = 0; i < acs_list_count; i++) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001752 if (BAND_2G == band) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301753 if (WLAN_REG_IS_24GHZ_CH(
1754 sap_config->acs_cfg.ch_list[i])) {
1755 sap_config->acs_cfg.ch_list[temp_count] =
1756 sap_config->acs_cfg.ch_list[i];
1757 temp_count++;
1758 }
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001759 } else if (BAND_5G == band) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301760 if (WLAN_REG_IS_5GHZ_CH(
1761 sap_config->acs_cfg.ch_list[i])) {
1762 sap_config->acs_cfg.ch_list[temp_count] =
1763 sap_config->acs_cfg.ch_list[i];
1764 temp_count++;
1765 }
1766 }
1767 }
1768 sap_config->acs_cfg.ch_list_count = temp_count;
1769}
1770
1771
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001772/**
1773 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1774 * @adapter: pointer to SAP adapter struct
1775 *
1776 * This function starts the ACS procedure if there are no
1777 * constraints like MBSSID DFS restrictions.
1778 *
1779 * Return: Status of ACS Start procedure
1780 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001781int wlan_hdd_cfg80211_start_acs(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001782{
1783
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001784 struct hdd_context *hdd_ctx;
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001785 tsap_config_t *sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001786 tpWLAN_SAPEventCB acs_event_callback;
Krunal Soni5e3f9622018-09-26 16:35:50 -07001787 uint8_t mcc_to_scc_switch = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001788 int status;
1789
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001790 if (!adapter) {
Jeff Johnsondd2f1fc2018-05-06 11:22:52 -07001791 hdd_err("adapter is NULL");
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001792 return -EINVAL;
1793 }
1794 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Ashish Kumar Dhanotiyadc3900f2019-01-11 20:42:04 +05301795 status = wlan_hdd_validate_context(hdd_ctx);
1796 if (0 != status)
1797 return status;
1798
Jeff Johnsonb9424862017-10-30 08:49:35 -07001799 sap_config = &adapter->session.ap.sap_config;
Ashish Kumar Dhanotiyab0629622018-09-21 18:58:59 +05301800 if (!sap_config) {
1801 hdd_err("SAP config is NULL");
1802 return -EINVAL;
1803 }
Agrawal Ashish65634612016-08-18 13:24:32 +05301804 if (hdd_ctx->acs_policy.acs_channel)
1805 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1806 else
1807 sap_config->channel = AUTO_CHANNEL_SELECT;
Krunal Soni5e3f9622018-09-26 16:35:50 -07001808 ucfg_policy_mgr_get_mcc_scc_switch(hdd_ctx->psoc,
1809 &mcc_to_scc_switch);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301810 /*
1811 * No DFS SCC is allowed in Auto use case. Hence not
1812 * calling DFS override
1813 */
1814 if (QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION !=
Krunal Soni5e3f9622018-09-26 16:35:50 -07001815 mcc_to_scc_switch) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301816 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1817 if (status < 0)
1818 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001819
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301820 if (status > 0) {
1821 /*notify hostapd about channel override */
1822 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1823 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1824 return 0;
1825 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826 }
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301827 /* When first 2 connections are on the same frequency band,
1828 * then PCL would include only channels from the other
1829 * frequency band on which no connections are active
1830 */
Dustin Brown76cd2932018-09-11 16:03:05 -07001831 if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301832 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
1833 struct policy_mgr_conc_connection_info *conc_connection_info;
1834 uint32_t i;
Jeff Johnson68755312017-02-10 11:46:55 -08001835
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301836 conc_connection_info = policy_mgr_get_conn_info(&i);
1837 if (conc_connection_info[0].mac ==
1838 conc_connection_info[1].mac) {
1839 if (WLAN_REG_IS_5GHZ_CH(sap_config->acs_cfg.
1840 pcl_channels[0])) {
1841 sap_config->acs_cfg.band =
1842 QCA_ACS_MODE_IEEE80211A;
1843 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001844 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301845 } else {
1846 sap_config->acs_cfg.band =
1847 QCA_ACS_MODE_IEEE80211G;
1848 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001849 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301850 }
1851 }
1852 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001853 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1854 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001855 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001856 return -EINVAL;
1857 }
1858
1859 acs_event_callback = hdd_hostapd_sap_event_cb;
1860
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301861 qdf_mem_copy(sap_config->self_macaddr.bytes,
Jeff Johnson1e851a12017-10-28 14:36:12 -07001862 adapter->mac_addr.bytes, sizeof(struct qdf_mac_addr));
Dustin Brown5e89ef82018-03-14 11:50:23 -07001863 hdd_info("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001864 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001865 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001866 acs_event_callback, sap_config, adapter->dev);
1867
1868
1869 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001870 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001871 return -EINVAL;
1872 }
bings394afdd2017-01-09 11:22:38 +08001873 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1874 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001875 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1876
1877 return 0;
1878}
1879
1880/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301881 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1882 * @hdd_ctx: hdd context
1883 * @acs_chan_params: external acs channel params
1884 * @sap_config: SAP config
1885 *
1886 * This API provides unsorted pcl list.
1887 * this list is a subset of the valid channel list given by hostapd.
1888 * if channel is not present in pcl, weightage will be given as zero
1889 *
1890 * Return: Zero on success, non-zero on failure
1891 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001892static void hdd_update_vendor_pcl_list(struct hdd_context *hdd_ctx,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301893 struct hdd_vendor_acs_chan_params *acs_chan_params,
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001894 tsap_config_t *sap_config)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301895{
1896 int i, j;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301897 /*
1898 * PCL shall contain only the preferred channels from the
1899 * application. If those channels are not present in the
1900 * driver PCL, then set the weight to zero
1901 */
1902 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1903 acs_chan_params->vendor_pcl_list[i] =
1904 sap_config->acs_cfg.ch_list[i];
1905 acs_chan_params->vendor_weight_list[i] = 0;
1906 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1907 if (sap_config->acs_cfg.ch_list[i] ==
1908 sap_config->acs_cfg.pcl_channels[j]) {
1909 acs_chan_params->vendor_weight_list[i] =
1910 sap_config->
1911 acs_cfg.pcl_channels_weight_list[j];
1912 break;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301913 }
1914 }
1915 }
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301916 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301917}
1918
1919/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301920 * hdd_update_reg_chan_info : This API contructs channel info
1921 * for all the given channel
1922 * @adapter: pointer to SAP adapter struct
1923 * @channel_count: channel count
1924 * @channel_list: channel list
1925 *
1926 * Return: Status of of channel information updation
1927 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001928static int hdd_update_reg_chan_info(struct hdd_adapter *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301929 uint32_t channel_count,
1930 uint8_t *channel_list)
1931{
1932 int i;
1933 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001934 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301935 uint8_t bw_offset = 0, chan = 0;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001936 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001937 tsap_config_t *sap_config = &adapter->session.ap.sap_config;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07001938 mac_handle_t mac_handle;
Vignesh Viswanathana1f3a1a2018-10-04 13:10:46 +05301939 uint8_t sub_20_chan_width = 0;
1940 QDF_STATUS status;
Kapil Gupta086c6202016-12-11 18:17:06 +05301941
Jeff Johnson34fc63a2018-06-14 10:10:02 -07001942 mac_handle = hdd_ctx->mac_handle;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301943 sap_config->channel_info_count = channel_count;
Vignesh Viswanathana1f3a1a2018-10-04 13:10:46 +05301944
1945 status = ucfg_mlme_get_sub_20_chan_width(hdd_ctx->psoc,
1946 &sub_20_chan_width);
1947 if (QDF_IS_STATUS_ERROR(status))
1948 hdd_err("Failed to get sub_20_chan_width config");
1949
Kapil Gupta086c6202016-12-11 18:17:06 +05301950 for (i = 0; i < channel_count; i++) {
1951 icv = &sap_config->channel_info[i];
1952 chan = channel_list[i];
1953
1954 if (chan == 0)
1955 continue;
1956
Dustin Brown07901ec2018-09-07 11:02:41 -07001957 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301958 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001959 icv->max_reg_power = wlan_reg_get_channel_reg_power(
Dustin Brown07901ec2018-09-07 11:02:41 -07001960 hdd_ctx->pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301961
1962 /* filling demo values */
1963 icv->max_radio_power = HDD_MAX_TX_POWER;
1964 icv->min_radio_power = HDD_MIN_TX_POWER;
1965 /* not supported in current driver */
1966 icv->max_antenna_gain = 0;
1967
jiad7b8a5e02018-11-26 16:37:57 +08001968 bw_offset = hdd_get_bw_offset(sap_config->acs_cfg.ch_width);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07001969 icv->reg_class_id =
1970 wlan_hdd_find_opclass(mac_handle, chan, bw_offset);
Kapil Gupta086c6202016-12-11 18:17:06 +05301971
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001972 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301973 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Dustin Brown07901ec2018-09-07 11:02:41 -07001974 wlan_reg_set_channel_params(hdd_ctx->pdev, chan,
1975 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301976 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1977 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1978 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001979
Kapil Gupta086c6202016-12-11 18:17:06 +05301980 icv->flags = 0;
Dustin Brown07901ec2018-09-07 11:02:41 -07001981 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301982 sap_config->acs_cfg.ch_width,
1983 sap_config->acs_cfg.is_ht_enabled,
1984 sap_config->acs_cfg.is_vht_enabled,
Vignesh Viswanathana1f3a1a2018-10-04 13:10:46 +05301985 sub_20_chan_width);
Kapil Guptac1224bf2017-06-22 21:22:40 +05301986 if (icv->flags & IEEE80211_CHAN_PASSIVE)
1987 icv->flagext |= IEEE80211_CHAN_DFS;
Kapil Gupta086c6202016-12-11 18:17:06 +05301988
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +05301989 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 +05301990 icv->freq, icv->flags,
1991 icv->flagext, icv->ieee_chan_number,
1992 icv->max_reg_power, icv->max_radio_power,
1993 icv->min_radio_power, icv->reg_class_id,
1994 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1995 icv->vht_center_freq_seg1);
1996 }
1997 return 0;
1998}
1999
2000/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
2001#define CHAN_INFO_ATTR_FLAGS \
2002 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
2003#define CHAN_INFO_ATTR_FLAG_EXT \
2004 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
2005#define CHAN_INFO_ATTR_FREQ \
2006 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
2007#define CHAN_INFO_ATTR_MAX_REG_POWER \
2008 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
2009#define CHAN_INFO_ATTR_MAX_POWER \
2010 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
2011#define CHAN_INFO_ATTR_MIN_POWER \
2012 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
2013#define CHAN_INFO_ATTR_REG_CLASS_ID \
2014 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
2015#define CHAN_INFO_ATTR_ANTENNA_GAIN \
2016 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
2017#define CHAN_INFO_ATTR_VHT_SEG_0 \
2018 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
2019#define CHAN_INFO_ATTR_VHT_SEG_1 \
2020 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
2021
2022/**
2023 * hdd_cfg80211_update_channel_info() - add channel info attributes
2024 * @skb: pointer to sk buff
2025 * @hdd_ctx: pointer to hdd station context
2026 * @idx: attribute index
2027 *
2028 * Return: Success(0) or reason code for failure
2029 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05302030static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05302031hdd_cfg80211_update_channel_info(struct sk_buff *skb,
Jeff Johnsone4c11db2018-05-05 23:22:32 -07002032 tsap_config_t *sap_config, int idx)
Kapil Gupta086c6202016-12-11 18:17:06 +05302033{
2034 struct nlattr *nla_attr, *channel;
2035 struct hdd_channel_info *icv;
2036 int i;
2037
2038 nla_attr = nla_nest_start(skb, idx);
2039 if (!nla_attr)
2040 goto fail;
2041
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302042 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05302043 channel = nla_nest_start(skb, i);
2044 if (!channel)
2045 goto fail;
2046
2047 icv = &sap_config->channel_info[i];
2048 if (!icv) {
2049 hdd_err("channel info not found");
2050 goto fail;
2051 }
2052 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
2053 icv->freq) ||
2054 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
2055 icv->flags) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302056 nla_put_u32(skb, CHAN_INFO_ATTR_FLAG_EXT,
Kapil Gupta086c6202016-12-11 18:17:06 +05302057 icv->flagext) ||
2058 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
2059 icv->max_reg_power) ||
2060 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
2061 icv->max_radio_power) ||
2062 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
2063 icv->min_radio_power) ||
2064 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
2065 icv->reg_class_id) ||
2066 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
2067 icv->max_antenna_gain) ||
2068 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
2069 icv->vht_center_freq_seg0) ||
2070 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
2071 icv->vht_center_freq_seg1)) {
2072 hdd_err("put fail");
2073 goto fail;
2074 }
2075 nla_nest_end(skb, channel);
2076 }
2077 nla_nest_end(skb, nla_attr);
2078 return 0;
2079fail:
2080 hdd_err("nl channel update failed");
2081 return -EINVAL;
2082}
2083#undef CHAN_INFO_ATTR_FLAGS
2084#undef CHAN_INFO_ATTR_FLAG_EXT
2085#undef CHAN_INFO_ATTR_FREQ
2086#undef CHAN_INFO_ATTR_MAX_REG_POWER
2087#undef CHAN_INFO_ATTR_MAX_POWER
2088#undef CHAN_INFO_ATTR_MIN_POWER
2089#undef CHAN_INFO_ATTR_REG_CLASS_ID
2090#undef CHAN_INFO_ATTR_ANTENNA_GAIN
2091#undef CHAN_INFO_ATTR_VHT_SEG_0
2092#undef CHAN_INFO_ATTR_VHT_SEG_1
2093
2094/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05302095 * hdd_cfg80211_update_pcl() - add pcl info attributes
2096 * @skb: pointer to sk buff
2097 * @hdd_ctx: pointer to hdd station context
2098 * @idx: attribute index
2099 * @vendor_pcl_list: PCL list
2100 * @vendor_weight_list: PCL weights
2101 *
2102 * Return: Success(0) or reason code for failure
2103 */
2104static int32_t
2105hdd_cfg80211_update_pcl(struct sk_buff *skb,
2106 uint8_t ch_list_count, int idx,
2107 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
2108{
2109 struct nlattr *nla_attr, *channel;
2110 int i;
2111
2112 nla_attr = nla_nest_start(skb, idx);
2113
2114 if (!nla_attr)
2115 goto fail;
2116
2117 for (i = 0; i < ch_list_count; i++) {
2118 channel = nla_nest_start(skb, i);
2119 if (!channel)
2120 goto fail;
Kapil Gupta63e75282017-05-18 20:55:10 +05302121 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302122 vendor_pcl_list[i]) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302123 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302124 vendor_weight_list[i])) {
2125 hdd_err("put fail");
2126 goto fail;
2127 }
2128 nla_nest_end(skb, channel);
2129 }
2130 nla_nest_end(skb, nla_attr);
2131
2132 return 0;
2133fail:
2134 hdd_err("updating pcl list failed");
2135 return -EINVAL;
2136}
2137
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002138static void hdd_get_scan_band(struct hdd_context *hdd_ctx,
Jeff Johnsone4c11db2018-05-05 23:22:32 -07002139 tsap_config_t *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002140 enum band_info *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302141{
2142 /* Get scan band */
Kapil Guptac1224bf2017-06-22 21:22:40 +05302143 if ((sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211B) ||
2144 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211G)) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002145 *band = BAND_2G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302146 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002147 *band = BAND_5G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302148 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002149 *band = BAND_ALL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302150 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302151}
2152
Kapil Gupta63e75282017-05-18 20:55:10 +05302153
2154/**
2155 * hdd_get_freq_list: API to get Frequency list based on channel list
2156 * @channel_list: channel list
2157 * @freq_list: frequency list
2158 * @channel_count: channel count
2159 *
2160 * Return: None
2161 */
2162static void hdd_get_freq_list(uint8_t *channel_list, uint32_t *freq_list,
2163 uint32_t channel_count)
2164{
2165 int count;
2166
2167 for (count = 0; count < channel_count ; count++)
2168 freq_list[count] = cds_chan_to_freq(channel_list[count]);
2169}
2170
Qiwei Caie689a262018-07-26 15:50:22 +08002171/**
2172 * wlan_hdd_sap_get_valid_channellist() - Get SAPs valid channel list
2173 * @ap_adapter: adapter
2174 * @channel_count: valid channel count
2175 * @channel_list: valid channel list
2176 * @band: frequency band
2177 *
2178 * This API returns valid channel list for SAP after removing nol and
2179 * channel which lies outside of configuration.
2180 *
2181 * Return: Zero on success, non-zero on failure
2182 */
2183static int wlan_hdd_sap_get_valid_channellist(struct hdd_adapter *adapter,
2184 uint32_t *channel_count,
2185 uint8_t *channel_list,
2186 enum band_info band)
2187{
2188 tsap_config_t *sap_config;
2189 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2190 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
2191 uint32_t chan_count;
2192 uint8_t i;
2193 QDF_STATUS status;
Dustin Brown07901ec2018-09-07 11:02:41 -07002194 struct wlan_objmgr_pdev *pdev = hdd_ctx->pdev;
Qiwei Caie689a262018-07-26 15:50:22 +08002195 uint8_t tmp_chan;
2196
2197 sap_config = &adapter->session.ap.sap_config;
2198
2199 status =
Dustin Brown76cd2932018-09-11 16:03:05 -07002200 policy_mgr_get_valid_chans(hdd_ctx->psoc,
Qiwei Caie689a262018-07-26 15:50:22 +08002201 tmp_chan_list,
2202 &chan_count);
2203 if (QDF_IS_STATUS_ERROR(status)) {
2204 hdd_err("Failed to get channel list");
2205 return -EINVAL;
2206 }
2207
2208 for (i = 0; i < chan_count; i++) {
2209 tmp_chan = tmp_chan_list[i];
2210 if (*channel_count < QDF_MAX_NUM_CHAN) {
2211 if ((band == BAND_2G) &&
2212 (WLAN_REG_IS_24GHZ_CH(tmp_chan)) &&
2213 (!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
2214 channel_list[*channel_count] = tmp_chan;
2215 *channel_count += 1;
2216 } else if ((band == BAND_5G) &&
2217 (WLAN_REG_IS_5GHZ_CH(tmp_chan)) &&
2218 (!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
2219 channel_list[*channel_count] = tmp_chan;
2220 *channel_count += 1;
2221 }
2222 } else {
2223 break;
2224 }
2225 }
2226
2227 if (*channel_count == 0) {
2228 hdd_err("no valid channel found");
2229 return -EINVAL;
2230 }
2231
2232 return 0;
2233}
2234
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302235int hdd_cfg80211_update_acs_config(struct hdd_adapter *adapter,
2236 uint8_t reason)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302237{
2238 struct sk_buff *skb;
Jeff Johnsone4c11db2018-05-05 23:22:32 -07002239 tsap_config_t *sap_config;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302240 uint32_t channel_count = 0, status = -EINVAL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302241 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
Kapil Gupta63e75282017-05-18 20:55:10 +05302242 uint32_t freq_list[QDF_MAX_NUM_CHAN] = {0};
Kapil Gupta8878ad92017-02-13 11:56:04 +05302243 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
2244 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
2245 struct hdd_vendor_acs_chan_params acs_chan_params;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002246 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002247 enum band_info band = BAND_2G;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302248 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302249 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
2250 uint32_t i;
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002251 QDF_STATUS qdf_status;
2252 bool is_external_acs_policy = cfg_default(CFG_EXTERNAL_ACS_POLICY);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302253
Kapil Gupta8878ad92017-02-13 11:56:04 +05302254 if (!hdd_ctx) {
2255 hdd_err("HDD context is NULL");
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302256 return -EINVAL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302257 }
2258
Dustin Brown491d54b2018-03-14 12:39:11 -07002259 hdd_enter();
Jeff Johnsonb9424862017-10-30 08:49:35 -07002260 sap_config = &adapter->session.ap.sap_config;
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302261 /* When first 2 connections are on the same frequency band,
2262 * then PCL would include only channels from the other
2263 * frequency band on which no connections are active
2264 */
Dustin Brown76cd2932018-09-11 16:03:05 -07002265 if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302266 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
2267 struct policy_mgr_conc_connection_info *conc_connection_info;
2268
2269 conc_connection_info = policy_mgr_get_conn_info(&i);
2270 if (conc_connection_info[0].mac ==
2271 conc_connection_info[1].mac) {
2272
2273 if (WLAN_REG_IS_5GHZ_CH(sap_config->acs_cfg.
2274 pcl_channels[0])) {
2275 sap_config->acs_cfg.band =
2276 QCA_ACS_MODE_IEEE80211A;
2277 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002278 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302279 } else {
2280 sap_config->acs_cfg.band =
2281 QCA_ACS_MODE_IEEE80211G;
2282 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002283 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302284 }
2285 }
2286 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302287
Jeff Johnsonb9424862017-10-30 08:49:35 -07002288 hdd_get_scan_band(hdd_ctx, &adapter->session.ap.sap_config, &band);
Nachiket Kukade3208c162017-08-29 17:40:59 +05302289
2290 if (sap_config->acs_cfg.ch_list) {
2291 /* Copy INI or hostapd provided ACS channel range*/
2292 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
2293 sap_config->acs_cfg.ch_list_count);
2294 channel_count = sap_config->acs_cfg.ch_list_count;
2295 } else {
2296 /* No channel list provided, copy all valid channels */
2297 wlan_hdd_sap_get_valid_channellist(adapter,
2298 &channel_count,
2299 channel_list,
2300 band);
2301 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302302
Lin Baifac77972018-07-05 19:51:49 +08002303 sap_config->channel_info = qdf_mem_malloc(
2304 sizeof(struct hdd_channel_info) *
2305 channel_count);
Min Liu74a1a502018-10-10 19:59:07 +08002306 if (!sap_config->channel_info)
Lin Baifac77972018-07-05 19:51:49 +08002307 return -ENOMEM;
Lin Baifac77972018-07-05 19:51:49 +08002308
Kapil Gupta8878ad92017-02-13 11:56:04 +05302309 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta63e75282017-05-18 20:55:10 +05302310 hdd_get_freq_list(channel_list, freq_list, channel_count);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302311 /* Get phymode */
Jeff Johnsonb9424862017-10-30 08:49:35 -07002312 phy_mode = adapter->session.ap.sap_config.acs_cfg.hw_mode;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302313
2314 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
2315 &(adapter->wdev),
2316 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2317 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
2318 GFP_KERNEL);
2319
2320 if (!skb) {
2321 hdd_err("cfg80211_vendor_event_alloc failed");
Lin Baifac77972018-07-05 19:51:49 +08002322 qdf_mem_free(sap_config->channel_info);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302323 return -ENOMEM;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302324 }
2325 /*
2326 * Application expects pcl to be a subset of channel list
2327 * Remove all channels which are not in channel list from pcl
2328 * and add weight as zero
2329 */
2330 acs_chan_params.channel_count = channel_count;
2331 acs_chan_params.channel_list = channel_list;
2332 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
2333 acs_chan_params.vendor_weight_list = vendor_weight_list;
2334
2335 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
2336 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302337
2338 if (acs_chan_params.channel_count) {
2339 hdd_debug("ACS channel list: len: %d",
2340 acs_chan_params.channel_count);
2341 for (i = 0; i < acs_chan_params.channel_count; i++)
2342 hdd_debug("%d ", acs_chan_params.channel_list[i]);
2343 }
2344
2345 if (acs_chan_params.pcl_count) {
2346 hdd_debug("ACS PCL list: len: %d",
2347 acs_chan_params.pcl_count);
2348 for (i = 0; i < acs_chan_params.pcl_count; i++)
2349 hdd_debug("channel:%d, weight:%d ",
2350 acs_chan_params.
2351 vendor_pcl_list[i],
2352 acs_chan_params.
2353 vendor_weight_list[i]);
2354 }
2355
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002356 qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
2357 &is_external_acs_policy);
2358 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2359 hdd_err("get_external_acs_policy failed, set default");
2360
2361 if (is_external_acs_policy) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302362 acs_policy =
2363 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
2364 } else {
2365 acs_policy =
2366 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
2367 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302368 /* Update values in NL buffer */
2369 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
2370 reason) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302371 nla_put_flag(skb,
2372 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED) ||
2373 nla_put_flag(skb,
2374 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT)
2375 ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302376 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
2377 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302378 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
2379 band) ||
2380 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
2381 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05302382 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta63e75282017-05-18 20:55:10 +05302383 channel_count * sizeof(uint32_t), freq_list)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302384 hdd_err("nla put fail");
2385 goto fail;
2386 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302387 status =
2388 hdd_cfg80211_update_pcl(skb,
2389 acs_chan_params.
2390 pcl_count,
2391 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
2392 vendor_pcl_list,
2393 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302394
2395 if (status != 0)
2396 goto fail;
2397
2398 status = hdd_cfg80211_update_channel_info(skb, sap_config,
2399 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
2400
2401 if (status != 0)
2402 goto fail;
2403
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302404 status = nla_put_u32(skb,
2405 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
2406 acs_policy);
2407
2408 if (status != 0)
2409 goto fail;
2410
Kapil Gupta8878ad92017-02-13 11:56:04 +05302411 cfg80211_vendor_event(skb, GFP_KERNEL);
Lin Baifac77972018-07-05 19:51:49 +08002412 qdf_mem_free(sap_config->channel_info);
2413
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302414 return 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302415fail:
Lin Baifac77972018-07-05 19:51:49 +08002416 qdf_mem_free(sap_config->channel_info);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302417 if (skb)
2418 kfree_skb(skb);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302419 return status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302420}
2421
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302422/**
2423 * hdd_create_acs_timer(): Initialize vendor ACS timer
2424 * @adapter: pointer to SAP adapter struct
2425 *
2426 * This function initializes the vendor ACS timer.
2427 *
2428 * Return: Status of create vendor ACS timer
2429 */
Jeff Johnsone5006672017-08-29 14:39:02 -07002430static int hdd_create_acs_timer(struct hdd_adapter *adapter)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302431{
2432 struct hdd_external_acs_timer_context *timer_context;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302433 QDF_STATUS status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302434
Jeff Johnsonb9424862017-10-30 08:49:35 -07002435 if (adapter->session.ap.vendor_acs_timer_initialized)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302436 return 0;
2437
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302438 hdd_debug("Starting vendor app based ACS");
Kapil Gupta8878ad92017-02-13 11:56:04 +05302439 timer_context = qdf_mem_malloc(sizeof(*timer_context));
Min Liu74a1a502018-10-10 19:59:07 +08002440 if (!timer_context)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302441 return -ENOMEM;
Min Liu74a1a502018-10-10 19:59:07 +08002442
Kapil Gupta8878ad92017-02-13 11:56:04 +05302443 timer_context->adapter = adapter;
2444
2445 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
Jeff Johnsonb9424862017-10-30 08:49:35 -07002446 status = qdf_mc_timer_init(&adapter->session.ap.vendor_acs_timer,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302447 QDF_TIMER_TYPE_SW,
2448 hdd_acs_response_timeout_handler, timer_context);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302449 if (status != QDF_STATUS_SUCCESS) {
2450 hdd_err("Failed to initialize acs response timeout timer");
2451 return -EFAULT;
2452 }
Jeff Johnsonb9424862017-10-30 08:49:35 -07002453 adapter->session.ap.vendor_acs_timer_initialized = true;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302454 return 0;
2455}
2456
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302457static const struct nla_policy
2458wlan_hdd_cfg80211_do_acs_policy[QCA_WLAN_VENDOR_ATTR_ACS_MAX+1] = {
2459 [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
2460 [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
2461 [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
2462 [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
2463 [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
2464 [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_UNSPEC },
2465 [QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_UNSPEC },
2466};
2467
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302468int hdd_start_vendor_acs(struct hdd_adapter *adapter)
2469{
2470 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2471 int status;
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002472 QDF_STATUS qdf_status;
2473 bool is_acs_support_for_dfs_ltecoex = cfg_default(CFG_USER_ACS_DFS_LTE);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302474
2475 status = hdd_create_acs_timer(adapter);
2476 if (status != 0) {
2477 hdd_err("failed to create acs timer");
2478 return status;
2479 }
2480 status = hdd_update_acs_timer_reason(adapter,
2481 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2482 if (status != 0) {
2483 hdd_err("failed to update acs timer reason");
2484 return status;
2485 }
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002486 qdf_status = ucfg_mlme_get_acs_support_for_dfs_ltecoex(
2487 hdd_ctx->psoc,
2488 &is_acs_support_for_dfs_ltecoex);
2489 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2490 hdd_err("get_acs_support_for_dfs_ltecoex failed, set def");
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302491
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002492 if (is_acs_support_for_dfs_ltecoex)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302493 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2494 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2495 true));
2496 else
2497 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2498 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2499 false));
2500
2501 return status;
2502}
2503
Kapil Gupta8878ad92017-02-13 11:56:04 +05302504/**
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302505 * __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002506 * @wiphy: Linux wiphy struct pointer
2507 * @wdev: Linux wireless device struct pointer
2508 * @data: ACS information from hostapd
2509 * @data_len: ACS information length
2510 *
2511 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2512 * and starts ACS procedure.
2513 *
2514 * Return: ACS procedure start status
2515 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002516static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2517 struct wireless_dev *wdev,
2518 const void *data, int data_len)
2519{
2520 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07002521 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002522 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsone4c11db2018-05-05 23:22:32 -07002523 tsap_config_t *sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 struct sk_buff *temp_skbuff;
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002525 int ret, i, ch_cnt = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
2527 bool ht_enabled, ht40_enabled, vht_enabled;
wadesong1795e142018-01-05 11:13:07 +08002528 uint8_t ch_width;
2529 enum qca_wlan_vendor_acs_hw_mode hw_mode;
Rachit Kankanedef2b172019-03-07 11:34:44 +05302530 enum policy_mgr_con_mode pm_mode;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302531 QDF_STATUS qdf_status;
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002532 bool skip_etsi13_srd_chan = false;
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002533 uint32_t auto_channel_select_weight =
2534 cfg_default(CFG_AUTO_CHANNEL_SELECT_WEIGHT);
2535 bool is_vendor_acs_support =
2536 cfg_default(CFG_USER_AUTO_CHANNEL_SELECTION);
2537 bool is_external_acs_policy =
2538 cfg_default(CFG_EXTERNAL_ACS_POLICY);
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302539 bool sap_force_11n_for_11ac = 0;
2540 bool go_force_11n_for_11ac = 0;
lifeng0b46ae52018-12-13 09:42:27 +08002541 bool etsi13_srd_chan;
Sandeep Puligilla34618782019-01-04 17:42:42 -08002542 bool go_11ac_override = 0;
2543 bool sap_11ac_override = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544
2545 /* ***Note*** Donot set SME config related to ACS operation here because
2546 * ACS operation is not synchronouse and ACS for Second AP may come when
2547 * ACS operation for first AP is going on. So only do_acs is split to
Jeff Johnsonfa7d9602018-05-06 11:25:31 -07002548 * separate start_acs routine. Also SME-PMAC struct that is used to
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
2550 * config shall be set only from start_acs.
2551 */
2552
Dustin Brownfdf17c12018-03-14 12:55:34 -07002553 hdd_enter_dev(ndev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08002554
Anurag Chouhan6d760662016-02-20 16:05:43 +05302555 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002556 hdd_err("Command not allowed in FTM mode");
2557 return -EPERM;
2558 }
2559
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302560 ret = wlan_hdd_validate_context(hdd_ctx);
2561 if (ret)
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302562 return ret;
2563
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302564 ucfg_mlme_get_sap_force_11n_for_11ac(hdd_ctx->psoc,
2565 &sap_force_11n_for_11ac);
2566 ucfg_mlme_get_go_force_11n_for_11ac(hdd_ctx->psoc,
2567 &go_force_11n_for_11ac);
2568
Amar Singhalf9898792018-08-20 12:13:34 -07002569 hdd_debug("current country is %s", hdd_ctx->reg.alpha2);
2570
Hanumanth Reddy Pothula89b0dce2018-05-18 12:49:43 +05302571 if (!((adapter->device_mode == QDF_SAP_MODE) ||
2572 (adapter->device_mode == QDF_P2P_GO_MODE))) {
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302573 hdd_err("Invalid device mode %d", adapter->device_mode);
2574 return -EINVAL;
2575 }
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302576
Naveen Rawat64e477e2016-05-20 10:34:56 -07002577 if (cds_is_sub_20_mhz_enabled()) {
2578 hdd_err("ACS not supported in sub 20 MHz ch wd.");
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302579 return -EINVAL;
Naveen Rawat64e477e2016-05-20 10:34:56 -07002580 }
2581
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302582 if (qdf_atomic_read(&adapter->session.ap.acs_in_progress) > 0) {
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302583 hdd_err("ACS rejected as previous req already in progress");
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302584 return -EINVAL;
2585 } else {
2586 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 1);
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302587 }
2588
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302589 ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
Dustin Brown4ea21db2018-01-05 14:13:17 -08002590 data_len,
2591 wlan_hdd_cfg80211_do_acs_policy);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302592 if (ret) {
Jeff Johnson020db452016-06-29 14:37:26 -07002593 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002594 goto out;
2595 }
2596
2597 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002598 hdd_err("Attr hw_mode failed");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302599 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600 goto out;
2601 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302602 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603
2604 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
2605 ht_enabled =
2606 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2607 else
2608 ht_enabled = 0;
2609
2610 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2611 ht40_enabled =
2612 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2613 else
2614 ht40_enabled = 0;
2615
Kapil Guptac1224bf2017-06-22 21:22:40 +05302616 hdd_debug("ht40_enabled %d", ht40_enabled);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002617 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2618 vht_enabled =
2619 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2620 else
2621 vht_enabled = 0;
2622
Bala Venkateshb9cf3362017-11-09 15:48:46 +05302623 if (((adapter->device_mode == QDF_SAP_MODE) &&
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302624 sap_force_11n_for_11ac) ||
2625 ((adapter->device_mode == QDF_P2P_GO_MODE) &&
2626 go_force_11n_for_11ac)) {
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302627 vht_enabled = 0;
Dustin Brownbacc48f2018-03-14 14:48:44 -07002628 hdd_info("VHT is Disabled in ACS");
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302629 }
2630
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002631 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2632 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2633 } else {
2634 if (ht_enabled && ht40_enabled)
2635 ch_width = 40;
2636 else
2637 ch_width = 20;
2638 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302639
Bala Venkateshb9cf3362017-11-09 15:48:46 +05302640 /* this may be possible, when sap_force_11n_for_11ac or
2641 * go_force_11n_for_11ac is set
2642 */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302643 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2644 if (ht_enabled && ht40_enabled)
2645 ch_width = 40;
2646 else
2647 ch_width = 20;
2648 }
2649
Hanumanth Reddy Pothula560d5712018-03-15 18:11:27 +05302650 sap_config = &adapter->session.ap.sap_config;
2651
2652 /* Check and free if memory is already allocated for acs channel list */
2653 wlan_hdd_undo_acs(adapter);
2654
2655 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
2656
Kapil Guptac1224bf2017-06-22 21:22:40 +05302657 hdd_debug("channel width =%d", ch_width);
Himanshu Agarwal75e74412018-02-01 20:51:47 +05302658 if (ch_width == 160)
2659 sap_config->acs_cfg.ch_width = CH_WIDTH_160MHZ;
2660 else if (ch_width == 80)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002661 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2662 else if (ch_width == 40)
2663 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2664 else
2665 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2666
2667 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2668 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2669 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2670 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2671 * since it contains the frequency values of the channels in
2672 * the channel list.
2673 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2674 * is present
2675 */
Himanshu Agarwal1b3be702018-02-20 12:16:57 +05302676
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2678 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
Srinivas Girigowda576b2352017-08-25 14:44:26 -07002679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680 sap_config->acs_cfg.ch_list_count = nla_len(
2681 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2682 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302683 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684 sizeof(uint8_t) *
2685 sap_config->acs_cfg.ch_list_count);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302686 if (!sap_config->acs_cfg.ch_list) {
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302687 ret = -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688 goto out;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302689 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002690
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302691 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002692 sap_config->acs_cfg.ch_list_count);
2693 }
2694 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2695 uint32_t *freq =
2696 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2697 sap_config->acs_cfg.ch_list_count = nla_len(
2698 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2699 sizeof(uint32_t);
2700 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302701 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002702 sap_config->acs_cfg.ch_list_count);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302703 if (!sap_config->acs_cfg.ch_list) {
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302704 ret = -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 goto out;
2706 }
2707
2708 /* convert frequency to channel */
2709 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2710 sap_config->acs_cfg.ch_list[i] =
2711 ieee80211_frequency_to_channel(freq[i]);
2712 }
2713 }
2714
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302715 if (!sap_config->acs_cfg.ch_list_count) {
Amar Singhal5f783132018-03-29 13:58:50 -07002716 hdd_err("acs config chan count 0");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302717 ret = -EINVAL;
2718 goto out;
2719 }
2720
lifeng0b46ae52018-12-13 09:42:27 +08002721 ucfg_mlme_get_etsi13_srd_chan_in_master_mode(hdd_ctx->psoc,
2722 &etsi13_srd_chan);
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002723 skip_etsi13_srd_chan =
lifeng0b46ae52018-12-13 09:42:27 +08002724 !etsi13_srd_chan &&
Dustin Brown07901ec2018-09-07 11:02:41 -07002725 wlan_reg_is_etsi13_regdmn(hdd_ctx->pdev);
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002726
2727 if (skip_etsi13_srd_chan) {
2728 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
Dustin Brown07901ec2018-09-07 11:02:41 -07002729 if (wlan_reg_is_etsi13_srd_chan(hdd_ctx->pdev,
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002730 sap_config->acs_cfg.
2731 ch_list[i]))
2732 sap_config->acs_cfg.ch_list[i] = 0;
2733 else
2734 sap_config->acs_cfg.ch_list[ch_cnt++] =
2735 sap_config->acs_cfg.ch_list[i];
2736 }
2737 sap_config->acs_cfg.ch_list_count = ch_cnt;
2738 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002739 hdd_debug("get pcl for DO_ACS vendor command");
2740
Rachit Kankanedef2b172019-03-07 11:34:44 +05302741 pm_mode =
2742 policy_mgr_convert_device_mode_to_qdf_type(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002743 /* consult policy manager to get PCL */
Rachit Kankanedef2b172019-03-07 11:34:44 +05302744 qdf_status = policy_mgr_get_pcl(hdd_ctx->psoc, pm_mode,
2745 sap_config->acs_cfg.pcl_channels,
2746 &sap_config->acs_cfg.pcl_ch_count,
2747 sap_config->acs_cfg.
2748 pcl_channels_weight_list,
2749 QDF_MAX_NUM_CHAN);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302750 if (qdf_status != QDF_STATUS_SUCCESS)
Jeff Johnson020db452016-06-29 14:37:26 -07002751 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002752
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302753 if (sap_config->acs_cfg.pcl_ch_count) {
2754 hdd_debug("ACS config PCL: len: %d",
2755 sap_config->acs_cfg.pcl_ch_count);
2756 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2757 hdd_debug("channel:%d, weight:%d ",
2758 sap_config->acs_cfg.
2759 pcl_channels[i],
2760 sap_config->acs_cfg.
2761 pcl_channels_weight_list[i]);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302762 }
Kapil Guptac1224bf2017-06-22 21:22:40 +05302763 sap_config->acs_cfg.band = hw_mode;
Rachit Kankanedef2b172019-03-07 11:34:44 +05302764
2765 qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
2766 &is_external_acs_policy);
2767 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2768 hdd_err("get_external_acs_policy failed");
2769
2770 if (is_external_acs_policy &&
2771 policy_mgr_is_force_scc(hdd_ctx->psoc) &&
2772 policy_mgr_get_connection_count(hdd_ctx->psoc)) {
2773 policy_mgr_trim_acs_channel_list(
2774 sap_config->acs_cfg.pcl_channels,
2775 sap_config->acs_cfg.pcl_ch_count,
2776 sap_config->acs_cfg.ch_list,
2777 &sap_config->acs_cfg.ch_list_count);
2778
2779 /* if it is only one channel, send ACS event to upper layer */
2780 if (sap_config->acs_cfg.ch_list_count == 1) {
2781 sap_config->acs_cfg.pri_ch =
2782 sap_config->acs_cfg.ch_list[0];
2783 wlan_sap_set_sap_ctx_acs_cfg(
2784 WLAN_HDD_GET_SAP_CTX_PTR(adapter), sap_config);
2785 sap_config_acs_result(hdd_ctx->mac_handle,
2786 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2787 sap_config->acs_cfg.ht_sec_ch);
2788 sap_config->ch_params.ch_width =
2789 sap_config->acs_cfg.ch_width;
2790 sap_config->ch_params.sec_ch_offset =
2791 sap_config->acs_cfg.ht_sec_ch;
2792 sap_config->ch_params.center_freq_seg0 =
2793 sap_config->acs_cfg.vht_seg0_center_ch;
2794 sap_config->ch_params.center_freq_seg1 =
2795 sap_config->acs_cfg.vht_seg1_center_ch;
2796 /*notify hostapd about channel override */
2797 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
2798 ret = 0;
2799 goto out;
2800 }
2801 }
2802
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302803 ret = wlan_hdd_set_acs_ch_range(sap_config, hw_mode,
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302804 ht_enabled, vht_enabled);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302805 if (ret) {
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302806 hdd_err("set acs channel range failed");
2807 goto out;
2808 }
2809
Sandeep Puligilla34618782019-01-04 17:42:42 -08002810 ucfg_mlme_is_go_11ac_override(hdd_ctx->psoc, &go_11ac_override);
2811 ucfg_mlme_is_sap_11ac_override(hdd_ctx->psoc, &sap_11ac_override);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302812 /* ACS override for android */
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05302813 if (ht_enabled &&
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302814 sap_config->acs_cfg.end_ch >= WLAN_REG_CH_NUM(CHAN_ENUM_36) &&
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05302815 ((adapter->device_mode == QDF_SAP_MODE &&
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302816 !sap_force_11n_for_11ac &&
Sandeep Puligilla34618782019-01-04 17:42:42 -08002817 sap_11ac_override) ||
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05302818 (adapter->device_mode == QDF_P2P_GO_MODE &&
Bala Venkatesh3d786eb2018-11-20 12:59:31 +05302819 !go_force_11n_for_11ac &&
Sandeep Puligilla34618782019-01-04 17:42:42 -08002820 go_11ac_override))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002821 vht_enabled = 1;
2822 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05302823 qdf_status =
2824 ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
2825 &ch_width);
2826 sap_config->acs_cfg.ch_width = ch_width;
Himanshu Agarwal29a9a3e2018-02-21 17:44:37 +05302827 }
2828
2829 /* No VHT80 in 2.4G so perform ACS accordingly */
2830 if (sap_config->acs_cfg.end_ch <= 14 &&
2831 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
2832 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
2833 hdd_debug("resetting to 40Mhz in 2.4Ghz");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834 }
2835
Kapil Guptac1224bf2017-06-22 21:22:40 +05302836 hdd_debug("ACS Config for %s: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d band %d",
2837 adapter->dev->name, sap_config->acs_cfg.hw_mode,
Himanshu Agarwal1ed8bff2018-02-07 12:50:41 +05302838 sap_config->acs_cfg.ch_width, ht_enabled, vht_enabled,
Kapil Guptac1224bf2017-06-22 21:22:40 +05302839 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch,
2840 sap_config->acs_cfg.band);
wadesongcb0ded22018-02-02 17:57:20 +08002841 host_log_acs_req_event(adapter->dev->name,
2842 csr_phy_mode_str(sap_config->acs_cfg.hw_mode),
2843 ch_width, ht_enabled, vht_enabled,
2844 sap_config->acs_cfg.start_ch,
2845 sap_config->acs_cfg.end_ch);
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002846
2847 qdf_status =
2848 ucfg_mlme_get_auto_channel_weight(hdd_ctx->psoc,
2849 &auto_channel_select_weight);
2850 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2851 hdd_err("get_auto_channel_weight failed");
2852
2853 if (auto_channel_select_weight)
gaoleze5108942017-03-31 16:56:42 +08002854 sap_config->auto_channel_select_weight =
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002855 auto_channel_select_weight;
gaoleze5108942017-03-31 16:56:42 +08002856
Kapil Gupta8878ad92017-02-13 11:56:04 +05302857 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2858 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2859
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002860 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002861 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002862 sap_config->acs_cfg.ch_list_count);
2863 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002864 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002865 }
Himanshu Agarwal33163982018-05-17 18:11:10 +05302866
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002867 sap_config->acs_cfg.acs_mode = true;
2868 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002869 /* ***Note*** Completion variable usage is not allowed
2870 * here since ACS scan operation may take max 2.2 sec
2871 * for 5G band:
2872 * 9 Active channel X 40 ms active scan time +
2873 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002874 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2875 * for this long. So we split up the scanning part.
2876 */
2877 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002878 hdd_debug("ACS Pending for %s", adapter->dev->name);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302879 ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002880 } else {
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002881 qdf_status =
2882 ucfg_mlme_get_vendor_acs_support(
2883 hdd_ctx->psoc,
2884 &is_vendor_acs_support);
2885 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2886 hdd_err("get_vendor_acs_support failed, set default");
2887
Kapil Gupta8878ad92017-02-13 11:56:04 +05302888 /* Check if vendor specific acs is enabled */
Harprit Chhabada1eeeb8d2018-09-14 15:16:56 -07002889 if (is_vendor_acs_support)
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302890 ret = hdd_start_vendor_acs(adapter);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302891 else
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302892 ret = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893 }
2894
2895out:
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302896 if (ret == 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002897 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2898 NLMSG_HDRLEN);
2899 if (temp_skbuff != NULL)
2900 return cfg80211_vendor_cmd_reply(temp_skbuff);
2901 }
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302902 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 0);
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002903 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002904 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2905
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302906 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907}
2908
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002909/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002910 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2911 * @wiphy: Linux wiphy struct pointer
2912 * @wdev: Linux wireless device struct pointer
2913 * @data: ACS information from hostapd
2914 * @data_len: ACS information len
2915 *
2916 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2917 * and starts ACS procedure.
2918 *
2919 * Return: ACS procedure start status
2920 */
2921
2922static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2923 struct wireless_dev *wdev,
2924 const void *data, int data_len)
2925{
Dustin Browna09acf42018-11-08 12:32:26 +05302926 int errno;
2927 struct osif_vdev_sync *vdev_sync;
2928
2929 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
2930 if (errno)
2931 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002932
Dustin Browna09acf42018-11-08 12:32:26 +05302933 errno = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002934
Dustin Browna09acf42018-11-08 12:32:26 +05302935 osif_vdev_sync_op_stop(vdev_sync);
2936
2937 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002938}
2939
2940/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002941 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2942 * @adapter: Pointer to adapter struct
2943 *
2944 * This function handle cleanup of what was done in DO_ACS, including free
2945 * memory.
2946 *
2947 * Return: void
2948 */
2949
Jeff Johnsone5006672017-08-29 14:39:02 -07002950void wlan_hdd_undo_acs(struct hdd_adapter *adapter)
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002951{
2952 if (adapter == NULL)
2953 return;
Jeff Johnsonb9424862017-10-30 08:49:35 -07002954 if (adapter->session.ap.sap_config.acs_cfg.ch_list) {
2955 qdf_mem_free(adapter->session.ap.sap_config.acs_cfg.ch_list);
2956 adapter->session.ap.sap_config.acs_cfg.ch_list = NULL;
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002957 }
2958}
2959
2960/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002961 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2962 * @work: Linux workqueue struct pointer for ACS work
2963 *
2964 * This function starts the ACS procedure which was marked pending when an ACS
2965 * procedure was in progress for a concurrent SAP interface.
2966 *
2967 * Return: None
2968 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002969static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2970{
Jeff Johnsone5006672017-08-29 14:39:02 -07002971 struct hdd_adapter *adapter = container_of(work, struct hdd_adapter,
Jeff Johnson3aa54d42018-06-26 11:36:50 -07002972 acs_pending_work.work);
Dustin Brown4376fed2019-03-06 11:00:38 -08002973 struct osif_vdev_sync *vdev_sync;
Jeff Johnson3aa54d42018-06-26 11:36:50 -07002974
Dustin Brown4376fed2019-03-06 11:00:38 -08002975 if (osif_vdev_sync_op_start(adapter->dev, &vdev_sync))
2976 return;
2977
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002978 wlan_hdd_cfg80211_start_acs(adapter);
Will Huang7049bae2018-08-13 17:25:02 +08002979 clear_bit(ACS_PENDING, &adapter->event_flags);
Dustin Brown4376fed2019-03-06 11:00:38 -08002980
2981 osif_vdev_sync_op_stop(vdev_sync);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002982}
2983
2984/**
2985 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2986 * @adapter: Pointer to SAP adapter struct
2987 * @pri_channel: SAP ACS procedure selected Primary channel
2988 * @sec_channel: SAP ACS procedure selected secondary channel
2989 *
2990 * This is a callback function from SAP module on ACS procedure is completed.
2991 * This function send the ACS selected channel information to hostapd
2992 *
2993 * Return: None
2994 */
2995
Jeff Johnsone5006672017-08-29 14:39:02 -07002996void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002997{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002998 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsone4c11db2018-05-05 23:22:32 -07002999 tsap_config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003000 struct sk_buff *vendor_event;
3001 int ret_val;
Jeff Johnsone5006672017-08-29 14:39:02 -07003002 struct hdd_adapter *con_sap_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003003 uint16_t ch_width;
3004
3005 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08003006 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
3008 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
3009 GFP_KERNEL);
3010
3011 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003012 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003013 return;
3014 }
3015
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003016 ret_val = nla_put_u8(vendor_event,
3017 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
3018 sap_cfg->acs_cfg.pri_ch);
3019 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003020 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003021 kfree_skb(vendor_event);
3022 return;
3023 }
3024
3025 ret_val = nla_put_u8(vendor_event,
3026 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
3027 sap_cfg->acs_cfg.ht_sec_ch);
3028 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003029 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003030 kfree_skb(vendor_event);
3031 return;
3032 }
3033
3034 ret_val = nla_put_u8(vendor_event,
3035 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
3036 sap_cfg->acs_cfg.vht_seg0_center_ch);
3037 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003038 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003039 kfree_skb(vendor_event);
3040 return;
3041 }
3042
3043 ret_val = nla_put_u8(vendor_event,
3044 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
3045 sap_cfg->acs_cfg.vht_seg1_center_ch);
3046 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003047 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003048 kfree_skb(vendor_event);
3049 return;
3050 }
3051
Himanshu Agarwal75e74412018-02-01 20:51:47 +05303052 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_160MHZ)
3053 ch_width = 160;
3054 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003055 ch_width = 80;
3056 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
3057 ch_width = 40;
3058 else
3059 ch_width = 20;
3060
3061 ret_val = nla_put_u16(vendor_event,
3062 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
3063 ch_width);
3064 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003065 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003066 kfree_skb(vendor_event);
3067 return;
3068 }
3069 if (sap_cfg->acs_cfg.pri_ch > 14)
3070 ret_val = nla_put_u8(vendor_event,
3071 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
3072 QCA_ACS_MODE_IEEE80211A);
3073 else
3074 ret_val = nla_put_u8(vendor_event,
3075 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
3076 QCA_ACS_MODE_IEEE80211G);
3077
3078 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07003079 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003080 kfree_skb(vendor_event);
3081 return;
3082 }
3083
Mahesh Kumar Kalikot Veetilec1da142017-09-20 10:01:13 -07003084 hdd_debug("ACS result for %s: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
3085 adapter->dev->name, sap_cfg->acs_cfg.pri_ch,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003086 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
3087 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
3088
3089 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
3090 /* ***Note*** As already mentioned Completion variable usage is not
3091 * allowed here since ACS scan operation may take max 2.2 sec.
3092 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
3093 * operation.
3094 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
3095 * when Primary AP ACS is complete and secondary AP ACS is started here
3096 * immediately, Primary AP start_bss may come inbetween ACS operation
Jeff Johnson60ed45a2018-05-06 15:28:49 -07003097 * and overwrite Sec AP ACS parameters. Thus Sec AP ACS is executed with
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003098 * delay. This path and below constraint will be removed on sessionizing
3099 * SAP acs parameters and decoupling SAP from PMAC (WIP).
3100 * As per design constraint user space control application must take
3101 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
3102 * this code path. Sec AP hostapd should be started after Primary AP
3103 * start beaconing which can be confirmed by getchannel iwpriv command
3104 */
3105
3106 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
3107 if (con_sap_adapter &&
3108 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003109 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
3110 wlan_hdd_cfg80211_start_pending_acs);
hqu71a1a3b2018-01-23 15:38:13 +08003111 /* Lets give 1500ms for OBSS + START_BSS to complete */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003112 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
hqu71a1a3b2018-01-23 15:38:13 +08003113 msecs_to_jiffies(1500));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003114 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115}
3116
Sourav Mohapatrac457ae62018-12-06 15:19:41 +05303117/**
3118 * hdd_is_wlm_latency_manager_supported - Checks if WLM Latency manager is
3119 * supported
3120 * @hdd_ctx: The HDD context
3121 *
3122 * Return: True if supported, false otherwise
3123 */
3124static inline
3125bool hdd_is_wlm_latency_manager_supported(struct hdd_context *hdd_ctx)
3126{
3127 bool latency_enable;
3128
3129 if (QDF_IS_STATUS_ERROR(ucfg_mlme_get_latency_enable
3130 (hdd_ctx->psoc, &latency_enable)))
3131 return false;
3132
3133 if (latency_enable &&
3134 sme_is_feature_supported_by_fw(VDEV_LATENCY_CONFIG))
3135 return true;
3136 else
3137 return false;
3138}
3139
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003140static int
3141__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
3142 struct wireless_dev *wdev,
3143 const void *data,
3144 int data_len)
3145{
Jeff Johnsonb8944722017-09-03 09:03:19 -07003146 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003147 struct sk_buff *skb = NULL;
3148 uint32_t fset = 0;
3149 int ret;
Wu Gaobdb7f272018-07-05 19:33:26 +08003150#ifdef FEATURE_WLAN_TDLS
3151 bool bvalue;
3152#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003153
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07003154 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303155
Anurag Chouhan6d760662016-02-20 16:05:43 +05303156 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003157 hdd_err("Command not allowed in FTM mode");
3158 return -EPERM;
3159 }
3160
Jeff Johnsonb8944722017-09-03 09:03:19 -07003161 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303162 if (ret)
3163 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164
3165 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003166 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167 fset |= WIFI_FEATURE_INFRA;
3168 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07003169 if (true == hdd_is_5g_supported(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003170 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003171 fset |= WIFI_FEATURE_INFRA_5G;
3172 }
3173#ifdef WLAN_FEATURE_P2P
3174 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
3175 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003176 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003177 fset |= WIFI_FEATURE_P2P;
3178 }
3179#endif
3180 fset |= WIFI_FEATURE_SOFT_AP;
3181
3182 /* HOTSPOT is a supplicant feature, enable it by default */
3183 fset |= WIFI_FEATURE_HOTSPOT;
3184
Dustin Brown76cd2932018-09-11 16:03:05 -07003185 if (ucfg_extscan_get_enable(hdd_ctx->psoc) &&
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303186 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003187 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003188 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
3189 }
Nachiket Kukade989bb352018-07-31 18:01:17 +05303190 if (wlan_hdd_nan_is_supported(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003191 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192 fset |= WIFI_FEATURE_NAN;
3193 }
Sourav Mohapatra9e014cf2018-12-11 09:39:33 +05303194 if (sme_is_feature_supported_by_fw(RTT) &&
3195 hdd_ctx->config->enable_rtt_support) {
3196 hdd_debug("RTT is supported by firmware and framework");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197 fset |= WIFI_FEATURE_D2D_RTT;
3198 fset |= WIFI_FEATURE_D2AP_RTT;
3199 }
3200#ifdef FEATURE_WLAN_SCAN_PNO
Pragaspathi Thilagaraj24789d32018-12-10 22:28:03 +05303201 if (ucfg_scan_get_pno_scan_support(hdd_ctx->psoc) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003203 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003204 fset |= WIFI_FEATURE_PNO;
3205 }
3206#endif
3207 fset |= WIFI_FEATURE_ADDITIONAL_STA;
3208#ifdef FEATURE_WLAN_TDLS
Dustin Brown76cd2932018-09-11 16:03:05 -07003209 cfg_tdls_get_support_enable(hdd_ctx->psoc, &bvalue);
Wu Gaobdb7f272018-07-05 19:33:26 +08003210 if ((bvalue) && sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003211 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003212 fset |= WIFI_FEATURE_TDLS;
3213 }
Wu Gaobdb7f272018-07-05 19:33:26 +08003214
Dustin Brown76cd2932018-09-11 16:03:05 -07003215 cfg_tdls_get_off_channel_enable(hdd_ctx->psoc, &bvalue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003216 if (sme_is_feature_supported_by_fw(TDLS) &&
Wu Gaobdb7f272018-07-05 19:33:26 +08003217 bvalue && sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003218 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003219 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
3220 }
3221#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003222 fset |= WIFI_FEATURE_AP_STA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003223 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07003224 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Srinivas Girigowda5a1da622017-07-12 17:07:44 -07003225 fset |= WIFI_FEATURE_SET_TX_POWER_LIMIT;
Sourav Mohapatra804359e2017-12-07 13:52:05 +05303226 fset |= WIFI_FEATURE_CONFIG_NDO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003227
3228 if (hdd_link_layer_stats_supported())
3229 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
3230
Jeff Johnsonb8944722017-09-03 09:03:19 -07003231 if (hdd_roaming_supported(hdd_ctx))
Srinivas Girigowda8df27ea2017-01-06 12:42:16 -08003232 fset |= WIFI_FEATURE_CONTROL_ROAMING;
3233
3234 if (hdd_scan_random_mac_addr_supported())
3235 fset |= WIFI_FEATURE_SCAN_RAND;
3236
Sourav Mohapatrac457ae62018-12-06 15:19:41 +05303237 if (hdd_is_wlm_latency_manager_supported(hdd_ctx))
3238 fset |= WIFI_FEATURE_SET_LATENCY_MODE;
3239
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003240 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
3241 NLMSG_HDRLEN);
3242 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003243 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003244 return -EINVAL;
3245 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003246 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003248 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003249 goto nla_put_failure;
3250 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303251 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303252 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003253nla_put_failure:
3254 kfree_skb(skb);
3255 return -EINVAL;
3256}
3257
3258/**
3259 * wlan_hdd_cfg80211_get_supported_features() - get supported features
3260 * @wiphy: pointer to wireless wiphy structure.
3261 * @wdev: pointer to wireless_dev structure.
3262 * @data: Pointer to the data to be passed via vendor interface
3263 * @data_len:Length of the data to be passed
3264 *
3265 * Return: Return the Success or Failure code.
3266 */
3267static int
3268wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
3269 struct wireless_dev *wdev,
3270 const void *data, int data_len)
3271{
Dustin Brown363b4792019-02-05 16:11:55 -08003272 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08003273 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303274
Dustin Brown363b4792019-02-05 16:11:55 -08003275 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08003276 if (errno)
3277 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278
Dustin Brownf0f00612019-01-31 16:02:24 -08003279 errno = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
3280 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003281
Dustin Brown363b4792019-02-05 16:11:55 -08003282 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303283
Dustin Brownf0f00612019-01-31 16:02:24 -08003284 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003285}
3286
3287/**
3288 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3289 * @wiphy: pointer to wireless wiphy structure.
3290 * @wdev: pointer to wireless_dev structure.
3291 * @data: Pointer to the data to be passed via vendor interface
3292 * @data_len:Length of the data to be passed
3293 *
3294 * Set the MAC address that is to be used for scanning.
3295 *
3296 * Return: Return the Success or Failure code.
3297 */
3298static int
3299__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3300 struct wireless_dev *wdev,
3301 const void *data,
3302 int data_len)
3303{
Jeff Johnson9d45f332019-01-29 08:42:00 -08003304 struct scan_mac_oui scan_mac_oui = { {0} };
Jeff Johnsonb8944722017-09-03 09:03:19 -07003305 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303307 QDF_STATUS status;
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +05303308 int ret, len;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303309 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07003310 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003311 mac_handle_t mac_handle;
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +05303312 bool mac_spoofing_enabled;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003313
Dustin Brownfdf17c12018-03-14 12:55:34 -07003314 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003315
Anurag Chouhan6d760662016-02-20 16:05:43 +05303316 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003317 hdd_err("Command not allowed in FTM mode");
3318 return -EPERM;
3319 }
3320
Jeff Johnsonb8944722017-09-03 09:03:19 -07003321 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303322 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003323 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003324
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +05303325 mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
3326 if (!mac_spoofing_enabled) {
Dustin Browna7bb6ae2018-08-16 16:51:50 -07003327 hdd_debug("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003328 return -ENOTSUPP;
3329 }
3330
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003331 /*
3332 * audit note: it is ok to pass a NULL policy here since only
3333 * one attribute is parsed and it is explicitly validated
3334 */
Dustin Brown4ea21db2018-01-05 14:13:17 -08003335 if (wlan_cfg80211_nla_parse(tb,
3336 QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
3337 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003338 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003339 return -EINVAL;
3340 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003341
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003342 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003343 hdd_err("attr mac oui failed");
Jeff Johnson9d45f332019-01-29 08:42:00 -08003344 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003345 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003346
3347 len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]);
Jeff Johnson9d45f332019-01-29 08:42:00 -08003348 if (len != sizeof(scan_mac_oui.oui)) {
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003349 hdd_err("attr mac oui invalid size %d expected %zu",
Jeff Johnson9d45f332019-01-29 08:42:00 -08003350 len, sizeof(scan_mac_oui.oui));
3351 return -EINVAL;
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003352 }
3353
Jeff Johnson9d45f332019-01-29 08:42:00 -08003354 nla_memcpy(scan_mac_oui.oui,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003355 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
Jeff Johnson9d45f332019-01-29 08:42:00 -08003356 sizeof(scan_mac_oui.oui));
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303357
Jeff Johnson9d45f332019-01-29 08:42:00 -08003358 /* populate rest of scan_mac_oui for mac addr randomization */
Jeff Johnsoncf07c312019-02-04 13:53:29 -08003359 scan_mac_oui.vdev_id = adapter->vdev_id;
Jeff Johnson9d45f332019-01-29 08:42:00 -08003360 scan_mac_oui.enb_probe_req_sno_randomization = true;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303361
Jeff Johnson9d45f332019-01-29 08:42:00 -08003362 hdd_debug("Oui (%02x:%02x:%02x), vdev_id = %d",
3363 scan_mac_oui.oui[0], scan_mac_oui.oui[1],
3364 scan_mac_oui.oui[2], scan_mac_oui.vdev_id);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303365
Jeff Johnson9d45f332019-01-29 08:42:00 -08003366 hdd_update_ie_whitelist_attr(&scan_mac_oui.ie_whitelist, hdd_ctx);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303367
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003368 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson9d45f332019-01-29 08:42:00 -08003369 status = sme_set_scanning_mac_oui(mac_handle, &scan_mac_oui);
3370 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson020db452016-06-29 14:37:26 -07003371 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Jeff Johnson9d45f332019-01-29 08:42:00 -08003372
3373 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003374}
3375
3376/**
3377 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3378 * @wiphy: pointer to wireless wiphy structure.
3379 * @wdev: pointer to wireless_dev structure.
3380 * @data: Pointer to the data to be passed via vendor interface
3381 * @data_len:Length of the data to be passed
3382 *
3383 * Set the MAC address that is to be used for scanning. This is an
3384 * SSR-protecting wrapper function.
3385 *
3386 * Return: Return the Success or Failure code.
3387 */
3388static int
3389wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3390 struct wireless_dev *wdev,
3391 const void *data,
3392 int data_len)
3393{
Dustin Browna09acf42018-11-08 12:32:26 +05303394 int errno;
3395 struct osif_vdev_sync *vdev_sync;
3396
3397 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
3398 if (errno)
3399 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003400
Dustin Browna09acf42018-11-08 12:32:26 +05303401 errno = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
3402 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003403
Dustin Browna09acf42018-11-08 12:32:26 +05303404 osif_vdev_sync_op_stop(vdev_sync);
3405
3406 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003407}
3408
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303409/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003410 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
3411 * @feature_flags: pointer to the byte array of features.
3412 * @feature: Feature to be turned ON in the byte array.
3413 *
3414 * Return: None
3415 *
3416 * This is called to turn ON or SET the feature flag for the requested feature.
3417 **/
3418#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07003419static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
3420 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003421{
3422 uint32_t index;
3423 uint8_t bit_mask;
3424
3425 index = feature / NUM_BITS_IN_BYTE;
3426 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
3427 feature_flags[index] |= bit_mask;
3428}
3429
3430/**
3431 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
3432 * @wiphy: pointer to wireless wiphy structure.
3433 * @wdev: pointer to wireless_dev structure.
3434 * @data: Pointer to the data to be passed via vendor interface
3435 * @data_len:Length of the data to be passed
3436 *
3437 * This is called when wlan driver needs to send supported feature set to
3438 * supplicant upon a request/query from the supplicant.
3439 *
3440 * Return: Return the Success or Failure code.
3441 **/
3442#define MAX_CONCURRENT_CHAN_ON_24G 2
3443#define MAX_CONCURRENT_CHAN_ON_5G 2
3444static int
3445__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3446 struct wireless_dev *wdev,
3447 const void *data, int data_len)
3448{
3449 struct sk_buff *skb = NULL;
3450 uint32_t dbs_capability = 0;
3451 bool one_by_one_dbs, two_by_two_dbs;
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303452 bool value;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303453 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303454 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003455 int ret_val;
3456
3457 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003458 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003459
Dustin Brownfdf17c12018-03-14 12:55:34 -07003460 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08003461
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003462 ret_val = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003463 if (ret_val)
3464 return ret_val;
3465
Anurag Chouhan6d760662016-02-20 16:05:43 +05303466 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003467 hdd_err("Command not allowed in FTM mode");
3468 return -EPERM;
3469 }
3470
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003471 if (roaming_offload_enabled(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003472 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003473 wlan_hdd_cfg80211_set_feature(feature_flags,
3474 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
3475 }
3476
3477 wlan_hdd_cfg80211_set_feature(feature_flags,
3478 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Dustin Brown76cd2932018-09-11 16:03:05 -07003479 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx->psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003480 wlan_hdd_cfg80211_set_feature(feature_flags,
3481 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07003482
3483 if (wma_is_p2p_lo_capable())
3484 wlan_hdd_cfg80211_set_feature(feature_flags,
3485 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
3486
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303487 value = 0;
Dustin Brown05d81302018-09-11 16:49:22 -07003488 status = ucfg_mlme_get_oce_sta_enabled_info(hdd_ctx->psoc, &value);
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303489 if (QDF_IS_STATUS_ERROR(status))
3490 hdd_err("could not get OCE STA enable info");
3491 if (value)
yeshwanth sriram guntuka1413dfb2017-06-23 14:09:48 +05303492 wlan_hdd_cfg80211_set_feature(feature_flags,
3493 QCA_WLAN_VENDOR_FEATURE_OCE_STA);
3494
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303495 value = 0;
Dustin Brown05d81302018-09-11 16:49:22 -07003496 status = ucfg_mlme_get_oce_sap_enabled_info(hdd_ctx->psoc, &value);
Karthik Kantamneni2231a232018-09-11 15:45:55 +05303497 if (QDF_IS_STATUS_ERROR(status))
3498 hdd_err("could not get OCE SAP enable info");
3499 if (value)
yeshwanth sriram guntuka1413dfb2017-06-23 14:09:48 +05303500 wlan_hdd_cfg80211_set_feature(feature_flags,
3501 QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON);
3502
Kiran Kumar Lokere0508af92018-04-23 18:38:32 -07003503 /* Check the kernel version for upstream commit aced43ce780dc5 that
3504 * has support for processing user cell_base hints when wiphy is
3505 * self managed or check the backport flag for the same.
3506 */
3507#if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
3508 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
3509 wlan_hdd_cfg80211_set_feature(feature_flags,
3510 QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY);
3511#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003512 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
3513 NLMSG_HDRLEN);
3514
3515 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003516 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003517 return -ENOMEM;
3518 }
3519
3520 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
3521 sizeof(feature_flags), feature_flags))
3522 goto nla_put_failure;
3523
Dustin Brown76cd2932018-09-11 16:03:05 -07003524 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx->psoc,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003525 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303526 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003527 if (one_by_one_dbs)
3528 dbs_capability = DRV_DBS_CAPABILITY_1X1;
3529
3530 if (two_by_two_dbs)
3531 dbs_capability = DRV_DBS_CAPABILITY_2X2;
3532
3533 if (!one_by_one_dbs && !two_by_two_dbs)
3534 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
3535 } else {
3536 hdd_err("wma_get_dbs_hw_mode failed");
3537 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
3538 }
3539
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003540 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003541
3542 if (nla_put_u32(skb,
Ganesh Kondabattinid921ed92017-06-20 16:40:48 +05303543 QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA,
3544 dbs_capability))
3545 goto nla_put_failure;
3546
3547
3548 if (nla_put_u32(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003549 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
3550 MAX_CONCURRENT_CHAN_ON_24G))
3551 goto nla_put_failure;
3552
3553 if (nla_put_u32(skb,
3554 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
3555 MAX_CONCURRENT_CHAN_ON_5G))
3556 goto nla_put_failure;
3557
3558 return cfg80211_vendor_cmd_reply(skb);
3559
3560nla_put_failure:
3561 kfree_skb(skb);
3562 return -EINVAL;
3563}
3564
3565/**
3566 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
3567 * @wiphy: pointer to wireless wiphy structure.
3568 * @wdev: pointer to wireless_dev structure.
3569 * @data: Pointer to the data to be passed via vendor interface
3570 * @data_len:Length of the data to be passed
3571 *
3572 * This is called when wlan driver needs to send supported feature set to
3573 * supplicant upon a request/query from the supplicant.
3574 *
3575 * Return: Return the Success or Failure code.
3576 */
3577static int
3578wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3579 struct wireless_dev *wdev,
3580 const void *data, int data_len)
3581{
Dustin Brown363b4792019-02-05 16:11:55 -08003582 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08003583 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303584
Dustin Brown363b4792019-02-05 16:11:55 -08003585 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08003586 if (errno)
3587 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003588
Dustin Brownf0f00612019-01-31 16:02:24 -08003589 errno = __wlan_hdd_cfg80211_get_features(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003590
Dustin Brown363b4792019-02-05 16:11:55 -08003591 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05303592
Dustin Brownf0f00612019-01-31 16:02:24 -08003593 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003594}
3595
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303596#define PARAM_NUM_NW \
3597 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
3598#define PARAM_SET_BSSID \
3599 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003600#define PARAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303601#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303602#define MAX_ROAMING_PARAM \
3603 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003604#define PARAM_NUM_BSSID \
3605 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID
3606#define PARAM_BSSID_PREFS \
3607 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS
3608#define PARAM_ROAM_BSSID \
3609 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID
3610#define PARAM_RSSI_MODIFIER \
3611 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER
3612#define PARAMS_NUM_BSSID \
3613 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID
3614#define PARAM_BSSID_PARAMS \
3615 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS
3616#define PARAM_A_BAND_BOOST_THLD \
3617 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD
3618#define PARAM_A_BAND_PELT_THLD \
3619 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD
3620#define PARAM_A_BAND_BOOST_FACTOR \
3621 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR
3622#define PARAM_A_BAND_PELT_FACTOR \
3623 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR
3624#define PARAM_A_BAND_MAX_BOOST \
3625 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST
3626#define PARAM_ROAM_HISTERESYS \
3627 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS
3628#define PARAM_RSSI_TRIGGER \
3629 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER
3630#define PARAM_ROAM_ENABLE \
3631 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE
3632
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303633
3634static const struct nla_policy
3635wlan_hdd_set_roam_param_policy[MAX_ROAMING_PARAM + 1] = {
3636 [QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD] = {.type = NLA_U32},
3637 [QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID] = {.type = NLA_U32},
3638 [PARAM_NUM_NW] = {.type = NLA_U32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003639 [PARAM_A_BAND_BOOST_FACTOR] = {.type = NLA_U32},
3640 [PARAM_A_BAND_PELT_FACTOR] = {.type = NLA_U32},
3641 [PARAM_A_BAND_MAX_BOOST] = {.type = NLA_U32},
3642 [PARAM_ROAM_HISTERESYS] = {.type = NLA_S32},
3643 [PARAM_A_BAND_BOOST_THLD] = {.type = NLA_S32},
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07003644 [PARAM_A_BAND_PELT_THLD] = {.type = NLA_S32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003645 [PARAM_RSSI_TRIGGER] = {.type = NLA_U32},
3646 [PARAM_ROAM_ENABLE] = { .type = NLA_S32},
3647 [PARAM_NUM_BSSID] = {.type = NLA_U32},
3648 [PARAM_RSSI_MODIFIER] = {.type = NLA_U32},
3649 [PARAMS_NUM_BSSID] = {.type = NLA_U32},
3650 [PARAM_ROAM_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
3651 [PARAM_SET_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303652};
3653
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003654/**
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003655 * hdd_set_white_list() - parse white list
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003656 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003657 * @roam_params: roam params
3658 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003659 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003660 *
3661 * Return: 0 on success; error number on failure
3662 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003663static int hdd_set_white_list(struct hdd_context *hdd_ctx,
3664 struct roam_ext_params *roam_params,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003665 struct nlattr **tb, uint8_t vdev_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003666{
3667 int rem, i;
3668 uint32_t buf_len = 0, count;
3669 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3670 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003671 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003672
3673 i = 0;
3674 if (tb[PARAM_NUM_NW]) {
3675 count = nla_get_u32(tb[PARAM_NUM_NW]);
3676 } else {
3677 hdd_err("Number of networks is not provided");
3678 goto fail;
3679 }
3680
3681 if (count && tb[PARAM_SSID_LIST]) {
3682 nla_for_each_nested(curr_attr,
3683 tb[PARAM_SSID_LIST], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08003684 if (wlan_cfg80211_nla_parse(tb2,
3685 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
3686 nla_data(curr_attr),
3687 nla_len(curr_attr),
3688 wlan_hdd_set_roam_param_policy)) {
3689 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003690 goto fail;
3691 }
3692 /* Parse and Fetch allowed SSID list*/
3693 if (!tb2[PARAM_LIST_SSID]) {
3694 hdd_err("attr allowed ssid failed");
3695 goto fail;
3696 }
3697 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
3698 /*
3699 * Upper Layers include a null termination
3700 * character. Check for the actual permissible
3701 * length of SSID and also ensure not to copy
3702 * the NULL termination character to the driver
3703 * buffer.
3704 */
3705 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
3706 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
3707 nla_memcpy(roam_params->ssid_allowed_list[i].ssId,
3708 tb2[PARAM_LIST_SSID], buf_len - 1);
3709 roam_params->ssid_allowed_list[i].length = buf_len - 1;
3710 hdd_debug("SSID[%d]: %.*s,length = %d",
3711 i,
3712 roam_params->ssid_allowed_list[i].length,
3713 roam_params->ssid_allowed_list[i].ssId,
3714 roam_params->ssid_allowed_list[i].length);
3715 i++;
3716 } else {
3717 hdd_err("Invalid buffer length");
3718 }
3719 }
3720 }
3721
3722 if (i != count) {
3723 hdd_err("Invalid number of SSIDs i = %d, count = %d", i, count);
3724 goto fail;
3725 }
3726
3727 roam_params->num_ssid_allowed_list = i;
3728 hdd_debug("Num of Allowed SSID %d", roam_params->num_ssid_allowed_list);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003729 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003730 sme_update_roam_params(mac_handle, vdev_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003731 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3732 return 0;
3733
3734fail:
3735 return -EINVAL;
3736}
3737
3738/**
3739 * hdd_set_bssid_prefs() - parse set bssid prefs
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003740 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003741 * @roam_params: roam params
3742 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003743 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003744 *
3745 * Return: 0 on success; error number on failure
3746 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003747static int hdd_set_bssid_prefs(struct hdd_context *hdd_ctx,
3748 struct roam_ext_params *roam_params,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003749 struct nlattr **tb, uint8_t vdev_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003750{
3751 int rem, i;
3752 uint32_t count;
3753 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3754 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003755 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003756
3757 /* Parse and fetch number of preferred BSSID */
3758 if (!tb[PARAM_NUM_BSSID]) {
3759 hdd_err("attr num of preferred bssid failed");
3760 goto fail;
3761 }
3762 count = nla_get_u32(tb[PARAM_NUM_BSSID]);
3763 if (count > MAX_BSSID_FAVORED) {
3764 hdd_err("Preferred BSSID count %u exceeds max %u",
3765 count, MAX_BSSID_FAVORED);
3766 goto fail;
3767 }
3768 hdd_debug("Num of Preferred BSSID (%d)", count);
3769 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS]) {
3770 hdd_err("attr Preferred BSSID failed");
3771 goto fail;
3772 }
3773
3774 i = 0;
3775 nla_for_each_nested(curr_attr,
3776 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3777 rem) {
3778 if (i == count) {
3779 hdd_warn("Ignoring excess Preferred BSSID");
3780 break;
3781 }
3782
Dustin Brown4ea21db2018-01-05 14:13:17 -08003783 if (wlan_cfg80211_nla_parse(tb2,
3784 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3785 nla_data(curr_attr),
3786 nla_len(curr_attr),
3787 wlan_hdd_set_roam_param_policy)) {
3788 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003789 goto fail;
3790 }
3791 /* Parse and fetch MAC address */
3792 if (!tb2[PARAM_ROAM_BSSID]) {
3793 hdd_err("attr mac address failed");
3794 goto fail;
3795 }
3796 nla_memcpy(roam_params->bssid_favored[i].bytes,
3797 tb2[PARAM_ROAM_BSSID],
3798 QDF_MAC_ADDR_SIZE);
3799 hdd_debug(MAC_ADDRESS_STR,
3800 MAC_ADDR_ARRAY(roam_params->bssid_favored[i].bytes));
3801 /* Parse and fetch preference factor*/
3802 if (!tb2[PARAM_RSSI_MODIFIER]) {
3803 hdd_err("BSSID Preference score failed");
3804 goto fail;
3805 }
3806 roam_params->bssid_favored_factor[i] = nla_get_u32(
3807 tb2[PARAM_RSSI_MODIFIER]);
3808 hdd_debug("BSSID Preference score (%d)",
3809 roam_params->bssid_favored_factor[i]);
3810 i++;
3811 }
3812 if (i < count)
3813 hdd_warn("Num Preferred BSSID %u less than expected %u",
3814 i, count);
3815
3816 roam_params->num_bssid_favored = i;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003817 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003818 sme_update_roam_params(mac_handle, vdev_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003819 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3820
3821 return 0;
3822
3823fail:
3824 return -EINVAL;
3825}
3826
3827/**
3828 * hdd_set_blacklist_bssid() - parse set blacklist bssid
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003829 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003830 * @roam_params: roam params
3831 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003832 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003833 *
3834 * Return: 0 on success; error number on failure
3835 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003836static int hdd_set_blacklist_bssid(struct hdd_context *hdd_ctx,
3837 struct roam_ext_params *roam_params,
3838 struct nlattr **tb,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003839 uint8_t vdev_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003840{
3841 int rem, i;
3842 uint32_t count;
3843 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3844 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003845 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003846
3847 /* Parse and fetch number of blacklist BSSID */
3848 if (!tb[PARAMS_NUM_BSSID]) {
3849 hdd_err("attr num of blacklist bssid failed");
3850 goto fail;
3851 }
3852 count = nla_get_u32(tb[PARAMS_NUM_BSSID]);
3853 if (count > MAX_BSSID_AVOID_LIST) {
3854 hdd_err("Blacklist BSSID count %u exceeds max %u",
3855 count, MAX_BSSID_AVOID_LIST);
3856 goto fail;
3857 }
3858 hdd_debug("Num of blacklist BSSID (%d)", count);
3859
3860 i = 0;
3861 if (count && tb[PARAM_BSSID_PARAMS]) {
3862 nla_for_each_nested(curr_attr,
3863 tb[PARAM_BSSID_PARAMS],
3864 rem) {
3865 if (i == count) {
3866 hdd_warn("Ignoring excess Blacklist BSSID");
3867 break;
3868 }
3869
Dustin Brown4ea21db2018-01-05 14:13:17 -08003870 if (wlan_cfg80211_nla_parse(tb2,
Dustin Brown3fb15042017-08-15 15:54:49 -07003871 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3872 nla_data(curr_attr),
3873 nla_len(curr_attr),
3874 wlan_hdd_set_roam_param_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08003875 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003876 goto fail;
3877 }
3878 /* Parse and fetch MAC address */
3879 if (!tb2[PARAM_SET_BSSID]) {
3880 hdd_err("attr blacklist addr failed");
3881 goto fail;
3882 }
3883 nla_memcpy(roam_params->bssid_avoid_list[i].bytes,
3884 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3885 hdd_debug(MAC_ADDRESS_STR,
3886 MAC_ADDR_ARRAY(roam_params->bssid_avoid_list[i].bytes));
3887 i++;
3888 }
3889 }
3890
3891 if (i < count)
3892 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3893 i, count);
3894
3895 roam_params->num_bssid_avoid_list = i;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003896 mac_handle = hdd_ctx->mac_handle;
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003897 sme_update_roam_params(mac_handle, vdev_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003898 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3899
3900 return 0;
3901fail:
3902 return -EINVAL;
3903}
3904
3905/**
3906 * hdd_set_ext_roam_params() - parse ext roam params
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003907 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003908 * @roam_params: roam params
3909 * @tb: list of attributes
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003910 * @vdev_id: vdev id
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003911 *
3912 * Return: 0 on success; error number on failure
3913 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003914static int hdd_set_ext_roam_params(struct hdd_context *hdd_ctx,
3915 const void *data, int data_len,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003916 uint8_t vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003917 struct roam_ext_params *roam_params)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003918{
3919 uint32_t cmd_type, req_id;
3920 struct nlattr *tb[MAX_ROAMING_PARAM + 1];
3921 int ret;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003922 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003923
Dustin Brown4ea21db2018-01-05 14:13:17 -08003924 if (wlan_cfg80211_nla_parse(tb, MAX_ROAMING_PARAM, data, data_len,
3925 wlan_hdd_set_roam_param_policy)) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003926 hdd_err("Invalid ATTR");
3927 return -EINVAL;
3928 }
3929 /* Parse and fetch Command Type */
3930 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
3931 hdd_err("roam cmd type failed");
3932 goto fail;
3933 }
3934
3935 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
3936 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
3937 hdd_err("attr request id failed");
3938 goto fail;
3939 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003940 mac_handle = hdd_ctx->mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003941 req_id = nla_get_u32(
3942 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
3943 hdd_debug("Req Id: %u Cmd Type: %u", req_id, cmd_type);
3944 switch (cmd_type) {
3945 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
Jeff Johnson55d2ab42019-03-06 11:43:49 -08003946 ret = hdd_set_white_list(hdd_ctx, roam_params, tb, vdev_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003947 if (ret)
3948 goto fail;
3949 break;
3950
3951 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
3952 /* Parse and fetch 5G Boost Threshold */
3953 if (!tb[PARAM_A_BAND_BOOST_THLD]) {
3954 hdd_err("5G boost threshold failed");
3955 goto fail;
3956 }
3957 roam_params->raise_rssi_thresh_5g = nla_get_s32(
3958 tb[PARAM_A_BAND_BOOST_THLD]);
3959 hdd_debug("5G Boost Threshold (%d)",
3960 roam_params->raise_rssi_thresh_5g);
3961 /* Parse and fetch 5G Penalty Threshold */
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07003962 if (!tb[PARAM_A_BAND_PELT_THLD]) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003963 hdd_err("5G penalty threshold failed");
3964 goto fail;
3965 }
3966 roam_params->drop_rssi_thresh_5g = nla_get_s32(
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07003967 tb[PARAM_A_BAND_PELT_THLD]);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003968 hdd_debug("5G Penalty Threshold (%d)",
3969 roam_params->drop_rssi_thresh_5g);
3970 /* Parse and fetch 5G Boost Factor */
3971 if (!tb[PARAM_A_BAND_BOOST_FACTOR]) {
3972 hdd_err("5G boost Factor failed");
3973 goto fail;
3974 }
3975 roam_params->raise_factor_5g = nla_get_u32(
3976 tb[PARAM_A_BAND_BOOST_FACTOR]);
3977 hdd_debug("5G Boost Factor (%d)",
3978 roam_params->raise_factor_5g);
3979 /* Parse and fetch 5G Penalty factor */
3980 if (!tb[PARAM_A_BAND_PELT_FACTOR]) {
3981 hdd_err("5G Penalty Factor failed");
3982 goto fail;
3983 }
3984 roam_params->drop_factor_5g = nla_get_u32(
3985 tb[PARAM_A_BAND_PELT_FACTOR]);
3986 hdd_debug("5G Penalty factor (%d)",
3987 roam_params->drop_factor_5g);
3988 /* Parse and fetch 5G Max Boost */
3989 if (!tb[PARAM_A_BAND_MAX_BOOST]) {
3990 hdd_err("5G Max Boost failed");
3991 goto fail;
3992 }
3993 roam_params->max_raise_rssi_5g = nla_get_u32(
3994 tb[PARAM_A_BAND_MAX_BOOST]);
3995 hdd_debug("5G Max Boost (%d)",
3996 roam_params->max_raise_rssi_5g);
3997 /* Parse and fetch Rssi Diff */
3998 if (!tb[PARAM_ROAM_HISTERESYS]) {
3999 hdd_err("Rssi Diff failed");
4000 goto fail;
4001 }
4002 roam_params->rssi_diff = nla_get_s32(
4003 tb[PARAM_ROAM_HISTERESYS]);
4004 hdd_debug("RSSI Diff (%d)",
4005 roam_params->rssi_diff);
4006 /* Parse and fetch Alert Rssi Threshold */
4007 if (!tb[PARAM_RSSI_TRIGGER]) {
4008 hdd_err("Alert Rssi Threshold failed");
4009 goto fail;
4010 }
4011 roam_params->alert_rssi_threshold = nla_get_u32(
4012 tb[PARAM_RSSI_TRIGGER]);
4013 hdd_debug("Alert RSSI Threshold (%d)",
4014 roam_params->alert_rssi_threshold);
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004015 sme_update_roam_params(mac_handle, vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004016 roam_params,
4017 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004018 break;
4019 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
4020 /* Parse and fetch Activate Good Rssi Roam */
4021 if (!tb[PARAM_ROAM_ENABLE]) {
4022 hdd_err("Activate Good Rssi Roam failed");
4023 goto fail;
4024 }
4025 roam_params->good_rssi_roam = nla_get_s32(
4026 tb[PARAM_ROAM_ENABLE]);
4027 hdd_debug("Activate Good Rssi Roam (%d)",
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004028 roam_params->good_rssi_roam);
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004029 sme_update_roam_params(mac_handle, vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004030 roam_params,
4031 REASON_ROAM_GOOD_RSSI_CHANGED);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004032 break;
4033 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004034 ret = hdd_set_bssid_prefs(hdd_ctx, roam_params, tb, vdev_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004035 if (ret)
4036 goto fail;
4037 break;
4038 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004039 ret = hdd_set_blacklist_bssid(hdd_ctx, roam_params,
Jeff Johnson55d2ab42019-03-06 11:43:49 -08004040 tb, vdev_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004041 if (ret)
4042 goto fail;
4043 break;
4044 }
4045
4046 return 0;
4047
4048fail:
4049 return -EINVAL;
4050}
4051
4052/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004053 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
4054 * @wiphy: The wiphy structure
4055 * @wdev: The wireless device
4056 * @data: Data passed by framework
4057 * @data_len: Parameters to be configured passed as data
4058 *
4059 * The roaming related parameters are configured by the framework
4060 * using this interface.
4061 *
4062 * Return: Return either success or failure code.
4063 */
4064static int
4065__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
4066 struct wireless_dev *wdev, const void *data, int data_len)
4067{
4068 struct net_device *dev = wdev->netdev;
Jeff Johnsonce2ba702017-10-02 13:30:24 -07004069 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -07004070 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004071 struct roam_ext_params *roam_params = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004072 int ret;
4073
Dustin Brownfdf17c12018-03-14 12:55:34 -07004074 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08004075
Anurag Chouhan6d760662016-02-20 16:05:43 +05304076 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004077 hdd_err("Command not allowed in FTM mode");
4078 return -EPERM;
4079 }
4080
Jeff Johnsonb8944722017-09-03 09:03:19 -07004081 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304082 if (ret)
4083 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004084
Jeff Johnsonb8944722017-09-03 09:03:19 -07004085 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05304086 hdd_err("Driver Modules are closed");
4087 return -EINVAL;
4088 }
4089
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004090 roam_params = qdf_mem_malloc(sizeof(*roam_params));
Min Liu74a1a502018-10-10 19:59:07 +08004091 if (!roam_params)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004092 return -ENOMEM;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004093
Jeff Johnsonb8944722017-09-03 09:03:19 -07004094 ret = hdd_set_ext_roam_params(hdd_ctx, data, data_len,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08004095 adapter->vdev_id, roam_params);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004096 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004097 goto fail;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304098
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004099 if (roam_params)
4100 qdf_mem_free(roam_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004101 return 0;
4102fail:
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004103 if (roam_params)
4104 qdf_mem_free(roam_params);
4105
4106 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004107}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304108#undef PARAM_NUM_NW
4109#undef PARAM_SET_BSSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004110#undef PARAM_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304111#undef PARAM_LIST_SSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004112#undef MAX_ROAMING_PARAM
4113#undef PARAM_NUM_BSSID
4114#undef PARAM_BSSID_PREFS
4115#undef PARAM_ROAM_BSSID
4116#undef PARAM_RSSI_MODIFIER
4117#undef PARAMS_NUM_BSSID
4118#undef PARAM_BSSID_PARAMS
4119#undef PARAM_A_BAND_BOOST_THLD
4120#undef PARAM_A_BAND_PELT_THLD
4121#undef PARAM_A_BAND_BOOST_FACTOR
4122#undef PARAM_A_BAND_PELT_FACTOR
4123#undef PARAM_A_BAND_MAX_BOOST
4124#undef PARAM_ROAM_HISTERESYS
4125#undef PARAM_RSSI_TRIGGER
4126#undef PARAM_ROAM_ENABLE
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304127
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004128
4129/**
4130 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
4131 * @wiphy: pointer to wireless wiphy structure.
4132 * @wdev: pointer to wireless_dev structure.
4133 * @data: Pointer to the data to be passed via vendor interface
4134 * @data_len:Length of the data to be passed
4135 *
4136 * Return: Return the Success or Failure code.
4137 */
4138static int
4139wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
4140 struct wireless_dev *wdev,
4141 const void *data,
4142 int data_len)
4143{
Dustin Browna09acf42018-11-08 12:32:26 +05304144 int errno;
4145 struct osif_vdev_sync *vdev_sync;
4146
4147 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
4148 if (errno)
4149 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004150
Dustin Browna09acf42018-11-08 12:32:26 +05304151 errno = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004152 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004153
Dustin Browna09acf42018-11-08 12:32:26 +05304154 osif_vdev_sync_op_stop(vdev_sync);
4155
4156 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004157}
4158
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304159#define PWR_SAVE_FAIL_CMD_INDEX \
4160 QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX
Jeff Johnsonb7fa2562018-07-02 08:36:17 -07004161
4162void hdd_chip_pwr_save_fail_detected_cb(hdd_handle_t hdd_handle,
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304163 struct chip_pwr_save_fail_detected_params
4164 *data)
4165{
Jeff Johnsonb7fa2562018-07-02 08:36:17 -07004166 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304167 struct sk_buff *skb;
4168 int flags = cds_get_gfp_flags();
4169
Dustin Brown491d54b2018-03-14 12:39:11 -07004170 hdd_enter();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304171
4172 if (wlan_hdd_validate_context(hdd_ctx))
4173 return;
4174
4175 if (!data) {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07004176 hdd_debug("data is null");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304177 return;
4178 }
4179
4180 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4181 NULL, NLMSG_HDRLEN +
4182 sizeof(data->failure_reason_code) +
4183 NLMSG_HDRLEN, PWR_SAVE_FAIL_CMD_INDEX,
4184 flags);
4185
4186 if (!skb) {
Dustin Brown5e89ef82018-03-14 11:50:23 -07004187 hdd_info("cfg80211_vendor_event_alloc failed");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304188 return;
4189 }
4190
Dustin Brownbacc48f2018-03-14 14:48:44 -07004191 hdd_debug("failure reason code: %u", data->failure_reason_code);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304192
4193 if (nla_put_u32(skb,
4194 QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON,
4195 data->failure_reason_code))
4196 goto fail;
4197
4198 cfg80211_vendor_event(skb, flags);
Dustin Browne74003f2018-03-14 12:51:58 -07004199 hdd_exit();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304200 return;
4201
4202fail:
4203 kfree_skb(skb);
4204}
4205#undef PWR_SAVE_FAIL_CMD_INDEX
4206
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207static const struct nla_policy
4208wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
4209 +1] = {
4210 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
4211};
4212
4213/**
4214 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
4215 * @hdd_ctx: HDD context
4216 * @device_mode: device mode
4217 * Return: bool
4218 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004219static bool wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context *hdd_ctx,
Jeff Johnsonc1e62782017-11-09 09:50:17 -08004220 enum QDF_OPMODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004221{
Jeff Johnsone5006672017-08-29 14:39:02 -07004222 struct hdd_adapter *adapter;
Jeff Johnson87251032017-08-29 13:31:11 -07004223 struct hdd_ap_ctx *ap_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004224 struct hdd_station_ctx *sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004225
Dustin Brown920397d2017-12-13 16:27:50 -08004226 hdd_for_each_adapter(hdd_ctx, adapter) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004227 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08004228 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004229 ap_ctx =
4230 WLAN_HDD_GET_AP_CTX_PTR(adapter);
4231
4232 /*
4233 * if there is SAP already running on DFS channel,
4234 * do not disable scan on dfs channels. Note that
4235 * with SAP on DFS, there cannot be conurrency on
4236 * single radio. But then we can have multiple
4237 * radios !!
4238 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07004239 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
Dustin Brown07901ec2018-09-07 11:02:41 -07004240 hdd_ctx->pdev,
Jeff Johnson01206862017-10-27 20:55:59 -07004241 ap_ctx->operating_channel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004242 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004243 return true;
4244 }
4245 }
4246
4247 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08004248 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004249 sta_ctx =
4250 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4251
4252 /*
4253 * if STA is already connected on DFS channel,
4254 * do not disable scan on dfs channels
4255 */
4256 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07004257 (CHANNEL_STATE_DFS ==
Dustin Brown07901ec2018-09-07 11:02:41 -07004258 wlan_reg_get_channel_state(hdd_ctx->pdev,
Jeff Johnson8626e932019-02-27 18:35:22 -08004259 sta_ctx->conn_info.channel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07004260 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004261 return true;
4262 }
4263 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004264 }
4265
4266 return false;
4267}
4268
4269/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004270 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004271 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004272 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004273 *
4274 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004275 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004276 * Fails the disable request if any device is active on a DFS channel.
4277 *
4278 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004280
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004281int wlan_hdd_enable_dfs_chan_scan(struct hdd_context *hdd_ctx,
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004282 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004283{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304284 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004285 bool err;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004286 mac_handle_t mac_handle;
gaurank kathpalia97c070b2019-01-07 17:23:06 +05304287 bool enable_dfs_scan = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004288
gaurank kathpalia97c070b2019-01-07 17:23:06 +05304289 ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
4290 &enable_dfs_scan);
4291
4292 if (enable_dfs_channels == enable_dfs_scan) {
Dustin Brown6a8d39b2018-08-14 15:27:26 -07004293 hdd_debug("DFS channels are already %s",
4294 enable_dfs_channels ? "enabled" : "disabled");
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004295 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004296 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004297
4298 if (!enable_dfs_channels) {
4299 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
4300 QDF_STA_MODE);
4301 if (err)
4302 return -EOPNOTSUPP;
4303
4304 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
4305 QDF_SAP_MODE);
4306 if (err)
4307 return -EOPNOTSUPP;
4308 }
4309
gaurank kathpalia97c070b2019-01-07 17:23:06 +05304310 ucfg_scan_cfg_set_dfs_chan_scan_allowed(hdd_ctx->psoc,
4311 enable_dfs_channels);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004312
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004313 mac_handle = hdd_ctx->mac_handle;
4314 status = sme_enable_dfs_chan_scan(mac_handle, enable_dfs_channels);
Min Liu5eaf7242018-03-13 17:32:15 +08004315 if (QDF_IS_STATUS_ERROR(status)) {
4316 hdd_err("Failed to set DFS channel scan flag to %d",
4317 enable_dfs_channels);
4318 return qdf_status_to_os_return(status);
4319 }
4320
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004321 hdd_abort_mac_scan_all_adapters(hdd_ctx);
4322
4323 /* pass dfs channel status to regulatory component */
Dustin Brown07901ec2018-09-07 11:02:41 -07004324 status = ucfg_reg_enable_dfs_channels(hdd_ctx->pdev,
4325 enable_dfs_channels);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004326
4327 if (QDF_IS_STATUS_ERROR(status))
4328 hdd_err("Failed to %s DFS channels",
4329 enable_dfs_channels ? "enable" : "disable");
4330
4331 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004332}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004333
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004334/**
4335 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
4336 * @wiphy: corestack handler
4337 * @wdev: wireless device
4338 * @data: data
4339 * @data_len: data length
4340 * Return: success(0) or reason code for failure
4341 */
4342static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
4343 struct wireless_dev *wdev,
4344 const void *data,
4345 int data_len)
4346{
4347 struct net_device *dev = wdev->netdev;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004348 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004349 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
4350 int ret_val;
4351 uint32_t no_dfs_flag = 0;
gaurank kathpalia97c070b2019-01-07 17:23:06 +05304352 bool enable_dfs_scan = true;
Dustin Brownfdf17c12018-03-14 12:55:34 -07004353 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08004354
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004355 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304356 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004357 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004358
Dustin Brown4ea21db2018-01-05 14:13:17 -08004359 if (wlan_cfg80211_nla_parse(tb,
4360 QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
4361 data, data_len,
4362 wlan_hdd_set_no_dfs_flag_config_policy)) {
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004363 hdd_err("invalid attr");
4364 return -EINVAL;
4365 }
4366
4367 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
4368 hdd_err("attr dfs flag failed");
4369 return -EINVAL;
4370 }
4371
4372 no_dfs_flag = nla_get_u32(
4373 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
4374
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004375 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004376
4377 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07004378 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004379 return -EINVAL;
4380 }
gaurank kathpalia97c070b2019-01-07 17:23:06 +05304381 ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
4382 &enable_dfs_scan);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004383
gaurank kathpalia97c070b2019-01-07 17:23:06 +05304384 if (enable_dfs_scan) {
bings50112bb2018-12-21 15:51:51 +08004385 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
4386 } else {
gaurank kathpalia97c070b2019-01-07 17:23:06 +05304387 if ((!no_dfs_flag) != enable_dfs_scan) {
bings50112bb2018-12-21 15:51:51 +08004388 hdd_err("DFS chan ini configured %d, no dfs flag: %d",
gaurank kathpalia97c070b2019-01-07 17:23:06 +05304389 enable_dfs_scan,
bings50112bb2018-12-21 15:51:51 +08004390 no_dfs_flag);
4391 return -EINVAL;
4392 }
4393 }
4394
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004395 return ret_val;
4396}
4397
4398/**
4399 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
4400 *
4401 * @wiphy: wiphy device pointer
4402 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07004403 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004404 * @data_len: Buffer length
4405 *
4406 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
4407 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
4408 *
4409 * Return: EOK or other error codes.
4410 */
4411
4412static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
4413 struct wireless_dev *wdev,
4414 const void *data,
4415 int data_len)
4416{
Dustin Brown363b4792019-02-05 16:11:55 -08004417 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08004418 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05304419
Dustin Brown363b4792019-02-05 16:11:55 -08004420 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08004421 if (errno)
4422 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004423
Dustin Brownf0f00612019-01-31 16:02:24 -08004424 errno = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
4425 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004426
Dustin Brown363b4792019-02-05 16:11:55 -08004427 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05304428
Dustin Brownf0f00612019-01-31 16:02:24 -08004429 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430}
4431
Manikandan Mohan80dea792016-04-28 16:36:48 -07004432static const struct nla_policy
4433wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
4434 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
4435};
4436
4437/**
4438 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
4439 * @wiphy: wiphy device pointer
4440 * @wdev: wireless device pointer
4441 * @data: Vendor command data buffer
4442 * @data_len: Buffer length
4443 *
4444 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
4445 * setup WISA Mode features.
4446 *
4447 * Return: Success(0) or reason code for failure
4448 */
4449static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
4450 struct wireless_dev *wdev, const void *data, int data_len)
4451{
4452 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07004453 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004454 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004455 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
4456 struct sir_wisa_params wisa;
4457 int ret_val;
4458 QDF_STATUS status;
4459 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07004460 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
4461 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004462 mac_handle_t mac_handle;
Manikandan Mohan80dea792016-04-28 16:36:48 -07004463
Dustin Brownfdf17c12018-03-14 12:55:34 -07004464 hdd_enter_dev(dev);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004465 ret_val = wlan_hdd_validate_context(hdd_ctx);
4466 if (ret_val)
4467 goto err;
4468
4469 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4470 hdd_err("Command not allowed in FTM mode");
4471 return -EPERM;
4472 }
4473
Dustin Brown4ea21db2018-01-05 14:13:17 -08004474 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data,
4475 data_len, wlan_hdd_wisa_cmd_policy)) {
Manikandan Mohan80dea792016-04-28 16:36:48 -07004476 hdd_err("Invalid WISA cmd attributes");
4477 ret_val = -EINVAL;
4478 goto err;
4479 }
4480 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
4481 hdd_err("Invalid WISA mode");
4482 ret_val = -EINVAL;
4483 goto err;
4484 }
4485
4486 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004487 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004488 wisa.mode = wisa_mode;
Jeff Johnsoncf07c312019-02-04 13:53:29 -08004489 wisa.vdev_id = adapter->vdev_id;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004490 mac_handle = hdd_ctx->mac_handle;
4491 status = sme_set_wisa_params(mac_handle, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07004492 if (!QDF_IS_STATUS_SUCCESS(status)) {
4493 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004494 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07004495 }
4496 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07004497 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08004498 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
4499 (struct cdp_pdev *)pdev,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08004500 adapter->vdev_id),
Leo Changfdb45c32016-10-28 11:09:23 -07004501 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004502err:
Dustin Browne74003f2018-03-14 12:51:58 -07004503 hdd_exit();
Manikandan Mohan80dea792016-04-28 16:36:48 -07004504 return ret_val;
4505}
4506
4507/**
4508 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
4509 * @wiphy: corestack handler
4510 * @wdev: wireless device
4511 * @data: data
4512 * @data_len: data length
4513 *
4514 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
4515 * setup WISA mode features.
4516 *
4517 * Return: Success(0) or reason code for failure
4518 */
4519static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
4520 struct wireless_dev *wdev,
4521 const void *data,
4522 int data_len)
4523{
Dustin Browna09acf42018-11-08 12:32:26 +05304524 int errno;
4525 struct osif_vdev_sync *vdev_sync;
4526
4527 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
4528 if (errno)
4529 return errno;
Manikandan Mohan80dea792016-04-28 16:36:48 -07004530
Dustin Browna09acf42018-11-08 12:32:26 +05304531 errno = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev,
4532 data, data_len);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004533
Dustin Browna09acf42018-11-08 12:32:26 +05304534 osif_vdev_sync_op_stop(vdev_sync);
4535
4536 return errno;
Manikandan Mohan80dea792016-04-28 16:36:48 -07004537}
4538
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05304539struct hdd_station_info *hdd_get_stainfo(struct hdd_station_info *astainfo,
4540 struct qdf_mac_addr mac_addr)
Will Huang496b36c2017-07-11 16:38:50 +08004541{
Jeff Johnson82155922017-09-30 16:54:14 -07004542 struct hdd_station_info *stainfo = NULL;
Will Huang496b36c2017-07-11 16:38:50 +08004543 int i;
4544
4545 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05304546 if (!qdf_mem_cmp(&astainfo[i].sta_mac,
Will Huang496b36c2017-07-11 16:38:50 +08004547 &mac_addr,
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05304548 QDF_MAC_ADDR_SIZE)) {
4549 stainfo = &astainfo[i];
4550 break;
4551 }
Will Huang496b36c2017-07-11 16:38:50 +08004552 }
4553
4554 return stainfo;
4555}
4556
Anurag Chouhan96919482016-07-13 16:36:57 +05304557/*
4558 * undef short names defined for get station command
4559 * used by __wlan_hdd_cfg80211_get_station_cmd()
4560 */
4561#undef STATION_INVALID
4562#undef STATION_INFO
4563#undef STATION_ASSOC_FAIL_REASON
Will Huang496b36c2017-07-11 16:38:50 +08004564#undef STATION_REMOTE
Anurag Chouhan96919482016-07-13 16:36:57 +05304565#undef STATION_MAX
Will Huang496b36c2017-07-11 16:38:50 +08004566#undef LINK_INFO_STANDARD_NL80211_ATTR
4567#undef AP_INFO_STANDARD_NL80211_ATTR
4568#undef INFO_ROAM_COUNT
4569#undef INFO_AKM
4570#undef WLAN802_11_MODE
4571#undef AP_INFO_HS20_INDICATION
4572#undef HT_OPERATION
4573#undef VHT_OPERATION
4574#undef INFO_ASSOC_FAIL_REASON
4575#undef REMOTE_MAX_PHY_RATE
4576#undef REMOTE_TX_PACKETS
4577#undef REMOTE_TX_BYTES
4578#undef REMOTE_RX_PACKETS
4579#undef REMOTE_RX_BYTES
4580#undef REMOTE_LAST_TX_RATE
4581#undef REMOTE_LAST_RX_RATE
4582#undef REMOTE_WMM
4583#undef REMOTE_SUPPORTED_MODE
4584#undef REMOTE_AMPDU
4585#undef REMOTE_TX_STBC
4586#undef REMOTE_RX_STBC
4587#undef REMOTE_CH_WIDTH
4588#undef REMOTE_SGI_ENABLE
4589#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
4590#undef REMOTE_PAD
4591#endif
Anurag Chouhan96919482016-07-13 16:36:57 +05304592
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004593#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4594/**
4595 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4596 * @wiphy: pointer to wireless wiphy structure.
4597 * @wdev: pointer to wireless_dev structure.
4598 * @data: Pointer to the Key data
4599 * @data_len:Length of the data passed
4600 *
4601 * This is called when wlan driver needs to save the keys received via
4602 * vendor specific command.
4603 *
4604 * Return: Return the Success or Failure code.
4605 */
4606static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4607 struct wireless_dev *wdev,
4608 const void *data, int data_len)
4609{
4610 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4611 struct net_device *dev = wdev->netdev;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004612 struct hdd_adapter *hdd_adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4613 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004614 int status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08004615 struct pmkid_mode_bits pmkid_modes;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004616 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004617
Dustin Brownfdf17c12018-03-14 12:55:34 -07004618 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08004619
Anurag Chouhan6d760662016-02-20 16:05:43 +05304620 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004621 hdd_err("Command not allowed in FTM mode");
4622 return -EPERM;
4623 }
4624
Hanumanth Reddy Pothula53874852018-03-08 19:57:49 +05304625 if ((data == NULL) || (data_len <= 0) ||
4626 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004627 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004628 return -EINVAL;
4629 }
4630
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004631 hdd_ctx = WLAN_HDD_GET_CTX(hdd_adapter);
4632 if (!hdd_ctx) {
Jeff Johnson020db452016-06-29 14:37:26 -07004633 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004634 return -EINVAL;
4635 }
4636
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004637 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304638 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004639 return status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08004640
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004641 hdd_get_pmkid_modes(hdd_ctx, &pmkid_modes);
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08004642
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004643 mac_handle = hdd_ctx->mac_handle;
4644 sme_update_roam_key_mgmt_offload_enabled(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08004645 hdd_adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004646 true, &pmkid_modes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304647 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4648 qdf_mem_copy(local_pmk, data, data_len);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08004649 sme_roam_set_psk_pmk(mac_handle, hdd_adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004650 local_pmk, data_len);
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +05304651 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004652 return 0;
4653}
4654
4655/**
4656 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4657 * @wiphy: pointer to wireless wiphy structure.
4658 * @wdev: pointer to wireless_dev structure.
4659 * @data: Pointer to the Key data
4660 * @data_len:Length of the data passed
4661 *
4662 * This is called when wlan driver needs to save the keys received via
4663 * vendor specific command.
4664 *
4665 * Return: Return the Success or Failure code.
4666 */
4667static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4668 struct wireless_dev *wdev,
4669 const void *data, int data_len)
4670{
Dustin Browna09acf42018-11-08 12:32:26 +05304671 int errno;
4672 struct osif_vdev_sync *vdev_sync;
4673
4674 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
4675 if (errno)
4676 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004677
Dustin Browna09acf42018-11-08 12:32:26 +05304678 errno = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev,
4679 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680
Dustin Browna09acf42018-11-08 12:32:26 +05304681 osif_vdev_sync_op_stop(vdev_sync);
4682
4683 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004684}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004685#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004686
4687static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4688 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4689 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4690 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004691 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004692};
4693
4694/**
4695 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4696 * @wiphy: pointer to wireless wiphy structure.
4697 * @wdev: pointer to wireless_dev structure.
4698 * @data: Pointer to the data to be passed via vendor interface
4699 * @data_len:Length of the data to be passed
4700 *
4701 * This is called when wlan driver needs to send wifi driver related info
4702 * (driver/fw version) to the user space application upon request.
4703 *
4704 * Return: Return the Success or Failure code.
4705 */
4706static int
4707__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4708 struct wireless_dev *wdev,
4709 const void *data, int data_len)
4710{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004711 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004712 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004713 tSirVersionString driver_version;
4714 tSirVersionString firmware_version;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004715 const char *hw_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004716 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004717 uint32_t sub_id = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004718 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004719 struct sk_buff *reply_skb;
4720 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004721
Dustin Brownfdf17c12018-03-14 12:55:34 -07004722 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08004723
Anurag Chouhan6d760662016-02-20 16:05:43 +05304724 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004725 hdd_err("Command not allowed in FTM mode");
4726 return -EPERM;
4727 }
4728
4729 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304730 if (status)
4731 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004732
Dustin Brown4ea21db2018-01-05 14:13:17 -08004733 if (wlan_cfg80211_nla_parse(tb_vendor,
4734 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
4735 data, data_len,
4736 qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004737 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004738 return -EINVAL;
4739 }
4740
4741 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004742 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004743 strlcpy(driver_version, QWLAN_VERSIONSTR,
4744 sizeof(driver_version));
4745 skb_len += strlen(driver_version) + 1;
4746 count++;
4747 }
4748
4749 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004750 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004751 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4752 &crmid);
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004753 sub_id = (hdd_ctx->target_fw_vers_ext & 0xf0000000) >> 28;
4754 hw_version = hdd_ctx->target_hw_name;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004755 snprintf(firmware_version, sizeof(firmware_version),
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004756 "FW:%d.%d.%d.%d.%d HW:%s", major_spid, minor_spid,
4757 siid, crmid, sub_id, hw_version);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004758 skb_len += strlen(firmware_version) + 1;
4759 count++;
4760 }
4761
Rajeev Kumar Sirasanagandla551613d2018-05-16 17:21:01 +05304762 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4763 hdd_debug("Rcvd req for Radio index");
4764 skb_len += sizeof(uint32_t);
4765 count++;
4766 }
4767
Ryan Hsu7ac88852016-04-28 10:20:34 -07004768 if (count == 0) {
4769 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004770 return -EINVAL;
4771 }
4772
Ryan Hsu7ac88852016-04-28 10:20:34 -07004773 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4774 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4775
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004776 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004777 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004778 return -ENOMEM;
4779 }
4780
Ryan Hsu7ac88852016-04-28 10:20:34 -07004781 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4782 if (nla_put_string(reply_skb,
4783 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4784 driver_version))
4785 goto error_nla_fail;
4786 }
4787
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304788 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004789 if (nla_put_string(reply_skb,
4790 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4791 firmware_version))
4792 goto error_nla_fail;
4793 }
4794
4795 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4796 if (nla_put_u32(reply_skb,
4797 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4798 hdd_ctx->radio_index))
4799 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004800 }
4801
4802 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004803
4804error_nla_fail:
4805 hdd_err("nla put fail");
4806 kfree_skb(reply_skb);
4807 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004808}
4809
4810/**
4811 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4812 * @wiphy: pointer to wireless wiphy structure.
4813 * @wdev: pointer to wireless_dev structure.
4814 * @data: Pointer to the data to be passed via vendor interface
4815 * @data_len:Length of the data to be passed
4816 *
4817 * This is called when wlan driver needs to send wifi driver related info
4818 * (driver/fw version) to the user space application upon request.
4819 *
4820 * Return: Return the Success or Failure code.
4821 */
4822static int
4823wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4824 struct wireless_dev *wdev,
4825 const void *data, int data_len)
4826{
Dustin Brown363b4792019-02-05 16:11:55 -08004827 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08004828 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004829
Dustin Brown363b4792019-02-05 16:11:55 -08004830 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08004831 if (errno)
4832 return errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05304833
Dustin Brownf0f00612019-01-31 16:02:24 -08004834 errno = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004835
Dustin Brown363b4792019-02-05 16:11:55 -08004836 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08004837
4838 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004839}
4840
4841/**
4842 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4843 * @wiphy: pointer to wireless wiphy structure.
4844 * @wdev: pointer to wireless_dev structure.
4845 * @data: Pointer to the data to be passed via vendor interface
4846 * @data_len:Length of the data to be passed
4847 *
4848 * This is called by userspace to know the supported logger features
4849 *
4850 * Return: Return the Success or Failure code.
4851 */
4852static int
4853__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4854 struct wireless_dev *wdev,
4855 const void *data, int data_len)
4856{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004857 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004858 int status;
4859 uint32_t features;
4860 struct sk_buff *reply_skb = NULL;
4861
Dustin Brownfdf17c12018-03-14 12:55:34 -07004862 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08004863
Anurag Chouhan6d760662016-02-20 16:05:43 +05304864 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004865 hdd_err("Command not allowed in FTM mode");
4866 return -EPERM;
4867 }
4868
4869 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304870 if (status)
4871 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004872
4873 features = 0;
4874
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004875 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4876 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4877 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
Srinivas Girigowdaa26eac02018-01-23 12:49:20 -08004878 features |= WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
Dundi Ravitejab189b742018-05-08 15:59:57 +05304879 features |= WIFI_LOGGER_PACKET_FATE_SUPPORTED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004880
4881 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4882 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4883 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004884 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004885 return -ENOMEM;
4886 }
4887
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004888 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004889 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4890 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004891 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004892 kfree_skb(reply_skb);
4893 return -EINVAL;
4894 }
4895
4896 return cfg80211_vendor_cmd_reply(reply_skb);
4897}
4898
4899/**
4900 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4901 * @wiphy: pointer to wireless wiphy structure.
4902 * @wdev: pointer to wireless_dev structure.
4903 * @data: Pointer to the data to be passed via vendor interface
4904 * @data_len:Length of the data to be passed
4905 *
4906 * This is called by userspace to know the supported logger features
4907 *
4908 * Return: Return the Success or Failure code.
4909 */
4910static int
4911wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4912 struct wireless_dev *wdev,
4913 const void *data, int data_len)
4914{
Dustin Brown363b4792019-02-05 16:11:55 -08004915 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08004916 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05304917
Dustin Brown363b4792019-02-05 16:11:55 -08004918 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08004919 if (errno)
4920 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004921
Dustin Brownf0f00612019-01-31 16:02:24 -08004922 errno = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4923 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004924
Dustin Brown363b4792019-02-05 16:11:55 -08004925 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05304926
Dustin Brownf0f00612019-01-31 16:02:24 -08004927 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004928}
4929
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304930#ifdef WLAN_FEATURE_GTK_OFFLOAD
4931void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
4932 uint8_t *kck_ptr, uint8_t *kek_ptr,
4933 uint32_t kek_len, uint8_t *replay_ctr,
4934 bool big_endian)
4935{
4936 struct hdd_station_ctx *hdd_sta_ctx;
4937 uint8_t *buf;
4938 int i;
4939 struct pmo_gtk_req *gtk_req = NULL;
Min Liu8c5d99e2018-09-10 17:18:44 +08004940 struct wlan_objmgr_vdev *vdev;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304941 QDF_STATUS status = QDF_STATUS_E_FAILURE;
4942
4943 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
Min Liu74a1a502018-10-10 19:59:07 +08004944 if (!gtk_req)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304945 return;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304946
4947 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4948 if (kck_ptr)
4949 qdf_mem_copy(gtk_req->kck, kck_ptr, NL80211_KCK_LEN);
4950
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08004951 if (kek_ptr) {
4952 /* paranoia */
4953 if (kek_len > sizeof(gtk_req->kek)) {
4954 kek_len = sizeof(gtk_req->kek);
4955 QDF_ASSERT(0);
4956 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304957 qdf_mem_copy(gtk_req->kek, kek_ptr, kek_len);
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08004958 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304959
Jeff Johnsone04b6992019-02-27 14:06:55 -08004960 qdf_copy_macaddr(&gtk_req->bssid, &hdd_sta_ctx->conn_info.bssid);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304961
4962 gtk_req->kek_len = kek_len;
gaurank kathpalia82a1b2b2018-07-10 16:49:10 +05304963 gtk_req->is_fils_connection = hdd_is_fils_connection(adapter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304964
4965 /* convert big to little endian since driver work on little endian */
4966 buf = (uint8_t *)&gtk_req->replay_counter;
4967 for (i = 0; i < 8; i++)
4968 buf[7 - i] = replay_ctr[i];
4969
Min Liu8c5d99e2018-09-10 17:18:44 +08004970 vdev = hdd_objmgr_get_vdev(adapter);
4971 if (!vdev)
4972 goto end;
4973 status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05304974 hdd_objmgr_put_vdev(vdev);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304975 if (status != QDF_STATUS_SUCCESS)
4976 hdd_err("Failed to cache GTK Offload");
4977
Min Liu8c5d99e2018-09-10 17:18:44 +08004978end:
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304979 qdf_mem_free(gtk_req);
4980}
4981#else
4982void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
4983 uint8_t *kck_ptr,
4984 uint8_t *kek_ptr,
4985 uint32_t kek_len,
4986 uint8_t *replay_ctr,
4987 bool big_endian)
4988{
4989}
4990#endif
4991
Sridhar Selvaraje5260442017-08-19 10:12:03 +05304992#if defined(WLAN_FEATURE_FILS_SK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304993/**
4994 * wlan_hdd_add_fils_params_roam_auth_event() - Adds FILS params in roam auth
4995 * @skb: SK buffer
4996 * @roam_info: Roam info
4997 *
4998 * API adds fils params[pmk, pmkid, next sequence number] to roam auth event
4999 *
5000 * Return: zero on success, error code on failure
5001 */
Jeff Johnson172237b2017-11-07 15:32:59 -08005002static int
5003wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
5004 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305005{
5006 if (roam_info->pmk_len &&
5007 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK,
5008 roam_info->pmk_len, roam_info->pmk)) {
5009 hdd_err("pmk send fail");
5010 return -EINVAL;
5011 }
5012
5013 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID,
5014 SIR_PMKID_LEN, roam_info->pmkid)) {
5015 hdd_err("pmkid send fail");
5016 return -EINVAL;
5017 }
5018
Vignesh Viswanathan8da68cf2017-09-07 14:00:04 +05305019 hdd_debug("Update ERP Seq Num %d, Next ERP Seq Num %d",
5020 roam_info->update_erp_next_seq_num,
5021 roam_info->next_erp_seq_num);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305022 if (roam_info->update_erp_next_seq_num &&
5023 nla_put_u16(skb,
5024 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM,
5025 roam_info->next_erp_seq_num)) {
5026 hdd_err("ERP seq num send fail");
5027 return -EINVAL;
5028 }
5029
5030 return 0;
5031}
5032#else
Jeff Johnson172237b2017-11-07 15:32:59 -08005033static inline int
5034wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
5035 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305036{
5037 return 0;
5038}
5039#endif
5040
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08005041#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005042/**
5043 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05305044 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005045 * @bssid: pointer to bssid of roamed AP.
5046 * @req_rsn_ie: Pointer to request RSN IE
5047 * @req_rsn_len: Length of the request RSN IE
5048 * @rsp_rsn_ie: Pointer to response RSN IE
5049 * @rsp_rsn_len: Length of the response RSN IE
5050 * @roam_info_ptr: Pointer to the roaming related information
5051 *
5052 * This is called when wlan driver needs to send the roaming and
5053 * authorization information after roaming.
5054 *
5055 * The information that would be sent is the request RSN IE, response
5056 * RSN IE and BSSID of the newly roamed AP.
5057 *
5058 * If the Authorized status is authenticated, then additional parameters
5059 * like PTK's KCK and KEK and Replay Counter would also be passed to the
5060 * supplicant.
5061 *
5062 * The supplicant upon receiving this event would ignore the legacy
5063 * cfg80211_roamed call and use the entire information from this event.
5064 * The cfg80211_roamed should still co-exist since the kernel will
5065 * make use of the parameters even if the supplicant ignores it.
5066 *
5067 * Return: Return the Success or Failure code.
5068 */
Jeff Johnsone5006672017-08-29 14:39:02 -07005069int wlan_hdd_send_roam_auth_event(struct hdd_adapter *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005070 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
Jeff Johnson172237b2017-11-07 15:32:59 -08005071 uint32_t rsp_rsn_len, struct csr_roam_info *roam_info_ptr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005072{
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005073 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005074 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08005075 eCsrAuthType auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305076 uint32_t fils_params_len;
5077 int status;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -07005078
Dustin Brown491d54b2018-03-14 12:39:11 -07005079 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005080
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005081 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005082 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005083
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005084 if (!roaming_offload_enabled(hdd_ctx) ||
5085 !roam_info_ptr->roamSynchInProgress)
Prashanth Bhattabfc25292015-11-05 11:16:21 -08005086 return 0;
5087
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305088 /*
5089 * PMK is sent from FW in Roam Synch Event for FILS Roaming.
5090 * In that case, add three more NL attributes.ie. PMK, PMKID
5091 * and ERP next sequence number. Add corresponding lengths
5092 * with 3 extra NL message headers for each of the
5093 * aforementioned params.
5094 */
5095 fils_params_len = roam_info_ptr->pmk_len + SIR_PMKID_LEN +
5096 sizeof(uint16_t) + (3 * NLMSG_HDRLEN);
5097
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005098 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05305099 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005100 ETH_ALEN + req_rsn_len + rsp_rsn_len +
5101 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305102 SIR_KCK_KEY_LEN + roam_info_ptr->kek_len +
5103 sizeof(uint8_t) + (8 * NLMSG_HDRLEN) +
5104 fils_params_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005105 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
5106 GFP_KERNEL);
5107
5108 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07005109 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005110 return -EINVAL;
5111 }
5112
5113 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
5114 ETH_ALEN, bssid) ||
5115 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
5116 req_rsn_len, req_rsn_ie) ||
5117 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
5118 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005119 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005120 goto nla_put_failure;
5121 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005122 if (roam_info_ptr->synchAuthStatus ==
5123 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07005124 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08005125 if (nla_put_u8(skb,
5126 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
5127 hdd_err("nla put fail");
5128 goto nla_put_failure;
5129 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08005130 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
5131 /* if FT or CCKM connection: dont send replay counter */
5132 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
5133 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
Pragaspathi Thilagaraj96259b22019-02-15 01:08:27 +05305134 auth_type != eCSR_AUTH_TYPE_FT_SAE &&
5135 auth_type != eCSR_AUTH_TYPE_FT_SUITEB_EAP_SHA384 &&
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08005136 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
5137 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
5138 nla_put(skb,
5139 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
5140 SIR_REPLAY_CTR_LEN,
5141 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005142 hdd_err("non FT/non CCKM connection");
5143 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08005144 goto nla_put_failure;
5145 }
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05305146 if (roam_info_ptr->kek_len > SIR_KEK_KEY_LEN_FILS ||
5147 nla_put(skb,
Naveen Rawat14298b92015-11-25 16:27:41 -08005148 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
5149 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
5150 nla_put(skb,
5151 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305152 roam_info_ptr->kek_len, roam_info_ptr->kek)) {
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05305153 hdd_err("nla put fail, kek_len %d",
5154 roam_info_ptr->kek_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005155 goto nla_put_failure;
5156 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305157
5158 status = wlan_hdd_add_fils_params_roam_auth_event(skb,
5159 roam_info_ptr);
5160 if (status)
5161 goto nla_put_failure;
5162
5163 /*
5164 * Save the gtk rekey parameters in HDD STA context. They will
5165 * be used next time when host enables GTK offload and goes
5166 * into power save state.
5167 */
5168 wlan_hdd_save_gtk_offload_params(adapter, roam_info_ptr->kck,
5169 roam_info_ptr->kek,
5170 roam_info_ptr->kek_len,
5171 roam_info_ptr->replay_ctr,
5172 true);
5173 hdd_debug("roam_info_ptr->replay_ctr 0x%llx",
5174 *((uint64_t *)roam_info_ptr->replay_ctr));
5175
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005176 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07005177 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005178 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
5179 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005180 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005181 goto nla_put_failure;
5182 }
5183 }
5184
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05305185 hdd_debug("Auth Status = %d Subnet Change Status = %d",
5186 roam_info_ptr->synchAuthStatus,
5187 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08005188
5189 /*
5190 * Add subnet change status if subnet has changed
5191 * 0 = unchanged
5192 * 1 = changed
5193 * 2 = unknown
5194 */
5195 if (roam_info_ptr->subnet_change_status) {
5196 if (nla_put_u8(skb,
5197 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
5198 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005199 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08005200 goto nla_put_failure;
5201 }
5202 }
5203
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005204 cfg80211_vendor_event(skb, GFP_KERNEL);
5205 return 0;
5206
5207nla_put_failure:
5208 kfree_skb(skb);
5209 return -EINVAL;
5210}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08005211#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005212
Jeff Johnson91f90ff2018-11-16 07:53:37 -08005213#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
5214 ((1 << 26) | \
5215 (((probe_period) & 0x1fff) << 13) | \
5216 ((stay_period) & 0x1fff))
5217
5218#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
5219 ((1 << 27) | \
5220 ((snr_diff) & 0x1fff))
5221
5222#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
5223 ((1 << 28) | \
5224 ((probe_dwell_time) & 0x1fff))
5225
5226#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
5227 ((1 << 29) | \
5228 (((mgmt_snr_weight) & 0xff) << 16) | \
5229 (((data_snr_weight) & 0xff) << 8) | \
5230 ((ack_snr_weight) & 0xff))
5231
lifeng66831662017-05-19 16:01:35 +08005232#define RX_REORDER_TIMEOUT_VOICE \
5233 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE
5234#define RX_REORDER_TIMEOUT_VIDEO \
5235 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO
5236#define RX_REORDER_TIMEOUT_BESTEFFORT \
5237 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT
5238#define RX_REORDER_TIMEOUT_BACKGROUND \
5239 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND
5240#define RX_BLOCKSIZE_PEER_MAC \
5241 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC
5242#define RX_BLOCKSIZE_WINLIMIT \
5243 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005244static const struct nla_policy
5245wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
5246
5247 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
5248 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
5249 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Jeff Johnson79f6a602017-06-15 09:48:25 -07005250 [QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT] = {.type = NLA_U32},
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05305251 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05305252 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
5253 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005254 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
5255 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
5256 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
5257 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
5258 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08005259 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY] = {
5260 .type = NLA_U32 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05305261 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08005262 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
5263 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
Jeff Johnson91f90ff2018-11-16 07:53:37 -08005264 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
Jeff Johnson77177bc2018-11-16 08:14:20 -08005265 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME] = {
5266 .type = NLA_U32},
Jeff Johnson1350e622018-11-16 18:36:55 -08005267 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT] = {
5268 .type = NLA_U32},
5269 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT] = {
5270 .type = NLA_U32},
5271 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT] = {
5272 .type = NLA_U32},
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305273 [QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL] = {.type = NLA_U8},
lifeng66831662017-05-19 16:01:35 +08005274 [RX_REORDER_TIMEOUT_VOICE] = {.type = NLA_U32},
5275 [RX_REORDER_TIMEOUT_VIDEO] = {.type = NLA_U32},
5276 [RX_REORDER_TIMEOUT_BESTEFFORT] = {.type = NLA_U32},
5277 [RX_REORDER_TIMEOUT_BACKGROUND] = {.type = NLA_U32},
Jeff Johnson19a5a7e2017-06-15 14:51:26 -07005278 [RX_BLOCKSIZE_PEER_MAC] = {
5279 .type = NLA_UNSPEC,
5280 .len = QDF_MAC_ADDR_SIZE},
lifeng66831662017-05-19 16:01:35 +08005281 [RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32},
Mukul Sharma6398b252017-05-01 17:58:12 +05305282 [QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL] = {.type = NLA_U32 },
Poddar, Siddarth4b3f7312017-11-02 17:00:20 +05305283 [QCA_WLAN_VENDOR_ATTR_CONFIG_LRO] = {.type = NLA_U8 },
Jeff Johnson1feb8a62018-11-14 13:18:41 -08005284 [QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER] = {.type = NLA_U8 },
lifengd217d192017-05-09 19:44:16 +08005285 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA] = {.type = NLA_U32 },
5286 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN] = {.type = NLA_U32 },
5287 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST] = {.type = NLA_U32 },
5288 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL] = {.type = NLA_U32 },
Paul Zhang99fe8842017-12-08 14:43:46 +08005289 [QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL] = {.type = NLA_U16 },
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05305290 [QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT] = {.type = NLA_U8},
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07005291 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE] = {.type = NLA_U8 },
Abhishek Singh6454ad32017-12-20 10:42:21 +05305292 [QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] = {.type = NLA_U8},
Ashish Kumar Dhanotiya1e20bcc2018-06-15 11:28:51 +05305293 [QCA_WLAN_VENDOR_ATTR_CONFIG_GTX] = {.type = NLA_U8},
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08005294 [QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY] = {.type = NLA_U32 },
5295 [QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST] = {
5296 .type = NLA_BINARY,
5297 .len = SIR_MAC_MAX_IE_LENGTH + 2},
5298
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005299};
5300
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08005301static const struct nla_policy
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08005302qca_wlan_vendor_attr_he_omi_tx_policy [QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX + 1] = {
5303 [QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS] = {.type = NLA_U8 },
5304 [QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW] = {.type = NLA_U8 },
5305 [QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE] = {.type = NLA_U8 },
5306 [QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS] = {.type = NLA_U8 },
Kiran Kumar Lokere49e3aff2019-02-06 17:00:48 -08005307 [QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE] = {.type = NLA_U8 },
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08005308};
5309
5310static const struct nla_policy
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08005311wlan_hdd_wifi_test_config_policy[
5312 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1] = {
5313 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE] = {
5314 .type = NLA_U8},
5315 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ] = {
5316 .type = NLA_U8},
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08005317 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS] = {
5318 .type = NLA_U8},
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08005319 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ] = {
5320 .type = NLA_U8},
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08005321 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION] = {
5322 .type = NLA_U8},
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08005323 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE] = {
5324 .type = NLA_U8},
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08005325 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION] = {
5326 .type = NLA_U8},
5327 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID] = {
5328 .type = NLA_U8},
5329 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE] = {
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07005330 .type = NLA_U16},
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08005331 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK] = {
5332 .type = NLA_U8},
5333 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC] = {
5334 .type = NLA_U8},
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08005335 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF] = {
5336 .type = NLA_U8},
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07005337 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE] = {
5338 .type = NLA_U8},
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07005339 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS] = {
5340 .type = NLA_U8},
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07005341 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR] = {
5342 .type = NLA_U8},
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07005343 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AC] = {
5344 .type = NLA_U8},
5345 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA] = {
5346 .type = NLA_U8},
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07005347 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP] = {
5348 .type = NLA_U8},
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07005349 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_BW] = {
5350 .type = NLA_U8},
5351 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_NSS] = {
5352 .type = NLA_U8},
5353 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG] = {
5354 .type = NLA_FLAG},
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07005355 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU] = {
5356 .type = NLA_U8},
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08005357 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP] = {
5358 .type = NLA_U8},
5359 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX] = {
5360 .type = NLA_NESTED},
Kiran Kumar Lokereee205772018-09-27 00:27:27 -07005361 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU] = {
5362 .type = NLA_U8},
Kiran Kumar Lokere921b5a52019-02-24 21:53:20 -08005363 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS]
5364 = {.type = NLA_U8},
Kiran Kumar Lokerea1c29ec2019-02-25 18:19:00 -08005365 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT] = {
5366 .type = NLA_U8},
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08005367};
5368
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005369/**
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305370 * wlan_hdd_add_qcn_ie() - Add QCN IE to a given IE buffer
5371 * @ie_data: IE buffer
5372 * @ie_len: length of the @ie_data
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305373 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305374 * Return: QDF_STATUS
5375 */
5376static QDF_STATUS wlan_hdd_add_qcn_ie(uint8_t *ie_data, uint16_t *ie_len)
5377{
5378 tDot11fIEQCN_IE qcn_ie;
5379 uint8_t qcn_ie_hdr[QCN_IE_HDR_LEN]
5380 = {IE_EID_VENDOR, DOT11F_IE_QCN_IE_MAX_LEN,
5381 0x8C, 0xFD, 0xF0, 0x1};
5382
5383 if (((*ie_len) + QCN_IE_HDR_LEN +
5384 QCN_IE_VERSION_SUBATTR_DATA_LEN) > MAX_DEFAULT_SCAN_IE_LEN) {
5385 hdd_err("IE buffer not enough for QCN IE");
5386 return QDF_STATUS_E_FAILURE;
5387 }
5388
5389 /* Add QCN IE header */
5390 qdf_mem_copy(ie_data + (*ie_len), qcn_ie_hdr, QCN_IE_HDR_LEN);
5391 (*ie_len) += QCN_IE_HDR_LEN;
5392
5393 /* Retrieve Version sub-attribute data */
5394 populate_dot11f_qcn_ie(&qcn_ie);
5395
5396 /* Add QCN IE data[version sub attribute] */
5397 qdf_mem_copy(ie_data + (*ie_len), qcn_ie.version,
5398 (QCN_IE_VERSION_SUBATTR_LEN));
5399 (*ie_len) += (QCN_IE_VERSION_SUBATTR_LEN);
5400
5401 return QDF_STATUS_SUCCESS;
5402}
5403
5404/**
5405 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
5406 * @hdd_ctx: HDD context
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305407 * @adapter: Pointer to HDD adapter
5408 * @ie_data: Pointer to Scan IEs buffer
5409 * @ie_len: Length of Scan IEs
5410 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305411 * This API is used to store the default scan ies received from
5412 * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
5413 *
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305414 * Return: 0 on success; error number otherwise
5415 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005416static int wlan_hdd_save_default_scan_ies(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07005417 struct hdd_adapter *adapter,
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305418 uint8_t *ie_data, uint16_t ie_len)
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305419{
Jeff Johnson37588942017-08-15 16:11:41 -07005420 struct hdd_scan_info *scan_info = &adapter->scan_info;
Wu Gao93816212018-08-31 16:49:54 +08005421 bool add_qcn_ie;
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305422
5423 if (!scan_info)
5424 return -EINVAL;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305425
5426 if (scan_info->default_scan_ies) {
5427 qdf_mem_free(scan_info->default_scan_ies);
5428 scan_info->default_scan_ies = NULL;
5429 }
5430
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05305431 scan_info->default_scan_ies_len = ie_len;
Dustin Brown1dbefe62018-09-11 16:32:03 -07005432 ucfg_mlme_get_qcn_ie_support(hdd_ctx->psoc, &add_qcn_ie);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305433 if (add_qcn_ie)
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05305434 ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305435
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305436 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05305437 if (!scan_info->default_scan_ies) {
5438 scan_info->default_scan_ies_len = 0;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305439 return -ENOMEM;
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05305440 }
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305441
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05305442 qdf_mem_copy(scan_info->default_scan_ies, ie_data,
5443 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305444
5445 /* Add QCN IE if g_qcn_ie_support INI is enabled */
5446 if (add_qcn_ie)
5447 wlan_hdd_add_qcn_ie(scan_info->default_scan_ies,
5448 &(scan_info->default_scan_ies_len));
5449
5450 hdd_debug("Saved default scan IE:");
5451 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
5452 (uint8_t *) scan_info->default_scan_ies,
5453 scan_info->default_scan_ies_len);
5454
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305455 return 0;
5456}
5457
5458/**
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305459 * wlan_hdd_handle_restrict_offchan_config() -
5460 * Handle wifi configuration attribute :
5461 * QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL
5462 * @adapter: Pointer to HDD adapter
5463 * @restrict_offchan: Restrict offchannel setting done by
5464 * application
5465 *
5466 * Return: 0 on success; error number otherwise
5467 */
Jeff Johnsone5006672017-08-29 14:39:02 -07005468static int wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter *adapter,
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305469 u8 restrict_offchan)
5470{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005471 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonc1e62782017-11-09 09:50:17 -08005472 enum QDF_OPMODE dev_mode = adapter->device_mode;
Min Liu8c5d99e2018-09-10 17:18:44 +08005473 struct wlan_objmgr_vdev *vdev;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305474 int ret_val = 0;
5475
5476 if (!(dev_mode == QDF_SAP_MODE || dev_mode == QDF_P2P_GO_MODE)) {
5477 hdd_err("Invalid interface type:%d", dev_mode);
5478 return -EINVAL;
5479 }
Min Liu8c5d99e2018-09-10 17:18:44 +08005480 vdev = hdd_objmgr_get_vdev(adapter);
5481 if (!vdev)
Liangwei Dongcf5a5062017-12-28 00:51:32 -05005482 return -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305483 if (restrict_offchan == 1) {
5484 enum policy_mgr_con_mode pmode =
5485 policy_mgr_convert_device_mode_to_qdf_type(dev_mode);
5486 int chan;
5487
Min Liu8c5d99e2018-09-10 17:18:44 +08005488 u32 vdev_id = wlan_vdev_get_id(vdev);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305489
Min Liu8c5d99e2018-09-10 17:18:44 +08005490 wlan_vdev_obj_lock(vdev);
5491 wlan_vdev_mlme_cap_set(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
5492 wlan_vdev_obj_unlock(vdev);
Dustin Brown76cd2932018-09-11 16:03:05 -07005493 chan = policy_mgr_get_channel(hdd_ctx->psoc, pmode,
Liangwei Dongcf5a5062017-12-28 00:51:32 -05005494 &vdev_id);
5495 if (!chan ||
5496 wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, chan)) {
5497 hdd_err("unable to send avoid_freq");
5498 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305499 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05005500 hdd_info("vdev %d mode %d dnbs enabled", vdev_id, dev_mode);
5501 } else if (restrict_offchan == 0) {
Min Liu8c5d99e2018-09-10 17:18:44 +08005502 wlan_vdev_obj_lock(vdev);
5503 wlan_vdev_mlme_cap_clear(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
5504 wlan_vdev_obj_unlock(vdev);
Liangwei Dongcf5a5062017-12-28 00:51:32 -05005505 if (wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0)) {
5506 hdd_err("unable to clear avoid_freq");
5507 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305508 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05005509 hdd_info("vdev mode %d dnbs disabled", dev_mode);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305510 } else {
5511 ret_val = -EINVAL;
5512 hdd_err("Invalid RESTRICT_OFFCHAN setting");
5513 }
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05305514 hdd_objmgr_put_vdev(vdev);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305515 return ret_val;
5516}
5517
5518/**
Jeff Johnson0dd687e2018-11-16 20:11:27 -08005519 * wlan_hdd_cfg80211_wifi_set_reorder_timeout() - set reorder timeout
5520 * @adapter: Pointer to HDD adapter
lifeng66831662017-05-19 16:01:35 +08005521 * @tb: array of pointer to struct nlattr
5522 *
5523 * Return: 0 on success; error number otherwise
5524 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005525static
Jeff Johnson0dd687e2018-11-16 20:11:27 -08005526int wlan_hdd_cfg80211_wifi_set_reorder_timeout(struct hdd_adapter *adapter,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005527 struct nlattr *tb[])
lifeng66831662017-05-19 16:01:35 +08005528{
Jeff Johnson0dd687e2018-11-16 20:11:27 -08005529 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Min Liuab6ed4f2018-01-09 13:13:57 +08005530 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08005531 QDF_STATUS qdf_status;
5532 struct sir_set_rx_reorder_timeout_val reorder_timeout;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005533 mac_handle_t mac_handle;
lifeng66831662017-05-19 16:01:35 +08005534
5535#define RX_TIMEOUT_VAL_MIN 10
5536#define RX_TIMEOUT_VAL_MAX 1000
5537
5538 if (tb[RX_REORDER_TIMEOUT_VOICE] ||
5539 tb[RX_REORDER_TIMEOUT_VIDEO] ||
5540 tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
5541 tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
5542
5543 /* if one is specified, all must be specified */
5544 if (!tb[RX_REORDER_TIMEOUT_VOICE] ||
5545 !tb[RX_REORDER_TIMEOUT_VIDEO] ||
5546 !tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
5547 !tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
5548 hdd_err("four AC timeout val are required MAC");
5549 return -EINVAL;
5550 }
5551
5552 reorder_timeout.rx_timeout_pri[0] = nla_get_u32(
5553 tb[RX_REORDER_TIMEOUT_VOICE]);
5554 reorder_timeout.rx_timeout_pri[1] = nla_get_u32(
5555 tb[RX_REORDER_TIMEOUT_VIDEO]);
5556 reorder_timeout.rx_timeout_pri[2] = nla_get_u32(
5557 tb[RX_REORDER_TIMEOUT_BESTEFFORT]);
5558 reorder_timeout.rx_timeout_pri[3] = nla_get_u32(
5559 tb[RX_REORDER_TIMEOUT_BACKGROUND]);
5560 /* timeout value is required to be in the rang 10 to 1000ms */
5561 if (reorder_timeout.rx_timeout_pri[0] >= RX_TIMEOUT_VAL_MIN &&
5562 reorder_timeout.rx_timeout_pri[0] <= RX_TIMEOUT_VAL_MAX &&
5563 reorder_timeout.rx_timeout_pri[1] >= RX_TIMEOUT_VAL_MIN &&
5564 reorder_timeout.rx_timeout_pri[1] <= RX_TIMEOUT_VAL_MAX &&
5565 reorder_timeout.rx_timeout_pri[2] >= RX_TIMEOUT_VAL_MIN &&
5566 reorder_timeout.rx_timeout_pri[2] <= RX_TIMEOUT_VAL_MAX &&
5567 reorder_timeout.rx_timeout_pri[3] >= RX_TIMEOUT_VAL_MIN &&
5568 reorder_timeout.rx_timeout_pri[3] <= RX_TIMEOUT_VAL_MAX) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005569 mac_handle = hdd_ctx->mac_handle;
5570 qdf_status = sme_set_reorder_timeout(mac_handle,
lifeng66831662017-05-19 16:01:35 +08005571 &reorder_timeout);
5572 if (qdf_status != QDF_STATUS_SUCCESS) {
5573 hdd_err("failed to set reorder timeout err %d",
5574 qdf_status);
5575 ret_val = -EPERM;
5576 }
5577 } else {
5578 hdd_err("one of the timeout value is not in range");
5579 ret_val = -EINVAL;
5580 }
5581 }
5582
5583 return ret_val;
5584}
5585
5586/**
Jeff Johnson339ede82018-11-16 20:27:52 -08005587 * wlan_hdd_cfg80211_wifi_set_rx_blocksize() - set rx blocksize
lifeng66831662017-05-19 16:01:35 +08005588 * @adapter: hdd adapter
5589 * @tb: array of pointer to struct nlattr
5590 *
5591 * Return: 0 on success; error number otherwise
5592 */
Jeff Johnson339ede82018-11-16 20:27:52 -08005593static int wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct hdd_adapter *adapter,
lifeng66831662017-05-19 16:01:35 +08005594 struct nlattr *tb[])
5595{
Jeff Johnson339ede82018-11-16 20:27:52 -08005596 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Min Liuab6ed4f2018-01-09 13:13:57 +08005597 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08005598 uint32_t set_value;
5599 QDF_STATUS qdf_status;
5600 struct sir_peer_set_rx_blocksize rx_blocksize;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005601 mac_handle_t mac_handle;
lifeng66831662017-05-19 16:01:35 +08005602
5603#define WINDOW_SIZE_VAL_MIN 1
5604#define WINDOW_SIZE_VAL_MAX 64
5605
5606 if (tb[RX_BLOCKSIZE_PEER_MAC] ||
5607 tb[RX_BLOCKSIZE_WINLIMIT]) {
5608
5609 /* if one is specified, both must be specified */
5610 if (!tb[RX_BLOCKSIZE_PEER_MAC] ||
5611 !tb[RX_BLOCKSIZE_WINLIMIT]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07005612 hdd_err("Both Peer MAC and windows limit required");
lifeng66831662017-05-19 16:01:35 +08005613 return -EINVAL;
5614 }
5615
5616 memcpy(&rx_blocksize.peer_macaddr,
5617 nla_data(tb[RX_BLOCKSIZE_PEER_MAC]),
5618 sizeof(rx_blocksize.peer_macaddr)),
5619
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005620 rx_blocksize.vdev_id = adapter->vdev_id;
lifeng66831662017-05-19 16:01:35 +08005621 set_value = nla_get_u32(tb[RX_BLOCKSIZE_WINLIMIT]);
5622 /* maximum window size is 64 */
5623 if (set_value >= WINDOW_SIZE_VAL_MIN &&
5624 set_value <= WINDOW_SIZE_VAL_MAX) {
5625 rx_blocksize.rx_block_ack_win_limit = set_value;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005626 mac_handle = hdd_ctx->mac_handle;
5627 qdf_status = sme_set_rx_set_blocksize(mac_handle,
lifeng66831662017-05-19 16:01:35 +08005628 &rx_blocksize);
5629 if (qdf_status != QDF_STATUS_SUCCESS) {
5630 hdd_err("failed to set aggr sizes err %d",
5631 qdf_status);
5632 ret_val = -EPERM;
5633 }
5634 } else {
5635 hdd_err("window size val is not in range");
5636 ret_val = -EINVAL;
5637 }
5638 }
5639
5640 return ret_val;
5641}
5642
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08005643static int hdd_config_access_policy(struct hdd_adapter *adapter,
5644 struct nlattr *tb[])
5645{
5646 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5647 struct nlattr *policy_attr =
5648 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY];
5649 struct nlattr *ielist_attr =
5650 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST];
5651 uint32_t access_policy;
5652 uint8_t ie[SIR_MAC_MAX_IE_LENGTH + 2];
5653 QDF_STATUS status;
5654
5655 /* nothing to do if neither attribute is present */
5656 if (!ielist_attr && !policy_attr)
5657 return 0;
5658
5659 /* if one is present, both must be present */
5660 if (!ielist_attr || !policy_attr) {
5661 hdd_err("Missing attribute for %s",
5662 policy_attr ?
5663 "ACCESS_POLICY_IE_LIST" : "ACCESS_POLICY");
5664 return -EINVAL;
5665 }
5666
5667 /* validate the access policy */
5668 access_policy = nla_get_u32(policy_attr);
5669 switch (access_policy) {
5670 case QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED:
5671 case QCA_ACCESS_POLICY_DENY_UNLESS_LISTED:
5672 /* valid */
5673 break;
5674 default:
5675 hdd_err("Invalid value. access_policy %u", access_policy);
5676 return -EINVAL;
5677 }
5678
5679 /*
5680 * ie length is validated by the nla_policy. need to make a
5681 * copy since SME will always read SIR_MAC_MAX_IE_LENGTH+2 bytes
5682 */
5683 nla_memcpy(ie, ielist_attr, sizeof(ie));
5684
5685 hdd_debug("calling sme_update_access_policy_vendor_ie");
5686 status = sme_update_access_policy_vendor_ie(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005687 adapter->vdev_id,
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08005688 ie, access_policy);
5689 if (QDF_IS_STATUS_ERROR(status))
5690 hdd_err("Failed to set vendor ie and access policy, %d",
5691 status);
5692
5693 return qdf_status_to_os_return(status);
5694}
5695
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08005696static int hdd_config_mpdu_aggregation(struct hdd_adapter *adapter,
5697 struct nlattr *tb[])
5698{
5699 struct nlattr *tx_attr =
5700 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION];
5701 struct nlattr *rx_attr =
5702 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION];
5703 uint8_t tx_size, rx_size;
5704 struct sir_set_tx_rx_aggregation_size request;
5705 QDF_STATUS status;
5706
5707 /* nothing to do if neither attribute is present */
5708 if (!tx_attr && !rx_attr)
5709 return 0;
5710
5711 /* if one is present, both must be present */
5712 if (!tx_attr || !rx_attr) {
5713 hdd_err("Missing attribute for %s",
5714 tx_attr ? "RX" : "TX");
5715 return -EINVAL;
5716 }
5717
5718 tx_size = nla_get_u8(tx_attr);
5719 rx_size = nla_get_u8(rx_attr);
5720 if (!cfg_in_range(CFG_TX_AGGREGATION_SIZE, tx_size) ||
5721 !cfg_in_range(CFG_RX_AGGREGATION_SIZE, rx_size)) {
5722 hdd_err("TX %d RX %d MPDU aggr size not in range",
5723 tx_size, rx_size);
5724
5725 return -EINVAL;
5726 }
5727
5728 qdf_mem_zero(&request, sizeof(request));
5729 request.tx_aggregation_size = tx_size;
5730 request.rx_aggregation_size = rx_size;
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005731 request.vdev_id = adapter->vdev_id;
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08005732 request.aggr_type = WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU;
5733
5734 status = wma_set_tx_rx_aggregation_size(&request);
5735 if (QDF_IS_STATUS_ERROR(status))
5736 hdd_err("failed to set aggr sizes err %d", status);
5737
5738 return qdf_status_to_os_return(status);
5739}
5740
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08005741static int hdd_config_ant_div_period(struct hdd_adapter *adapter,
5742 struct nlattr *tb[])
5743{
5744 struct nlattr *probe_attr =
5745 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD];
5746 struct nlattr *stay_attr =
5747 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD];
5748 uint32_t probe_period, stay_period, ant_div_usrcfg;
5749 int errno;
5750
5751 /* nothing to do if neither attribute is present */
5752 if (!probe_attr && !stay_attr)
5753 return 0;
5754
5755 /* if one is present, both must be present */
5756 if (!probe_attr || !stay_attr) {
5757 hdd_err("Missing attribute for %s",
5758 probe_attr ? "STAY" : "PROBE");
5759 return -EINVAL;
5760 }
5761
5762 probe_period = nla_get_u32(probe_attr);
5763 stay_period = nla_get_u32(stay_attr);
5764 ant_div_usrcfg = ANT_DIV_SET_PERIOD(probe_period, stay_period);
5765 hdd_debug("ant div set period: %x", ant_div_usrcfg);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005766 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08005767 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5768 ant_div_usrcfg, PDEV_CMD);
5769 if (errno)
5770 hdd_err("Failed to set ant div period, %d", errno);
5771
5772 return errno;
5773}
5774
Jeff Johnson1350e622018-11-16 18:36:55 -08005775static int hdd_config_ant_div_snr_weight(struct hdd_adapter *adapter,
5776 struct nlattr *tb[])
5777{
5778 struct nlattr *mgmt_attr =
5779 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT];
5780 struct nlattr *data_attr =
5781 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT];
5782 struct nlattr *ack_attr =
5783 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT];
5784 uint32_t mgmt_snr, data_snr, ack_snr, ant_div_usrcfg;
5785 int errno;
5786
5787 /* nothing to do if none of the attributes are present */
5788 if (!mgmt_attr && !data_attr && !ack_attr)
5789 return 0;
5790
5791 /* if one is present, all must be present */
5792 if (!mgmt_attr || !data_attr || !ack_attr) {
5793 hdd_err("Missing attribute");
5794 return -EINVAL;
5795 }
5796
5797 mgmt_snr = nla_get_u32(mgmt_attr);
5798 data_snr = nla_get_u32(data_attr);
5799 ack_snr = nla_get_u32(ack_attr);
5800 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(mgmt_snr, data_snr, ack_snr);
5801 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005802 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson1350e622018-11-16 18:36:55 -08005803 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5804 ant_div_usrcfg, PDEV_CMD);
5805 if (errno)
5806 hdd_err("Failed to set ant div weight, %d", errno);
5807
5808 return errno;
5809}
5810
Jeff Johnson7f4fd702018-11-14 11:19:52 -08005811static int hdd_config_fine_time_measurement(struct hdd_adapter *adapter,
5812 const struct nlattr *attr)
5813{
5814 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5815 uint32_t user_capability;
5816 uint32_t target_capability;
5817 uint32_t final_capability;
5818 QDF_STATUS status;
5819
5820 user_capability = nla_get_u32(attr);
5821 target_capability = hdd_ctx->fine_time_meas_cap_target;
5822 final_capability = user_capability & target_capability;
5823
5824 status = ucfg_mlme_set_fine_time_meas_cap(hdd_ctx->psoc,
5825 final_capability);
5826 if (QDF_IS_STATUS_ERROR(status)) {
5827 hdd_err("Unable to set value, status %d", status);
5828 return -EINVAL;
5829 }
5830
5831 sme_update_fine_time_measurement_capab(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005832 adapter->vdev_id,
Jeff Johnson7f4fd702018-11-14 11:19:52 -08005833 final_capability);
5834 ucfg_wifi_pos_set_ftm_cap(hdd_ctx->psoc, final_capability);
5835
5836 hdd_debug("user: 0x%x, target: 0x%x, final: 0x%x",
5837 user_capability, target_capability, final_capability);
5838
5839 return 0;
5840}
5841
Jeff Johnsonbcaeafb2018-11-14 12:14:24 -08005842static int hdd_config_modulated_dtim(struct hdd_adapter *adapter,
5843 const struct nlattr *attr)
5844{
5845 struct wlan_objmgr_vdev *vdev;
5846 uint32_t modulated_dtim;
5847 QDF_STATUS status;
5848
5849 modulated_dtim = nla_get_u32(attr);
5850
5851 vdev = hdd_objmgr_get_vdev(adapter);
5852 if (!vdev)
5853 return -EINVAL;
5854
5855 status = ucfg_pmo_config_modulated_dtim(vdev, modulated_dtim);
5856
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05305857 hdd_objmgr_put_vdev(vdev);
Jeff Johnsonbcaeafb2018-11-14 12:14:24 -08005858
5859 return qdf_status_to_os_return(status);
5860}
5861
Jeff Johnson6db91622018-11-14 12:33:28 -08005862static int hdd_config_listen_interval(struct hdd_adapter *adapter,
5863 const struct nlattr *attr)
5864{
5865 struct wlan_objmgr_vdev *vdev;
5866 uint32_t listen_interval;
5867 QDF_STATUS status;
5868
5869 listen_interval = nla_get_u32(attr);
5870 if (listen_interval > cfg_max(CFG_PMO_ENABLE_DYNAMIC_DTIM)) {
5871 hdd_err_rl("Invalid value for listen interval - %d",
5872 listen_interval);
5873 return -EINVAL;
5874 }
5875
5876 vdev = hdd_objmgr_get_vdev(adapter);
5877 if (!vdev)
5878 return -EINVAL;
5879
5880 status = ucfg_pmo_config_listen_interval(vdev, listen_interval);
5881
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +05305882 hdd_objmgr_put_vdev(vdev);
Jeff Johnson6db91622018-11-14 12:33:28 -08005883
5884 return qdf_status_to_os_return(status);
5885}
5886
Jeff Johnson9381d032018-11-14 12:42:22 -08005887static int hdd_config_lro(struct hdd_adapter *adapter,
5888 const struct nlattr *attr)
5889{
5890 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5891 uint8_t enable_flag;
5892
5893 enable_flag = nla_get_u8(attr);
5894
5895 return hdd_lro_set_reset(hdd_ctx, adapter, enable_flag);
5896}
5897
Jeff Johnson3d4f64c2018-11-14 13:13:04 -08005898static int hdd_config_scan_enable(struct hdd_adapter *adapter,
5899 const struct nlattr *attr)
5900{
5901 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5902 uint8_t enable_flag;
5903
5904 enable_flag = nla_get_u8(attr);
5905 if (enable_flag)
5906 ucfg_scan_psoc_set_enable(hdd_ctx->psoc,
5907 REASON_USER_SPACE);
5908 else
5909 ucfg_scan_psoc_set_disable(hdd_ctx->psoc,
5910 REASON_USER_SPACE);
5911
5912 return 0;
5913}
5914
Jeff Johnson1feb8a62018-11-14 13:18:41 -08005915static int hdd_config_qpower(struct hdd_adapter *adapter,
5916 const struct nlattr *attr)
5917{
5918 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5919 uint8_t qpower;
5920
5921 qpower = nla_get_u8(attr);
5922
5923 return hdd_set_qpower_config(hdd_ctx, adapter, qpower);
5924}
5925
Jeff Johnsonf15ede02018-11-14 13:27:13 -08005926static int hdd_config_stats_avg_factor(struct hdd_adapter *adapter,
5927 const struct nlattr *attr)
5928{
5929 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5930 uint16_t stats_avg_factor;
5931 QDF_STATUS status;
5932
5933 stats_avg_factor = nla_get_u16(attr);
5934 status = sme_configure_stats_avg_factor(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005935 adapter->vdev_id,
Jeff Johnsonf15ede02018-11-14 13:27:13 -08005936 stats_avg_factor);
5937
5938 return qdf_status_to_os_return(status);
5939}
5940
Jeff Johnsonf3827502018-11-14 14:00:58 -08005941static int hdd_config_non_agg_retry(struct hdd_adapter *adapter,
5942 const struct nlattr *attr)
5943{
5944 uint8_t retry;
5945 int param_id;
5946
5947 retry = nla_get_u8(attr);
5948 retry = retry > CFG_NON_AGG_RETRY_MAX ?
5949 CFG_NON_AGG_RETRY_MAX : retry;
5950 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
5951
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005952 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnsonf3827502018-11-14 14:00:58 -08005953 retry, PDEV_CMD);
5954}
5955
Jeff Johnsonb9021002018-11-15 15:51:36 -08005956static int hdd_config_agg_retry(struct hdd_adapter *adapter,
5957 const struct nlattr *attr)
5958{
5959 uint8_t retry;
5960 int param_id;
5961
5962 retry = nla_get_u8(attr);
5963 retry = retry > CFG_AGG_RETRY_MAX ?
5964 CFG_AGG_RETRY_MAX : retry;
5965
5966 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
5967 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
5968 CFG_AGG_RETRY_MIN : retry;
5969 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
5970
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005971 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnsonb9021002018-11-15 15:51:36 -08005972 retry, PDEV_CMD);
5973}
5974
Jeff Johnson0e8259c2018-11-15 19:44:57 -08005975static int hdd_config_mgmt_retry(struct hdd_adapter *adapter,
5976 const struct nlattr *attr)
5977{
5978 uint8_t retry;
5979 int param_id;
5980
5981 retry = nla_get_u8(attr);
5982 retry = retry > CFG_MGMT_RETRY_MAX ?
5983 CFG_MGMT_RETRY_MAX : retry;
5984 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
5985
Jeff Johnsoncf07c312019-02-04 13:53:29 -08005986 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson0e8259c2018-11-15 19:44:57 -08005987 retry, PDEV_CMD);
5988}
5989
Jeff Johnson6b48a2f2018-11-15 19:48:47 -08005990static int hdd_config_ctrl_retry(struct hdd_adapter *adapter,
5991 const struct nlattr *attr)
5992{
5993 uint8_t retry;
5994 int param_id;
5995
5996 retry = nla_get_u8(attr);
5997 retry = retry > CFG_CTRL_RETRY_MAX ?
5998 CFG_CTRL_RETRY_MAX : retry;
5999 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
6000
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006001 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson6b48a2f2018-11-15 19:48:47 -08006002 retry, PDEV_CMD);
6003}
6004
Jeff Johnson98214742018-11-15 19:56:37 -08006005static int hdd_config_propagation_delay(struct hdd_adapter *adapter,
6006 const struct nlattr *attr)
6007{
6008 uint8_t delay;
6009 uint32_t abs_delay;
6010 int param_id;
6011
6012 delay = nla_get_u8(attr);
6013 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
6014 CFG_PROPAGATION_DELAY_MAX : delay;
6015 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
6016 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
6017
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006018 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson98214742018-11-15 19:56:37 -08006019 abs_delay, PDEV_CMD);
6020}
6021
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08006022static int hdd_config_propagation_abs_delay(struct hdd_adapter *adapter,
6023 const struct nlattr *attr)
6024{
6025 uint32_t abs_delay;
6026 int param_id;
6027
6028 abs_delay = nla_get_u32(attr);
6029 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
6030
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006031 return wma_cli_set_command(adapter->vdev_id, param_id,
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08006032 abs_delay, PDEV_CMD);
6033}
6034
Jeff Johnson7c5e6dc2018-11-15 21:20:18 -08006035static int hdd_config_tx_fail_count(struct hdd_adapter *adapter,
6036 const struct nlattr *attr)
6037{
6038 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6039 uint32_t tx_fail_count;
6040 QDF_STATUS status;
6041
6042 tx_fail_count = nla_get_u32(attr);
6043 if (!tx_fail_count)
6044 return 0;
6045
6046 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006047 adapter->vdev_id,
Jeff Johnson7c5e6dc2018-11-15 21:20:18 -08006048 tx_fail_count);
6049 if (QDF_IS_STATUS_ERROR(status))
6050 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
6051 status);
6052
6053 return qdf_status_to_os_return(status);
6054}
6055
Jeff Johnson7766fd22018-11-15 21:52:37 -08006056static int hdd_config_channel_avoidance_ind(struct hdd_adapter *adapter,
6057 const struct nlattr *attr)
6058{
6059 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6060 uint8_t set_value;
6061
6062 set_value = nla_get_u8(attr);
6063 hdd_debug("set_value: %d", set_value);
6064
6065 return hdd_enable_disable_ca_event(hdd_ctx, set_value);
6066}
6067
Jeff Johnson47e2e842018-11-14 13:49:43 -08006068static int hdd_config_guard_time(struct hdd_adapter *adapter,
6069 const struct nlattr *attr)
6070{
6071 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6072 uint32_t guard_time;
6073 QDF_STATUS status;
6074
6075 guard_time = nla_get_u32(attr);
6076 status = sme_configure_guard_time(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006077 adapter->vdev_id,
Jeff Johnson47e2e842018-11-14 13:49:43 -08006078 guard_time);
6079
6080 return qdf_status_to_os_return(status);
6081}
6082
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006083static int hdd_config_scan_default_ies(struct hdd_adapter *adapter,
6084 const struct nlattr *attr)
6085{
6086 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6087 uint8_t *scan_ie;
6088 uint16_t scan_ie_len;
6089 QDF_STATUS status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006090 mac_handle_t mac_handle;
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006091
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006092 scan_ie_len = nla_len(attr);
6093 hdd_debug("IE len %d session %d device mode %d",
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006094 scan_ie_len, adapter->vdev_id, adapter->device_mode);
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006095
6096 if (!scan_ie_len) {
6097 hdd_err("zero-length IE prohibited");
6098 return -EINVAL;
6099 }
6100
6101 if (scan_ie_len > MAX_DEFAULT_SCAN_IE_LEN) {
6102 hdd_err("IE length %d exceeds max of %d",
6103 scan_ie_len, MAX_DEFAULT_SCAN_IE_LEN);
6104 return -EINVAL;
6105 }
6106
6107 scan_ie = nla_data(attr);
Jeff Johnson4933c3a2018-01-10 19:33:33 -08006108 if (!wlan_is_ie_valid(scan_ie, scan_ie_len)) {
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006109 hdd_err("Invalid default scan IEs");
6110 return -EINVAL;
6111 }
6112
6113 if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
6114 scan_ie, scan_ie_len))
6115 hdd_err("Failed to save default scan IEs");
6116
6117 if (adapter->device_mode == QDF_STA_MODE) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006118 mac_handle = hdd_ctx->mac_handle;
6119 status = sme_set_default_scan_ie(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006120 adapter->vdev_id, scan_ie,
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006121 scan_ie_len);
6122 if (QDF_STATUS_SUCCESS != status) {
6123 hdd_err("failed to set default scan IEs in sme: %d",
6124 status);
6125 return -EPERM;
6126 }
6127 }
6128
6129 return 0;
6130}
6131
Jeff Johnsonf9871e42018-11-15 22:24:06 -08006132static int hdd_config_ant_div_ena(struct hdd_adapter *adapter,
6133 const struct nlattr *attr)
6134{
6135 uint32_t antdiv_enable;
6136 int errno;
6137
6138 antdiv_enable = nla_get_u32(attr);
6139 hdd_debug("antdiv_enable: %d", antdiv_enable);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006140 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonf9871e42018-11-15 22:24:06 -08006141 WMI_PDEV_PARAM_ENA_ANT_DIV,
6142 antdiv_enable, PDEV_CMD);
6143 if (errno)
6144 hdd_err("Failed to set antdiv_enable, %d", errno);
6145
6146 return errno;
6147}
6148
Jeff Johnson91f90ff2018-11-16 07:53:37 -08006149static int hdd_config_ant_div_snr_diff(struct hdd_adapter *adapter,
6150 const struct nlattr *attr)
6151{
6152 uint32_t ant_div_snr_diff;
6153 uint32_t ant_div_usrcfg;
6154 int errno;
6155
6156 ant_div_snr_diff = nla_get_u32(attr);
6157 hdd_debug("snr diff: %x", ant_div_snr_diff);
6158
6159 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(ant_div_snr_diff);
6160 hdd_debug("usrcfg: %x", ant_div_usrcfg);
6161
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006162 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson91f90ff2018-11-16 07:53:37 -08006163 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
6164 ant_div_usrcfg, PDEV_CMD);
6165 if (errno)
6166 hdd_err("Failed to set snr diff, %d", errno);
6167
6168 return errno;
6169}
6170
Jeff Johnson77177bc2018-11-16 08:14:20 -08006171static int hdd_config_ant_div_probe_dwell_time(struct hdd_adapter *adapter,
6172 const struct nlattr *attr)
6173{
6174 uint32_t dwell_time;
6175 uint32_t ant_div_usrcfg;
6176 int errno;
6177
6178 dwell_time = nla_get_u32(attr);
6179 hdd_debug("dwell time: %x", dwell_time);
6180
6181 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(dwell_time);
6182 hdd_debug("usrcfg: %x", ant_div_usrcfg);
6183
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006184 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson77177bc2018-11-16 08:14:20 -08006185 WMI_PDEV_PARAM_ANT_DIV_USRCFG,
6186 ant_div_usrcfg, PDEV_CMD);
6187 if (errno)
6188 hdd_err("Failed to set probe dwell time, %d", errno);
6189
6190 return errno;
6191}
6192
Jeff Johnsonaa172222018-11-16 09:16:11 -08006193static int hdd_config_ant_div_chain(struct hdd_adapter *adapter,
6194 const struct nlattr *attr)
6195{
6196 uint32_t antdiv_chain;
6197 int errno;
6198
6199 antdiv_chain = nla_get_u32(attr);
6200 hdd_debug("antdiv_chain: %d", antdiv_chain);
6201
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006202 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonaa172222018-11-16 09:16:11 -08006203 WMI_PDEV_PARAM_FORCE_CHAIN_ANT,
6204 antdiv_chain, PDEV_CMD);
6205 if (errno)
6206 hdd_err("Failed to set chain, %d", errno);
6207
6208 return errno;
6209}
6210
Jeff Johnsonef427ad2018-11-16 09:22:17 -08006211static int hdd_config_ant_div_selftest(struct hdd_adapter *adapter,
6212 const struct nlattr *attr)
6213{
6214 uint32_t antdiv_selftest;
6215 int errno;
6216
6217 antdiv_selftest = nla_get_u32(attr);
6218 hdd_debug("antdiv_selftest: %d", antdiv_selftest);
6219
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006220 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonef427ad2018-11-16 09:22:17 -08006221 WMI_PDEV_PARAM_ANT_DIV_SELFTEST,
6222 antdiv_selftest, PDEV_CMD);
6223 if (errno)
6224 hdd_err("Failed to set selftest, %d", errno);
6225
6226 return errno;
6227}
6228
Jeff Johnsonae21be82018-11-16 09:43:53 -08006229static int hdd_config_ant_div_selftest_intvl(struct hdd_adapter *adapter,
6230 const struct nlattr *attr)
6231{
6232 uint32_t antdiv_selftest_intvl;
6233 int errno;
6234
6235 antdiv_selftest_intvl = nla_get_u32(attr);
6236 hdd_debug("antdiv_selftest_intvl: %d", antdiv_selftest_intvl);
6237
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006238 errno = wma_cli_set_command(adapter->vdev_id,
Jeff Johnsonae21be82018-11-16 09:43:53 -08006239 WMI_PDEV_PARAM_ANT_DIV_SELFTEST_INTVL,
6240 antdiv_selftest_intvl, PDEV_CMD);
6241 if (errno)
6242 hdd_err("Failed to set selftest interval, %d", errno);
6243
6244 return errno;
6245}
6246
Jeff Johnson3a25de82018-11-16 07:26:46 -08006247static int hdd_config_ignore_assoc_disallowed(struct hdd_adapter *adapter,
6248 const struct nlattr *attr)
6249{
6250 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6251 uint8_t ignore_assoc_disallowed;
6252
6253 ignore_assoc_disallowed = nla_get_u8(attr);
6254 hdd_debug("%u", ignore_assoc_disallowed);
6255 if ((ignore_assoc_disallowed < QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
6256 (ignore_assoc_disallowed > QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
6257 return -EINVAL;
6258
6259 sme_update_session_param(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006260 adapter->vdev_id,
Jeff Johnson3a25de82018-11-16 07:26:46 -08006261 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
6262 ignore_assoc_disallowed);
6263
6264 return 0;
6265}
6266
Jeff Johnson72dc91e2018-11-16 08:46:12 -08006267static int hdd_config_restrict_offchannel(struct hdd_adapter *adapter,
6268 const struct nlattr *attr)
6269{
6270 uint8_t restrict_offchan;
6271
6272 restrict_offchan = nla_get_u8(attr);
6273 hdd_debug("%u", restrict_offchan);
6274
6275 if (restrict_offchan > 1) {
6276 hdd_err("Invalid value %u", restrict_offchan);
6277 return -EINVAL;
6278 }
6279
6280 return wlan_hdd_handle_restrict_offchan_config(adapter,
6281 restrict_offchan);
6282}
6283
Jeff Johnson320feeb2018-11-16 10:14:24 -08006284static int hdd_config_total_beacon_miss_count(struct hdd_adapter *adapter,
6285 const struct nlattr *attr)
6286{
6287 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6288 uint8_t first_miss_count;
6289 uint8_t final_miss_count;
6290 uint8_t total_miss_count;
6291 QDF_STATUS status;
6292
6293 total_miss_count = nla_get_u8(attr);
6294 ucfg_mlme_get_roam_bmiss_first_bcnt(hdd_ctx->psoc,
6295 &first_miss_count);
6296 if (total_miss_count <= first_miss_count) {
6297 hdd_err("Total %u needs to exceed first %u",
6298 total_miss_count, first_miss_count);
6299 return -EINVAL;
6300 }
6301
6302 final_miss_count = total_miss_count - first_miss_count;
6303
6304 hdd_debug("First count %u, final count %u",
6305 first_miss_count, final_miss_count);
6306
6307 /*****
Jeff Johnson55d2ab42019-03-06 11:43:49 -08006308 * TODO: research why is 0 being passed for vdev id???
Jeff Johnson320feeb2018-11-16 10:14:24 -08006309 */
6310 status = sme_set_roam_bmiss_final_bcnt(hdd_ctx->mac_handle,
6311 0,
6312 final_miss_count);
6313 if (QDF_IS_STATUS_ERROR(status)) {
6314 hdd_err("Failed to set final count, status %u", status);
6315 return qdf_status_to_os_return(status);
6316 }
6317
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006318 status = sme_set_bmiss_bcnt(adapter->vdev_id,
Jeff Johnson320feeb2018-11-16 10:14:24 -08006319 first_miss_count,
6320 final_miss_count);
6321 if (QDF_IS_STATUS_ERROR(status))
6322 hdd_err("Failed to set count, status %u", status);
6323
6324 return qdf_status_to_os_return(status);
6325}
6326
Jeff Johnson2502ddd2018-11-16 10:59:30 -08006327static int hdd_config_latency_level(struct hdd_adapter *adapter,
6328 const struct nlattr *attr)
6329{
6330 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6331 uint16_t latency_level;
6332 QDF_STATUS status;
6333
6334 latency_level = nla_get_u16(attr);
6335 switch (latency_level) {
6336 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL:
6337 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE:
6338 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW:
6339 case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW:
6340 /* valid values */
6341 break;
6342 default:
6343 hdd_err("Invalid value %u", latency_level);
6344 return -EINVAL;
6345 }
6346
6347 /* Map the latency value to the level which fw expected
6348 * 0 - normal, 1 - moderate, 2 - low, 3 - ultralow
6349 */
6350 latency_level = latency_level - 1;
6351 status = sme_set_wlm_latency_level(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006352 adapter->vdev_id,
Jeff Johnson2502ddd2018-11-16 10:59:30 -08006353 latency_level);
6354 if (QDF_IS_STATUS_ERROR(status))
6355 hdd_err("set latency level failed, %u", status);
6356
6357 return qdf_status_to_os_return(status);
6358}
6359
Jeff Johnson0a315912018-11-16 11:18:21 -08006360static int hdd_config_disable_fils(struct hdd_adapter *adapter,
6361 const struct nlattr *attr)
6362{
6363 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6364 uint8_t disable_fils;
6365 bool enabled;
6366 QDF_STATUS status;
6367
6368 /* ignore unless in STA mode */
6369 if (adapter->device_mode != QDF_STA_MODE)
6370 return 0;
6371
6372 disable_fils = nla_get_u8(attr);
6373 hdd_debug("%u", disable_fils);
6374
6375 enabled = !disable_fils;
6376 status = ucfg_mlme_set_fils_enabled_info(hdd_ctx->psoc, enabled);
6377 if (QDF_IS_STATUS_ERROR(status))
6378 hdd_err("could not set fils enabled info, %d", status);
6379
6380 status = ucfg_mlme_set_enable_bcast_probe_rsp(hdd_ctx->psoc, enabled);
6381 if (QDF_IS_STATUS_ERROR(status))
6382 hdd_err("could not set enable bcast probe resp info, %d",
6383 status);
6384
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006385 status = wma_cli_set_command(adapter->vdev_id,
Jeff Johnson0a315912018-11-16 11:18:21 -08006386 WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE,
6387 !disable_fils, VDEV_CMD);
6388 if (QDF_IS_STATUS_ERROR(status))
6389 hdd_err("failed to set enable bcast probe resp, %d",
6390 status);
6391
6392 return qdf_status_to_os_return(status);
6393}
6394
Jeff Johnson0bdbb962018-11-16 11:42:10 -08006395static int hdd_config_rsn_ie(struct hdd_adapter *adapter,
6396 const struct nlattr *attr)
6397{
6398 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6399 bool override_enabled;
6400 uint8_t force_rsne_override;
6401
6402 /* ignore unless support explicitly enabled */
6403 ucfg_mlme_get_force_rsne_override(hdd_ctx->psoc, &override_enabled);
6404 if (!override_enabled)
6405 return 0;
6406
6407 force_rsne_override = nla_get_u8(attr);
6408 if (force_rsne_override > 1) {
6409 hdd_err("Invalid value %d", force_rsne_override);
6410 return -EINVAL;
6411 }
6412
6413 hdd_ctx->force_rsne_override = force_rsne_override;
6414 hdd_debug("force_rsne_override - %d", force_rsne_override);
6415
6416 return 0;
6417}
6418
Jeff Johnson7acca0d2018-11-16 11:53:18 -08006419static int hdd_config_gtx(struct hdd_adapter *adapter,
6420 const struct nlattr *attr)
6421{
6422 uint8_t config_gtx;
6423 int errno;
6424
6425 config_gtx = nla_get_u8(attr);
6426 if (config_gtx > 1) {
6427 hdd_err_rl("Invalid config_gtx value %d", config_gtx);
6428 return -EINVAL;
6429 }
6430
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006431 errno = sme_cli_set_command(adapter->vdev_id,
Jeff Johnson7acca0d2018-11-16 11:53:18 -08006432 WMI_VDEV_PARAM_GTX_ENABLE,
6433 config_gtx, VDEV_CMD);
6434 if (errno)
6435 hdd_err("Failed to set GTX, %d", errno);
6436
6437 return errno;
6438}
6439
lifeng66831662017-05-19 16:01:35 +08006440/**
Jeff Johnsonb48efe22018-11-15 11:53:09 -08006441 * typedef independent_setter_fn - independent attribute handler
6442 * @adapter: The adapter being configured
6443 * @attr: The nl80211 attribute being applied
6444 *
6445 * Defines the signature of functions in the independent attribute vtable
6446 *
6447 * Return: 0 if the attribute was handled successfully, otherwise an errno
6448 */
6449typedef int (*independent_setter_fn)(struct hdd_adapter *adapter,
6450 const struct nlattr *attr);
6451
6452/**
6453 * struct independent_setters
6454 * @id: vendor attribute which this entry handles
6455 * @cb: callback function to invoke to process the attribute when present
6456 */
6457struct independent_setters {
6458 uint32_t id;
6459 independent_setter_fn cb;
6460};
6461
6462/* vtable for independent setters */
6463static const struct independent_setters independent_setters[] = {
Jeff Johnson522464b2018-11-15 13:07:26 -08006464 {QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES,
6465 hdd_config_scan_default_ies},
Jeff Johnson7f4fd702018-11-14 11:19:52 -08006466 {QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT,
6467 hdd_config_fine_time_measurement},
Jeff Johnsonbcaeafb2018-11-14 12:14:24 -08006468 {QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM,
6469 hdd_config_modulated_dtim},
Jeff Johnson6db91622018-11-14 12:33:28 -08006470 {QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL,
6471 hdd_config_listen_interval},
Jeff Johnson9381d032018-11-14 12:42:22 -08006472 {QCA_WLAN_VENDOR_ATTR_CONFIG_LRO,
6473 hdd_config_lro},
Jeff Johnson3d4f64c2018-11-14 13:13:04 -08006474 {QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE,
6475 hdd_config_scan_enable},
Jeff Johnson1feb8a62018-11-14 13:18:41 -08006476 {QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER,
6477 hdd_config_qpower},
Jeff Johnsonf15ede02018-11-14 13:27:13 -08006478 {QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR,
6479 hdd_config_stats_avg_factor},
Jeff Johnson47e2e842018-11-14 13:49:43 -08006480 {QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME,
6481 hdd_config_guard_time},
Jeff Johnsonf3827502018-11-14 14:00:58 -08006482 {QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY,
6483 hdd_config_non_agg_retry},
Jeff Johnsonb9021002018-11-15 15:51:36 -08006484 {QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY,
6485 hdd_config_agg_retry},
Jeff Johnson0e8259c2018-11-15 19:44:57 -08006486 {QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY,
6487 hdd_config_mgmt_retry},
Jeff Johnson6b48a2f2018-11-15 19:48:47 -08006488 {QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY,
6489 hdd_config_ctrl_retry},
Jeff Johnson98214742018-11-15 19:56:37 -08006490 {QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY,
6491 hdd_config_propagation_delay},
Jeff Johnson8fb9ded2018-11-15 20:44:56 -08006492 {QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY,
6493 hdd_config_propagation_abs_delay},
Jeff Johnson7c5e6dc2018-11-15 21:20:18 -08006494 {QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT,
6495 hdd_config_tx_fail_count},
Jeff Johnson7766fd22018-11-15 21:52:37 -08006496 {QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND,
6497 hdd_config_channel_avoidance_ind},
Jeff Johnsonf9871e42018-11-15 22:24:06 -08006498 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA,
6499 hdd_config_ant_div_ena},
Jeff Johnson91f90ff2018-11-16 07:53:37 -08006500 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF,
6501 hdd_config_ant_div_snr_diff},
Jeff Johnson77177bc2018-11-16 08:14:20 -08006502 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME,
6503 hdd_config_ant_div_probe_dwell_time},
Jeff Johnsonaa172222018-11-16 09:16:11 -08006504 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN,
6505 hdd_config_ant_div_chain},
Jeff Johnsonef427ad2018-11-16 09:22:17 -08006506 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST,
6507 hdd_config_ant_div_selftest},
Jeff Johnsonae21be82018-11-16 09:43:53 -08006508 {QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL,
6509 hdd_config_ant_div_selftest_intvl},
Jeff Johnson3a25de82018-11-16 07:26:46 -08006510 {QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED,
6511 hdd_config_ignore_assoc_disallowed},
Jeff Johnson72dc91e2018-11-16 08:46:12 -08006512 {QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL,
6513 hdd_config_restrict_offchannel},
Jeff Johnson320feeb2018-11-16 10:14:24 -08006514 {QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT,
6515 hdd_config_total_beacon_miss_count},
Jeff Johnson2502ddd2018-11-16 10:59:30 -08006516 {QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL,
6517 hdd_config_latency_level},
Jeff Johnson0a315912018-11-16 11:18:21 -08006518 {QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS,
6519 hdd_config_disable_fils},
Jeff Johnson0bdbb962018-11-16 11:42:10 -08006520 {QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE,
6521 hdd_config_rsn_ie},
Jeff Johnson7acca0d2018-11-16 11:53:18 -08006522 {QCA_WLAN_VENDOR_ATTR_CONFIG_GTX,
6523 hdd_config_gtx},
Jeff Johnsonb48efe22018-11-15 11:53:09 -08006524};
6525
6526/**
6527 * hdd_set_independent_configuration() - Handle independent attributes
6528 * @adapter: adapter upon which the vendor command was received
6529 * @tb: parsed attribute array
6530 *
6531 * This is a table-driven function which dispatches independent
6532 * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
6533 * vendor command. An attribute is considered independent if it
6534 * doesn't depend upon any other attributes
6535 *
6536 * Return: 0 if there were no issues, otherwise errno of the last issue
6537 */
6538static int hdd_set_independent_configuration(struct hdd_adapter *adapter,
6539 struct nlattr **tb)
6540{
6541 uint32_t i;
6542 uint32_t id;
6543 struct nlattr *attr;
6544 independent_setter_fn cb;
6545 int errno = 0;
6546 int ret;
6547
6548 for (i = 0; i < QDF_ARRAY_SIZE(independent_setters); i++) {
6549 id = independent_setters[i].id;
6550 attr = tb[id];
6551 if (!attr)
6552 continue;
6553
6554 cb = independent_setters[i].cb;
6555 ret = cb(adapter, attr);
6556 if (ret)
6557 errno = ret;
6558 }
6559
6560 return errno;
6561}
6562
6563/**
6564 * typedef interdependent_setter_fn - interdependent attribute handler
6565 * @adapter: The adapter being configured
6566 * @tb: The parsed nl80211 attributes being applied
6567 *
6568 * Defines the signature of functions in the interdependent attribute vtable
6569 *
6570 * Return: 0 if attributes were handled successfully, otherwise an errno
6571 */
6572typedef int (*interdependent_setter_fn)(struct hdd_adapter *adapter,
6573 struct nlattr **tb);
6574
6575/* vtable for interdependent setters */
6576static const interdependent_setter_fn interdependent_setters[] = {
Jeff Johnsonaffc4da2018-11-16 14:10:07 -08006577 hdd_config_access_policy,
Jeff Johnson0fbb43b2018-11-16 15:38:56 -08006578 hdd_config_mpdu_aggregation,
Jeff Johnson7bf20cb2018-11-16 17:38:27 -08006579 hdd_config_ant_div_period,
Jeff Johnson1350e622018-11-16 18:36:55 -08006580 hdd_config_ant_div_snr_weight,
Jeff Johnson0dd687e2018-11-16 20:11:27 -08006581 wlan_hdd_cfg80211_wifi_set_reorder_timeout,
Jeff Johnson339ede82018-11-16 20:27:52 -08006582 wlan_hdd_cfg80211_wifi_set_rx_blocksize,
Jeff Johnsonb48efe22018-11-15 11:53:09 -08006583};
6584
6585/**
6586 * hdd_set_interdependent_configuration() - Handle interdependent attributes
6587 * @adapter: adapter upon which the vendor command was received
6588 * @tb: parsed attribute array
6589 *
6590 * This is a table-driven function which handles interdependent
6591 * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
6592 * vendor command. A set of attributes is considered interdependent if
6593 * they depend upon each other. In the typical case if one of the
6594 * attributes is present in the the attribute array, then all of the
6595 * attributes must be present.
6596 *
6597 * Return: 0 if there were no issues, otherwise errno of the last issue
6598 */
6599static int hdd_set_interdependent_configuration(struct hdd_adapter *adapter,
6600 struct nlattr **tb)
6601{
6602 uint32_t i;
6603 interdependent_setter_fn cb;
6604 int errno = 0;
6605 int ret;
6606
6607 for (i = 0; i < QDF_ARRAY_SIZE(interdependent_setters); i++) {
6608 cb = interdependent_setters[i];
6609 ret = cb(adapter, tb);
6610 if (ret)
6611 errno = ret;
6612 }
6613
6614 return errno;
6615}
6616
6617/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006618 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
6619 * vendor command
6620 *
6621 * @wiphy: wiphy device pointer
6622 * @wdev: wireless device pointer
6623 * @data: Vendor command data buffer
6624 * @data_len: Buffer length
6625 *
6626 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
6627 *
6628 * Return: Error code.
6629 */
6630static int
6631__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
6632 struct wireless_dev *wdev,
6633 const void *data,
6634 int data_len)
6635{
6636 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07006637 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006638 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006639 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
Jeff Johnsonb48efe22018-11-15 11:53:09 -08006640 int errno;
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006641 int ret;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05306642
Dustin Brownfdf17c12018-03-14 12:55:34 -07006643 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08006644
Anurag Chouhan6d760662016-02-20 16:05:43 +05306645 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006646 hdd_err("Command not allowed in FTM mode");
6647 return -EPERM;
6648 }
6649
Jeff Johnsonb48efe22018-11-15 11:53:09 -08006650 errno = wlan_hdd_validate_context(hdd_ctx);
6651 if (errno)
6652 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006653
Dustin Brown4ea21db2018-01-05 14:13:17 -08006654 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
6655 data_len, wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006656 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006657 return -EINVAL;
6658 }
6659
Jeff Johnsonb48efe22018-11-15 11:53:09 -08006660 ret = hdd_set_independent_configuration(adapter, tb);
6661 if (ret)
6662 errno = ret;
6663
6664 ret = hdd_set_interdependent_configuration(adapter, tb);
6665 if (ret)
6666 errno = ret;
6667
Jeff Johnsonb48efe22018-11-15 11:53:09 -08006668 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006669}
6670
6671/**
6672 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
6673 * vendor command
6674 *
6675 * @wiphy: wiphy device pointer
6676 * @wdev: wireless device pointer
6677 * @data: Vendor command data buffer
6678 * @data_len: Buffer length
6679 *
6680 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
6681 *
6682 * Return: EOK or other error codes.
6683 */
6684static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
6685 struct wireless_dev *wdev,
6686 const void *data,
6687 int data_len)
6688{
Dustin Browna09acf42018-11-08 12:32:26 +05306689 int errno;
6690 struct osif_vdev_sync *vdev_sync;
6691
6692 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
6693 if (errno)
6694 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006695
Dustin Browna09acf42018-11-08 12:32:26 +05306696 errno = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
6697 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006698
Dustin Browna09acf42018-11-08 12:32:26 +05306699 osif_vdev_sync_op_stop(vdev_sync);
6700
6701 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006702}
6703
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006704/**
6705 * __wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
6706 * vendor command
6707 *
6708 * @wiphy: wiphy device pointer
6709 * @wdev: wireless device pointer
6710 * @data: Vendor command data buffer
6711 * @data_len: Buffer length
6712 *
6713 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
6714 *
6715 * Return: Error code.
6716 */
6717static int
6718__wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
Srinivas Girigowdaa19eafd2018-09-07 15:28:21 -07006719 struct wireless_dev *wdev, const void *data, int data_len)
6720{
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006721 struct net_device *dev = wdev->netdev;
6722 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6723 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
6724 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1];
6725 int ret_val = 0;
6726 uint8_t cfg_val = 0;
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08006727 uint8_t set_val = 0;
Jeff Johnson46b4f0e2019-03-08 10:48:35 -08006728 struct sme_config_params *sme_config;
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006729 bool update_sme_cfg = false;
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08006730 uint8_t tid = 0, ac;
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006731 uint16_t buff_size = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006732 mac_handle_t mac_handle;
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05306733 QDF_STATUS status;
6734 bool bval = false;
6735 uint8_t value = 0;
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +05306736 uint8_t wmm_mode = 0;
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07006737 uint32_t cmd_id;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006738
Dustin Brownfdf17c12018-03-14 12:55:34 -07006739 hdd_enter_dev(dev);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006740
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006741 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Min Liu74a1a502018-10-10 19:59:07 +08006742 if (!sme_config)
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006743 return -ENOMEM;
Min Liu74a1a502018-10-10 19:59:07 +08006744
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006745 mac_handle = hdd_ctx->mac_handle;
6746 sme_get_config_param(mac_handle, sme_config);
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006747
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006748 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6749 hdd_err("Command not allowed in FTM mode");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006750 ret_val = -EPERM;
6751 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006752 }
6753
6754 ret_val = wlan_hdd_validate_context(hdd_ctx);
6755 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006756 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006757
6758 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
6759 hdd_err("Driver Modules are closed, can not start logger");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006760 ret_val = -EINVAL;
6761 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006762 }
6763
6764 if (wlan_cfg80211_nla_parse(tb,
6765 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX,
6766 data, data_len, wlan_hdd_wifi_test_config_policy)) {
6767 hdd_err("invalid attr");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006768 ret_val = -EINVAL;
6769 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006770 }
6771
6772 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]) {
6773 cfg_val = nla_get_u8(tb[
6774 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]
6775 );
6776 hdd_debug("set addba accept req from peer value %d", cfg_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006777 ret_val = sme_set_addba_accept(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006778 cfg_val);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006779 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006780 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006781 }
6782
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08006783 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]) {
6784 cfg_val = nla_get_u8(tb[
6785 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]);
6786 hdd_debug("set HE MCS value 0x%0X", cfg_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006787 ret_val = sme_update_he_mcs(mac_handle, adapter->vdev_id,
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08006788 cfg_val);
6789 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006790 goto send_err;
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08006791 }
6792
Krunal Soni707eb782018-01-18 12:04:19 -08006793 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]) {
6794 cfg_val = nla_get_u8(tb[
6795 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]);
Krunal Soni707eb782018-01-18 12:04:19 -08006796 if (!cfg_val) {
6797 sme_config->csrConfig.WMMSupportMode =
6798 hdd_to_csr_wmm_mode(HDD_WMM_USER_MODE_NO_QOS);
6799 hdd_debug("wmm is disabled");
6800 } else {
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +05306801 status = ucfg_mlme_get_wmm_mode(hdd_ctx->psoc,
6802 &wmm_mode);
6803 if (!QDF_IS_STATUS_SUCCESS(status)) {
6804 hdd_err("Get wmm_mode failed");
6805 return QDF_STATUS_E_FAILURE;
6806 }
Krunal Soni707eb782018-01-18 12:04:19 -08006807 sme_config->csrConfig.WMMSupportMode =
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +05306808 hdd_to_csr_wmm_mode(wmm_mode);
Krunal Soni707eb782018-01-18 12:04:19 -08006809 hdd_debug("using wmm default value");
6810 }
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006811 update_sme_cfg = true;
Krunal Soni707eb782018-01-18 12:04:19 -08006812 }
6813
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08006814 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]) {
6815 cfg_val = nla_get_u8(tb[
6816 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]);
6817 if (cfg_val) {
6818 /*Auto BA mode*/
6819 set_val = 0;
6820 hdd_debug("BA operating mode is set to auto");
6821 } else {
6822 /*Manual BA mode*/
6823 set_val = 1;
6824 hdd_debug("BA operating mode is set to Manual");
6825 }
6826
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006827 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08006828 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
Kiran Kumar Lokere015f77f2018-04-24 18:25:28 -07006829 if (ret_val) {
6830 hdd_err("Set BA operating mode failed");
6831 goto send_err;
6832 }
6833 if (!cfg_val) {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006834 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere015f77f2018-04-24 18:25:28 -07006835 WMI_VDEV_PARAM_AMSDU_AGGREGATION_SIZE_OPTIMIZATION,
6836 0, VDEV_CMD);
6837 }
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08006838 }
6839
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08006840 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]) {
6841 cfg_val = nla_get_u8(tb[
6842 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]
6843 );
6844 if (cfg_val > HE_FRAG_LEVEL1)
6845 set_val = HE_FRAG_LEVEL1;
6846 else
6847 set_val = cfg_val;
6848
6849 hdd_debug("set HE fragmention to %d", set_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006850 ret_val = sme_update_he_frag_supp(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006851 adapter->vdev_id, set_val);
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08006852 }
6853
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006854 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]) {
6855 cfg_val = nla_get_u8(tb[
6856 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]);
6857 sme_config->csrConfig.wep_tkip_in_he = cfg_val;
6858 hdd_debug("Set WEP/TKIP allow in HE %d", cfg_val);
6859
6860 update_sme_cfg = true;
6861 }
6862
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006863 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]) {
6864 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]) {
6865 tid = nla_get_u8(tb[
6866 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]);
6867 } else {
6868 hdd_err("TID is not set for ADD/DEL BA cfg");
6869 ret_val = -EINVAL;
6870 goto send_err;
6871 }
6872 cfg_val = nla_get_u8(tb[
6873 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]);
6874 if (cfg_val == QCA_WLAN_ADD_BA) {
6875 if (tb[
6876 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE])
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07006877 buff_size = nla_get_u16(tb[
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006878 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006879 ret_val = sme_send_addba_req(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006880 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006881 tid, buff_size);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006882 } else if (cfg_val == QCA_WLAN_DELETE_BA) {
6883 } else {
6884 hdd_err("Invalid BA session cfg");
6885 ret_val = -EINVAL;
6886 goto send_err;
6887 }
6888 } else if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]) {
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07006889 buff_size = nla_get_u16(tb[
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006890 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
6891 hdd_debug("set buff size to %d for all tids", buff_size);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006892 ret_val = sme_set_ba_buff_size(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006893 adapter->vdev_id, buff_size);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006894 if (ret_val)
6895 goto send_err;
6896 if (buff_size > 64)
6897 /* Configure ADDBA req buffer size to 256 */
6898 set_val = 3;
6899 else
6900 /* Configure ADDBA req buffer size to 64 */
6901 set_val = 2;
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006902 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006903 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07006904 if (ret_val)
6905 hdd_err("Failed to set BA operating mode %d", set_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006906 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07006907 GEN_VDEV_PARAM_AMPDU,
6908 buff_size, GEN_CMD);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006909 }
6910
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08006911 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]) {
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07006912 int he_mcs_val;
Srinivas Girigowda50335342018-09-07 15:21:01 -07006913
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08006914 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]) {
6915 ac = nla_get_u8(tb[
6916 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]);
6917 } else {
6918 hdd_err("AC is not set for NO ACK policy config");
6919 ret_val = -EINVAL;
6920 goto send_err;
6921 }
6922 cfg_val = nla_get_u8(tb[
6923 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]);
6924 hdd_debug("Set NO_ACK to %d for ac %d", cfg_val, ac);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006925 ret_val = sme_set_no_ack_policy(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006926 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006927 cfg_val, ac);
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07006928 if (cfg_val) {
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05306929 status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc,
6930 &bval);
6931 if (!QDF_IS_STATUS_SUCCESS(status))
6932 hdd_err("unable to get vht_enable2x2");
6933 if (bval)
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07006934 /*2x2 MCS 5 value*/
6935 he_mcs_val = 0x45;
6936 else
6937 /*1x1 MCS 5 value*/
6938 he_mcs_val = 0x25;
6939
6940 if (hdd_set_11ax_rate(adapter, he_mcs_val, NULL))
6941 hdd_err("HE MCS set failed, MCS val %0x",
6942 he_mcs_val);
6943 } else {
6944 if (hdd_set_11ax_rate(adapter, 0xFF, NULL))
6945 hdd_err("disable fixed rate failed");
6946 }
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08006947 }
6948
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08006949 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]) {
6950 cfg_val = nla_get_u8(tb[
6951 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]);
6952 hdd_debug("Set HE LTF to %d", cfg_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006953 ret_val = sme_set_auto_rate_he_ltf(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006954 adapter->vdev_id,
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08006955 cfg_val);
6956 if (ret_val)
6957 sme_err("Failed to set auto rate HE LTF");
6958
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006959 ret_val = wma_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08006960 WMI_VDEV_PARAM_HE_LTF,
6961 cfg_val, VDEV_CMD);
6962 if (ret_val)
6963 goto send_err;
6964 }
6965
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07006966 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]) {
6967 cfg_val = nla_get_u8(tb[
6968 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]);
6969 hdd_debug("Set Tx beamformee to %d", cfg_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006970 ret_val = sme_update_tx_bfee_supp(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006971 adapter->vdev_id,
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07006972 cfg_val);
6973 if (ret_val)
6974 sme_err("Failed to set Tx beamformee cap");
6975
6976 }
6977
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07006978 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]) {
6979 cfg_val = nla_get_u8(tb[
6980 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]);
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05306981 status = ucfg_mlme_cfg_get_vht_tx_bfee_ant_supp(hdd_ctx->psoc,
Abhinav Kumare057b412018-10-09 17:28:16 +05306982 &value);
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05306983 if (!QDF_IS_STATUS_SUCCESS(status))
6984 hdd_err("unable to get tx_bfee_ant_supp");
6985
Kiran Kumar Lokerea67af052018-12-12 19:18:51 -08006986 if (!cfg_in_range(CFG_VHT_BEAMFORMEE_ANT_SUPP, cfg_val)) {
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07006987 hdd_err("NSTS %d not supported, supp_val %d", cfg_val,
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05306988 value);
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07006989 ret_val = -ENOTSUPP;
6990 goto send_err;
6991 }
6992 hdd_debug("Set Tx beamformee NSTS to %d", cfg_val);
6993 ret_val = sme_update_tx_bfee_nsts(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08006994 adapter->vdev_id,
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07006995 cfg_val,
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05306996 value);
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07006997 if (ret_val)
6998 sme_err("Failed to set Tx beamformee cap");
6999
7000 }
7001
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07007002 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]) {
7003 cfg_val = nla_get_u8(tb[
7004 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]);
7005 if (cfg_val) {
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07007006 hdd_debug("Set HE mac padding dur to %d", cfg_val);
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007007 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07007008 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
7009 0, VDEV_CMD);
7010 if (ret_val)
7011 hdd_err("MU_EDCA update disable failed");
7012 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
7013 sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
7014 if (sme_update_mu_edca_params(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007015 adapter->vdev_id))
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07007016 hdd_err("Failed to send mu edca params");
7017 } else {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007018 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07007019 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
7020 1, VDEV_CMD);
7021 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
7022 }
7023 ret_val = sme_update_he_trigger_frm_mac_pad(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007024 adapter->vdev_id,
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07007025 cfg_val);
7026 if (ret_val)
7027 hdd_err("Failed to set Trig frame mac padding cap");
7028 }
7029
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07007030 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]) {
7031 cfg_val = nla_get_u8(tb[
7032 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]);
7033 if (cfg_val) {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007034 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07007035 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
7036 0, VDEV_CMD);
7037 if (ret_val)
7038 hdd_err("MU_EDCA update disable failed");
7039 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
7040 sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
7041 if (sme_update_mu_edca_params(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007042 adapter->vdev_id))
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07007043 hdd_err("Failed to send mu edca params");
7044 } else {
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007045 ret_val = sme_cli_set_command(adapter->vdev_id,
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07007046 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
7047 1, VDEV_CMD);
7048 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
7049 }
7050 }
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07007051
7052 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]) {
7053 cfg_val = nla_get_u8(tb[
7054 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]);
7055 ret_val = sme_update_he_om_ctrl_supp(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007056 adapter->vdev_id,
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07007057 cfg_val);
7058 }
7059
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08007060 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX;
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07007061 if (tb[cmd_id]) {
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08007062 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX + 1];
7063 struct nlattr *curr_attr;
7064 int tmp, rc;
7065 nla_for_each_nested(curr_attr, tb[cmd_id], tmp) {
7066 rc = wlan_cfg80211_nla_parse(
7067 tb2, QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX,
7068 nla_data(curr_attr),
7069 nla_len(curr_attr),
7070 qca_wlan_vendor_attr_he_omi_tx_policy);
7071 if (rc) {
7072 hdd_err("Invalid ATTR");
7073 goto send_err;
7074 }
7075 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW;
7076 if (tb2[cmd_id]) {
7077 cfg_val = nla_get_u8(tb2[cmd_id]);
7078 ret_val = sme_set_he_om_ctrl_param(
7079 hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007080 adapter->vdev_id,
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08007081 cmd_id, cfg_val);
7082 }
7083 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS;
7084 if (tb2[cmd_id]) {
7085 cfg_val = nla_get_u8(tb2[cmd_id]);
7086 ret_val = sme_set_he_om_ctrl_param(
7087 hdd_ctx->mac_handle,
7088 adapter->vdev_id,
7089 cmd_id, cfg_val);
7090 }
7091
7092 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE;
7093 if (tb2[cmd_id]) {
7094 cfg_val = nla_get_u8(tb2[cmd_id]);
7095 ret_val = sme_set_he_om_ctrl_param(
7096 hdd_ctx->mac_handle,
7097 adapter->vdev_id,
7098 cmd_id, cfg_val);
7099 }
7100
7101 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS;
7102 if (tb2[cmd_id]) {
7103 cfg_val = nla_get_u8(tb2[cmd_id]);
7104 ret_val = sme_set_he_om_ctrl_param(
7105 hdd_ctx->mac_handle,
7106 adapter->vdev_id,
7107 cmd_id, cfg_val);
7108 }
Kiran Kumar Lokere49e3aff2019-02-06 17:00:48 -08007109
7110 cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE;
7111 if (tb2[cmd_id]) {
7112 cfg_val = nla_get_u8(tb2[cmd_id]);
7113 ret_val = sme_set_he_om_ctrl_param(
7114 hdd_ctx->mac_handle,
7115 adapter->vdev_id,
7116 cmd_id, cfg_val);
7117 }
7118
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08007119 }
7120 if (ret_val) {
7121 sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
7122 goto send_err;
7123 }
7124 ret_val = sme_send_he_om_ctrl_update(hdd_ctx->mac_handle,
7125 adapter->vdev_id);
Kiran Kumar Lokere94634152018-09-24 19:08:35 -07007126 }
7127
7128 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG])
7129 sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
7130
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07007131 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU;
7132 if (tb[cmd_id]) {
7133 cfg_val = nla_get_u8(tb[cmd_id]);
7134 hdd_debug("Configure Tx SU PPDU enable %d", cfg_val);
7135 if (cfg_val)
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007136 sme_config_su_ppdu_queue(adapter->vdev_id, true);
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07007137 else
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007138 sme_config_su_ppdu_queue(adapter->vdev_id, false);
Kiran Kumar Lokereefdbd0b2018-09-25 18:53:46 -07007139 }
7140
Kiran Kumar Lokerea1c29ec2019-02-25 18:19:00 -08007141 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT;
7142 if (tb[cmd_id]) {
7143 cfg_val = nla_get_u8(tb[cmd_id]);
7144 hdd_debug("Configure 2G VHT support %d", cfg_val);
7145 ucfg_mlme_set_vht_for_24ghz(hdd_ctx->psoc,
7146 (cfg_val ? true : false));
7147 }
7148
Kiran Kumar Lokereacd107d2019-01-09 15:02:11 -08007149 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP;
7150 if (tb[cmd_id]) {
7151 cfg_val = nla_get_u8(tb[cmd_id]);
7152 hdd_debug("Configure +HTC_HE support %d", cfg_val);
7153 sme_update_he_htc_he_supp(hdd_ctx->mac_handle,
7154 adapter->vdev_id,
7155 (cfg_val ? true : false));
7156 }
7157
Kiran Kumar Lokere921b5a52019-02-24 21:53:20 -08007158 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS;
7159 if (tb[cmd_id]) {
7160 cfg_val = nla_get_u8(tb[cmd_id]);
7161 hdd_debug("Configure HE testbed defaults %d", cfg_val);
7162 if (!cfg_val)
7163 sme_reset_he_caps(hdd_ctx->mac_handle,
7164 adapter->vdev_id);
7165 else
7166 sme_set_he_testbed_def(hdd_ctx->mac_handle,
7167 adapter->vdev_id);
7168 }
7169
Kiran Kumar Lokereee205772018-09-27 00:27:27 -07007170 cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU;
7171 if (tb[cmd_id]) {
7172 cfg_val = nla_get_u8(tb[cmd_id]);
7173 hdd_debug("Configure Action frame Tx in TB PPDU %d", cfg_val);
7174 sme_config_action_tx_in_tb_ppdu(hdd_ctx->mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08007175 adapter->vdev_id, cfg_val);
Kiran Kumar Lokereee205772018-09-27 00:27:27 -07007176 }
7177
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007178 if (update_sme_cfg)
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007179 sme_update_config(mac_handle, sme_config);
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007180
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007181send_err:
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007182 qdf_mem_free(sme_config);
7183
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007184 return ret_val;
7185}
7186
7187/**
7188 * wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
7189 * vendor command
7190 *
7191 * @wiphy: wiphy device pointer
7192 * @wdev: wireless device pointer
7193 * @data: Vendor command data buffer
7194 * @data_len: Buffer length
7195 *
7196 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
7197 *
7198 * Return: EOK or other error codes.
7199 */
7200static int wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
7201 struct wireless_dev *wdev, const void *data, int data_len)
7202{
Dustin Browna09acf42018-11-08 12:32:26 +05307203 int errno;
7204 struct osif_vdev_sync *vdev_sync;
7205
7206 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7207 if (errno)
7208 return errno;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007209
Dustin Browna09acf42018-11-08 12:32:26 +05307210 errno = __wlan_hdd_cfg80211_set_wifi_test_config(wiphy, wdev,
7211 data, data_len);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007212
Dustin Browna09acf42018-11-08 12:32:26 +05307213 osif_vdev_sync_op_stop(vdev_sync);
7214
7215 return errno;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007216}
7217
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007218static const struct
7219nla_policy
7220qca_wlan_vendor_wifi_logger_start_policy
7221[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
7222 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
7223 = {.type = NLA_U32 },
7224 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
7225 = {.type = NLA_U32 },
7226 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
7227 = {.type = NLA_U32 },
7228};
7229
7230/**
7231 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
7232 * or disable the collection of packet statistics from the firmware
7233 * @wiphy: WIPHY structure pointer
7234 * @wdev: Wireless device structure pointer
7235 * @data: Pointer to the data received
7236 * @data_len: Length of the data received
7237 *
7238 * This function enables or disables the collection of packet statistics from
7239 * the firmware
7240 *
7241 * Return: 0 on success and errno on failure
7242 */
7243static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
7244 struct wireless_dev *wdev,
7245 const void *data,
7246 int data_len)
7247{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307248 QDF_STATUS status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007249 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007250 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
Hanumanth Reddy Pothulae9af1162018-06-13 13:41:44 +05307251 struct sir_wifi_start_log start_log = { 0 };
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007252 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007253
Dustin Brownfdf17c12018-03-14 12:55:34 -07007254 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08007255
Anurag Chouhan6d760662016-02-20 16:05:43 +05307256 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007257 hdd_err("Command not allowed in FTM mode");
7258 return -EPERM;
7259 }
7260
7261 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05307262 if (status)
7263 return status;
7264
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05307265 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
7266 hdd_err("Driver Modules are closed, can not start logger");
7267 return -EINVAL;
7268 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007269
Dustin Brown4ea21db2018-01-05 14:13:17 -08007270 if (wlan_cfg80211_nla_parse(tb,
7271 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
7272 data, data_len,
7273 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007274 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007275 return -EINVAL;
7276 }
7277
7278 /* Parse and fetch ring id */
7279 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007280 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007281 return -EINVAL;
7282 }
7283 start_log.ring_id = nla_get_u32(
7284 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007285 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007286
7287 /* Parse and fetch verbose level */
7288 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007289 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007290 return -EINVAL;
7291 }
7292 start_log.verbose_level = nla_get_u32(
7293 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007294 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007295
7296 /* Parse and fetch flag */
7297 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007298 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007299 return -EINVAL;
7300 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05307301 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007302 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007303
Hanumanth Reddy Pothulae9af1162018-06-13 13:41:44 +05307304 start_log.user_triggered = 1;
7305
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307306 /* size is buff size which can be set using iwpriv command*/
7307 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05307308 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307309
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007310 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
7311
7312 if (start_log.ring_id == RING_ID_WAKELOCK) {
7313 /* Start/stop wakelock events */
7314 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
7315 cds_set_wakelock_logging(true);
7316 else
7317 cds_set_wakelock_logging(false);
7318 return 0;
7319 }
7320
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007321 mac_handle = hdd_ctx->mac_handle;
7322 status = sme_wifi_start_logger(mac_handle, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307323 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007324 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007325 status);
7326 return -EINVAL;
7327 }
7328 return 0;
7329}
7330
7331/**
7332 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
7333 * or disable the collection of packet statistics from the firmware
7334 * @wiphy: WIPHY structure pointer
7335 * @wdev: Wireless device structure pointer
7336 * @data: Pointer to the data received
7337 * @data_len: Length of the data received
7338 *
7339 * This function is used to enable or disable the collection of packet
7340 * statistics from the firmware
7341 *
7342 * Return: 0 on success and errno on failure
7343 */
7344static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
7345 struct wireless_dev *wdev,
7346 const void *data,
7347 int data_len)
7348{
Dustin Brown363b4792019-02-05 16:11:55 -08007349 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08007350 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05307351
Dustin Brown363b4792019-02-05 16:11:55 -08007352 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08007353 if (errno)
7354 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007355
Dustin Brownf0f00612019-01-31 16:02:24 -08007356 errno = __wlan_hdd_cfg80211_wifi_logger_start(wiphy, wdev,
7357 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007358
Dustin Brown363b4792019-02-05 16:11:55 -08007359 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05307360
Dustin Brownf0f00612019-01-31 16:02:24 -08007361 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007362}
7363
7364static const struct
7365nla_policy
7366qca_wlan_vendor_wifi_logger_get_ring_data_policy
7367[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
7368 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
7369 = {.type = NLA_U32 },
7370};
7371
7372/**
7373 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
7374 * @wiphy: WIPHY structure pointer
7375 * @wdev: Wireless device structure pointer
7376 * @data: Pointer to the data received
7377 * @data_len: Length of the data received
7378 *
7379 * This function is used to flush or retrieve the per packet statistics from
7380 * the driver
7381 *
7382 * Return: 0 on success and errno on failure
7383 */
7384static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
7385 struct wireless_dev *wdev,
7386 const void *data,
7387 int data_len)
7388{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307389 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007390 uint32_t ring_id;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007391 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007392 struct nlattr *tb
7393 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
7394
Dustin Brownfdf17c12018-03-14 12:55:34 -07007395 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08007396
Anurag Chouhan6d760662016-02-20 16:05:43 +05307397 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007398 hdd_err("Command not allowed in FTM mode");
7399 return -EPERM;
7400 }
7401
7402 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05307403 if (status)
7404 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007405
Dustin Brown4ea21db2018-01-05 14:13:17 -08007406 if (wlan_cfg80211_nla_parse(tb,
7407 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
7408 data, data_len,
7409 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007410 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007411 return -EINVAL;
7412 }
7413
7414 /* Parse and fetch ring id */
7415 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007416 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007417 return -EINVAL;
7418 }
7419
7420 ring_id = nla_get_u32(
7421 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
7422
7423 if (ring_id == RING_ID_PER_PACKET_STATS) {
7424 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007425 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05307426 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
7427 /*
7428 * As part of DRIVER ring ID, flush both driver and fw logs.
7429 * For other Ring ID's driver doesn't have any rings to flush
7430 */
Dustin Brown5e89ef82018-03-14 11:50:23 -07007431 hdd_info("Bug report triggered by framework");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05307432
7433 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
7434 WLAN_LOG_INDICATOR_FRAMEWORK,
7435 WLAN_LOG_REASON_CODE_UNUSED,
7436 true, false);
7437 if (QDF_STATUS_SUCCESS != status) {
7438 hdd_err("Failed to trigger bug report");
7439 return -EINVAL;
7440 }
7441 } else {
7442 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
7443 WLAN_LOG_INDICATOR_FRAMEWORK,
Agrawal Ashishaff28982017-05-30 15:25:47 +05307444 WLAN_LOG_REASON_CODE_UNUSED,
7445 ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007446 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007447 return 0;
7448}
7449
7450/**
7451 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
7452 * @wiphy: WIPHY structure pointer
7453 * @wdev: Wireless device structure pointer
7454 * @data: Pointer to the data received
7455 * @data_len: Length of the data received
7456 *
7457 * This function is used to flush or retrieve the per packet statistics from
7458 * the driver
7459 *
7460 * Return: 0 on success and errno on failure
7461 */
7462static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
7463 struct wireless_dev *wdev,
7464 const void *data,
7465 int data_len)
7466{
Dustin Brown363b4792019-02-05 16:11:55 -08007467 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08007468 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05307469
Dustin Brown363b4792019-02-05 16:11:55 -08007470 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08007471 if (errno)
7472 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007473
Dustin Brownf0f00612019-01-31 16:02:24 -08007474 errno = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy, wdev,
7475 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007476
Dustin Brown363b4792019-02-05 16:11:55 -08007477 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08007478
7479 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007480}
7481
7482#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
7483/**
7484 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
7485 * @hdd_ctx: HDD context
7486 * @request_id: [input] request id
7487 * @pattern_id: [output] pattern id
7488 *
7489 * This function loops through request id to pattern id array
7490 * if the slot is available, store the request id and return pattern id
7491 * if entry exists, return the pattern id
7492 *
7493 * Return: 0 on success and errno on failure
7494 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007495static int hdd_map_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007496 uint32_t request_id,
7497 uint8_t *pattern_id)
7498{
7499 uint32_t i;
7500
7501 mutex_lock(&hdd_ctx->op_ctx.op_lock);
7502 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
7503 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
7504 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
7505 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
7506 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7507 return 0;
7508 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
7509 request_id) {
7510 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
7511 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7512 return 0;
7513 }
7514 }
7515 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7516 return -EINVAL;
7517}
7518
7519/**
7520 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
7521 * @hdd_ctx: HDD context
7522 * @request_id: [input] request id
7523 * @pattern_id: [output] pattern id
7524 *
7525 * This function loops through request id to pattern id array
7526 * reset request id to 0 (slot available again) and
7527 * return pattern id
7528 *
7529 * Return: 0 on success and errno on failure
7530 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007531static int hdd_unmap_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007532 uint32_t request_id,
7533 uint8_t *pattern_id)
7534{
7535 uint32_t i;
7536
7537 mutex_lock(&hdd_ctx->op_ctx.op_lock);
7538 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
7539 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
7540 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
7541 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
7542 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7543 return 0;
7544 }
7545 }
7546 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7547 return -EINVAL;
7548}
7549
7550
7551/*
7552 * define short names for the global vendor params
7553 * used by __wlan_hdd_cfg80211_offloaded_packets()
7554 */
7555#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
7556#define PARAM_REQUEST_ID \
7557 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
7558#define PARAM_CONTROL \
7559 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
7560#define PARAM_IP_PACKET \
7561 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
7562#define PARAM_SRC_MAC_ADDR \
7563 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
7564#define PARAM_DST_MAC_ADDR \
7565 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
7566#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05307567#define PARAM_PROTO_TYPE \
7568 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007569
7570/**
7571 * wlan_hdd_add_tx_ptrn() - add tx pattern
7572 * @adapter: adapter pointer
7573 * @hdd_ctx: hdd context
7574 * @tb: nl attributes
7575 *
7576 * This function reads the NL attributes and forms a AddTxPtrn message
7577 * posts it to SME.
7578 *
7579 */
7580static int
Jeff Johnsone5006672017-08-29 14:39:02 -07007581wlan_hdd_add_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007582 struct nlattr **tb)
7583{
7584 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307585 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007586 uint32_t request_id, ret, len;
7587 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307588 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007589 uint16_t eth_type = htons(ETH_P_IP);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007590 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007591
7592 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07007593 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007594 return -ENOTSUPP;
7595 }
7596
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307597 add_req = qdf_mem_malloc(sizeof(*add_req));
Min Liu74a1a502018-10-10 19:59:07 +08007598 if (!add_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007599 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007600
7601 /* Parse and fetch request Id */
7602 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007603 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007604 goto fail;
7605 }
7606
7607 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
7608 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07007609 hdd_err("request_id cannot be MAX");
SaidiReddy Yenuga466b3ce2017-05-02 18:50:25 +05307610 goto fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007611 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007612 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007613
7614 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007615 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007616 goto fail;
7617 }
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05307618
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007619 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007620 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007621 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07007622 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007623 goto fail;
7624 }
7625
7626 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007627 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007628 goto fail;
7629 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08007630 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05307631 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007632 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08007633 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007634
Anurag Chouhanc5548422016-02-24 18:33:27 +05307635 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Jeff Johnson1e851a12017-10-28 14:36:12 -07007636 &adapter->mac_addr)) {
Srinivas Girigowda31896552015-11-18 22:59:52 -08007637 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007638 goto fail;
7639 }
7640
7641 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007642 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007643 goto fail;
7644 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05307645 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007646 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007647 MAC_ADDR_ARRAY(dst_addr.bytes));
7648
7649 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007650 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007651 goto fail;
7652 }
7653 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007654 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007655
7656 if (add_req->ucPtrnSize < 0 ||
7657 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
7658 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007659 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007660 add_req->ucPtrnSize);
7661 goto fail;
7662 }
7663
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05307664 if (!tb[PARAM_PROTO_TYPE])
7665 eth_type = htons(ETH_P_IP);
7666 else
7667 eth_type = htons(nla_get_u16(tb[PARAM_PROTO_TYPE]));
7668
7669 hdd_debug("packet proto type: %u", eth_type);
7670
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007671 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307672 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05307673 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307674 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307675 QDF_MAC_ADDR_SIZE);
7676 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307677 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007678 len += 2;
7679
7680 /*
7681 * This is the IP packet, add 14 bytes Ethernet (802.3) header
7682 * ------------------------------------------------------------
7683 * | 14 bytes Ethernet (802.3) header | IP header and payload |
7684 * ------------------------------------------------------------
7685 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307686 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007687 nla_data(tb[PARAM_IP_PACKET]),
7688 add_req->ucPtrnSize);
7689 add_req->ucPtrnSize += len;
7690
7691 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
7692 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007693 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007694 goto fail;
7695 }
7696 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007697 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007698
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007699 mac_handle = hdd_ctx->mac_handle;
7700 status = sme_add_periodic_tx_ptrn(mac_handle, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307701 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007702 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007703 goto fail;
7704 }
7705
Dustin Browne74003f2018-03-14 12:51:58 -07007706 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307707 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007708 return 0;
7709
7710fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307711 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007712 return -EINVAL;
7713}
7714
7715/**
7716 * wlan_hdd_del_tx_ptrn() - delete tx pattern
7717 * @adapter: adapter pointer
7718 * @hdd_ctx: hdd context
7719 * @tb: nl attributes
7720 *
7721 * This function reads the NL attributes and forms a DelTxPtrn message
7722 * posts it to SME.
7723 *
7724 */
7725static int
Jeff Johnsone5006672017-08-29 14:39:02 -07007726wlan_hdd_del_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007727 struct nlattr **tb)
7728{
7729 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307730 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007731 uint32_t request_id, ret;
7732 uint8_t pattern_id = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007733 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007734
7735 /* Parse and fetch request Id */
7736 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007737 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007738 return -EINVAL;
7739 }
7740 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
7741 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07007742 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007743 return -EINVAL;
7744 }
7745
7746 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
7747 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007748 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007749 return -EINVAL;
7750 }
7751
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307752 del_req = qdf_mem_malloc(sizeof(*del_req));
Min Liu74a1a502018-10-10 19:59:07 +08007753 if (!del_req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007754 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007755
Jeff Johnson1e851a12017-10-28 14:36:12 -07007756 qdf_copy_macaddr(&del_req->mac_address, &adapter->mac_addr);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007757 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007758 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007759 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007760 request_id, del_req->ucPtrnId);
7761
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007762 mac_handle = hdd_ctx->mac_handle;
7763 status = sme_del_periodic_tx_ptrn(mac_handle, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307764 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007765 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007766 goto fail;
7767 }
7768
Dustin Browne74003f2018-03-14 12:51:58 -07007769 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307770 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007771 return 0;
7772
7773fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307774 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007775 return -EINVAL;
7776}
7777
7778
7779/**
7780 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
7781 * @wiphy: Pointer to wireless phy
7782 * @wdev: Pointer to wireless device
7783 * @data: Pointer to data
7784 * @data_len: Data length
7785 *
7786 * Return: 0 on success, negative errno on failure
7787 */
7788static int
7789__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
7790 struct wireless_dev *wdev,
7791 const void *data,
7792 int data_len)
7793{
7794 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07007795 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007796 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007797 struct nlattr *tb[PARAM_MAX + 1];
7798 uint8_t control;
7799 int ret;
7800 static const struct nla_policy policy[PARAM_MAX + 1] = {
7801 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
7802 [PARAM_CONTROL] = { .type = NLA_U32 },
7803 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307804 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007805 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307806 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007807 [PARAM_PERIOD] = { .type = NLA_U32 },
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05307808 [PARAM_PROTO_TYPE] = {.type = NLA_U16},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007809 };
7810
Dustin Brownfdf17c12018-03-14 12:55:34 -07007811 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007812
Anurag Chouhan6d760662016-02-20 16:05:43 +05307813 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007814 hdd_err("Command not allowed in FTM mode");
7815 return -EPERM;
7816 }
7817
7818 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05307819 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007820 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007821
7822 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007823 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007824 return -ENOTSUPP;
7825 }
7826
Dustin Brown4ea21db2018-01-05 14:13:17 -08007827 if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007828 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007829 return -EINVAL;
7830 }
7831
7832 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007833 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007834 return -EINVAL;
7835 }
7836 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007837 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007838
7839 if (control == WLAN_START_OFFLOADED_PACKETS)
7840 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08007841 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007842 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08007843
7844 hdd_err("Invalid control: %d", control);
Jeff Johnson68755312017-02-10 11:46:55 -08007845 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007846}
7847
7848/*
7849 * done with short names for the global vendor params
7850 * used by __wlan_hdd_cfg80211_offloaded_packets()
7851 */
7852#undef PARAM_MAX
7853#undef PARAM_REQUEST_ID
7854#undef PARAM_CONTROL
7855#undef PARAM_IP_PACKET
7856#undef PARAM_SRC_MAC_ADDR
7857#undef PARAM_DST_MAC_ADDR
7858#undef PARAM_PERIOD
Arun Kumar Khandavallif1f65922019-02-27 16:00:24 +05307859#undef PARAM_PROTO_TYPE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007860
7861/**
7862 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
7863 * @wiphy: wiphy structure pointer
7864 * @wdev: Wireless device structure pointer
7865 * @data: Pointer to the data received
7866 * @data_len: Length of @data
7867 *
7868 * Return: 0 on success; errno on failure
7869 */
7870static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
7871 struct wireless_dev *wdev,
7872 const void *data,
7873 int data_len)
7874{
Dustin Browna09acf42018-11-08 12:32:26 +05307875 int errno;
7876 struct osif_vdev_sync *vdev_sync;
7877
7878 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7879 if (errno)
7880 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007881
Dustin Browna09acf42018-11-08 12:32:26 +05307882 errno = __wlan_hdd_cfg80211_offloaded_packets(wiphy, wdev,
7883 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007884
Dustin Browna09acf42018-11-08 12:32:26 +05307885 osif_vdev_sync_op_stop(vdev_sync);
7886
7887 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007888}
7889#endif
7890
Qiwei Cai1083f5b2018-07-02 19:10:11 +08007891#ifdef WLAN_NS_OFFLOAD
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307892static const struct nla_policy
7893ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
7894 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
7895};
7896
7897/**
7898 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
7899 * @wiphy: Pointer to wireless phy
7900 * @wdev: Pointer to wireless device
7901 * @data: Pointer to data
7902 * @data_len: Length of @data
7903 *
7904 * Return: 0 on success, negative errno on failure
7905 */
7906static int
7907__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
7908 struct wireless_dev *wdev,
7909 const void *data, int data_len)
7910{
7911 int status;
7912 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
Jeff Johnsonb8944722017-09-03 09:03:19 -07007913 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07007914 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07007915 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307916
Dustin Brownfdf17c12018-03-14 12:55:34 -07007917 hdd_enter_dev(wdev->netdev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307918
Jeff Johnsonb8944722017-09-03 09:03:19 -07007919 status = wlan_hdd_validate_context(hdd_ctx);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307920 if (0 != status)
7921 return status;
Wu Gao66454f12018-09-26 19:55:41 +08007922
7923 if (!ucfg_pmo_is_ns_offloaded(hdd_ctx->psoc)) {
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307924 hdd_err("ND Offload not supported");
7925 return -EINVAL;
7926 }
7927
Wu Gao66454f12018-09-26 19:55:41 +08007928 if (!ucfg_pmo_is_active_mode_offloaded(hdd_ctx->psoc)) {
Mukul Sharma495df602017-09-25 14:52:18 +05307929 hdd_warn("Active mode offload is disabled");
7930 return -EINVAL;
7931 }
7932
Dustin Brown4ea21db2018-01-05 14:13:17 -08007933 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
7934 (struct nlattr *)data, data_len,
7935 ns_offload_set_policy)) {
7936 hdd_err("nla_parse failed");
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307937 return -EINVAL;
7938 }
7939
7940 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
7941 hdd_err("ND Offload flag attribute not present");
7942 return -EINVAL;
7943 }
7944
Jeff Johnsonb8944722017-09-03 09:03:19 -07007945 hdd_ctx->ns_offload_enable =
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307946 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
7947
Nachiket Kukadedbffab82017-04-25 19:26:02 +05307948 if (QDF_IBSS_MODE == adapter->device_mode) {
7949 hdd_debug("NS Offload is not supported in IBSS mode");
7950 return -EINVAL;
7951 }
7952
Dustin Brownd8279d22016-09-07 14:52:57 -07007953 /* update ns offload in case it is already enabled/disabled */
Jeff Johnsonb8944722017-09-03 09:03:19 -07007954 if (hdd_ctx->ns_offload_enable)
Mukul Sharma3ba26b82017-01-12 21:59:41 +05307955 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
7956 else
7957 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07007958
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307959 return 0;
7960}
7961
7962/**
7963 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
7964 * @wiphy: pointer to wireless wiphy structure.
7965 * @wdev: pointer to wireless_dev structure.
7966 * @data: Pointer to the data to be passed via vendor interface
7967 * @data_len:Length of the data to be passed
7968 *
7969 * Return: Return the Success or Failure code.
7970 */
7971static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
7972 struct wireless_dev *wdev,
7973 const void *data, int data_len)
7974{
Dustin Browna09acf42018-11-08 12:32:26 +05307975 int errno;
7976 struct osif_vdev_sync *vdev_sync;
7977
7978 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7979 if (errno)
7980 return errno;
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307981
Dustin Browna09acf42018-11-08 12:32:26 +05307982 errno = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307983
Dustin Browna09acf42018-11-08 12:32:26 +05307984 osif_vdev_sync_op_stop(vdev_sync);
7985
7986 return errno;
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307987}
Qiwei Cai1083f5b2018-07-02 19:10:11 +08007988#endif /* WLAN_NS_OFFLOAD */
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307989
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05307990/**
7991 * struct weighed_pcl: Preferred channel info
7992 * @freq: Channel frequency
7993 * @weight: Weightage of the channel
7994 * @flag: Validity of the channel in p2p negotiation
7995 */
7996struct weighed_pcl {
7997 u32 freq;
7998 u32 weight;
7999 u32 flag;
8000};
8001
Jeff Johnsondd7bd3e2017-06-05 13:25:24 -07008002static const struct nla_policy get_preferred_freq_list_policy
8003 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1] = {
8004 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE] = {
8005 .type = NLA_U32},
8006};
8007
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05308008static uint32_t wlan_hdd_populate_weigh_pcl(
8009 struct policy_mgr_pcl_chan_weights *
8010 chan_weights,
8011 struct weighed_pcl *w_pcl,
8012 enum policy_mgr_con_mode intf_mode)
8013{
8014 int i, j;
8015 uint32_t chan_idx = 0;
8016 uint32_t set = 0;
8017 uint32_t pcl_len = chan_weights->pcl_len;
8018 uint32_t valid_weight;
8019
8020 /* convert channel number to frequency */
8021 for (i = 0; i < chan_weights->pcl_len; i++) {
8022 if (chan_weights->pcl_list[i] <=
8023 ARRAY_SIZE(hdd_channels_2_4_ghz))
8024 w_pcl[i].freq = ieee80211_channel_to_frequency(
8025 chan_weights->pcl_list[i],
8026 HDD_NL80211_BAND_2GHZ);
8027 else
8028 w_pcl[i].freq = ieee80211_channel_to_frequency(
8029 chan_weights->pcl_list[i],
8030 HDD_NL80211_BAND_5GHZ);
8031 w_pcl[i].weight = chan_weights->weight_list[i];
8032
8033 if (intf_mode == PM_SAP_MODE || intf_mode == PM_P2P_GO_MODE)
8034 w_pcl[i].flag = set | PCL_CHANNEL_SUPPORT_GO;
8035 else
8036 w_pcl[i].flag = set | PCL_CHANNEL_SUPPORT_CLI;
8037 }
8038 chan_idx = pcl_len;
8039 if (chan_weights->weight_list[pcl_len - 1] >
8040 PCL_GROUPS_WEIGHT_DIFFERENCE)
8041 /* Set non-pcl channels weight 20 point less than the last PCL entry */
8042 valid_weight = chan_weights->weight_list[pcl_len - 1] -
8043 PCL_GROUPS_WEIGHT_DIFFERENCE;
8044 else
8045 valid_weight = 1;
8046
8047 /* Include rest of the valid channels */
8048 for (i = 0; i < chan_weights->saved_num_chan; i++) {
8049 for (j = 0; j < chan_weights->pcl_len; j++) {
8050 if (chan_weights->saved_chan_list[i] ==
8051 chan_weights->pcl_list[j])
8052 break;
8053 }
8054 if (j == chan_weights->pcl_len) {
8055 if (chan_weights->saved_chan_list[i] <=
8056 ARRAY_SIZE(hdd_channels_2_4_ghz))
8057 w_pcl[chan_idx].freq =
8058 ieee80211_channel_to_frequency(
8059 chan_weights->saved_chan_list[i],
8060 HDD_NL80211_BAND_2GHZ);
8061 else
8062 w_pcl[chan_idx].freq =
8063 ieee80211_channel_to_frequency(
8064 chan_weights->saved_chan_list[i],
8065 HDD_NL80211_BAND_5GHZ);
8066
8067 if (!chan_weights->weighed_valid_list[i]) {
8068 w_pcl[chan_idx].flag =
8069 set | PCL_CHANNEL_EXCLUDE_IN_GO_NEG;
8070 w_pcl[chan_idx].weight = 0;
8071 } else {
8072 if (intf_mode == PM_SAP_MODE ||
8073 intf_mode == PM_P2P_GO_MODE)
8074 w_pcl[chan_idx].flag =
8075 set | PCL_CHANNEL_SUPPORT_GO;
8076 else
8077 w_pcl[chan_idx].flag =
8078 set | PCL_CHANNEL_SUPPORT_CLI;
8079 w_pcl[chan_idx].weight = valid_weight;
8080 }
8081 chan_idx++;
8082 }
8083 }
8084 return chan_idx;
8085}
8086
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008087/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
8088 * @wiphy: Pointer to wireless phy
8089 * @wdev: Pointer to wireless device
8090 * @data: Pointer to data
8091 * @data_len: Data length
8092 *
8093 * This function return the preferred frequency list generated by the policy
8094 * manager.
8095 *
8096 * Return: success or failure code
8097 */
8098static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
8099 struct wireless_dev
8100 *wdev, const void *data,
8101 int data_len)
8102{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008103 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008104 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308105 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008106 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308107 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008108 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008109 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
8110 struct sk_buff *reply_skb;
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05308111 struct weighed_pcl *w_pcl;
8112 struct nlattr *nla_attr, *channel;
8113 struct policy_mgr_pcl_chan_weights *chan_weights;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008114
Dustin Brownfdf17c12018-03-14 12:55:34 -07008115 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08008116
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008117 ret = wlan_hdd_validate_context(hdd_ctx);
8118 if (ret)
8119 return -EINVAL;
8120
Dustin Brown4ea21db2018-01-05 14:13:17 -08008121 if (wlan_cfg80211_nla_parse(tb,
8122 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
8123 data, data_len,
8124 get_preferred_freq_list_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008125 hdd_err("Invalid ATTR");
8126 return -EINVAL;
8127 }
8128
8129 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
8130 hdd_err("attr interface type failed");
8131 return -EINVAL;
8132 }
8133
8134 intf_mode = nla_get_u32(tb
8135 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
8136
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008137 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008138 hdd_err("Invalid interface type");
8139 return -EINVAL;
8140 }
8141
8142 hdd_debug("Userspace requested pref freq list");
8143
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05308144 chan_weights =
8145 qdf_mem_malloc(sizeof(struct policy_mgr_pcl_chan_weights));
8146 if (!chan_weights)
8147 return -ENOMEM;
8148
Dustin Brown76cd2932018-09-11 16:03:05 -07008149 status = policy_mgr_get_pcl(hdd_ctx->psoc,
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05308150 intf_mode, chan_weights->pcl_list,
8151 &chan_weights->pcl_len,
8152 chan_weights->weight_list,
8153 QDF_ARRAY_SIZE(chan_weights->weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308154 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008155 hdd_err("Get pcl failed");
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05308156 qdf_mem_free(chan_weights);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008157 return -EINVAL;
8158 }
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05308159 sme_get_valid_channels(chan_weights->saved_chan_list,
8160 &chan_weights->saved_num_chan);
8161 policy_mgr_get_valid_chan_weights(hdd_ctx->psoc, chan_weights);
8162 w_pcl = qdf_mem_malloc(sizeof(struct weighed_pcl) * QDF_MAX_NUM_CHAN);
8163 if (!w_pcl) {
8164 qdf_mem_free(chan_weights);
8165 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008166 }
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05308167 pcl_len = wlan_hdd_populate_weigh_pcl(chan_weights, w_pcl, intf_mode);
8168 qdf_mem_free(chan_weights);
8169
8170 for (i = 0; i < pcl_len; i++)
8171 freq_list[i] = w_pcl[i].freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008172
8173 /* send the freq_list back to supplicant */
8174 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05308175 sizeof(u32) * pcl_len +
8176 sizeof(struct weighed_pcl) * pcl_len +
8177 NLMSG_HDRLEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008178
8179 if (!reply_skb) {
8180 hdd_err("Allocate reply_skb failed");
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05308181 qdf_mem_free(w_pcl);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008182 return -EINVAL;
8183 }
8184
8185 if (nla_put_u32(reply_skb,
8186 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
8187 intf_mode) ||
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05308188 nla_put(reply_skb,
8189 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
8190 sizeof(uint32_t) * pcl_len,
8191 freq_list)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008192 hdd_err("nla put fail");
8193 kfree_skb(reply_skb);
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05308194 qdf_mem_free(w_pcl);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008195 return -EINVAL;
8196 }
8197
Jayachandran Sreekumaran91f96ec2019-01-09 17:37:33 +05308198 i = QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL;
8199 nla_attr = nla_nest_start(reply_skb, i);
8200
8201 if (!nla_attr) {
8202 hdd_err("nla nest start fail");
8203 kfree_skb(reply_skb);
8204 qdf_mem_free(w_pcl);
8205 return -EINVAL;
8206 }
8207
8208 for (i = 0; i < pcl_len; i++) {
8209 channel = nla_nest_start(reply_skb, i);
8210 if (!channel) {
8211 hdd_err("updating pcl list failed");
8212 kfree_skb(reply_skb);
8213 qdf_mem_free(w_pcl);
8214 return -EINVAL;
8215 }
8216 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FREQ,
8217 w_pcl[i].freq) ||
8218 nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
8219 w_pcl[i].weight) ||
8220 nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FLAG,
8221 w_pcl[i].flag)) {
8222 hdd_err("nla put fail");
8223 kfree_skb(reply_skb);
8224 qdf_mem_free(w_pcl);
8225 return -EINVAL;
8226 }
8227 nla_nest_end(reply_skb, channel);
8228 }
8229 nla_nest_end(reply_skb, nla_attr);
8230 qdf_mem_free(w_pcl);
8231
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008232 return cfg80211_vendor_cmd_reply(reply_skb);
8233}
8234
8235/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
8236 * @wiphy: Pointer to wireless phy
8237 * @wdev: Pointer to wireless device
8238 * @data: Pointer to data
8239 * @data_len: Data length
8240 *
8241 * This function return the preferred frequency list generated by the policy
8242 * manager.
8243 *
8244 * Return: success or failure code
8245 */
8246static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
8247 struct wireless_dev
8248 *wdev, const void *data,
8249 int data_len)
8250{
Dustin Brown363b4792019-02-05 16:11:55 -08008251 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08008252 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05308253
Dustin Brown363b4792019-02-05 16:11:55 -08008254 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08008255 if (errno)
8256 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008257
Dustin Brownf0f00612019-01-31 16:02:24 -08008258 errno = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
8259 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008260
Dustin Brown363b4792019-02-05 16:11:55 -08008261 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05308262
Dustin Brownf0f00612019-01-31 16:02:24 -08008263 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008264}
8265
Jeff Johnsone5f33ba2017-06-05 14:48:48 -07008266static const struct nla_policy set_probable_oper_channel_policy
8267 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1] = {
8268 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE] = {
8269 .type = NLA_U32},
8270 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ] = {
8271 .type = NLA_U32},
8272};
8273
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008274/**
8275 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
8276 * @wiphy: Pointer to wireless phy
8277 * @wdev: Pointer to wireless device
8278 * @data: Pointer to data
8279 * @data_len: Data length
8280 *
8281 * Return: 0 on success, negative errno on failure
8282 */
8283static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
8284 struct wireless_dev *wdev,
8285 const void *data,
8286 int data_len)
8287{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05308288 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008289 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008290 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008291 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008292 enum policy_mgr_con_mode intf_mode;
Jeff Johnsone5f33ba2017-06-05 14:48:48 -07008293 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008294 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008295
Dustin Brownfdf17c12018-03-14 12:55:34 -07008296 hdd_enter_dev(ndev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08008297
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008298 ret = wlan_hdd_validate_context(hdd_ctx);
8299 if (ret)
8300 return ret;
8301
Dustin Brown4ea21db2018-01-05 14:13:17 -08008302 if (wlan_cfg80211_nla_parse(tb,
8303 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
8304 data, data_len,
8305 set_probable_oper_channel_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008306 hdd_err("Invalid ATTR");
8307 return -EINVAL;
8308 }
8309
8310 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
8311 hdd_err("attr interface type failed");
8312 return -EINVAL;
8313 }
8314
8315 intf_mode = nla_get_u32(tb
8316 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
8317
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008318 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008319 hdd_err("Invalid interface type");
8320 return -EINVAL;
8321 }
8322
8323 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
8324 hdd_err("attr probable freq failed");
8325 return -EINVAL;
8326 }
8327
8328 channel_hint = cds_freq_to_chan(nla_get_u32(tb
8329 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
8330
8331 /* check pcl table */
Dustin Brown76cd2932018-09-11 16:03:05 -07008332 if (!policy_mgr_allow_concurrency(hdd_ctx->psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008333 channel_hint, HW_MODE_20_MHZ)) {
8334 hdd_err("Set channel hint failed due to concurrency check");
8335 return -EINVAL;
8336 }
8337
Krunal Soni09e55032016-06-07 10:06:55 -07008338 if (0 != wlan_hdd_check_remain_on_channel(adapter))
8339 hdd_warn("Remain On Channel Pending");
8340
Krunal Sonied3bc8e2018-01-26 12:13:34 -08008341 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, channel_hint,
8342 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
8343 hdd_err("Failed to change hw mode");
Krunal Soni3091bcc2016-06-23 12:28:21 -07008344 return -EINVAL;
8345 }
8346
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008347 return 0;
8348}
8349
8350/**
8351 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
8352 * @wiphy: Pointer to wireless phy
8353 * @wdev: Pointer to wireless device
8354 * @data: Pointer to data
8355 * @data_len: Data length
8356 *
8357 * Return: 0 on success, negative errno on failure
8358 */
8359static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
8360 struct wireless_dev *wdev,
8361 const void *data,
8362 int data_len)
8363{
Dustin Browna09acf42018-11-08 12:32:26 +05308364 int errno;
8365 struct osif_vdev_sync *vdev_sync;
8366
8367 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
8368 if (errno)
8369 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008370
Dustin Browna09acf42018-11-08 12:32:26 +05308371 errno = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
8372 data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008373
Dustin Browna09acf42018-11-08 12:32:26 +05308374 osif_vdev_sync_op_stop(vdev_sync);
8375
8376 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008377}
8378
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308379static const struct
8380nla_policy
8381qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +05308382 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {
8383 .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308384};
8385
8386/**
8387 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
8388 * @wiphy: WIPHY structure pointer
8389 * @wdev: Wireless device structure pointer
8390 * @data: Pointer to the data received
8391 * @data_len: Length of the data received
8392 *
8393 * This function is used to get link properties like nss, rate flags and
8394 * operating frequency for the active connection with the given peer.
8395 *
8396 * Return: 0 on success and errno on failure
8397 */
8398static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
8399 struct wireless_dev *wdev,
8400 const void *data,
8401 int data_len)
8402{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008403 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308404 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008405 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson40dae4e2017-08-29 14:00:25 -07008406 struct hdd_station_ctx *hdd_sta_ctx;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308407 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05308408 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308409 uint32_t sta_id;
8410 struct sk_buff *reply_skb;
8411 uint32_t rate_flags = 0;
8412 uint8_t nss;
8413 uint8_t final_rate_flags = 0;
8414 uint32_t freq;
8415
Dustin Brownfdf17c12018-03-14 12:55:34 -07008416 hdd_enter_dev(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308417
Anurag Chouhan6d760662016-02-20 16:05:43 +05308418 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308419 hdd_err("Command not allowed in FTM mode");
8420 return -EPERM;
8421 }
8422
8423 if (0 != wlan_hdd_validate_context(hdd_ctx))
8424 return -EINVAL;
8425
Dustin Brown4ea21db2018-01-05 14:13:17 -08008426 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
8427 data_len, qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008428 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308429 return -EINVAL;
8430 }
8431
8432 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008433 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308434 adapter->device_mode);
8435 return -EINVAL;
8436 }
8437
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +05308438 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) < QDF_MAC_ADDR_SIZE) {
8439 hdd_err("Attribute peerMac is invalid for mode=%d",
8440 adapter->device_mode);
8441 return -EINVAL;
8442 }
8443
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308444 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05308445 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008446 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308447 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
8448
Krunal Sonib4326f22016-03-10 13:05:51 -08008449 if (adapter->device_mode == QDF_STA_MODE ||
8450 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308451 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnsone7951512019-02-27 10:02:51 -08008452 if ((hdd_sta_ctx->conn_info.conn_state !=
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308453 eConnectionState_Associated) ||
Jeff Johnsone04b6992019-02-27 14:06:55 -08008454 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssid.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308455 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008456 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308457 MAC_ADDR_ARRAY(peer_mac));
8458 return -EINVAL;
8459 }
8460
8461 nss = hdd_sta_ctx->conn_info.nss;
8462 freq = cds_chan_to_freq(
Jeff Johnson8626e932019-02-27 18:35:22 -08008463 hdd_sta_ctx->conn_info.channel);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308464 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08008465 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
8466 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308467
8468 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008469 if (adapter->sta_info[sta_id].in_use &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05308470 !qdf_is_macaddr_broadcast(
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008471 &adapter->sta_info[sta_id].sta_mac) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308472 !qdf_mem_cmp(
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008473 &adapter->sta_info[sta_id].sta_mac.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308474 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308475 break;
8476 }
8477
8478 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07008479 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308480 MAC_ADDR_ARRAY(peer_mac));
8481 return -EINVAL;
8482 }
8483
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008484 nss = adapter->sta_info[sta_id].nss;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308485 freq = cds_chan_to_freq(
Jeff Johnson01206862017-10-27 20:55:59 -07008486 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operating_channel);
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008487 rate_flags = adapter->sta_info[sta_id].rate_flags;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308488 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07008489 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308490 MAC_ADDR_ARRAY(peer_mac));
8491 return -EINVAL;
8492 }
8493
Naveen Rawatea1564b2018-05-17 15:56:11 -07008494 if (!(rate_flags & TX_RATE_LEGACY)) {
8495 if (rate_flags & TX_RATE_VHT80) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308496 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008497#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308498 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008499#endif
Naveen Rawatea1564b2018-05-17 15:56:11 -07008500 } else if (rate_flags & TX_RATE_VHT40) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308501 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008502#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308503 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008504#endif
Naveen Rawatea1564b2018-05-17 15:56:11 -07008505 } else if (rate_flags & TX_RATE_VHT20) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308506 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
8507 } else if (rate_flags &
Naveen Rawatea1564b2018-05-17 15:56:11 -07008508 (TX_RATE_HT20 | TX_RATE_HT40)) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308509 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008510#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Naveen Rawatea1564b2018-05-17 15:56:11 -07008511 if (rate_flags & TX_RATE_HT40)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308512 final_rate_flags |=
8513 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008514#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308515 }
8516
Naveen Rawatea1564b2018-05-17 15:56:11 -07008517 if (rate_flags & TX_RATE_SGI) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308518 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
8519 final_rate_flags |= RATE_INFO_FLAGS_MCS;
8520 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
8521 }
8522 }
8523
8524 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
8525 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
8526
8527 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07008528 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308529 return -EINVAL;
8530 }
8531
8532 if (nla_put_u8(reply_skb,
8533 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
8534 nss) ||
8535 nla_put_u8(reply_skb,
8536 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
8537 final_rate_flags) ||
8538 nla_put_u32(reply_skb,
8539 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
8540 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008541 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308542 kfree_skb(reply_skb);
8543 return -EINVAL;
8544 }
8545
8546 return cfg80211_vendor_cmd_reply(reply_skb);
8547}
8548
8549/**
8550 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
8551 * properties.
8552 * @wiphy: WIPHY structure pointer
8553 * @wdev: Wireless device structure pointer
8554 * @data: Pointer to the data received
8555 * @data_len: Length of the data received
8556 *
8557 * This function is used to get link properties like nss, rate flags and
8558 * operating frequency for the active connection with the given peer.
8559 *
8560 * Return: 0 on success and errno on failure
8561 */
8562static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
8563 struct wireless_dev *wdev,
8564 const void *data,
8565 int data_len)
8566{
Dustin Browna09acf42018-11-08 12:32:26 +05308567 int errno;
8568 struct osif_vdev_sync *vdev_sync;
8569
8570 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
8571 if (errno)
8572 return errno;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308573
Dustin Browna09acf42018-11-08 12:32:26 +05308574 errno = __wlan_hdd_cfg80211_get_link_properties(wiphy, wdev,
8575 data, data_len);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308576
Dustin Browna09acf42018-11-08 12:32:26 +05308577 osif_vdev_sync_op_stop(vdev_sync);
8578
8579 return errno;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308580}
8581
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308582static const struct nla_policy
8583wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
8584 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
Ganesh Kondabattini099e6e82017-06-28 12:24:20 +05308585 [QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST] = {
8586 .type = NLA_NESTED },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308587};
8588
Agrawal Ashish65634612016-08-18 13:24:32 +05308589static const struct nla_policy
8590wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
8591 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
8592 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
8593};
8594
8595/**
8596 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
8597 * @wiphy: Pointer to wireless phy
8598 * @wdev: Pointer to wireless device
8599 * @data: Pointer to data
8600 * @data_len: Length of @data
8601 *
8602 * This function parses the incoming NL vendor command data attributes and
8603 * updates the SAP context about channel_hint and DFS mode.
8604 * If channel_hint is set, SAP will choose that channel
8605 * as operating channel.
8606 *
8607 * If DFS mode is enabled, driver will include DFS channels
8608 * in ACS else driver will skip DFS channels.
8609 *
8610 * Return: 0 on success, negative errno on failure
8611 */
8612static int
8613__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8614 struct wireless_dev *wdev,
8615 const void *data, int data_len)
8616{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008617 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish65634612016-08-18 13:24:32 +05308618 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
8619 int ret;
8620 struct acs_dfs_policy *acs_policy;
8621 int mode = DFS_MODE_NONE;
8622 int channel_hint = 0;
8623
Dustin Brownfdf17c12018-03-14 12:55:34 -07008624 hdd_enter_dev(wdev->netdev);
Agrawal Ashish65634612016-08-18 13:24:32 +05308625
8626 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8627 hdd_err("Command not allowed in FTM mode");
8628 return -EINVAL;
8629 }
8630
8631 ret = wlan_hdd_validate_context(hdd_ctx);
8632 if (0 != ret)
8633 return ret;
8634
Dustin Brown4ea21db2018-01-05 14:13:17 -08008635 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
8636 data, data_len,
8637 wlan_hdd_set_acs_dfs_config_policy)) {
Agrawal Ashish65634612016-08-18 13:24:32 +05308638 hdd_err("invalid attr");
8639 return -EINVAL;
8640 }
8641
8642 acs_policy = &hdd_ctx->acs_policy;
8643 /*
8644 * SCM sends this attribute to restrict SAP from choosing
8645 * DFS channels from ACS.
8646 */
8647 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
8648 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
8649
8650 if (!IS_DFS_MODE_VALID(mode)) {
8651 hdd_err("attr acs dfs mode is not valid");
8652 return -EINVAL;
8653 }
8654 acs_policy->acs_dfs_mode = mode;
8655
8656 /*
8657 * SCM sends this attribute to provide an active channel,
8658 * to skip redundant ACS between drivers, and save driver start up time
8659 */
8660 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
8661 channel_hint = nla_get_u8(
8662 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
8663
8664 if (!IS_CHANNEL_VALID(channel_hint)) {
8665 hdd_err("acs channel is not valid");
8666 return -EINVAL;
8667 }
8668 acs_policy->acs_channel = channel_hint;
8669
8670 return 0;
8671}
8672
8673/**
8674 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
8675 * @wiphy: wiphy structure pointer
8676 * @wdev: Wireless device structure pointer
8677 * @data: Pointer to the data received
8678 * @data_len: Length of @data
8679 *
8680 * This function parses the incoming NL vendor command data attributes and
8681 * updates the SAP context about channel_hint and DFS mode.
8682 *
8683 * Return: 0 on success; errno on failure
8684 */
8685static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8686 struct wireless_dev *wdev,
8687 const void *data, int data_len)
8688{
Dustin Brown363b4792019-02-05 16:11:55 -08008689 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08008690 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05308691
Dustin Brown363b4792019-02-05 16:11:55 -08008692 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08008693 if (errno)
8694 return errno;
Agrawal Ashish65634612016-08-18 13:24:32 +05308695
Dustin Brownf0f00612019-01-31 16:02:24 -08008696 errno = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
Agrawal Ashish65634612016-08-18 13:24:32 +05308697
Dustin Brown363b4792019-02-05 16:11:55 -08008698 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05308699
Dustin Brownf0f00612019-01-31 16:02:24 -08008700 return errno;
Agrawal Ashish65634612016-08-18 13:24:32 +05308701}
8702
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308703/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308704 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
8705 * @mode : cfg80211 dfs mode
8706 *
8707 * Return: return csr sta roam dfs mode else return NONE
8708 */
8709static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
8710 enum dfs_mode mode)
8711{
8712 switch (mode) {
8713 case DFS_MODE_ENABLE:
8714 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308715 case DFS_MODE_DISABLE:
8716 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308717 case DFS_MODE_DEPRIORITIZE:
8718 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308719 default:
8720 hdd_err("STA Roam policy dfs mode is NONE");
8721 return CSR_STA_ROAM_POLICY_NONE;
8722 }
8723}
8724
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308725/*
8726 * hdd_get_sap_operating_band: Get current operating channel
8727 * for sap.
8728 * @hdd_ctx: hdd context
8729 *
8730 * Return : Corresponding band for SAP operating channel
8731 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008732uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308733{
Jeff Johnsone5006672017-08-29 14:39:02 -07008734 struct hdd_adapter *adapter;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308735 uint8_t operating_channel = 0;
8736 uint8_t sap_operating_band = 0;
Srinivas Girigowda576b2352017-08-25 14:44:26 -07008737
Dustin Brown920397d2017-12-13 16:27:50 -08008738 hdd_for_each_adapter(hdd_ctx, adapter) {
8739 if (adapter->device_mode != QDF_SAP_MODE)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308740 continue;
Dustin Brown920397d2017-12-13 16:27:50 -08008741
Jeff Johnsonb9424862017-10-30 08:49:35 -07008742 operating_channel = adapter->session.ap.operating_channel;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308743 if (IS_24G_CH(operating_channel))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08008744 sap_operating_band = BAND_2G;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308745 else if (IS_5G_CH(operating_channel))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08008746 sap_operating_band = BAND_5G;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308747 else
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08008748 sap_operating_band = BAND_ALL;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308749 }
Dustin Brown920397d2017-12-13 16:27:50 -08008750
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308751 return sap_operating_band;
8752}
8753
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308754static const struct nla_policy
8755wlan_hdd_set_sta_roam_config_policy[
8756QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
8757 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
8758 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
8759};
8760
8761/**
8762 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
8763 * for station connection or roaming.
8764 * @wiphy: Pointer to wireless phy
8765 * @wdev: Pointer to wireless device
8766 * @data: Pointer to data
8767 * @data_len: Length of @data
8768 *
8769 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8770 * channels needs to be skipped in scanning or not.
8771 * If dfs_mode is disabled, driver will not scan DFS channels.
8772 * If skip_unsafe_channels is set, driver will skip unsafe channels
8773 * in Scanning.
8774 *
8775 * Return: 0 on success, negative errno on failure
8776 */
8777static int
8778__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8779 struct wireless_dev *wdev,
8780 const void *data, int data_len)
8781{
8782 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008783 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008784 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308785 struct nlattr *tb[
8786 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
8787 int ret;
8788 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
8789 enum dfs_mode mode = DFS_MODE_NONE;
8790 bool skip_unsafe_channels = false;
8791 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308792 uint8_t sap_operating_band;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008793 mac_handle_t mac_handle;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308794
Dustin Brownfdf17c12018-03-14 12:55:34 -07008795 hdd_enter_dev(dev);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308796
8797 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8798 hdd_err("Command not allowed in FTM mode");
8799 return -EINVAL;
8800 }
8801
8802 ret = wlan_hdd_validate_context(hdd_ctx);
8803 if (0 != ret)
8804 return ret;
Dustin Brown4ea21db2018-01-05 14:13:17 -08008805 if (wlan_cfg80211_nla_parse(tb,
8806 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
8807 data, data_len,
8808 wlan_hdd_set_sta_roam_config_policy)) {
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308809 hdd_err("invalid attr");
8810 return -EINVAL;
8811 }
8812 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
8813 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
8814 if (!IS_DFS_MODE_VALID(mode)) {
8815 hdd_err("attr sta roam dfs mode policy is not valid");
8816 return -EINVAL;
8817 }
8818
8819 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
8820
8821 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
8822 skip_unsafe_channels = nla_get_u8(
8823 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308824 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008825 mac_handle = hdd_ctx->mac_handle;
8826 status = sme_update_sta_roam_policy(mac_handle, sta_roam_dfs_mode,
8827 skip_unsafe_channels,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08008828 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008829 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308830
8831 if (!QDF_IS_STATUS_SUCCESS(status)) {
8832 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
8833 return -EINVAL;
8834 }
8835 return 0;
8836}
8837
8838/**
8839 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
8840 * connection and roaming for station.
8841 * @wiphy: wiphy structure pointer
8842 * @wdev: Wireless device structure pointer
8843 * @data: Pointer to the data received
8844 * @data_len: Length of @data
8845 *
8846 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8847 * channels needs to be skipped in scanning or not.
8848 * If dfs_mode is disabled, driver will not scan DFS channels.
8849 * If skip_unsafe_channels is set, driver will skip unsafe channels
8850 * in Scanning.
8851 * Return: 0 on success; errno on failure
8852 */
8853static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8854 struct wireless_dev *wdev,
8855 const void *data, int data_len)
8856{
Dustin Browna09acf42018-11-08 12:32:26 +05308857 int errno;
8858 struct osif_vdev_sync *vdev_sync;
8859
8860 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
8861 if (errno)
8862 return errno;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308863
Dustin Browna09acf42018-11-08 12:32:26 +05308864 errno = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev,
8865 data, data_len);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308866
Dustin Browna09acf42018-11-08 12:32:26 +05308867 osif_vdev_sync_op_stop(vdev_sync);
8868
8869 return errno;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308870}
8871
Agrawal Ashish467dde42016-09-08 18:44:22 +05308872#ifdef FEATURE_WLAN_CH_AVOID
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308873
8874static int hdd_validate_avoid_freq_chanlist(
8875 struct hdd_context *hdd_ctx,
8876 struct ch_avoid_ind_type *channel_list)
8877{
8878 unsigned int range_idx, ch_idx;
8879 unsigned int unsafe_channel_index, unsafe_channel_count = 0;
8880 bool ch_found = false;
8881
8882 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8883 (uint16_t)NUM_CHANNELS);
8884
8885 for (range_idx = 0; range_idx < channel_list->ch_avoid_range_cnt;
8886 range_idx++) {
8887 if ((channel_list->avoid_freq_range[range_idx].start_freq <
8888 CDS_24_GHZ_CHANNEL_1) ||
8889 (channel_list->avoid_freq_range[range_idx].end_freq >
8890 CDS_5_GHZ_CHANNEL_165) ||
8891 (channel_list->avoid_freq_range[range_idx].start_freq >
8892 channel_list->avoid_freq_range[range_idx].end_freq))
8893 continue;
8894
8895 for (ch_idx = channel_list->
8896 avoid_freq_range[range_idx].start_freq;
8897 ch_idx <= channel_list->
8898 avoid_freq_range[range_idx].end_freq;
8899 ch_idx++) {
Ashish Kumar Dhanotiyaaa9fdbb2018-12-14 15:29:14 +05308900 if (INVALID_CHANNEL == wlan_reg_get_chan_enum(ch_idx))
Ashish Kumar Dhanotiyabf00f822018-11-30 20:29:09 +05308901 continue;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308902 for (unsafe_channel_index = 0;
8903 unsafe_channel_index < unsafe_channel_count;
8904 unsafe_channel_index++) {
8905 if (ch_idx ==
8906 hdd_ctx->unsafe_channel_list[
8907 unsafe_channel_index]) {
Dustin Brown632af712018-03-14 15:03:55 -07008908 hdd_info("Duplicate channel %d",
8909 ch_idx);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308910 ch_found = true;
8911 break;
8912 }
8913 }
8914 if (!ch_found) {
8915 hdd_ctx->unsafe_channel_list[
8916 unsafe_channel_count++] = ch_idx;
8917 }
8918 ch_found = false;
8919 }
8920 }
8921 return unsafe_channel_count;
8922}
8923
Agrawal Ashish467dde42016-09-08 18:44:22 +05308924/**
8925 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8926 * is on unsafe channel.
8927 * @wiphy: wiphy structure pointer
8928 * @wdev: Wireless device structure pointer
8929 * @data: Pointer to the data received
8930 * @data_len: Length of @data
8931 *
8932 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8933 * on any of unsafe channels.
8934 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8935 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8936 *
8937 * Return: 0 on success; errno on failure
8938 */
8939static int
8940__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8941 struct wireless_dev *wdev,
8942 const void *data, int data_len)
8943{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008944 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish467dde42016-09-08 18:44:22 +05308945 int ret;
Agrawal Ashish467dde42016-09-08 18:44:22 +05308946 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
Liangwei Dong6e1a2092017-08-30 16:29:06 +08008947 uint16_t *local_unsafe_list;
hqubf1b6182018-08-14 17:22:41 +08008948 uint16_t unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308949 uint16_t unsafe_channel_index, local_unsafe_list_count;
8950 struct ch_avoid_ind_type *channel_list;
Jeff Johnson2e60a142018-05-20 12:08:12 -07008951 enum QDF_GLOBAL_MODE curr_mode;
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +05308952 uint8_t num_args = 0;
hqubf1b6182018-08-14 17:22:41 +08008953 bool user_set_avoid_channel = true;
Agrawal Ashish467dde42016-09-08 18:44:22 +05308954
Dustin Brownfdf17c12018-03-14 12:55:34 -07008955 hdd_enter_dev(wdev->netdev);
Agrawal Ashish467dde42016-09-08 18:44:22 +05308956
8957 if (!qdf_ctx) {
Jeff Johnson6867ec32017-09-29 20:30:20 -07008958 hdd_err("qdf_ctx is NULL");
Agrawal Ashish467dde42016-09-08 18:44:22 +05308959 return -EINVAL;
8960 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308961 curr_mode = hdd_get_conparam();
8962 if (QDF_GLOBAL_FTM_MODE == curr_mode ||
8963 QDF_GLOBAL_MONITOR_MODE == curr_mode) {
8964 hdd_err("Command not allowed in FTM/MONITOR mode");
Agrawal Ashish467dde42016-09-08 18:44:22 +05308965 return -EINVAL;
8966 }
8967
8968 ret = wlan_hdd_validate_context(hdd_ctx);
8969 if (0 != ret)
8970 return ret;
hqubf1b6182018-08-14 17:22:41 +08008971 if (!data && data_len == 0) {
8972 hdd_debug("Userspace doesn't set avoid frequency channel list");
8973 user_set_avoid_channel = false;
8974 goto process_unsafe_channel;
8975 }
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +05308976 if (!data || data_len < (sizeof(channel_list->ch_avoid_range_cnt) +
8977 sizeof(struct ch_avoid_freq_type))) {
8978 hdd_err("Avoid frequency channel list empty");
8979 return -EINVAL;
8980 }
8981 num_args = (data_len - sizeof(channel_list->ch_avoid_range_cnt)) /
8982 sizeof(channel_list->avoid_freq_range[0].start_freq);
8983
8984 if (num_args < 2 || num_args > CH_AVOID_MAX_RANGE * 2 ||
8985 num_args % 2 != 0) {
8986 hdd_err("Invalid avoid frequency channel list");
8987 return -EINVAL;
8988 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308989
8990 channel_list = (struct ch_avoid_ind_type *)data;
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +05308991 if (channel_list->ch_avoid_range_cnt == 0 ||
8992 channel_list->ch_avoid_range_cnt > CH_AVOID_MAX_RANGE ||
8993 2 * channel_list->ch_avoid_range_cnt != num_args) {
8994 hdd_err("Invalid frequency range count %d",
8995 channel_list->ch_avoid_range_cnt);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308996 return -EINVAL;
8997 }
8998
hqubf1b6182018-08-14 17:22:41 +08008999process_unsafe_channel:
Liangwei Dong6e1a2092017-08-30 16:29:06 +08009000 ret = hdd_clone_local_unsafe_chan(hdd_ctx,
9001 &local_unsafe_list,
9002 &local_unsafe_list_count);
9003 if (0 != ret) {
9004 hdd_err("failed to clone the cur unsafe chan list");
9005 return ret;
9006 }
9007
Agrawal Ashish467dde42016-09-08 18:44:22 +05309008 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
9009 &(hdd_ctx->unsafe_channel_count),
9010 sizeof(hdd_ctx->unsafe_channel_list));
hqubf1b6182018-08-14 17:22:41 +08009011 if (user_set_avoid_channel) {
9012 hdd_ctx->unsafe_channel_count =
9013 hdd_validate_avoid_freq_chanlist(
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05309014 hdd_ctx,
9015 channel_list);
hqubf1b6182018-08-14 17:22:41 +08009016 unsafe_channel_count = hdd_ctx->unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05309017
hqubf1b6182018-08-14 17:22:41 +08009018 pld_set_wlan_unsafe_channel(qdf_ctx->dev,
9019 hdd_ctx->unsafe_channel_list,
9020 hdd_ctx->unsafe_channel_count);
9021 } else {
9022 unsafe_channel_count = QDF_MIN(
9023 (uint16_t)hdd_ctx->unsafe_channel_count,
9024 (uint16_t)NUM_CHANNELS);
9025 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05309026
Agrawal Ashish467dde42016-09-08 18:44:22 +05309027 for (unsafe_channel_index = 0;
hqubf1b6182018-08-14 17:22:41 +08009028 unsafe_channel_index < unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05309029 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009030 hdd_debug("Channel %d is not safe",
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05309031 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
Agrawal Ashish467dde42016-09-08 18:44:22 +05309032 }
Liangwei Dong6e1a2092017-08-30 16:29:06 +08009033 if (hdd_local_unsafe_channel_updated(hdd_ctx, local_unsafe_list,
9034 local_unsafe_list_count))
9035 hdd_unsafe_channel_restart_sap(hdd_ctx);
9036 qdf_mem_free(local_unsafe_list);
9037
Agrawal Ashish467dde42016-09-08 18:44:22 +05309038 return 0;
9039}
9040
9041/**
9042 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
9043 * is on unsafe channel.
9044 * @wiphy: wiphy structure pointer
9045 * @wdev: Wireless device structure pointer
9046 * @data: Pointer to the data received
9047 * @data_len: Length of @data
9048 *
9049 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
9050 * on any of unsafe channels.
9051 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
9052 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
9053 *
9054 * Return: 0 on success; errno on failure
9055 */
9056static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
9057 struct wireless_dev *wdev,
9058 const void *data, int data_len)
9059{
Dustin Brown363b4792019-02-05 16:11:55 -08009060 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08009061 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309062
Dustin Brown363b4792019-02-05 16:11:55 -08009063 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08009064 if (errno)
9065 return errno;
Agrawal Ashish467dde42016-09-08 18:44:22 +05309066
Dustin Brownf0f00612019-01-31 16:02:24 -08009067 errno = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
Agrawal Ashish467dde42016-09-08 18:44:22 +05309068
Dustin Brown363b4792019-02-05 16:11:55 -08009069 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309070
Dustin Brownf0f00612019-01-31 16:02:24 -08009071 return errno;
Agrawal Ashish467dde42016-09-08 18:44:22 +05309072}
9073
9074#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309075/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309076 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
9077 * SAP is on unsafe channel.
9078 * @wiphy: wiphy structure pointer
9079 * @wdev: Wireless device structure pointer
9080 * @data: Pointer to the data received
9081 * @data_len: Length of @data
9082 *
9083 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
9084 * driver.
9085 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
9086 * will initiate restart of sap.
9087 *
9088 * Return: 0 on success; errno on failure
9089 */
9090static int
9091__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
9092 struct wireless_dev *wdev,
9093 const void *data, int data_len)
9094{
9095 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009096 struct hdd_adapter *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009097 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309098 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
9099 uint8_t config_channel = 0;
Jeff Johnson87251032017-08-29 13:31:11 -07009100 struct hdd_ap_ctx *ap_ctx;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309101 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05309102 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309103
Dustin Brown491d54b2018-03-14 12:39:11 -07009104 hdd_enter();
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309105
9106 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009107 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309108 return -EINVAL;
9109 }
9110
9111 ret = wlan_hdd_validate_context(hdd_ctx);
9112 if (0 != ret)
9113 return -EINVAL;
9114
Dustin Brown4ea21db2018-01-05 14:13:17 -08009115 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
9116 data, data_len,
9117 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009118 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309119 return -EINVAL;
9120 }
9121
9122 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
9123 if (!test_bit(SOFTAP_BSS_STARTED,
9124 &hostapd_adapter->event_flags)) {
9125 hdd_err("SAP is not started yet. Restart sap will be invalid");
9126 return -EINVAL;
9127 }
9128
9129 config_channel =
9130 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
9131
9132 if (!((IS_24G_CH(config_channel)) ||
9133 (IS_5G_CH(config_channel)))) {
9134 hdd_err("Channel %d is not valid to restart SAP",
9135 config_channel);
9136 return -ENOTSUPP;
9137 }
9138
9139 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
Jeff Johnson91df29d2017-10-27 19:29:50 -07009140 ap_ctx->sap_config.channel = config_channel;
9141 ap_ctx->sap_config.ch_params.ch_width =
9142 ap_ctx->sap_config.ch_width_orig;
hqu73bccf22017-10-28 15:34:17 +08009143 ap_ctx->bss_stop_reason = BSS_STOP_DUE_TO_VENDOR_CONFIG_CHAN;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309144
Dustin Brown07901ec2018-09-07 11:02:41 -07009145 wlan_reg_set_channel_params(hdd_ctx->pdev,
9146 ap_ctx->sap_config.channel,
9147 ap_ctx->sap_config.sec_ch,
9148 &ap_ctx->sap_config.ch_params);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309149
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08009150 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309151 }
9152
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05309153 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
9154 uint32_t freq_len, i;
9155 uint32_t *freq;
9156 uint8_t chans[QDF_MAX_NUM_CHAN];
9157
9158 hdd_debug("setting mandatory freq/chan list");
9159
9160 freq_len = nla_len(
9161 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
9162 sizeof(uint32_t);
9163
9164 if (freq_len > QDF_MAX_NUM_CHAN) {
9165 hdd_err("insufficient space to hold channels");
9166 return -ENOMEM;
9167 }
9168
9169 freq = nla_data(
9170 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
9171
9172 hdd_debug("freq_len=%d", freq_len);
9173
9174 for (i = 0; i < freq_len; i++) {
9175 chans[i] = ieee80211_frequency_to_channel(freq[i]);
9176 hdd_debug("freq[%d]=%d", i, freq[i]);
9177 }
9178
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08009179 status = policy_mgr_set_sap_mandatory_channels(
Dustin Brown76cd2932018-09-11 16:03:05 -07009180 hdd_ctx->psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05309181 if (QDF_IS_STATUS_ERROR(status))
9182 return -EINVAL;
9183 }
9184
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309185 return 0;
9186}
9187
9188/**
9189 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
9190 * @wiphy: wiphy structure pointer
9191 * @wdev: Wireless device structure pointer
9192 * @data: Pointer to the data received
9193 * @data_len: Length of @data
9194 *
9195 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
9196 * driver.
9197 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
9198 * will initiate restart of sap.
9199 *
9200 * Return: 0 on success; errno on failure
9201 */
9202static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
9203 struct wireless_dev *wdev,
9204 const void *data, int data_len)
9205{
Dustin Browna09acf42018-11-08 12:32:26 +05309206 int errno;
9207 struct osif_vdev_sync *vdev_sync;
9208
9209 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
9210 if (errno)
9211 return errno;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309212
Dustin Browna09acf42018-11-08 12:32:26 +05309213 errno = __wlan_hdd_cfg80211_sap_configuration_set(wiphy, wdev,
9214 data, data_len);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309215
Dustin Browna09acf42018-11-08 12:32:26 +05309216 osif_vdev_sync_op_stop(vdev_sync);
9217
9218 return errno;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309219}
9220
Naveen Rawat3ff5cff2018-01-29 14:31:16 -08009221#ifndef QCA_SUPPORT_CP_STATS
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309222/**
9223 * define short names for the global vendor params
9224 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
9225 */
9226#define PARAM_TOTAL_CMD_EVENT_WAKE \
9227 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
9228#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
9229 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
9230#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
9231 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
9232#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
9233 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
9234#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
9235 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
9236#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
9237 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
9238#define PARAM_TOTAL_RX_DATA_WAKE \
9239 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
9240#define PARAM_RX_UNICAST_CNT \
9241 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
9242#define PARAM_RX_MULTICAST_CNT \
9243 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
9244#define PARAM_RX_BROADCAST_CNT \
9245 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
9246#define PARAM_ICMP_PKT \
9247 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
9248#define PARAM_ICMP6_PKT \
9249 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
9250#define PARAM_ICMP6_RA \
9251 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
9252#define PARAM_ICMP6_NA \
9253 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
9254#define PARAM_ICMP6_NS \
9255 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
9256#define PARAM_ICMP4_RX_MULTICAST_CNT \
9257 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
9258#define PARAM_ICMP6_RX_MULTICAST_CNT \
9259 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
9260#define PARAM_OTHER_RX_MULTICAST_CNT \
9261 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05309262#define PARAM_RSSI_BREACH_CNT \
9263 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
9264#define PARAM_LOW_RSSI_CNT \
9265 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
9266#define PARAM_GSCAN_CNT \
9267 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
9268#define PARAM_PNO_COMPLETE_CNT \
9269 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
9270#define PARAM_PNO_MATCH_CNT \
9271 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
9272
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309273/**
9274 * hdd_send_wakelock_stats() - API to send wakelock stats
9275 * @ctx: context to be passed to callback
9276 * @data: data passed to callback
9277 *
9278 * This function is used to send wake lock stats to HAL layer
9279 *
9280 * Return: 0 on success, error number otherwise.
9281 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009282static uint32_t hdd_send_wakelock_stats(struct hdd_context *hdd_ctx,
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309283 const struct sir_wake_lock_stats *data)
9284{
9285 struct sk_buff *skb;
9286 uint32_t nl_buf_len;
9287 uint32_t total_rx_data_wake, rx_multicast_cnt;
9288 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05309289 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309290
Dustin Brown491d54b2018-03-14 12:39:11 -07009291 hdd_enter();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309292
9293 nl_buf_len = NLMSG_HDRLEN;
9294 nl_buf_len +=
9295 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
9296 (NLMSG_HDRLEN + sizeof(uint32_t));
9297
9298 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
9299
9300 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07009301 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309302 return -ENOMEM;
9303 }
9304
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009305 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309306 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009307 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309308 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009309 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309310 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009311 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309312 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009313 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309314 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009315 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309316 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009317 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309318 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009319 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
9320 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05309321 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009322 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05309323 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009324 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05309325 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009326 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05309327 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009328 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05309329 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009330 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05309331 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309332
9333 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05309334 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309335
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05309336 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05309337 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05309338
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309339 rx_multicast_cnt =
9340 data->wow_ipv4_mcast_wake_up_count +
9341 ipv6_rx_multicast_addr_cnt;
9342
9343 total_rx_data_wake =
9344 data->wow_ucast_wake_up_count +
9345 data->wow_bcast_wake_up_count +
9346 rx_multicast_cnt;
9347
9348 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
9349 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
9350 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
9351 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
9352 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
9353 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
9354 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
9355 total_rx_data_wake) ||
9356 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
9357 data->wow_ucast_wake_up_count) ||
9358 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
9359 rx_multicast_cnt) ||
9360 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
9361 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05309362 nla_put_u32(skb, PARAM_ICMP_PKT,
9363 data->wow_icmpv4_count) ||
9364 nla_put_u32(skb, PARAM_ICMP6_PKT,
9365 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309366 nla_put_u32(skb, PARAM_ICMP6_RA,
9367 data->wow_ipv6_mcast_ra_stats) ||
9368 nla_put_u32(skb, PARAM_ICMP6_NA,
9369 data->wow_ipv6_mcast_na_stats) ||
9370 nla_put_u32(skb, PARAM_ICMP6_NS,
9371 data->wow_ipv6_mcast_ns_stats) ||
9372 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
9373 data->wow_ipv4_mcast_wake_up_count) ||
9374 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
9375 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05309376 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
9377 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
9378 data->wow_rssi_breach_wake_up_count) ||
9379 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
9380 data->wow_low_rssi_wake_up_count) ||
9381 nla_put_u32(skb, PARAM_GSCAN_CNT,
9382 data->wow_gscan_wake_up_count) ||
9383 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
9384 data->wow_pno_complete_wake_up_count) ||
9385 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
9386 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07009387 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309388 goto nla_put_failure;
9389 }
9390
9391 cfg80211_vendor_cmd_reply(skb);
9392
Dustin Browne74003f2018-03-14 12:51:58 -07009393 hdd_exit();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309394 return 0;
9395
9396nla_put_failure:
9397 kfree_skb(skb);
9398 return -EINVAL;
9399}
Naveen Rawat3ff5cff2018-01-29 14:31:16 -08009400#endif
9401
9402#ifdef QCA_SUPPORT_CP_STATS
9403static int wlan_hdd_process_wake_lock_stats(struct hdd_context *hdd_ctx)
9404{
Dustin Brown76cd2932018-09-11 16:03:05 -07009405 return wlan_cfg80211_mc_cp_stats_get_wakelock_stats(hdd_ctx->psoc,
Naveen Rawat3ff5cff2018-01-29 14:31:16 -08009406 hdd_ctx->wiphy);
9407}
9408#else
9409/**
9410 * wlan_hdd_process_wake_lock_stats() - wrapper function to absract cp_stats
9411 * or legacy get_wake_lock_stats API.
9412 * @hdd_ctx: pointer to hdd_ctx
9413 *
9414 * Return: 0 on success; error number otherwise.
9415 */
9416static int wlan_hdd_process_wake_lock_stats(struct hdd_context *hdd_ctx)
9417{
9418 int ret;
9419 QDF_STATUS qdf_status;
9420 struct sir_wake_lock_stats wake_lock_stats = {0};
9421
9422 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
9423 if (qdf_status != QDF_STATUS_SUCCESS) {
9424 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
9425 return -EINVAL;
9426 }
9427
9428 ret = hdd_send_wakelock_stats(hdd_ctx, &wake_lock_stats);
9429 if (ret)
9430 hdd_err("Failed to post wake lock stats");
9431
9432 return ret;
9433}
9434#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309435
9436/**
9437 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
9438 * @wiphy: wiphy pointer
9439 * @wdev: pointer to struct wireless_dev
9440 * @data: pointer to incoming NL vendor data
9441 * @data_len: length of @data
9442 *
9443 * This function parses the incoming NL vendor command data attributes and
9444 * invokes the SME Api and blocks on a completion variable.
9445 * WMA copies required data and invokes callback
9446 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
9447 *
9448 * Return: 0 on success; error number otherwise.
9449 */
9450static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
9451 struct wireless_dev *wdev,
9452 const void *data,
9453 int data_len)
9454{
Naveen Rawat3ff5cff2018-01-29 14:31:16 -08009455 int ret;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009456 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309457
Dustin Brown491d54b2018-03-14 12:39:11 -07009458 hdd_enter();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309459
9460 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07009461 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309462 return -EINVAL;
9463 }
9464
Naveen Rawat3ff5cff2018-01-29 14:31:16 -08009465 ret = wlan_hdd_validate_context(hdd_ctx);
9466 if (0 != ret)
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309467 return -EINVAL;
9468
Naveen Rawat3ff5cff2018-01-29 14:31:16 -08009469 ret = wlan_hdd_process_wake_lock_stats(hdd_ctx);
Dustin Browne74003f2018-03-14 12:51:58 -07009470 hdd_exit();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309471 return ret;
9472}
9473
9474/**
9475 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
9476 * @wiphy: wiphy pointer
9477 * @wdev: pointer to struct wireless_dev
9478 * @data: pointer to incoming NL vendor data
9479 * @data_len: length of @data
9480 *
9481 * This function parses the incoming NL vendor command data attributes and
9482 * invokes the SME Api and blocks on a completion variable.
9483 * WMA copies required data and invokes callback
9484 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
9485 *
9486 * Return: 0 on success; error number otherwise.
9487 */
9488static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
9489 struct wireless_dev *wdev,
9490 const void *data, int data_len)
9491{
Dustin Brown363b4792019-02-05 16:11:55 -08009492 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08009493 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309494
Dustin Brown363b4792019-02-05 16:11:55 -08009495 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08009496 if (errno)
9497 return errno;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309498
Dustin Brownf0f00612019-01-31 16:02:24 -08009499 errno = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev,
9500 data, data_len);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309501
Dustin Brown363b4792019-02-05 16:11:55 -08009502 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08009503
9504 return errno;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309505}
9506
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309507/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309508 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
9509 * @wiphy: wiphy structure pointer
9510 * @wdev: Wireless device structure pointer
9511 * @data: Pointer to the data received
9512 * @data_len: Length of @data
9513 *
9514 * This function reads wmi max bus size and fill in the skb with
9515 * NL attributes and send up the NL event.
9516 * Return: 0 on success; errno on failure
9517 */
9518static int
9519__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
9520 struct wireless_dev *wdev,
9521 const void *data, int data_len)
9522{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009523 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309524 int ret_val;
9525 struct sk_buff *skb;
9526 uint32_t nl_buf_len;
9527
Dustin Brown491d54b2018-03-14 12:39:11 -07009528 hdd_enter();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309529
9530 ret_val = wlan_hdd_validate_context(hdd_ctx);
9531 if (ret_val)
9532 return ret_val;
9533
9534 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9535 hdd_err("Command not allowed in FTM mode");
9536 return -EINVAL;
9537 }
9538
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009539 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309540
9541 nl_buf_len = NLMSG_HDRLEN;
9542 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
9543
9544 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
9545 if (!skb) {
9546 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
9547 return -ENOMEM;
9548 }
9549
9550 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
9551 hdd_ctx->wmi_max_len)) {
9552 hdd_err("nla put failure");
9553 goto nla_put_failure;
9554 }
9555
9556 cfg80211_vendor_cmd_reply(skb);
9557
Dustin Browne74003f2018-03-14 12:51:58 -07009558 hdd_exit();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309559
9560 return 0;
9561
9562nla_put_failure:
9563 kfree_skb(skb);
9564 return -EINVAL;
9565}
9566
9567/**
9568 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
9569 * @wiphy: wiphy structure pointer
9570 * @wdev: Wireless device structure pointer
9571 * @data: Pointer to the data received
9572 * @data_len: Length of @data
9573 *
9574 * Return: 0 on success; errno on failure
9575 */
9576static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
9577 struct wireless_dev *wdev,
9578 const void *data, int data_len)
9579{
Dustin Brown363b4792019-02-05 16:11:55 -08009580 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08009581 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +05309582
Dustin Brown363b4792019-02-05 16:11:55 -08009583 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08009584 if (errno)
9585 return errno;
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309586
Dustin Brownf0f00612019-01-31 16:02:24 -08009587 errno = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309588
Dustin Brown363b4792019-02-05 16:11:55 -08009589 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08009590
9591 return errno;
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309592}
9593
9594/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309595 *__wlan_hdd_cfg80211_setband() - set band
9596 * @wiphy: Pointer to wireless phy
9597 * @wdev: Pointer to wireless device
9598 * @data: Pointer to data
9599 * @data_len: Length of @data
9600 *
9601 * Return: 0 on success, negative errno on failure
9602 */
9603static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9604 struct wireless_dev *wdev,
9605 const void *data, int data_len)
9606{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009607 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07009608 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309609 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9610 int ret;
9611 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
9612 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
9613
Dustin Brown491d54b2018-03-14 12:39:11 -07009614 hdd_enter();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309615
9616 ret = wlan_hdd_validate_context(hdd_ctx);
9617 if (ret)
9618 return ret;
9619
Dustin Brown4ea21db2018-01-05 14:13:17 -08009620 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
9621 data, data_len, policy)) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07009622 hdd_err("Invalid ATTR");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309623 return -EINVAL;
9624 }
9625
9626 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07009627 hdd_err("attr SETBAND_VALUE failed");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309628 return -EINVAL;
9629 }
9630
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07009631 ret = hdd_reg_set_band(dev,
9632 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309633
Dustin Browne74003f2018-03-14 12:51:58 -07009634 hdd_exit();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309635 return ret;
9636}
9637
9638/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309639 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
9640 * @adapter: hdd adapter
9641 * @channel: channel number
9642 *
9643 * return: QDF status based on success or failure
9644 */
Jeff Johnsone5006672017-08-29 14:39:02 -07009645static QDF_STATUS wlan_hdd_validate_acs_channel(struct hdd_adapter *adapter,
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309646 int channel, int chan_bw)
9647{
9648 if (QDF_STATUS_SUCCESS !=
9649 wlan_hdd_validate_operation_channel(adapter, channel))
9650 return QDF_STATUS_E_FAILURE;
9651 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9652 channel,
9653 PHY_SINGLE_CHANNEL_CENTERED))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -07009654 hdd_info("channel %d is in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309655 return -EINVAL;
9656 }
9657
9658 if ((wlansap_is_channel_leaking_in_nol(
9659 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9660 channel, chan_bw))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -07009661 hdd_info("channel %d is leaking in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309662 return -EINVAL;
9663 }
9664
9665 return 0;
9666
9667}
9668
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009669static void hdd_update_acs_sap_config(struct hdd_context *hdd_ctx,
Jeff Johnsone4c11db2018-05-05 23:22:32 -07009670 tsap_config_t *sap_config,
Kapil Gupta8878ad92017-02-13 11:56:04 +05309671 struct hdd_vendor_chan_info *channel_list)
9672{
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05309673 uint8_t ch_width;
9674 QDF_STATUS status;
Wu Gaoed616a12019-01-16 15:19:21 +08009675 uint32_t channel_bonding_mode;
9676
Kapil Gupta8878ad92017-02-13 11:56:04 +05309677 sap_config->channel = channel_list->pri_ch;
9678
9679 sap_config->ch_params.center_freq_seg0 =
9680 channel_list->vht_seg0_center_ch;
9681 sap_config->ch_params.center_freq_seg1 =
9682 channel_list->vht_seg1_center_ch;
9683
9684 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
9685 sap_config->ch_params.ch_width = channel_list->chan_width;
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05309686 if (sap_config->channel >= 36) {
9687 status =
9688 ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
9689 &ch_width);
9690 if (!QDF_IS_STATUS_SUCCESS(status))
9691 hdd_err("Failed to set channel_width");
9692 sap_config->ch_width_orig = ch_width;
9693 } else {
Wu Gaoed616a12019-01-16 15:19:21 +08009694 ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
9695 &channel_bonding_mode);
9696 sap_config->ch_width_orig = channel_bonding_mode ?
9697 eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ;
Abhinav Kumarb074f2f2018-09-15 15:32:11 +05309698 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05309699 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
9700 sap_config->acs_cfg.ch_width = channel_list->chan_width;
9701 sap_config->acs_cfg.vht_seg0_center_ch =
9702 channel_list->vht_seg0_center_ch;
9703 sap_config->acs_cfg.vht_seg1_center_ch =
9704 channel_list->vht_seg1_center_ch;
9705 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
9706}
9707
Jeff Johnsone5006672017-08-29 14:39:02 -07009708static int hdd_update_acs_channel(struct hdd_adapter *adapter, uint8_t reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +05309709 uint8_t channel_cnt,
9710 struct hdd_vendor_chan_info *channel_list)
9711{
Jeff Johnsone4c11db2018-05-05 23:22:32 -07009712 tsap_config_t *sap_config;
Jeff Johnson87251032017-08-29 13:31:11 -07009713 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009714 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Kapil Gupta8878ad92017-02-13 11:56:04 +05309715 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009716 mac_handle_t mac_handle;
Kapil Gupta8878ad92017-02-13 11:56:04 +05309717
Min Liuab6ed4f2018-01-09 13:13:57 +08009718 if (!channel_list) {
9719 hdd_err("channel_list is NULL");
9720 return -EINVAL;
9721 }
9722
Kapil Gupta8878ad92017-02-13 11:56:04 +05309723 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnsonb9424862017-10-30 08:49:35 -07009724 sap_config = &adapter->session.ap.sap_config;
Kapil Gupta8878ad92017-02-13 11:56:04 +05309725
9726 if (QDF_TIMER_STATE_RUNNING ==
Jeff Johnsonb9424862017-10-30 08:49:35 -07009727 qdf_mc_timer_get_current_state(&adapter->session.
Kapil Gupta8878ad92017-02-13 11:56:04 +05309728 ap.vendor_acs_timer)) {
Jeff Johnsonb9424862017-10-30 08:49:35 -07009729 qdf_mc_timer_stop(&adapter->session.ap.vendor_acs_timer);
Kapil Gupta8878ad92017-02-13 11:56:04 +05309730 }
9731
Min Liuab6ed4f2018-01-09 13:13:57 +08009732 if (channel_list->pri_ch == 0) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05309733 /* Check mode, set default channel */
9734 channel_list->pri_ch = 6;
9735 /*
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009736 * sap_select_default_oper_chan(mac_handle,
Kapil Gupta8878ad92017-02-13 11:56:04 +05309737 * sap_config->acs_cfg.hw_mode);
9738 */
9739 }
9740
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009741 mac_handle = hdd_ctx->mac_handle;
Kapil Gupta8878ad92017-02-13 11:56:04 +05309742 switch (reason) {
9743 /* SAP init case */
9744 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
9745 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
9746 /* Update Hostapd */
9747 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
9748 break;
9749
9750 /* DFS detected on current channel */
9751 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
9752 wlan_sap_update_next_channel(
9753 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9754 channel_list->pri_ch,
9755 channel_list->chan_width);
9756 status = sme_update_new_channel_event(
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009757 mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -08009758 adapter->vdev_id);
Kapil Gupta8878ad92017-02-13 11:56:04 +05309759 break;
9760
9761 /* LTE coex event on current channel */
9762 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
9763 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
9764 sap_config->acs_cfg.ch_width = channel_list->chan_width;
Jeff Johnson91df29d2017-10-27 19:29:50 -07009765 hdd_ap_ctx->sap_config.ch_width_orig =
Kapil Gupta8878ad92017-02-13 11:56:04 +05309766 channel_list->chan_width;
Min Liu2fef5792018-01-19 17:59:42 +08009767 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch,
9768 true);
Kapil Gupta8878ad92017-02-13 11:56:04 +05309769 break;
9770
9771 default:
9772 hdd_info("invalid reason for timer invoke");
9773 }
Dustin Browne74003f2018-03-14 12:51:58 -07009774 hdd_exit();
Min Liuab6ed4f2018-01-09 13:13:57 +08009775 return qdf_status_to_os_return(status);
Kapil Gupta8878ad92017-02-13 11:56:04 +05309776}
9777
9778/**
9779 * Define short name for vendor channel set config
9780 */
9781#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
Kapil Gupta8878ad92017-02-13 11:56:04 +05309782#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
9783#define SET_CHAN_PRIMARY_CHANNEL \
9784 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
9785#define SET_CHAN_SECONDARY_CHANNEL \
9786 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
9787#define SET_CHAN_SEG0_CENTER_CHANNEL \
9788 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
9789#define SET_CHAN_SEG1_CENTER_CHANNEL \
9790 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
9791#define SET_CHAN_CHANNEL_WIDTH \
9792 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
9793#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
Kapil Gupta63e75282017-05-18 20:55:10 +05309794#define SET_EXT_ACS_BAND QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND
Kapil Gupta8878ad92017-02-13 11:56:04 +05309795
9796/**
9797 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
9798 * @channel_list: pointer to hdd_vendor_chan_info
9799 * @reason: channel change reason
9800 * @channel_cnt: channel count
9801 * @data: data
9802 * @data_len: data len
9803 *
9804 * Return: 0 on success, negative errno on failure
9805 */
9806static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
9807 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
9808 const void *data, int data_len)
9809{
9810 int rem, i = 0;
9811 struct nlattr *tb[SET_CHAN_MAX + 1];
9812 struct nlattr *tb2[SET_CHAN_MAX + 1];
9813 struct nlattr *curr_attr;
9814 struct hdd_vendor_chan_info *channel_list;
9815
Dustin Brown4ea21db2018-01-05 14:13:17 -08009816 if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05309817 hdd_err("Invalid ATTR");
9818 return -EINVAL;
9819 }
9820
9821 if (tb[SET_CHAN_REASON])
9822 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
9823
Kapil Gupta63e75282017-05-18 20:55:10 +05309824 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem)
9825 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +05309826
Kapil Gupta63e75282017-05-18 20:55:10 +05309827 *channel_cnt = i;
9828
9829 if (i == 0)
9830 hdd_err("incorrect channel count");
Kapil Gupta8878ad92017-02-13 11:56:04 +05309831
9832 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
9833 (*channel_cnt));
Min Liu74a1a502018-10-10 19:59:07 +08009834 if (!channel_list)
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05309835 return -ENOMEM;
Kapil Gupta8878ad92017-02-13 11:56:04 +05309836
Kapil Gupta63e75282017-05-18 20:55:10 +05309837 i = 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +05309838 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08009839 if (wlan_cfg80211_nla_parse(tb2, SET_CHAN_MAX,
9840 nla_data(curr_attr),
9841 nla_len(curr_attr), NULL)) {
9842 hdd_err("nla_parse failed");
Kapil Gupta8878ad92017-02-13 11:56:04 +05309843 return -EINVAL;
9844 }
Kapil Gupta63e75282017-05-18 20:55:10 +05309845 if (tb2[SET_EXT_ACS_BAND]) {
9846 channel_list[i].band =
9847 nla_get_u8(tb2[SET_EXT_ACS_BAND]);
9848 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05309849 /* Parse and Fetch allowed SSID list*/
9850 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
9851 channel_list[i].pri_ch =
9852 nla_get_u8(
9853 tb2[SET_CHAN_PRIMARY_CHANNEL]);
9854 }
9855 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
9856 channel_list[i].ht_sec_ch =
9857 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
9858 }
9859 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
9860 channel_list[i].vht_seg0_center_ch =
9861 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
9862 }
9863 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
9864 channel_list[i].vht_seg1_center_ch =
9865 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
9866 }
9867 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
9868 channel_list[i].chan_width =
9869 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
9870 }
Kapil Gupta63e75282017-05-18 20:55:10 +05309871 hdd_debug("index %d pri %d sec %d seg0 %d seg1 %d width %d",
Kapil Gupta8878ad92017-02-13 11:56:04 +05309872 i, channel_list[i].pri_ch,
9873 channel_list[i].ht_sec_ch,
9874 channel_list[i].vht_seg0_center_ch,
9875 channel_list[i].vht_seg1_center_ch,
9876 channel_list[i].chan_width);
9877 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +05309878 }
9879 *chan_list_ptr = channel_list;
9880
9881 return 0;
9882}
9883
9884/**
9885 * Undef short names for vendor set channel configuration
9886 */
9887#undef SET_CHAN_REASON
Kapil Gupta8878ad92017-02-13 11:56:04 +05309888#undef SET_CHAN_CHAN_LIST
9889#undef SET_CHAN_PRIMARY_CHANNEL
9890#undef SET_CHAN_SECONDARY_CHANNEL
9891#undef SET_CHAN_SEG0_CENTER_CHANNEL
9892#undef SET_CHAN_SEG1_CENTER_CHANNEL
9893#undef SET_CHAN_CHANNEL_WIDTH
9894#undef SET_CHAN_MAX
9895
9896/**
9897 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9898 * @wiphy: Pointer to wireless phy
9899 * @wdev: Pointer to wireless device
9900 * @data: Pointer to data
9901 * @data_len: Length of @data
9902 *
9903 * Return: 0 on success, negative errno on failure
9904 */
9905static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9906 struct wireless_dev *wdev,
9907 const void *data, int data_len)
9908{
9909 int ret_val;
9910 QDF_STATUS qdf_status;
9911 uint8_t channel_cnt = 0, reason = -1;
9912 struct hdd_vendor_chan_info *channel_list = NULL;
Jeff Johnsone5006672017-08-29 14:39:02 -07009913 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009914 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05309915 struct hdd_vendor_chan_info *channel_list_ptr;
Kapil Gupta8878ad92017-02-13 11:56:04 +05309916
Dustin Brown491d54b2018-03-14 12:39:11 -07009917 hdd_enter();
Kapil Gupta8878ad92017-02-13 11:56:04 +05309918
9919 ret_val = wlan_hdd_validate_context(hdd_ctx);
9920 if (ret_val)
9921 return ret_val;
9922
9923 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9924 hdd_err("Command not allowed in FTM mode");
9925 return -EINVAL;
9926 }
9927
9928 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
9929 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
9930 else {
9931 hdd_err("already timeout happened for acs");
9932 return -EINVAL;
9933 }
9934
9935 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
9936 &channel_cnt, data, data_len);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05309937 channel_list_ptr = channel_list;
Kapil Gupta8878ad92017-02-13 11:56:04 +05309938 if (ret_val)
9939 return ret_val;
9940
9941 /* Validate channel to be set */
9942 while (channel_cnt && channel_list) {
9943 qdf_status = wlan_hdd_validate_acs_channel(adapter,
9944 channel_list->pri_ch,
9945 channel_list->chan_width);
9946 if (qdf_status == QDF_STATUS_SUCCESS)
9947 break;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05309948 else if (channel_cnt == 1) {
9949 hdd_err("invalid channel %d received from app",
9950 channel_list->pri_ch);
9951 channel_list->pri_ch = 0;
9952 break;
9953 }
9954
Kapil Gupta8878ad92017-02-13 11:56:04 +05309955 channel_cnt--;
9956 channel_list++;
9957 }
Min Liuab6ed4f2018-01-09 13:13:57 +08009958
Kapil Gupta8878ad92017-02-13 11:56:04 +05309959 if ((channel_cnt <= 0) || !channel_list) {
Jeff Johnson36e74c42017-09-18 08:15:42 -07009960 hdd_err("no available channel/chanlist %d/%pK", channel_cnt,
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05309961 channel_list);
9962 qdf_mem_free(channel_list_ptr);
Kapil Gupta8878ad92017-02-13 11:56:04 +05309963 return -EINVAL;
9964 }
9965
Min Liuab6ed4f2018-01-09 13:13:57 +08009966 hdd_debug("received primary channel as %d", channel_list->pri_ch);
9967
9968 ret_val = hdd_update_acs_channel(adapter, reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +05309969 channel_cnt, channel_list);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05309970 qdf_mem_free(channel_list_ptr);
Min Liuab6ed4f2018-01-09 13:13:57 +08009971 return ret_val;
Kapil Gupta8878ad92017-02-13 11:56:04 +05309972}
9973
9974/**
9975 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9976 * @wiphy: Pointer to wireless phy
9977 * @wdev: Pointer to wireless device
9978 * @data: Pointer to data
9979 * @data_len: Length of @data
9980 *
9981 * Return: 0 on success, negative errno on failure
9982 */
9983static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9984 struct wireless_dev *wdev,
9985 const void *data, int data_len)
9986{
Dustin Browna09acf42018-11-08 12:32:26 +05309987 int errno;
9988 struct osif_vdev_sync *vdev_sync;
9989
9990 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
9991 if (errno)
9992 return errno;
Kapil Gupta8878ad92017-02-13 11:56:04 +05309993
Dustin Browna09acf42018-11-08 12:32:26 +05309994 errno = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev,
9995 data, data_len);
Kapil Gupta8878ad92017-02-13 11:56:04 +05309996
Dustin Browna09acf42018-11-08 12:32:26 +05309997 osif_vdev_sync_op_stop(vdev_sync);
9998
9999 return errno;
Kapil Gupta8878ad92017-02-13 11:56:04 +053010000}
Kapil Gupta94ca6f62016-12-11 18:43:12 +053010001
10002/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010003 * wlan_hdd_cfg80211_setband() - Wrapper to setband
10004 * @wiphy: wiphy structure pointer
10005 * @wdev: Wireless device structure pointer
10006 * @data: Pointer to the data received
10007 * @data_len: Length of @data
10008 *
10009 * Return: 0 on success; errno on failure
10010 */
10011static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
10012 struct wireless_dev *wdev,
10013 const void *data, int data_len)
10014{
Dustin Browna09acf42018-11-08 12:32:26 +053010015 int errno;
10016 struct osif_vdev_sync *vdev_sync;
10017
10018 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
10019 if (errno)
10020 return errno;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010021
Dustin Browna09acf42018-11-08 12:32:26 +053010022 errno = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010023
Dustin Browna09acf42018-11-08 12:32:26 +053010024 osif_vdev_sync_op_stop(vdev_sync);
10025
10026 return errno;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010027}
10028
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010029/**
10030 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
10031 * @nl80211_value: Vendor command attribute value
10032 * @wmi_value: Pointer to return converted WMI return value
10033 *
10034 * Convert NL80211 vendor command value for SAR limit set to WMI value
10035 * Return: 0 on success, -1 on invalid value
10036 */
10037static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
10038 u32 *wmi_value)
10039{
10040 int ret = 0;
10041
10042 switch (nl80211_value) {
10043 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
10044 *wmi_value = WMI_SAR_FEATURE_OFF;
10045 break;
10046 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
10047 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
10048 break;
10049 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
10050 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
10051 break;
10052 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
10053 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
10054 break;
10055 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
10056 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
10057 break;
10058 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
10059 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
10060 break;
10061 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
10062 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
10063 break;
Kabilan Kannancaa85502018-04-13 18:04:58 -070010064 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0:
10065 *wmi_value = WMI_SAR_FEATURE_ON_SAR_V2_0;
10066 break;
10067
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010068 default:
10069 ret = -1;
10070 }
10071 return ret;
10072}
10073
Jeff Johnson354c20b2018-07-17 20:15:56 -070010074#ifdef WLAN_FEATURE_SARV1_TO_SARV2
10075/**
10076 * hdd_convert_sarv1_to_sarv2() - convert SAR V1 BDF reference to SAR V2
10077 * @hdd_ctx: The HDD global context
10078 * @tb: The parsed array of netlink attributes
10079 * @sar_limit_cmd: The WMI command to be filled
10080 *
10081 * This feature/function is designed to solve the following problem:
10082 * 1) Userspace application was written to use SARv1 BDF entries
10083 * 2) Product is configured with SAR V2 BDF entries
10084 *
10085 * So if this feature is enabled, and if the firmware is configured
10086 * with SAR V2 support, and if the incoming request is to enable a SAR
10087 * V1 BDF entry, then the WMI command is generated to actually
10088 * configure a SAR V2 BDF entry.
10089 *
10090 * Return: true if conversion was performed and @sar_limit_cmd is
10091 * ready to be sent to firmware. Otherwise false in which case the
10092 * normal parsing logic should be applied.
10093 */
10094
10095static bool
10096hdd_convert_sarv1_to_sarv2(struct hdd_context *hdd_ctx,
10097 struct nlattr *tb[],
10098 struct sar_limit_cmd_params *sar_limit_cmd)
10099{
10100 struct nlattr *attr;
10101 uint32_t bdf_index, set;
10102 struct sar_limit_cmd_row *row;
10103
10104 if (hdd_ctx->sar_version != SAR_VERSION_2) {
10105 hdd_debug("SAR version: %d", hdd_ctx->sar_version);
10106 return false;
10107 }
10108
10109 attr = tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE];
10110 if (!attr)
10111 return false;
10112
10113 bdf_index = nla_get_u32(attr);
10114
10115 if ((bdf_index >= QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0) &&
10116 (bdf_index <= QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4)) {
10117 set = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0;
10118 } else if (bdf_index == QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE) {
10119 set = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE;
10120 bdf_index = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0;
10121 } else {
10122 return false;
10123 }
10124
10125 /* Need two rows to hold the per-chain V2 power index
10126 * To disable SARv2 limit, send chain, num_limits_row and
10127 * power limit set to 0 (except power index 0xff)
10128 */
10129 row = qdf_mem_malloc(2 * sizeof(*row));
10130 if (!row)
10131 return false;
10132
10133 if (wlan_hdd_cfg80211_sar_convert_limit_set(
10134 set, &sar_limit_cmd->sar_enable)) {
10135 hdd_err("Failed to convert SAR limit to WMI value");
10136 return false;
10137 }
10138
10139 sar_limit_cmd->commit_limits = 1;
10140 sar_limit_cmd->num_limit_rows = 2;
10141 sar_limit_cmd->sar_limit_row_list = row;
10142 row[0].limit_value = bdf_index;
10143 row[1].limit_value = row[0].limit_value;
10144 row[0].chain_id = 0;
10145 row[1].chain_id = 1;
10146 row[0].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
10147 row[1].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
10148
10149 return true;
10150}
10151
10152#else /* WLAN_FEATURE_SARV1_TO_SARV2 */
10153
10154static bool
10155hdd_convert_sarv1_to_sarv2(struct hdd_context *hdd_ctx,
10156 struct nlattr *tb[],
10157 struct sar_limit_cmd_params *sar_limit_cmd)
10158{
10159 return false;
10160}
10161
10162#endif /* WLAN_FEATURE_SARV1_TO_SARV2 */
10163
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010164/**
10165 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
10166 * @nl80211_value: Vendor command attribute value
10167 * @wmi_value: Pointer to return converted WMI return value
10168 *
10169 * Convert NL80211 vendor command value for SAR BAND to WMI value
10170 * Return: 0 on success, -1 on invalid value
10171 */
10172static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
10173{
10174 int ret = 0;
10175
10176 switch (nl80211_value) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070010177 case HDD_NL80211_BAND_2GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010178 *wmi_value = WMI_SAR_2G_ID;
10179 break;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070010180 case HDD_NL80211_BAND_5GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010181 *wmi_value = WMI_SAR_5G_ID;
10182 break;
10183 default:
10184 ret = -1;
10185 }
10186 return ret;
10187}
10188
10189/**
10190 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
10191 * @nl80211_value: Vendor command attribute value
10192 * @wmi_value: Pointer to return converted WMI return value
10193 *
10194 * Convert NL80211 vendor command value for SAR Modulation to WMI value
10195 * Return: 0 on success, -1 on invalid value
10196 */
10197static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
10198 u32 *wmi_value)
10199{
10200 int ret = 0;
10201
10202 switch (nl80211_value) {
10203 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
10204 *wmi_value = WMI_SAR_MOD_CCK;
10205 break;
10206 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
10207 *wmi_value = WMI_SAR_MOD_OFDM;
10208 break;
10209 default:
10210 ret = -1;
10211 }
10212 return ret;
10213}
10214
Jeff Johnsonb17a93c2017-06-02 12:26:55 -070010215static const struct nla_policy
10216sar_limits_policy[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1] = {
10217 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE] = {.type = NLA_U32},
10218 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS] = {.type = NLA_U32},
10219 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND] = {.type = NLA_U32},
10220 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN] = {.type = NLA_U32},
10221 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION] = {.type = NLA_U32},
10222 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT] = {.type = NLA_U32},
Kabilan Kannancaa85502018-04-13 18:04:58 -070010223 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX] = {.type = NLA_U32},
Jeff Johnsonb17a93c2017-06-02 12:26:55 -070010224};
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010225
10226/**
10227 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
10228 * @wiphy: Pointer to wireless phy
10229 * @wdev: Pointer to wireless device
10230 * @data: Pointer to data
10231 * @data_len: Length of @data
10232 *
10233 * This function is used to setup Specific Absorption Rate limit specs.
10234 *
10235 * Return: 0 on success, negative errno on failure
10236 */
10237static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
10238 struct wireless_dev *wdev,
10239 const void *data, int data_len)
10240{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010241 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010242 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
10243 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
10244 *sar_spec_list;
10245 struct sar_limit_cmd_params sar_limit_cmd = {0};
10246 int ret = -EINVAL, i = 0, rem = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010247 mac_handle_t mac_handle;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010248
Dustin Brown491d54b2018-03-14 12:39:11 -070010249 hdd_enter();
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010250
10251 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10252 hdd_err("Command not allowed in FTM mode");
10253 return -EPERM;
10254 }
10255
10256 if (wlan_hdd_validate_context(hdd_ctx))
10257 return -EINVAL;
10258
Dustin Brown4ea21db2018-01-05 14:13:17 -080010259 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
10260 data, data_len, sar_limits_policy)) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010261 hdd_err("Invalid SAR attributes");
10262 return -EINVAL;
10263 }
10264
Jeff Johnson354c20b2018-07-17 20:15:56 -070010265 /* is special SAR V1 => SAR V2 logic enabled and applicable? */
10266 if (hdd_convert_sarv1_to_sarv2(hdd_ctx, tb, &sar_limit_cmd))
10267 goto send_sar_limits;
10268
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010269 /* Vendor command manadates all SAR Specs in single call */
10270 sar_limit_cmd.commit_limits = 1;
10271 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
10272 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
10273 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
10274 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
10275 &sar_limit_cmd.sar_enable) < 0) {
10276 hdd_err("Invalid SAR Enable attr");
10277 goto fail;
10278 }
10279 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010280 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010281
10282 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
10283 sar_limit_cmd.num_limit_rows = nla_get_u32(
10284 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010285 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010286 sar_limit_cmd.num_limit_rows);
10287 }
10288 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
10289 hdd_err("SAR Spec list exceed supported size");
10290 goto fail;
10291 }
10292 if (sar_limit_cmd.num_limit_rows == 0)
10293 goto send_sar_limits;
10294 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
10295 struct sar_limit_cmd_row) *
10296 sar_limit_cmd.num_limit_rows);
10297 if (!sar_limit_cmd.sar_limit_row_list) {
10298 ret = -ENOMEM;
10299 goto fail;
10300 }
10301 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
10302 hdd_err("Invalid SAR SPECs list");
10303 goto fail;
10304 }
10305
10306 nla_for_each_nested(sar_spec_list,
10307 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
10308 if (i == sar_limit_cmd.num_limit_rows) {
10309 hdd_warn("SAR Cmd has excess SPECs in list");
10310 break;
10311 }
10312
Dustin Brown4ea21db2018-01-05 14:13:17 -080010313 if (wlan_cfg80211_nla_parse(sar_spec,
10314 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
10315 nla_data(sar_spec_list),
10316 nla_len(sar_spec_list),
10317 sar_limits_policy)) {
10318 hdd_err("nla_parse failed for SAR Spec list");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010319 goto fail;
10320 }
10321 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
10322 if (sar_spec[
10323 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
10324 sar_limit_cmd.sar_limit_row_list[i].limit_value =
10325 nla_get_u32(sar_spec[
10326 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
Kabilan Kannancaa85502018-04-13 18:04:58 -070010327 } else if (sar_spec[
10328 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX]) {
10329 sar_limit_cmd.sar_limit_row_list[i].limit_value =
10330 nla_get_u32(sar_spec[
10331 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX]);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010332 } else {
Kabilan Kannancaa85502018-04-13 18:04:58 -070010333 hdd_err("SAR Spec does not have power limit or index value");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010334 goto fail;
10335 }
10336
10337 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
10338 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
10339 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
10340 &sar_limit_cmd.sar_limit_row_list[i].band_id)
10341 < 0) {
10342 hdd_err("Invalid SAR Band attr");
10343 goto fail;
10344 }
10345 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
10346 WMI_SAR_BAND_ID_VALID_MASK;
10347 }
10348 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
10349 sar_limit_cmd.sar_limit_row_list[i].chain_id =
10350 nla_get_u32(sar_spec[
10351 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
10352 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
10353 WMI_SAR_CHAIN_ID_VALID_MASK;
10354 }
10355 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
10356 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
10357 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
10358 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
10359 < 0) {
10360 hdd_err("Invalid SAR Modulation attr");
10361 goto fail;
10362 }
10363 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
10364 WMI_SAR_MOD_ID_VALID_MASK;
10365 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010366 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010367 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
10368 sar_limit_cmd.sar_limit_row_list[i].chain_id,
10369 sar_limit_cmd.sar_limit_row_list[i].mod_id,
10370 sar_limit_cmd.sar_limit_row_list[i].limit_value,
10371 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
10372 i++;
10373 }
10374
10375 if (i < sar_limit_cmd.num_limit_rows) {
10376 hdd_warn("SAR Cmd has less SPECs in list");
10377 sar_limit_cmd.num_limit_rows = i;
10378 }
10379
10380send_sar_limits:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010381 mac_handle = hdd_ctx->mac_handle;
10382 if (sme_set_sar_power_limits(mac_handle, &sar_limit_cmd) ==
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010383 QDF_STATUS_SUCCESS)
10384 ret = 0;
10385fail:
10386 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
10387 return ret;
10388}
10389
10390/**
10391 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
10392 * @wiphy: Pointer to wireless phy
10393 * @wdev: Pointer to wireless device
10394 * @data: Pointer to data
10395 * @data_len: Length of @data
10396 *
10397 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
10398 *
10399 * Return: 0 on success, negative errno on failure
10400 */
10401static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
10402 struct wireless_dev *wdev,
10403 const void *data,
10404 int data_len)
10405{
Dustin Brown363b4792019-02-05 16:11:55 -080010406 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080010407 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010408
Dustin Brown363b4792019-02-05 16:11:55 -080010409 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080010410 if (errno)
10411 return errno;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010412
Dustin Brownf0f00612019-01-31 16:02:24 -080010413 errno = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data, data_len);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010414
Dustin Brown363b4792019-02-05 16:11:55 -080010415 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010416
Dustin Brownf0f00612019-01-31 16:02:24 -080010417 return errno;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010418}
10419
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010420static const struct
10421nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
10422 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
10423 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
10424 .len = QDF_MAC_ADDR_SIZE},
10425};
10426
Jeff Johnson43975142018-07-04 15:33:47 -070010427void wlan_hdd_rso_cmd_status_cb(hdd_handle_t hdd_handle,
10428 struct rso_cmd_status *rso_status)
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053010429{
Jeff Johnson43975142018-07-04 15:33:47 -070010430 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Jeff Johnsone5006672017-08-29 14:39:02 -070010431 struct hdd_adapter *adapter;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053010432
10433 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
10434 if (!adapter) {
10435 hdd_err("adapter NULL");
10436 return;
10437 }
10438
10439 adapter->lfr_fw_status.is_disabled = rso_status->status;
10440 complete(&adapter->lfr_fw_status.disable_lfr_event);
10441}
10442
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010443/**
10444 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
10445 * @wiphy: Pointer to wireless phy
10446 * @wdev: Pointer to wireless device
10447 * @data: Pointer to data
10448 * @data_len: Length of @data
10449 *
10450 * This function is used to enable/disable roaming using vendor commands
10451 *
10452 * Return: 0 on success, negative errno on failure
10453 */
10454static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
10455 struct wireless_dev *wdev,
10456 const void *data, int data_len)
10457{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010458 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010459 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010460 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010461 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Abhishek Singh1f217ec2017-12-22 11:48:27 +053010462 uint32_t is_fast_roam_enabled;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010463 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +053010464 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053010465 unsigned long rc;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010466 struct hdd_station_ctx *hdd_sta_ctx =
10467 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
10468 mac_handle_t mac_handle;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010469
Dustin Brownfdf17c12018-03-14 12:55:34 -070010470 hdd_enter_dev(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010471
10472 ret = wlan_hdd_validate_context(hdd_ctx);
10473 if (0 != ret)
10474 return ret;
10475
10476 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10477 hdd_err("Command not allowed in FTM mode");
10478 return -EINVAL;
10479 }
10480
Dustin Brown4ea21db2018-01-05 14:13:17 -080010481 ret = wlan_cfg80211_nla_parse(tb,
10482 QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
10483 qca_wlan_vendor_attr);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010484 if (ret) {
10485 hdd_err("Invalid ATTR");
10486 return -EINVAL;
10487 }
10488
10489 /* Parse and fetch Enable flag */
10490 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
10491 hdd_err("attr enable failed");
10492 return -EINVAL;
10493 }
10494
10495 is_fast_roam_enabled = nla_get_u32(
10496 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Abhishek Singh1f217ec2017-12-22 11:48:27 +053010497 hdd_debug("isFastRoamEnabled %d", is_fast_roam_enabled);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010498
10499 /* Update roaming */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010500 mac_handle = hdd_ctx->mac_handle;
Jeff Johnsoncf07c312019-02-04 13:53:29 -080010501 qdf_status = sme_config_fast_roaming(mac_handle, adapter->vdev_id,
Abhishek Singh1f217ec2017-12-22 11:48:27 +053010502 is_fast_roam_enabled);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +053010503 if (qdf_status != QDF_STATUS_SUCCESS)
10504 hdd_err("sme_config_fast_roaming failed with status=%d",
10505 qdf_status);
10506 ret = qdf_status_to_os_return(qdf_status);
10507
Jeff Johnsone7951512019-02-27 10:02:51 -080010508 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.conn_state &&
Abhishek Singh1f217ec2017-12-22 11:48:27 +053010509 QDF_IS_STATUS_SUCCESS(qdf_status) && !is_fast_roam_enabled) {
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +053010510
10511 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053010512 /*
10513 * wait only for LFR disable in fw as LFR enable
10514 * is always success
10515 */
10516 rc = wait_for_completion_timeout(
10517 &adapter->lfr_fw_status.disable_lfr_event,
10518 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
10519 if (!rc) {
10520 hdd_err("Timed out waiting for RSO CMD status");
10521 return -ETIMEDOUT;
10522 }
10523
10524 if (!adapter->lfr_fw_status.is_disabled) {
10525 hdd_err("Roam disable attempt in FW fails");
10526 return -EBUSY;
10527 }
10528 }
10529
Dustin Browne74003f2018-03-14 12:51:58 -070010530 hdd_exit();
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010531 return ret;
10532}
10533
10534/**
10535 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
10536 * @wiphy: Pointer to wireless phy
10537 * @wdev: Pointer to wireless device
10538 * @data: Pointer to data
10539 * @data_len: Length of @data
10540 *
10541 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
10542 *
10543 * Return: 0 on success, negative errno on failure
10544 */
10545static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
10546 struct wireless_dev *wdev,
10547 const void *data, int data_len)
10548{
Dustin Browna09acf42018-11-08 12:32:26 +053010549 int errno;
10550 struct osif_vdev_sync *vdev_sync;
10551
10552 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
10553 if (errno)
10554 return errno;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010555
Dustin Browna09acf42018-11-08 12:32:26 +053010556 errno = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev,
10557 data, data_len);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010558
Dustin Browna09acf42018-11-08 12:32:26 +053010559 osif_vdev_sync_op_stop(vdev_sync);
10560
10561 return errno;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010562}
10563
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010564/*
10565 * define short names for the global vendor params
10566 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
10567 */
10568#define STATS_SET_INVALID \
10569 QCA_ATTR_NUD_STATS_SET_INVALID
10570#define STATS_SET_START \
10571 QCA_ATTR_NUD_STATS_SET_START
10572#define STATS_GW_IPV4 \
10573 QCA_ATTR_NUD_STATS_GW_IPV4
10574#define STATS_SET_DATA_PKT_INFO \
10575 QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
10576#define STATS_SET_MAX \
10577 QCA_ATTR_NUD_STATS_SET_MAX
10578
10579const struct nla_policy
10580qca_wlan_vendor_set_nud_stats[STATS_SET_MAX + 1] = {
10581 [STATS_SET_START] = {.type = NLA_FLAG },
10582 [STATS_GW_IPV4] = {.type = NLA_U32 },
10583 [STATS_SET_DATA_PKT_INFO] = {.type = NLA_U32 },
10584};
10585
10586/* define short names for the global vendor params */
10587#define CONNECTIVITY_STATS_SET_INVALID \
10588 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
10589#define STATS_PKT_INFO_TYPE \
10590 QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
10591#define STATS_DNS_DOMAIN_NAME \
10592 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
10593#define STATS_SRC_PORT \
10594 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
10595#define STATS_DEST_PORT \
10596 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
10597#define STATS_DEST_IPV4 \
10598 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
10599#define STATS_DEST_IPV6 \
10600 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
10601#define CONNECTIVITY_STATS_SET_MAX \
10602 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
10603
10604const struct nla_policy
10605qca_wlan_vendor_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
10606 [STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
Sourav Mohapatraaaa0f882019-03-07 09:28:40 +053010607 [STATS_DNS_DOMAIN_NAME] = {.type = NLA_NUL_STRING,
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010608 .len = DNS_DOMAIN_NAME_MAX_LEN },
10609 [STATS_SRC_PORT] = {.type = NLA_U32 },
10610 [STATS_DEST_PORT] = {.type = NLA_U32 },
10611 [STATS_DEST_IPV4] = {.type = NLA_U32 },
10612 [STATS_DEST_IPV6] = {.type = NLA_BINARY,
10613 .len = ICMPv6_ADDR_LEN },
10614};
10615
10616/**
10617 * hdd_dns_unmake_name_query() - Convert an uncompressed DNS name to a
10618 * NUL-terminated string
10619 * @name: DNS name
10620 *
10621 * Return: Produce a printable version of a DNS name.
10622 */
10623static inline uint8_t *hdd_dns_unmake_name_query(uint8_t *name)
10624{
10625 uint8_t *p;
10626 unsigned int len;
10627
10628 p = name;
10629 while ((len = *p)) {
10630 *(p++) = '.';
10631 p += len;
10632 }
10633
10634 return name + 1;
10635}
10636
10637/**
10638 * hdd_dns_make_name_query() - Convert a standard NUL-terminated string
10639 * to DNS name
10640 * @string: Name as a NUL-terminated string
10641 * @buf: Buffer in which to place DNS name
10642 *
10643 * DNS names consist of "<length>element" pairs.
10644 *
10645 * Return: Byte following constructed DNS name
10646 */
Sourav Mohapatra47710c32018-11-30 16:27:05 +053010647static uint8_t *hdd_dns_make_name_query(const uint8_t *string,
10648 uint8_t *buf, uint8_t len)
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010649{
10650 uint8_t *length_byte = buf++;
10651 uint8_t c;
10652
Sourav Mohapatra47710c32018-11-30 16:27:05 +053010653 if (string[len - 1]) {
10654 hdd_debug("DNS name is not null terminated");
10655 return NULL;
10656 }
10657
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010658 while ((c = *(string++))) {
10659 if (c == '.') {
10660 *length_byte = buf - length_byte - 1;
10661 length_byte = buf;
10662 }
10663 *(buf++) = c;
10664 }
10665 *length_byte = buf - length_byte - 1;
10666 *(buf++) = '\0';
10667 return buf;
10668}
10669
10670/**
10671 * hdd_set_clear_connectivity_check_stats_info() - set/clear stats info
10672 * @adapter: Pointer to hdd adapter
10673 * @arp_stats_params: arp stats structure to be sent to FW
10674 * @tb: nl attribute
10675 * @is_set_stats: set/clear stats
10676 *
10677 *
10678 * Return: 0 on success, negative errno on failure
10679 */
10680static int hdd_set_clear_connectivity_check_stats_info(
10681 struct hdd_adapter *adapter,
10682 struct set_arp_stats_params *arp_stats_params,
10683 struct nlattr **tb, bool is_set_stats)
10684{
10685 struct nlattr *tb2[CONNECTIVITY_STATS_SET_MAX + 1];
10686 struct nlattr *curr_attr = NULL;
10687 int err = 0;
10688 uint32_t pkt_bitmap;
10689 int rem;
10690
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010691 /* Set NUD command for start tracking is received. */
10692 nla_for_each_nested(curr_attr,
10693 tb[STATS_SET_DATA_PKT_INFO],
10694 rem) {
10695
10696 if (wlan_cfg80211_nla_parse(tb2,
10697 CONNECTIVITY_STATS_SET_MAX,
10698 nla_data(curr_attr), nla_len(curr_attr),
10699 qca_wlan_vendor_set_connectivity_check_stats)) {
10700 hdd_err("nla_parse failed");
10701 err = -EINVAL;
10702 goto end;
10703 }
10704
10705 if (tb2[STATS_PKT_INFO_TYPE]) {
10706 pkt_bitmap = nla_get_u32(tb2[STATS_PKT_INFO_TYPE]);
10707 if (!pkt_bitmap) {
10708 hdd_err("pkt tracking bitmap is empty");
10709 err = -EINVAL;
10710 goto end;
10711 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053010712
10713 if (is_set_stats) {
10714 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
10715 arp_stats_params->flag = true;
10716 adapter->pkt_type_bitmap |=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010717 arp_stats_params->pkt_type_bitmap;
10718
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053010719 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
Srinivas Girigowda683726a2018-09-07 15:10:40 -070010720 if (!tb[STATS_GW_IPV4]) {
10721 hdd_err("GW ipv4 address is not present");
10722 err = -EINVAL;
10723 goto end;
10724 }
10725 arp_stats_params->ip_addr =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010726 nla_get_u32(tb[STATS_GW_IPV4]);
Srinivas Girigowda683726a2018-09-07 15:10:40 -070010727 arp_stats_params->pkt_type =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010728 WLAN_NUD_STATS_ARP_PKT_TYPE;
Srinivas Girigowda683726a2018-09-07 15:10:40 -070010729 adapter->track_arp_ip =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010730 arp_stats_params->ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010731 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053010732
10733 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
10734 uint8_t *domain_name;
10735
10736 if (!tb2[STATS_DNS_DOMAIN_NAME]) {
10737 hdd_err("DNS domain id is not present");
10738 err = -EINVAL;
10739 goto end;
10740 }
10741 domain_name = nla_data(
10742 tb2[STATS_DNS_DOMAIN_NAME]);
10743 adapter->track_dns_domain_len =
10744 nla_len(tb2[
10745 STATS_DNS_DOMAIN_NAME]);
Sourav Mohapatra47710c32018-11-30 16:27:05 +053010746 if (!hdd_dns_make_name_query(
10747 domain_name,
10748 adapter->dns_payload,
10749 adapter->track_dns_domain_len))
10750 adapter->track_dns_domain_len =
10751 0;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053010752 /* DNStracking isn't supported in FW. */
10753 arp_stats_params->pkt_type_bitmap &=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010754 ~CONNECTIVITY_CHECK_SET_DNS;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010755 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053010756
10757 if (pkt_bitmap &
10758 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
10759 if (!tb2[STATS_SRC_PORT] ||
10760 !tb2[STATS_DEST_PORT]) {
10761 hdd_err("Source/Dest port is not present");
10762 err = -EINVAL;
10763 goto end;
10764 }
10765 arp_stats_params->tcp_src_port =
10766 nla_get_u32(
10767 tb2[STATS_SRC_PORT]);
10768 arp_stats_params->tcp_dst_port =
10769 nla_get_u32(
10770 tb2[STATS_DEST_PORT]);
10771 adapter->track_src_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010772 arp_stats_params->tcp_src_port;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053010773 adapter->track_dest_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010774 arp_stats_params->tcp_dst_port;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010775 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053010776
10777 if (pkt_bitmap &
10778 CONNECTIVITY_CHECK_SET_ICMPV4) {
10779 if (!tb2[STATS_DEST_IPV4]) {
10780 hdd_err("destination ipv4 address to track ping packets is not present");
10781 err = -EINVAL;
10782 goto end;
10783 }
10784 arp_stats_params->icmp_ipv4 =
10785 nla_get_u32(
10786 tb2[STATS_DEST_IPV4]);
10787 adapter->track_dest_ipv4 =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010788 arp_stats_params->icmp_ipv4;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053010789 }
10790 } else {
10791 /* clear stats command received */
10792 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
10793 arp_stats_params->flag = false;
10794 adapter->pkt_type_bitmap &=
10795 (~arp_stats_params->pkt_type_bitmap);
10796
10797 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
10798 arp_stats_params->pkt_type =
10799 WLAN_NUD_STATS_ARP_PKT_TYPE;
10800 qdf_mem_zero(&adapter->hdd_stats.
10801 hdd_arp_stats,
10802 sizeof(adapter->hdd_stats.
10803 hdd_arp_stats));
10804 adapter->track_arp_ip = 0;
10805 }
10806
10807 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
10808 /* DNStracking isn't supported in FW. */
10809 arp_stats_params->pkt_type_bitmap &=
10810 ~CONNECTIVITY_CHECK_SET_DNS;
10811 qdf_mem_zero(&adapter->hdd_stats.
10812 hdd_dns_stats,
10813 sizeof(adapter->hdd_stats.
10814 hdd_dns_stats));
10815 qdf_mem_zero(adapter->dns_payload,
10816 adapter->track_dns_domain_len);
10817 adapter->track_dns_domain_len = 0;
10818 }
10819
10820 if (pkt_bitmap &
10821 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
10822 qdf_mem_zero(&adapter->hdd_stats.
10823 hdd_tcp_stats,
10824 sizeof(adapter->hdd_stats.
10825 hdd_tcp_stats));
10826 adapter->track_src_port = 0;
10827 adapter->track_dest_port = 0;
10828 }
10829
10830 if (pkt_bitmap &
10831 CONNECTIVITY_CHECK_SET_ICMPV4) {
10832 qdf_mem_zero(&adapter->hdd_stats.
10833 hdd_icmpv4_stats,
10834 sizeof(adapter->hdd_stats.
10835 hdd_icmpv4_stats));
10836 adapter->track_dest_ipv4 = 0;
10837 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010838 }
10839 } else {
10840 hdd_err("stats list empty");
10841 err = -EINVAL;
10842 goto end;
10843 }
10844 }
10845
10846end:
10847 return err;
10848}
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053010849
Jeff Johnsonf6182e42018-07-03 14:46:17 -070010850void hdd_update_cca_info_cb(hdd_handle_t hdd_handle, uint32_t congestion,
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010851 uint32_t vdev_id)
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053010852{
Jeff Johnsonf6182e42018-07-03 14:46:17 -070010853 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053010854 int status;
Jeff Johnsone5006672017-08-29 14:39:02 -070010855 struct hdd_adapter *adapter = NULL;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070010856 struct hdd_station_ctx *hdd_sta_ctx;
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053010857
10858 status = wlan_hdd_validate_context(hdd_ctx);
10859 if (status != 0)
10860 return;
10861
10862 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
10863 if (adapter == NULL) {
10864 hdd_err("vdev_id %d does not exist with host", vdev_id);
10865 return;
10866 }
10867
10868 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
10869 hdd_sta_ctx->conn_info.cca = congestion;
10870 hdd_info("congestion:%d", congestion);
10871}
10872
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010873static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
10874 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
10875 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
10876 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
10877 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
10878};
10879
10880/**
10881 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
10882 * @wiphy: Pointer to wireless phy
10883 * @wdev: Pointer to wireless device
10884 * @data: Pointer to data
10885 * @data_len: Length of @data
10886 *
10887 * Return: 0 on success, negative errno on failure
10888 */
10889static int
10890__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
10891 struct wireless_dev *wdev,
10892 const void *data,
10893 int data_len)
10894{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010895 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010896 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
10897 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
10898 struct nlattr *apth;
10899 int rem;
10900 int ret = 1;
10901 int print_idx = -1;
10902 int module_id = -1;
10903 int bit_mask = -1;
10904 int status;
10905
Dustin Brown491d54b2018-03-14 12:39:11 -070010906 hdd_enter();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010907
10908 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
10909 hdd_err("Command not allowed in FTM mode");
10910 return -EINVAL;
10911 }
10912
10913 ret = wlan_hdd_validate_context(hdd_ctx);
10914 if (ret != 0)
10915 return -EINVAL;
10916
10917 print_idx = qdf_get_pidx();
10918 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
10919 hdd_err("Invalid print controle object index");
10920 return -EINVAL;
10921 }
10922
Dustin Brown4ea21db2018-01-05 14:13:17 -080010923 if (wlan_cfg80211_nla_parse(tb1,
10924 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
10925 data, data_len,
10926 qca_wlan_vendor_set_trace_level_policy)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010927 hdd_err("Invalid attr");
10928 return -EINVAL;
10929 }
10930
10931 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
10932 hdd_err("attr trace level param failed");
10933 return -EINVAL;
10934 }
10935
10936 nla_for_each_nested(apth,
10937 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -080010938 if (wlan_cfg80211_nla_parse(tb2,
10939 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
10940 nla_data(apth), nla_len(apth), NULL)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010941 hdd_err("Invalid attr");
10942 return -EINVAL;
10943 }
10944
10945 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
10946 hdd_err("attr Module ID failed");
10947 return -EINVAL;
10948 }
10949 module_id = nla_get_u32
10950 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
10951
10952 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
10953 hdd_err("attr Verbose mask failed");
10954 return -EINVAL;
10955 }
10956 bit_mask = nla_get_u32
10957 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
10958
10959 status = hdd_qdf_trace_enable(module_id, bit_mask);
10960
10961 if (status != 0)
10962 hdd_err("can not set verbose mask %d for the category %d",
10963 bit_mask, module_id);
10964 }
10965
Dustin Browne74003f2018-03-14 12:51:58 -070010966 hdd_exit();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010967 return ret;
10968}
10969
10970/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +053010971 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
10972 * @wiphy: Pointer to wireless phy
10973 * @wdev: Pointer to wireless device
10974 * @data: Pointer to data
10975 * @data_len: Length of @data
10976 *
10977 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
10978 *
10979 * Return: 0 on success, negative errno on failure
10980 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010981
10982static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
10983 struct wireless_dev *wdev,
10984 const void *data,
10985 int data_len)
10986{
Dustin Brown363b4792019-02-05 16:11:55 -080010987 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080010988 int errno;
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010989
Dustin Brown363b4792019-02-05 16:11:55 -080010990 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080010991 if (errno)
10992 return errno;
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010993
Dustin Brownf0f00612019-01-31 16:02:24 -080010994 errno = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev,
10995 data, data_len);
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010996
Dustin Brown363b4792019-02-05 16:11:55 -080010997 osif_psoc_sync_op_stop(psoc_sync);
Arunk Khandavalli99716d12018-11-14 15:02:02 +053010998
Dustin Brownf0f00612019-01-31 16:02:24 -080010999 return errno;
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053011000}
11001
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011002/**
11003 * __wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
11004 * @wiphy: pointer to wireless wiphy structure.
11005 * @wdev: pointer to wireless_dev structure.
11006 * @data: pointer to apfind configuration data.
11007 * @data_len: the length in byte of apfind data.
11008 *
11009 * This is called when wlan driver needs to send arp stats to
11010 * firmware.
11011 *
11012 * Return: An error code or 0 on success.
11013 */
11014static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
11015 struct wireless_dev *wdev,
11016 const void *data, int data_len)
11017{
11018 struct nlattr *tb[STATS_SET_MAX + 1];
11019 struct net_device *dev = wdev->netdev;
11020 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
11021 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011022 struct set_arp_stats_params arp_stats_params = {0};
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011023 int err = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011024 mac_handle_t mac_handle;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011025
Dustin Brown491d54b2018-03-14 12:39:11 -070011026 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011027
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053011028 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
11029 hdd_err("Command not allowed in FTM mode");
11030 return -EINVAL;
11031 }
11032
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011033 err = wlan_hdd_validate_context(hdd_ctx);
11034 if (0 != err)
11035 return err;
11036
Jeff Johnson912b1bb2019-03-06 10:12:36 -080011037 if (adapter->vdev_id == WLAN_UMAC_VDEV_ID_MAX) {
11038 hdd_err("Invalid vdev id");
Yeshwanth Sriram Guntukad5aae7f2017-11-27 14:33:51 +053011039 return -EINVAL;
11040 }
11041
Poddar, Siddarthdf076672018-02-26 14:21:45 +053011042 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070011043 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053011044 return -EINVAL;
11045 }
11046
Jeff Johnson912b1bb2019-03-06 10:12:36 -080011047 err = wlan_cfg80211_nla_parse(tb, STATS_SET_MAX, data, data_len,
11048 qca_wlan_vendor_set_nud_stats);
11049 if (err) {
11050 hdd_err("STATS_SET_START ATTR");
11051 return err;
11052 }
11053
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011054 if (tb[STATS_SET_START]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011055 /* tracking is enabled for stats other than arp. */
11056 if (tb[STATS_SET_DATA_PKT_INFO]) {
11057 err = hdd_set_clear_connectivity_check_stats_info(
11058 adapter,
11059 &arp_stats_params, tb, true);
11060 if (err)
11061 return -EINVAL;
11062
11063 /*
11064 * if only tracking dns, then don't send
11065 * wmi command to FW.
11066 */
11067 if (!arp_stats_params.pkt_type_bitmap)
11068 return err;
11069 } else {
11070 if (!tb[STATS_GW_IPV4]) {
Dustin Browna2868622018-03-20 11:38:14 -070011071 hdd_err("STATS_SET_START CMD");
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011072 return -EINVAL;
11073 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053011074
11075 arp_stats_params.pkt_type_bitmap =
11076 CONNECTIVITY_CHECK_SET_ARP;
11077 adapter->pkt_type_bitmap |=
11078 arp_stats_params.pkt_type_bitmap;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011079 arp_stats_params.flag = true;
11080 arp_stats_params.ip_addr =
11081 nla_get_u32(tb[STATS_GW_IPV4]);
11082 adapter->track_arp_ip = arp_stats_params.ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011083 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011084 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011085 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053011086 /* clear stats command received. */
11087 if (tb[STATS_SET_DATA_PKT_INFO]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011088 err = hdd_set_clear_connectivity_check_stats_info(
11089 adapter,
11090 &arp_stats_params, tb, false);
11091 if (err)
11092 return -EINVAL;
11093
11094 /*
11095 * if only tracking dns, then don't send
11096 * wmi command to FW.
11097 */
11098 if (!arp_stats_params.pkt_type_bitmap)
11099 return err;
11100 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053011101 arp_stats_params.pkt_type_bitmap =
11102 CONNECTIVITY_CHECK_SET_ARP;
11103 adapter->pkt_type_bitmap &=
11104 (~arp_stats_params.pkt_type_bitmap);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011105 arp_stats_params.flag = false;
11106 qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
11107 sizeof(adapter->hdd_stats.hdd_arp_stats));
11108 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
11109 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011110 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011111
Abhinav Kumar50d4dc72018-06-15 16:35:50 +053011112 hdd_debug("STATS_SET_START Received flag %d!", arp_stats_params.flag);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011113
Jeff Johnsoncf07c312019-02-04 13:53:29 -080011114 arp_stats_params.vdev_id = adapter->vdev_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011115
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011116 mac_handle = hdd_ctx->mac_handle;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011117 if (QDF_STATUS_SUCCESS !=
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011118 sme_set_nud_debug_stats(mac_handle, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070011119 hdd_err("STATS_SET_START CMD Failed!");
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011120 return -EINVAL;
11121 }
11122
Dustin Browne74003f2018-03-14 12:51:58 -070011123 hdd_exit();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011124
11125 return err;
11126}
11127
11128/**
11129 * wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
11130 * @wiphy: pointer to wireless wiphy structure.
11131 * @wdev: pointer to wireless_dev structure.
11132 * @data: pointer to apfind configuration data.
11133 * @data_len: the length in byte of apfind data.
11134 *
11135 * This is called when wlan driver needs to send arp stats to
11136 * firmware.
11137 *
11138 * Return: An error code or 0 on success.
11139 */
11140static int wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
11141 struct wireless_dev *wdev,
11142 const void *data, int data_len)
11143{
Dustin Browna09acf42018-11-08 12:32:26 +053011144 int errno;
11145 struct osif_vdev_sync *vdev_sync;
11146
11147 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
11148 if (errno)
11149 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011150
Dustin Browna09acf42018-11-08 12:32:26 +053011151 errno = __wlan_hdd_cfg80211_set_nud_stats(wiphy, wdev, data, data_len);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011152
Dustin Browna09acf42018-11-08 12:32:26 +053011153 osif_vdev_sync_op_stop(vdev_sync);
11154
11155 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011156}
11157
11158#undef STATS_SET_INVALID
11159#undef STATS_SET_START
11160#undef STATS_GW_IPV4
11161#undef STATS_SET_MAX
11162
11163/*
11164 * define short names for the global vendor params
11165 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
11166 */
11167#define STATS_GET_INVALID \
11168 QCA_ATTR_NUD_STATS_SET_INVALID
11169#define COUNT_FROM_NETDEV \
11170 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
11171#define COUNT_TO_LOWER_MAC \
11172 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
11173#define RX_COUNT_BY_LOWER_MAC \
11174 QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
11175#define COUNT_TX_SUCCESS \
11176 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
11177#define RSP_RX_COUNT_BY_LOWER_MAC \
11178 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
11179#define RSP_RX_COUNT_BY_UPPER_MAC \
11180 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
11181#define RSP_COUNT_TO_NETDEV \
11182 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
11183#define RSP_COUNT_OUT_OF_ORDER_DROP \
11184 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
11185#define AP_LINK_ACTIVE \
11186 QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
11187#define AP_LINK_DAD \
11188 QCA_ATTR_NUD_STATS_IS_DAD
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011189#define DATA_PKT_STATS \
11190 QCA_ATTR_NUD_STATS_DATA_PKT_STATS
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011191#define STATS_GET_MAX \
11192 QCA_ATTR_NUD_STATS_GET_MAX
11193
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011194#define CHECK_STATS_INVALID \
11195 QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
11196#define CHECK_STATS_PKT_TYPE \
11197 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
11198#define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
11199 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
11200#define CHECK_STATS_PKT_SRC_PORT \
11201 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
11202#define CHECK_STATS_PKT_DEST_PORT \
11203 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
11204#define CHECK_STATS_PKT_DEST_IPV4 \
11205 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
11206#define CHECK_STATS_PKT_DEST_IPV6 \
11207 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
11208#define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
11209 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
11210#define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
11211 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
11212#define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
11213 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
11214#define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
11215 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
11216#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
11217 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
11218#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
11219 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
11220#define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
11221 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
11222#define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
11223 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
11224#define CHECK_DATA_STATS_MAX \
11225 QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
11226
11227
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011228const struct nla_policy
11229qca_wlan_vendor_get_nud_stats[STATS_GET_MAX + 1] = {
11230 [COUNT_FROM_NETDEV] = {.type = NLA_U16 },
11231 [COUNT_TO_LOWER_MAC] = {.type = NLA_U16 },
11232 [RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
11233 [COUNT_TX_SUCCESS] = {.type = NLA_U16 },
11234 [RSP_RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
11235 [RSP_RX_COUNT_BY_UPPER_MAC] = {.type = NLA_U16 },
11236 [RSP_COUNT_TO_NETDEV] = {.type = NLA_U16 },
11237 [RSP_COUNT_OUT_OF_ORDER_DROP] = {.type = NLA_U16 },
11238 [AP_LINK_ACTIVE] = {.type = NLA_FLAG },
11239 [AP_LINK_DAD] = {.type = NLA_FLAG },
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011240 [DATA_PKT_STATS] = {.type = NLA_U16 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011241};
11242
11243/**
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011244 * hdd_populate_dns_stats_info() - send dns stats info to network stack
11245 * @adapter: pointer to adapter context
11246 * @skb: pointer to skb
11247 *
11248 *
11249 * Return: An error code or 0 on success.
11250 */
11251static int hdd_populate_dns_stats_info(struct hdd_adapter *adapter,
11252 struct sk_buff *skb)
11253{
11254 uint8_t *dns_query;
11255
11256 dns_query = qdf_mem_malloc(adapter->track_dns_domain_len + 1);
Min Liu74a1a502018-10-10 19:59:07 +080011257 if (!dns_query)
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011258 return -EINVAL;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011259
11260 qdf_mem_copy(dns_query, adapter->dns_payload,
11261 adapter->track_dns_domain_len);
11262
11263 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
11264 CONNECTIVITY_CHECK_SET_DNS) ||
11265 nla_put(skb, CHECK_STATS_PKT_DNS_DOMAIN_NAME,
11266 adapter->track_dns_domain_len,
11267 hdd_dns_unmake_name_query(dns_query)) ||
11268 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
11269 adapter->hdd_stats.hdd_dns_stats.tx_dns_req_count) ||
11270 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
11271 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
11272 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
11273 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
11274 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
11275 adapter->hdd_stats.hdd_dns_stats.tx_ack_cnt) ||
11276 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
11277 adapter->hdd_stats.hdd_dns_stats.rx_dns_rsp_count) ||
11278 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
11279 adapter->hdd_stats.hdd_dns_stats.rx_delivered) ||
11280 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
11281 adapter->hdd_stats.hdd_dns_stats.rx_host_drop)) {
11282 hdd_err("nla put fail");
11283 qdf_mem_free(dns_query);
11284 kfree_skb(skb);
11285 return -EINVAL;
11286 }
11287 qdf_mem_free(dns_query);
11288 return 0;
11289}
11290
11291/**
11292 * hdd_populate_tcp_stats_info() - send tcp stats info to network stack
11293 * @adapter: pointer to adapter context
11294 * @skb: pointer to skb
11295 * @pkt_type: tcp pkt type
11296 *
11297 * Return: An error code or 0 on success.
11298 */
11299static int hdd_populate_tcp_stats_info(struct hdd_adapter *adapter,
11300 struct sk_buff *skb,
11301 uint8_t pkt_type)
11302{
11303 switch (pkt_type) {
11304 case CONNECTIVITY_CHECK_SET_TCP_SYN:
11305 /* Fill info for tcp syn packets (tx packet) */
11306 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
11307 CONNECTIVITY_CHECK_SET_TCP_SYN) ||
11308 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
11309 adapter->track_src_port) ||
11310 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
11311 adapter->track_dest_port) ||
11312 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
11313 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_count) ||
11314 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
11315 adapter->hdd_stats.hdd_tcp_stats.
11316 tx_tcp_syn_host_fw_sent) ||
11317 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
11318 adapter->hdd_stats.hdd_tcp_stats.
11319 tx_tcp_syn_host_fw_sent) ||
11320 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
11321 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_ack_cnt)) {
11322 hdd_err("nla put fail");
11323 kfree_skb(skb);
11324 return -EINVAL;
11325 }
11326 break;
11327 case CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
11328 /* Fill info for tcp syn-ack packets (rx packet) */
11329 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
11330 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK) ||
11331 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
11332 adapter->track_src_port) ||
11333 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
11334 adapter->track_dest_port) ||
11335 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
11336 adapter->hdd_stats.hdd_tcp_stats.rx_fw_cnt) ||
11337 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
11338 adapter->hdd_stats.hdd_tcp_stats.
11339 rx_tcp_syn_ack_count) ||
11340 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
11341 adapter->hdd_stats.hdd_tcp_stats.rx_delivered) ||
11342 nla_put_u16(skb,
11343 CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
11344 adapter->hdd_stats.hdd_tcp_stats.rx_host_drop)) {
11345 hdd_err("nla put fail");
11346 kfree_skb(skb);
11347 return -EINVAL;
11348 }
11349 break;
11350 case CONNECTIVITY_CHECK_SET_TCP_ACK:
11351 /* Fill info for tcp ack packets (tx packet) */
11352 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
11353 CONNECTIVITY_CHECK_SET_TCP_ACK) ||
11354 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
11355 adapter->track_src_port) ||
11356 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
11357 adapter->track_dest_port) ||
11358 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
11359 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_count) ||
11360 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
11361 adapter->hdd_stats.hdd_tcp_stats.
11362 tx_tcp_ack_host_fw_sent) ||
11363 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
11364 adapter->hdd_stats.hdd_tcp_stats.
11365 tx_tcp_ack_host_fw_sent) ||
11366 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
11367 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_ack_cnt)) {
11368 hdd_err("nla put fail");
11369 kfree_skb(skb);
11370 return -EINVAL;
11371 }
11372 break;
11373 default:
11374 break;
11375 }
11376 return 0;
11377}
11378
11379/**
11380 * hdd_populate_icmpv4_stats_info() - send icmpv4 stats info to network stack
11381 * @adapter: pointer to adapter context
11382 * @skb: pointer to skb
11383 *
11384 *
11385 * Return: An error code or 0 on success.
11386 */
11387static int hdd_populate_icmpv4_stats_info(struct hdd_adapter *adapter,
11388 struct sk_buff *skb)
11389{
11390 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
11391 CONNECTIVITY_CHECK_SET_ICMPV4) ||
11392 nla_put_u32(skb, CHECK_STATS_PKT_DEST_IPV4,
11393 adapter->track_dest_ipv4) ||
11394 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
11395 adapter->hdd_stats.hdd_icmpv4_stats.tx_icmpv4_req_count) ||
11396 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
11397 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
11398 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
11399 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
11400 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
11401 adapter->hdd_stats.hdd_icmpv4_stats.tx_ack_cnt) ||
11402 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
11403 adapter->hdd_stats.hdd_icmpv4_stats.rx_fw_cnt) ||
11404 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
11405 adapter->hdd_stats.hdd_icmpv4_stats.rx_icmpv4_rsp_count) ||
11406 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
11407 adapter->hdd_stats.hdd_icmpv4_stats.rx_delivered) ||
11408 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
11409 adapter->hdd_stats.hdd_icmpv4_stats.rx_host_drop)) {
11410 hdd_err("nla put fail");
11411 kfree_skb(skb);
11412 return -EINVAL;
11413 }
11414 return 0;
11415}
11416
11417/**
11418 * hdd_populate_connectivity_check_stats_info() - send connectivity stats info
11419 * to network stack
11420 * @adapter: pointer to adapter context
11421 * @skb: pointer to skb
11422 *
11423 *
11424 * Return: An error code or 0 on success.
11425 */
11426
11427static int hdd_populate_connectivity_check_stats_info(
11428 struct hdd_adapter *adapter, struct sk_buff *skb)
11429{
11430 struct nlattr *connect_stats, *connect_info;
11431 uint32_t count = 0;
11432
11433 connect_stats = nla_nest_start(skb, DATA_PKT_STATS);
11434 if (connect_stats == NULL) {
11435 hdd_err("nla_nest_start failed");
11436 return -EINVAL;
11437 }
11438
11439 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
11440 connect_info = nla_nest_start(skb, count);
11441 if (connect_info == NULL) {
11442 hdd_err("nla_nest_start failed count %u", count);
11443 return -EINVAL;
11444 }
11445
11446 if (hdd_populate_dns_stats_info(adapter, skb))
11447 goto put_attr_fail;
11448 nla_nest_end(skb, connect_info);
11449 count++;
11450 }
11451
11452 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
11453 connect_info = nla_nest_start(skb, count);
11454 if (connect_info == NULL) {
11455 hdd_err("nla_nest_start failed count %u", count);
11456 return -EINVAL;
11457 }
11458 if (hdd_populate_tcp_stats_info(adapter, skb,
11459 CONNECTIVITY_CHECK_SET_TCP_SYN))
11460 goto put_attr_fail;
11461 nla_nest_end(skb, connect_info);
11462 count++;
11463
11464 connect_info = nla_nest_start(skb, count);
11465 if (connect_info == NULL) {
11466 hdd_err("nla_nest_start failed count %u", count);
11467 return -EINVAL;
11468 }
11469 if (hdd_populate_tcp_stats_info(adapter, skb,
11470 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK))
11471 goto put_attr_fail;
11472 nla_nest_end(skb, connect_info);
11473 count++;
11474
11475 connect_info = nla_nest_start(skb, count);
11476 if (connect_info == NULL) {
11477 hdd_err("nla_nest_start failed count %u", count);
11478 return -EINVAL;
11479 }
11480 if (hdd_populate_tcp_stats_info(adapter, skb,
11481 CONNECTIVITY_CHECK_SET_TCP_ACK))
11482 goto put_attr_fail;
11483 nla_nest_end(skb, connect_info);
11484 count++;
11485 }
11486
11487 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ICMPV4) {
11488 connect_info = nla_nest_start(skb, count);
11489 if (connect_info == NULL) {
11490 hdd_err("nla_nest_start failed count %u", count);
11491 return -EINVAL;
11492 }
11493
11494 if (hdd_populate_icmpv4_stats_info(adapter, skb))
11495 goto put_attr_fail;
11496 nla_nest_end(skb, connect_info);
11497 count++;
11498 }
11499
11500 nla_nest_end(skb, connect_stats);
11501 return 0;
11502
11503put_attr_fail:
11504 hdd_err("QCA_WLAN_VENDOR_ATTR put fail. count %u", count);
11505 return -EINVAL;
11506}
11507
11508
11509/**
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011510 * __wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
11511 * @wiphy: pointer to wireless wiphy structure.
11512 * @wdev: pointer to wireless_dev structure.
11513 * @data: pointer to apfind configuration data.
11514 * @data_len: the length in byte of apfind data.
11515 *
11516 * This is called when wlan driver needs to get arp stats to
11517 * firmware.
11518 *
11519 * Return: An error code or 0 on success.
11520 */
11521static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
11522 struct wireless_dev *wdev,
11523 const void *data, int data_len)
11524{
11525 int err = 0;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011526 struct net_device *dev = wdev->netdev;
11527 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
11528 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
11529 struct get_arp_stats_params arp_stats_params;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011530 mac_handle_t mac_handle;
Poddar, Siddarthdb568162017-07-27 18:16:38 +053011531 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011532 uint32_t pkt_type_bitmap;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011533 struct sk_buff *skb;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011534 struct osif_request *request = NULL;
11535 static const struct osif_request_params params = {
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053011536 .priv_size = 0,
11537 .timeout_ms = WLAN_WAIT_TIME_NUD_STATS,
11538 };
11539 void *cookie = NULL;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011540
Dustin Brown491d54b2018-03-14 12:39:11 -070011541 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011542
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053011543 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
11544 hdd_err("Command not allowed in FTM mode");
11545 return -EINVAL;
11546 }
11547
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011548 err = wlan_hdd_validate_context(hdd_ctx);
11549 if (0 != err)
11550 return err;
11551
Rajeev Kumar7f28e8a32017-08-23 15:41:30 -070011552 err = hdd_validate_adapter(adapter);
11553 if (err)
11554 return err;
11555
Poddar, Siddarthdf076672018-02-26 14:21:45 +053011556 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070011557 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053011558 return -EINVAL;
11559 }
11560
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011561 request = osif_request_alloc(&params);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053011562 if (!request) {
11563 hdd_err("Request allocation failure");
11564 return -ENOMEM;
11565 }
11566
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011567 cookie = osif_request_cookie(request);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053011568
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011569 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Jeff Johnsoncf07c312019-02-04 13:53:29 -080011570 arp_stats_params.vdev_id = adapter->vdev_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011571
Poddar, Siddarth762c5472018-03-20 14:55:35 +053011572 pkt_type_bitmap = adapter->pkt_type_bitmap;
11573
11574 /* send NUD failure event only when ARP tracking is enabled. */
jitiphil377bcc12018-10-05 19:46:08 +053011575 if (cdp_cfg_get(soc, cfg_dp_enable_data_stall) &&
Poddar, Siddarth762c5472018-03-20 14:55:35 +053011576 (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ARP))
Poddar, Siddarth37033032017-10-11 15:47:40 +053011577 cdp_post_data_stall_event(soc,
11578 DATA_STALL_LOG_INDICATOR_FRAMEWORK,
Poddar, Siddarthdb568162017-07-27 18:16:38 +053011579 DATA_STALL_LOG_NUD_FAILURE,
11580 0xFF, 0XFF,
11581 DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
11582
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011583 mac_handle = hdd_ctx->mac_handle;
11584 if (sme_set_nud_debug_stats_cb(mac_handle, hdd_get_nud_stats_cb,
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053011585 cookie) != QDF_STATUS_SUCCESS) {
11586 hdd_err("Setting NUD debug stats callback failure");
11587 err = -EINVAL;
11588 goto exit;
11589 }
11590
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011591 if (QDF_STATUS_SUCCESS !=
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011592 sme_get_nud_debug_stats(mac_handle, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070011593 hdd_err("STATS_SET_START CMD Failed!");
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053011594 err = -EINVAL;
11595 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011596 }
11597
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011598 err = osif_request_wait_for_response(request);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053011599 if (err) {
11600 hdd_err("SME timedout while retrieving NUD stats");
11601 err = -ETIMEDOUT;
11602 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011603 }
11604
11605 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
11606 WLAN_NUD_STATS_LEN);
11607 if (!skb) {
11608 hdd_err("%s: cfg80211_vendor_cmd_alloc_reply_skb failed",
11609 __func__);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053011610 err = -ENOMEM;
11611 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011612 }
11613
11614 if (nla_put_u16(skb, COUNT_FROM_NETDEV,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053011615 adapter->hdd_stats.hdd_arp_stats.tx_arp_req_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011616 nla_put_u16(skb, COUNT_TO_LOWER_MAC,
11617 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
11618 nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053011619 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011620 nla_put_u16(skb, COUNT_TX_SUCCESS,
11621 adapter->hdd_stats.hdd_arp_stats.tx_ack_cnt) ||
11622 nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC,
11623 adapter->hdd_stats.hdd_arp_stats.rx_fw_cnt) ||
11624 nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053011625 adapter->hdd_stats.hdd_arp_stats.rx_arp_rsp_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011626 nla_put_u16(skb, RSP_COUNT_TO_NETDEV,
11627 adapter->hdd_stats.hdd_arp_stats.rx_delivered) ||
11628 nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP,
11629 adapter->hdd_stats.hdd_arp_stats.
11630 rx_host_drop_reorder)) {
11631 hdd_err("nla put fail");
11632 kfree_skb(skb);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053011633 err = -EINVAL;
11634 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011635 }
11636 if (adapter->con_status)
11637 nla_put_flag(skb, AP_LINK_ACTIVE);
11638 if (adapter->dad)
11639 nla_put_flag(skb, AP_LINK_DAD);
11640
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011641 /* ARP tracking is done above. */
11642 pkt_type_bitmap &= ~CONNECTIVITY_CHECK_SET_ARP;
11643
11644 if (pkt_type_bitmap) {
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053011645 if (hdd_populate_connectivity_check_stats_info(adapter, skb)) {
11646 err = -EINVAL;
11647 goto exit;
11648 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053011649 }
11650
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011651 cfg80211_vendor_cmd_reply(skb);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053011652exit:
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011653 osif_request_put(request);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011654 return err;
11655}
11656
11657/**
11658 * wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
11659 * @wiphy: pointer to wireless wiphy structure.
11660 * @wdev: pointer to wireless_dev structure.
11661 * @data: pointer to apfind configuration data.
11662 * @data_len: the length in byte of apfind data.
11663 *
11664 * This is called when wlan driver needs to get arp stats to
11665 * firmware.
11666 *
11667 * Return: An error code or 0 on success.
11668 */
11669static int wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
11670 struct wireless_dev *wdev,
11671 const void *data, int data_len)
11672{
Dustin Browna09acf42018-11-08 12:32:26 +053011673 int errno;
11674 struct osif_vdev_sync *vdev_sync;
11675
11676 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
11677 if (errno)
11678 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011679
Dustin Browna09acf42018-11-08 12:32:26 +053011680 errno = __wlan_hdd_cfg80211_get_nud_stats(wiphy, wdev, data, data_len);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011681
Dustin Browna09acf42018-11-08 12:32:26 +053011682 osif_vdev_sync_op_stop(vdev_sync);
11683
11684 return errno;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011685}
11686
11687#undef QCA_ATTR_NUD_STATS_SET_INVALID
11688#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
11689#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
11690#undef QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
11691#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
11692#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
11693#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
11694#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
11695#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
11696#undef QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
11697#undef QCA_ATTR_NUD_STATS_GET_MAX
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053011698
Jeff Johnsond0b6c7e2018-07-04 14:53:06 -070011699void hdd_bt_activity_cb(hdd_handle_t hdd_handle, uint32_t bt_activity)
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053011700{
Jeff Johnsond0b6c7e2018-07-04 14:53:06 -070011701 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053011702 int status;
11703
11704 status = wlan_hdd_validate_context(hdd_ctx);
11705 if (0 != status)
11706 return;
11707
11708 if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_ADD)
11709 hdd_ctx->bt_a2dp_active = 1;
11710 else if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_REMOVE)
11711 hdd_ctx->bt_a2dp_active = 0;
11712 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_ADD)
11713 hdd_ctx->bt_vo_active = 1;
11714 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_REMOVE)
11715 hdd_ctx->bt_vo_active = 0;
11716 else
11717 return;
11718
Dustin Brown76cd2932018-09-11 16:03:05 -070011719 ucfg_scan_set_bt_activity(hdd_ctx->psoc, hdd_ctx->bt_a2dp_active);
Srinivas Girigowda6598eea2017-07-06 19:26:19 -070011720 hdd_debug("a2dp_active: %d vo_active: %d", hdd_ctx->bt_a2dp_active,
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053011721 hdd_ctx->bt_vo_active);
11722}
11723
lifengd217d192017-05-09 19:44:16 +080011724struct chain_rssi_priv {
11725 struct chain_rssi_result chain_rssi;
11726};
11727
11728/**
11729 * hdd_get_chain_rssi_cb() - Callback function to get chain rssi
11730 * @context: opaque context originally passed to SME. HDD always passes
11731 * a cookie for the request context
11732 * @data: struct for get chain rssi
11733 *
11734 * This function receives the response/data from the lower layer and
11735 * checks to see if the thread is still waiting then post the results to
11736 * upper layer, if the request has timed out then ignore.
11737 *
11738 * Return: None
11739 */
11740static void hdd_get_chain_rssi_cb(void *context,
11741 struct chain_rssi_result *data)
11742{
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011743 struct osif_request *request;
lifengd217d192017-05-09 19:44:16 +080011744 struct chain_rssi_priv *priv;
11745
Dustin Brown491d54b2018-03-14 12:39:11 -070011746 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080011747
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011748 request = osif_request_get(context);
lifengd217d192017-05-09 19:44:16 +080011749 if (!request) {
11750 hdd_err("Obsolete request");
11751 return;
11752 }
11753
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011754 priv = osif_request_priv(request);
lifengd217d192017-05-09 19:44:16 +080011755 priv->chain_rssi = *data;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011756 osif_request_complete(request);
11757 osif_request_put(request);
lifengd217d192017-05-09 19:44:16 +080011758}
11759
11760/**
11761 * hdd_post_get_chain_rssi_rsp - send rsp to user space
11762 * @hdd_ctx: pointer to hdd context
11763 * @result: chain rssi result
11764 *
11765 * Return: 0 for success, non-zero for failure
11766 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011767static int hdd_post_get_chain_rssi_rsp(struct hdd_context *hdd_ctx,
lifengd217d192017-05-09 19:44:16 +080011768 struct chain_rssi_result *result)
11769{
11770 struct sk_buff *skb;
lifengd217d192017-05-09 19:44:16 +080011771
11772 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
lifengfe6c3e22018-04-03 12:10:04 +080011773 (sizeof(result->chain_rssi) + NLA_HDRLEN) +
stonez396a9732019-01-16 12:29:16 +080011774 (sizeof(result->chain_evm) + NLA_HDRLEN) +
lifengfe6c3e22018-04-03 12:10:04 +080011775 (sizeof(result->ant_id) + NLA_HDRLEN) +
11776 NLMSG_HDRLEN);
lifengd217d192017-05-09 19:44:16 +080011777
11778 if (!skb) {
11779 hdd_err("cfg80211_vendor_event_alloc failed");
11780 return -ENOMEM;
11781 }
11782
lifengfe6c3e22018-04-03 12:10:04 +080011783 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI,
stonez396a9732019-01-16 12:29:16 +080011784 sizeof(result->chain_rssi),
11785 result->chain_rssi)) {
11786 hdd_err("put fail");
11787 goto nla_put_failure;
11788 }
11789
11790 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_EVM,
11791 sizeof(result->chain_evm),
11792 result->chain_evm)) {
lifengd217d192017-05-09 19:44:16 +080011793 hdd_err("put fail");
11794 goto nla_put_failure;
11795 }
11796
lifengfe6c3e22018-04-03 12:10:04 +080011797 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO,
stonez396a9732019-01-16 12:29:16 +080011798 sizeof(result->ant_id),
11799 result->ant_id)) {
lifengfe6c3e22018-04-03 12:10:04 +080011800 hdd_err("put fail");
11801 goto nla_put_failure;
11802 }
11803
lifengd217d192017-05-09 19:44:16 +080011804 cfg80211_vendor_cmd_reply(skb);
11805 return 0;
11806
11807nla_put_failure:
11808 kfree_skb(skb);
11809 return -EINVAL;
11810}
11811
11812/**
11813 * __wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
11814 * @wiphy: wiphy pointer
11815 * @wdev: pointer to struct wireless_dev
11816 * @data: pointer to incoming NL vendor data
11817 * @data_len: length of @data
11818 *
11819 * Return: 0 on success; error number otherwise.
11820 */
11821static int __wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
11822 struct wireless_dev *wdev,
11823 const void *data,
11824 int data_len)
11825{
Jeff Johnsone5006672017-08-29 14:39:02 -070011826 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011827 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011828 mac_handle_t mac_handle;
lifengd217d192017-05-09 19:44:16 +080011829 struct get_chain_rssi_req_params req_msg;
11830 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
11831 QDF_STATUS status;
11832 int retval;
11833 void *cookie;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011834 struct osif_request *request;
lifengd217d192017-05-09 19:44:16 +080011835 struct chain_rssi_priv *priv;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011836 static const struct osif_request_params params = {
lifengd217d192017-05-09 19:44:16 +080011837 .priv_size = sizeof(*priv),
11838 .timeout_ms = WLAN_WAIT_TIME_STATS,
11839 };
11840
Dustin Brown491d54b2018-03-14 12:39:11 -070011841 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080011842
11843 retval = wlan_hdd_validate_context(hdd_ctx);
11844 if (0 != retval)
11845 return retval;
11846
Dustin Brown4ea21db2018-01-05 14:13:17 -080011847 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
11848 data, data_len, NULL)) {
lifengd217d192017-05-09 19:44:16 +080011849 hdd_err("Invalid ATTR");
11850 return -EINVAL;
11851 }
11852
11853 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
11854 hdd_err("attr mac addr failed");
11855 return -EINVAL;
11856 }
11857 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) !=
11858 QDF_MAC_ADDR_SIZE) {
11859 hdd_err("incorrect mac size");
11860 return -EINVAL;
11861 }
11862 memcpy(&req_msg.peer_macaddr,
11863 nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
11864 QDF_MAC_ADDR_SIZE);
Jeff Johnsoncf07c312019-02-04 13:53:29 -080011865 req_msg.session_id = adapter->vdev_id;
lifengd217d192017-05-09 19:44:16 +080011866
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011867 request = osif_request_alloc(&params);
lifengd217d192017-05-09 19:44:16 +080011868 if (!request) {
11869 hdd_err("Request allocation failure");
11870 return -ENOMEM;
11871 }
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011872 cookie = osif_request_cookie(request);
lifengd217d192017-05-09 19:44:16 +080011873
Jeff Johnson34fc63a2018-06-14 10:10:02 -070011874 mac_handle = hdd_ctx->mac_handle;
11875 status = sme_get_chain_rssi(mac_handle,
11876 &req_msg,
11877 hdd_get_chain_rssi_cb,
11878 cookie);
lifengd217d192017-05-09 19:44:16 +080011879 if (QDF_STATUS_SUCCESS != status) {
11880 hdd_err("Unable to get chain rssi");
11881 retval = qdf_status_to_os_return(status);
11882 } else {
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011883 retval = osif_request_wait_for_response(request);
lifengd217d192017-05-09 19:44:16 +080011884 if (retval) {
11885 hdd_err("Target response timed out");
11886 } else {
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011887 priv = osif_request_priv(request);
lifengd217d192017-05-09 19:44:16 +080011888 retval = hdd_post_get_chain_rssi_rsp(hdd_ctx,
11889 &priv->chain_rssi);
11890 if (retval)
11891 hdd_err("Failed to post chain rssi");
11892 }
11893 }
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070011894 osif_request_put(request);
lifengd217d192017-05-09 19:44:16 +080011895
Dustin Browne74003f2018-03-14 12:51:58 -070011896 hdd_exit();
lifengd217d192017-05-09 19:44:16 +080011897 return retval;
11898}
11899
11900/**
11901 * wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
11902 * @wiphy: wiphy pointer
11903 * @wdev: pointer to struct wireless_dev
11904 * @data: pointer to incoming NL vendor data
11905 * @data_len: length of @data
11906 *
11907 * Return: 0 on success; error number otherwise.
11908 */
11909static int wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
11910 struct wireless_dev *wdev,
11911 const void *data,
11912 int data_len)
11913{
Dustin Browna09acf42018-11-08 12:32:26 +053011914 int errno;
11915 struct osif_vdev_sync *vdev_sync;
11916
11917 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
11918 if (errno)
11919 return errno;
lifengd217d192017-05-09 19:44:16 +080011920
Dustin Browna09acf42018-11-08 12:32:26 +053011921 errno = __wlan_hdd_cfg80211_get_chain_rssi(wiphy, wdev, data, data_len);
lifengd217d192017-05-09 19:44:16 +080011922
Dustin Browna09acf42018-11-08 12:32:26 +053011923 osif_vdev_sync_op_stop(vdev_sync);
11924
11925 return errno;
lifengd217d192017-05-09 19:44:16 +080011926}
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053011927
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053011928/**
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053011929 * wlan_hdd_fill_intf_info() - Fill skb buffer with interface info
11930 * @skb: Pointer to skb
11931 * @info: mac mode info
11932 * @index: attribute type index for nla_nest_start()
11933 *
11934 * Return : 0 on success and errno on failure
11935 */
11936static int wlan_hdd_fill_intf_info(struct sk_buff *skb,
11937 struct connection_info *info, int index)
11938{
11939 struct nlattr *attr;
11940 uint32_t freq;
11941 struct hdd_context *hdd_ctx;
11942 struct hdd_adapter *hdd_adapter;
11943
11944 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11945 if (!hdd_ctx)
11946 goto error;
11947
11948 hdd_adapter = hdd_get_adapter_by_vdev(hdd_ctx, info->vdev_id);
11949 if (!hdd_adapter)
11950 goto error;
11951
11952 attr = nla_nest_start(skb, index);
11953 if (!attr)
11954 goto error;
11955
11956 freq = sme_chn_to_freq(info->channel);
11957
11958 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX,
11959 hdd_adapter->dev->ifindex) ||
11960 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ, freq))
11961 goto error;
11962
11963 nla_nest_end(skb, attr);
11964
11965 return 0;
11966error:
11967 hdd_err("Fill buffer with interface info failed");
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053011968 return -EINVAL;
11969}
11970
11971/**
11972 * wlan_hdd_fill_mac_info() - Fill skb buffer with mac info
11973 * @skb: Pointer to skb
11974 * @info: mac mode info
11975 * @mac_id: MAC id
11976 * @conn_count: number of current connections
11977 *
11978 * Return : 0 on success and errno on failure
11979 */
11980static int wlan_hdd_fill_mac_info(struct sk_buff *skb,
11981 struct connection_info *info, uint32_t mac_id,
11982 uint32_t conn_count)
11983{
11984 struct nlattr *attr, *intf_attr;
11985 uint32_t band = 0, i = 0, j = 0;
11986 bool present = false;
11987
11988 while (i < conn_count) {
11989 if (info[i].mac_id == mac_id) {
11990 present = true;
11991 if (info[i].channel <= SIR_11B_CHANNEL_END)
11992 band |= 1 << NL80211_BAND_2GHZ;
11993 else if (info[i].channel <= SIR_11A_CHANNEL_END)
11994 band |= 1 << NL80211_BAND_5GHZ;
11995 }
11996 i++;
11997 }
11998
11999 if (!present)
12000 return 0;
12001
12002 i = 0;
12003 attr = nla_nest_start(skb, mac_id);
12004 if (!attr)
12005 goto error;
12006
12007 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID, mac_id) ||
12008 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND, band))
12009 goto error;
12010
12011 intf_attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO);
12012 if (!intf_attr)
12013 goto error;
12014
12015 while (i < conn_count) {
12016 if (info[i].mac_id == mac_id) {
12017 if (wlan_hdd_fill_intf_info(skb, &info[i], j))
12018 return -EINVAL;
12019 j++;
12020 }
12021 i++;
12022 }
12023
12024 nla_nest_end(skb, intf_attr);
12025
12026 nla_nest_end(skb, attr);
12027
12028 return 0;
12029error:
12030 hdd_err("Fill buffer with mac info failed");
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053012031 return -EINVAL;
12032}
12033
12034
12035int wlan_hdd_send_mode_change_event(void)
12036{
12037 int err;
12038 struct hdd_context *hdd_ctx;
12039 struct sk_buff *skb;
12040 struct nlattr *attr;
12041 struct connection_info info[MAX_NUMBER_OF_CONC_CONNECTIONS];
12042 uint32_t conn_count, mac_id;
12043
Dustin Brown491d54b2018-03-14 12:39:11 -070012044 hdd_enter();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053012045 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12046 if (!hdd_ctx) {
12047 hdd_err("HDD context is NULL");
12048 return -EINVAL;
12049 }
12050
12051 err = wlan_hdd_validate_context(hdd_ctx);
12052 if (0 != err)
12053 return err;
12054
Dustin Brown76cd2932018-09-11 16:03:05 -070012055 conn_count = policy_mgr_get_connection_info(hdd_ctx->psoc, info);
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053012056 if (!conn_count)
12057 return -EINVAL;
12058
12059 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
12060 (sizeof(uint32_t) * 4) *
12061 MAX_NUMBER_OF_CONC_CONNECTIONS + NLMSG_HDRLEN,
12062 QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX,
12063 GFP_KERNEL);
12064 if (!skb) {
12065 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
12066 return -ENOMEM;
12067 }
12068
12069 attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO);
12070 if (!attr) {
12071 hdd_err("nla_nest_start failed");
12072 kfree_skb(skb);
12073 return -EINVAL;
12074 }
12075
12076 for (mac_id = 0; mac_id < MAX_MAC; mac_id++) {
Lin Baifac77972018-07-05 19:51:49 +080012077 if (wlan_hdd_fill_mac_info(skb, info, mac_id, conn_count)) {
12078 kfree_skb(skb);
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053012079 return -EINVAL;
Lin Baifac77972018-07-05 19:51:49 +080012080 }
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053012081 }
12082
12083 nla_nest_end(skb, attr);
12084
12085 cfg80211_vendor_event(skb, GFP_KERNEL);
Dustin Browne74003f2018-03-14 12:51:58 -070012086 hdd_exit();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053012087
12088 return err;
12089}
12090
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012091const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
12092 {
12093 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12094 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
12095 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +053012096 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012097 .doit = is_driver_dfs_capable
12098 },
12099
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012100#ifdef WLAN_FEATURE_STATS_EXT
12101 {
12102 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12103 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
12104 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12105 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
12106 .doit = wlan_hdd_cfg80211_stats_ext_request
12107 },
12108#endif
12109#ifdef FEATURE_WLAN_EXTSCAN
12110 {
12111 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12112 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
12113 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12114 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
12115 .doit = wlan_hdd_cfg80211_extscan_start
12116 },
12117 {
12118 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12119 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
12120 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12121 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
12122 .doit = wlan_hdd_cfg80211_extscan_stop
12123 },
12124 {
12125 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12126 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
Manjeet Singh3abd7302017-01-11 16:07:42 +053012127 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12128 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012129 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
12130 },
12131 {
12132 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12133 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
12134 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12135 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
12136 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
12137 },
12138 {
12139 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12140 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
12141 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12142 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
12143 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
12144 },
12145 {
12146 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12147 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
12148 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12149 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
12150 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
12151 },
12152 {
12153 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12154 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
12155 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12156 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
12157 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
12158 },
12159 {
12160 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12161 .info.subcmd =
12162 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
12163 .flags =
12164 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
12165 WIPHY_VENDOR_CMD_NEED_RUNNING,
12166 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
12167 },
12168 {
12169 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12170 .info.subcmd =
12171 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
12172 .flags =
12173 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
12174 WIPHY_VENDOR_CMD_NEED_RUNNING,
12175 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
12176 },
12177 {
12178 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12179 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
12180 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12181 WIPHY_VENDOR_CMD_NEED_NETDEV |
12182 WIPHY_VENDOR_CMD_NEED_RUNNING,
12183 .doit = wlan_hdd_cfg80211_set_epno_list
12184 },
12185#endif /* FEATURE_WLAN_EXTSCAN */
12186
12187#ifdef WLAN_FEATURE_LINK_LAYER_STATS
12188 {
12189 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12190 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
12191 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12192 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
12193 .doit = wlan_hdd_cfg80211_ll_stats_clear
12194 },
12195
12196 {
12197 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12198 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
12199 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12200 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
12201 .doit = wlan_hdd_cfg80211_ll_stats_set
12202 },
12203
12204 {
12205 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12206 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
12207 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12208 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
12209 .doit = wlan_hdd_cfg80211_ll_stats_get
12210 },
12211#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
12212#ifdef FEATURE_WLAN_TDLS
12213 {
12214 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12215 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
12216 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12217 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
12218 .doit = wlan_hdd_cfg80211_exttdls_enable
12219 },
12220 {
12221 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12222 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
12223 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12224 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
12225 .doit = wlan_hdd_cfg80211_exttdls_disable
12226 },
12227 {
12228 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12229 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
12230 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
12231 .doit = wlan_hdd_cfg80211_exttdls_get_status
12232 },
12233#endif
12234 {
12235 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12236 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
12237 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
12238 .doit = wlan_hdd_cfg80211_get_supported_features
12239 },
12240 {
12241 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12242 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053012243 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12244 WIPHY_VENDOR_CMD_NEED_NETDEV |
12245 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012246 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
12247 },
Qiwei Caie689a262018-07-26 15:50:22 +080012248
12249 FEATURE_CONCURRENCY_MATRIX_VENDOR_COMMANDS
12250
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012251 {
12252 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12253 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
12254 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053012255 WIPHY_VENDOR_CMD_NEED_NETDEV |
12256 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012257 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
12258 },
Manikandan Mohan80dea792016-04-28 16:36:48 -070012259 {
12260 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12261 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
12262 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053012263 WIPHY_VENDOR_CMD_NEED_NETDEV |
12264 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -070012265 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
12266 },
Qiwei Caie689a262018-07-26 15:50:22 +080012267
12268 FEATURE_STATION_INFO_VENDOR_COMMANDS
12269
Anurag Chouhan96919482016-07-13 16:36:57 +053012270 {
12271 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012272 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
12273 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12274 WIPHY_VENDOR_CMD_NEED_NETDEV |
12275 WIPHY_VENDOR_CMD_NEED_RUNNING,
12276 .doit = wlan_hdd_cfg80211_do_acs
12277 },
12278
12279 {
12280 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12281 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
12282 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12283 WIPHY_VENDOR_CMD_NEED_NETDEV,
12284 .doit = wlan_hdd_cfg80211_get_features
12285 },
12286#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12287 {
12288 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12289 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
12290 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12291 WIPHY_VENDOR_CMD_NEED_NETDEV |
12292 WIPHY_VENDOR_CMD_NEED_RUNNING,
12293 .doit = wlan_hdd_cfg80211_keymgmt_set_key
12294 },
12295#endif
12296#ifdef FEATURE_WLAN_EXTSCAN
12297 {
12298 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12299 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
12300 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12301 WIPHY_VENDOR_CMD_NEED_NETDEV |
12302 WIPHY_VENDOR_CMD_NEED_RUNNING,
12303 .doit = wlan_hdd_cfg80211_set_passpoint_list
12304 },
12305 {
12306 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12307 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
12308 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12309 WIPHY_VENDOR_CMD_NEED_NETDEV |
12310 WIPHY_VENDOR_CMD_NEED_RUNNING,
12311 .doit = wlan_hdd_cfg80211_reset_passpoint_list
12312 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012313#endif /* FEATURE_WLAN_EXTSCAN */
12314 {
12315 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12316 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
12317 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12318 WIPHY_VENDOR_CMD_NEED_NETDEV,
12319 .doit = wlan_hdd_cfg80211_get_wifi_info
12320 },
Paul Zhang3a210c52016-12-08 10:18:12 +080012321#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012322 {
12323 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12324 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
12325 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12326 WIPHY_VENDOR_CMD_NEED_NETDEV |
12327 WIPHY_VENDOR_CMD_NEED_RUNNING,
12328 .doit = wlan_hdd_cfg80211_wifi_configuration_set
12329 },
Paul Zhang3a210c52016-12-08 10:18:12 +080012330#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012331 {
12332 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -080012333 .info.subcmd =
12334 QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION,
12335 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12336 WIPHY_VENDOR_CMD_NEED_NETDEV |
12337 WIPHY_VENDOR_CMD_NEED_RUNNING,
12338 .doit = wlan_hdd_cfg80211_set_wifi_test_config
12339 },
12340
12341 {
12342 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012343 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
12344 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053012345 WIPHY_VENDOR_CMD_NEED_NETDEV |
12346 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012347 .doit = wlan_hdd_cfg80211_set_ext_roam_params
12348 },
12349 {
12350 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12351 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
12352 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053012353 WIPHY_VENDOR_CMD_NEED_NETDEV |
12354 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012355 .doit = wlan_hdd_cfg80211_wifi_logger_start
12356 },
12357 {
12358 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12359 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
12360 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053012361 WIPHY_VENDOR_CMD_NEED_NETDEV |
12362 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012363 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
12364 },
12365 {
12366 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12367 .info.subcmd =
12368 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
12369 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12370 WIPHY_VENDOR_CMD_NEED_NETDEV |
12371 WIPHY_VENDOR_CMD_NEED_RUNNING,
12372 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
12373 },
12374 {
12375 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12376 .info.subcmd =
12377 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
12378 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12379 WIPHY_VENDOR_CMD_NEED_NETDEV |
12380 WIPHY_VENDOR_CMD_NEED_RUNNING,
12381 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
12382 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070012383#ifdef WLAN_FEATURE_TSF
12384 {
12385 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12386 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
12387 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12388 WIPHY_VENDOR_CMD_NEED_NETDEV |
12389 WIPHY_VENDOR_CMD_NEED_RUNNING,
12390 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
12391 },
12392#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012393#ifdef FEATURE_WLAN_TDLS
12394 {
12395 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12396 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
12397 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12398 WIPHY_VENDOR_CMD_NEED_NETDEV |
12399 WIPHY_VENDOR_CMD_NEED_RUNNING,
12400 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
12401 },
12402#endif
12403#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
12404 {
12405 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12406 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
12407 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12408 WIPHY_VENDOR_CMD_NEED_NETDEV |
12409 WIPHY_VENDOR_CMD_NEED_RUNNING,
12410 .doit = wlan_hdd_cfg80211_offloaded_packets
12411 },
12412#endif
Qiwei Caie689a262018-07-26 15:50:22 +080012413 FEATURE_RSSI_MONITOR_VENDOR_COMMANDS
12414
Qiwei Cai1083f5b2018-07-02 19:10:11 +080012415#ifdef WLAN_NS_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012416 {
12417 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053012418 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
12419 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12420 WIPHY_VENDOR_CMD_NEED_NETDEV |
12421 WIPHY_VENDOR_CMD_NEED_RUNNING,
12422 .doit = wlan_hdd_cfg80211_set_ns_offload
12423 },
Qiwei Cai1083f5b2018-07-02 19:10:11 +080012424#endif /* WLAN_NS_OFFLOAD */
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053012425 {
12426 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012427 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
12428 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Sourav Mohapatra412ceb92018-03-07 18:41:16 +053012429 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012430 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
12431 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012432 {
12433 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12434 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
12435 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12436 WIPHY_VENDOR_CMD_NEED_NETDEV |
12437 WIPHY_VENDOR_CMD_NEED_RUNNING,
12438 .doit = wlan_hdd_cfg80211_vendor_scan
12439 },
12440
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053012441 /* Vendor abort scan */
12442 {
12443 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12444 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
12445 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12446 WIPHY_VENDOR_CMD_NEED_NETDEV |
12447 WIPHY_VENDOR_CMD_NEED_RUNNING,
12448 .doit = wlan_hdd_vendor_abort_scan
12449 },
12450
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012451 /* OCB commands */
12452 {
12453 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12454 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
12455 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12456 WIPHY_VENDOR_CMD_NEED_NETDEV |
12457 WIPHY_VENDOR_CMD_NEED_RUNNING,
12458 .doit = wlan_hdd_cfg80211_ocb_set_config
12459 },
12460 {
12461 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12462 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
12463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12464 WIPHY_VENDOR_CMD_NEED_NETDEV |
12465 WIPHY_VENDOR_CMD_NEED_RUNNING,
12466 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
12467 },
12468 {
12469 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12470 .info.subcmd =
12471 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
12472 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12473 WIPHY_VENDOR_CMD_NEED_NETDEV |
12474 WIPHY_VENDOR_CMD_NEED_RUNNING,
12475 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
12476 },
12477 {
12478 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12479 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
12480 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12481 WIPHY_VENDOR_CMD_NEED_NETDEV |
12482 WIPHY_VENDOR_CMD_NEED_RUNNING,
12483 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
12484 },
12485 {
12486 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12487 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
12488 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12489 WIPHY_VENDOR_CMD_NEED_NETDEV |
12490 WIPHY_VENDOR_CMD_NEED_RUNNING,
12491 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
12492 },
12493 {
12494 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12495 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
12496 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12497 WIPHY_VENDOR_CMD_NEED_NETDEV |
12498 WIPHY_VENDOR_CMD_NEED_RUNNING,
12499 .doit = wlan_hdd_cfg80211_dcc_get_stats
12500 },
12501 {
12502 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12503 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
12504 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12505 WIPHY_VENDOR_CMD_NEED_NETDEV |
12506 WIPHY_VENDOR_CMD_NEED_RUNNING,
12507 .doit = wlan_hdd_cfg80211_dcc_clear_stats
12508 },
12509 {
12510 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12511 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
12512 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12513 WIPHY_VENDOR_CMD_NEED_NETDEV |
12514 WIPHY_VENDOR_CMD_NEED_RUNNING,
12515 .doit = wlan_hdd_cfg80211_dcc_update_ndl
12516 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053012517 {
12518 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12519 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
12520 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12521 WIPHY_VENDOR_CMD_NEED_NETDEV |
12522 WIPHY_VENDOR_CMD_NEED_RUNNING,
12523 .doit = wlan_hdd_cfg80211_get_link_properties
12524 },
Qiwei Caie689a262018-07-26 15:50:22 +080012525
12526 FEATURE_OTA_TEST_VENDOR_COMMANDS
12527
Ravi Joshideb5a8d2015-11-09 19:11:43 -080012528#ifdef FEATURE_LFR_SUBNET_DETECTION
12529 {
12530 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12531 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
12532 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12533 WIPHY_VENDOR_CMD_NEED_NETDEV |
12534 WIPHY_VENDOR_CMD_NEED_RUNNING,
12535 .doit = wlan_hdd_cfg80211_set_gateway_params
12536 },
12537#endif /* FEATURE_LFR_SUBNET_DETECTION */
Qiwei Caie689a262018-07-26 15:50:22 +080012538
12539 FEATURE_TX_POWER_VENDOR_COMMANDS
12540
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053012541#ifdef FEATURE_WLAN_APF
Arun Khandavalli2476ef52016-04-26 20:19:43 +053012542 {
12543 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12544 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
12545 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12546 WIPHY_VENDOR_CMD_NEED_NETDEV |
12547 WIPHY_VENDOR_CMD_NEED_RUNNING,
Nachiket Kukadee547a482018-05-22 16:43:30 +053012548 .doit = wlan_hdd_cfg80211_apf_offload
Arun Khandavalli2476ef52016-04-26 20:19:43 +053012549 },
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053012550#endif /* FEATURE_WLAN_APF */
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053012551 {
12552 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053012553 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
12554 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12555 WIPHY_VENDOR_CMD_NEED_NETDEV |
12556 WIPHY_VENDOR_CMD_NEED_RUNNING,
12557 .doit = wlan_hdd_cfg80211_acs_dfs_mode
12558 },
12559 {
12560 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053012561 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
12562 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12563 WIPHY_VENDOR_CMD_NEED_NETDEV |
12564 WIPHY_VENDOR_CMD_NEED_RUNNING,
12565 .doit = wlan_hdd_cfg80211_sta_roam_policy
12566 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053012567#ifdef FEATURE_WLAN_CH_AVOID
12568 {
12569 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12570 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
12571 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12572 WIPHY_VENDOR_CMD_NEED_NETDEV |
12573 WIPHY_VENDOR_CMD_NEED_RUNNING,
12574 .doit = wlan_hdd_cfg80211_avoid_freq
12575 },
12576#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053012577 {
12578 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053012579 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
12580 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12581 WIPHY_VENDOR_CMD_NEED_NETDEV |
12582 WIPHY_VENDOR_CMD_NEED_RUNNING,
12583 .doit = wlan_hdd_cfg80211_sap_configuration_set
12584 },
Qiwei Caie689a262018-07-26 15:50:22 +080012585
12586 FEATURE_P2P_LISTEN_OFFLOAD_VENDOR_COMMANDS
12587
12588 FEATURE_SAP_COND_CHAN_SWITCH_VENDOR_COMMANDS
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053012589 {
12590 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12591 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
12592 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12593 WIPHY_VENDOR_CMD_NEED_NETDEV |
12594 WIPHY_VENDOR_CMD_NEED_RUNNING,
12595 .doit = wlan_hdd_cfg80211_get_wakelock_stats
12596 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053012597 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053012598 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12599 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
12600 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12601 WIPHY_VENDOR_CMD_NEED_NETDEV |
12602 WIPHY_VENDOR_CMD_NEED_RUNNING,
12603 .doit = wlan_hdd_cfg80211_get_bus_size
12604 },
12605 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053012606 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12607 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
12608 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12609 WIPHY_VENDOR_CMD_NEED_NETDEV |
12610 WIPHY_VENDOR_CMD_NEED_RUNNING,
12611 .doit = wlan_hdd_cfg80211_update_vendor_channel
12612 },
12613 {
bingsd09dea32017-03-17 10:08:26 +080012614 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053012615 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
12616 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12617 WIPHY_VENDOR_CMD_NEED_NETDEV |
12618 WIPHY_VENDOR_CMD_NEED_RUNNING,
12619 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012620 },
12621 {
12622 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12623 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
12624 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12625 WIPHY_VENDOR_CMD_NEED_NETDEV |
12626 WIPHY_VENDOR_CMD_NEED_RUNNING,
12627 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053012628 },
12629#ifdef WLAN_FEATURE_DISA
12630 {
12631 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12632 .info.subcmd =
12633 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
12634 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12635 WIPHY_VENDOR_CMD_NEED_NETDEV |
12636 WIPHY_VENDOR_CMD_NEED_RUNNING,
12637 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
12638 },
12639#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070012640#ifdef FEATURE_WLAN_TDLS
12641 {
12642 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12643 .info.subcmd =
12644 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
12645 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12646 WIPHY_VENDOR_CMD_NEED_NETDEV |
12647 WIPHY_VENDOR_CMD_NEED_RUNNING,
12648 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012649 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070012650#endif
Qiwei Caie689a262018-07-26 15:50:22 +080012651 FEATURE_SAR_LIMITS_VENDOR_COMMANDS
12652
Jeff Johnson8c83f132017-12-18 16:41:37 -080012653 {
12654 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012655 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
12656 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12657 WIPHY_VENDOR_CMD_NEED_RUNNING,
12658 .doit = wlan_hdd_cfg80211_set_sar_power_limits
12659 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012660 {
12661 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12662 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
12663 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12664 WIPHY_VENDOR_CMD_NEED_NETDEV |
12665 WIPHY_VENDOR_CMD_NEED_RUNNING,
12666 .doit = wlan_hdd_cfg80211_set_trace_level
12667 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080012668 {
12669 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12670 .info.subcmd =
12671 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
12672 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12673 WIPHY_VENDOR_CMD_NEED_NETDEV |
12674 WIPHY_VENDOR_CMD_NEED_RUNNING,
12675 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
12676 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012677 {
12678 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12679 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET,
12680 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12681 WIPHY_VENDOR_CMD_NEED_NETDEV |
12682 WIPHY_VENDOR_CMD_NEED_RUNNING,
12683 .doit = wlan_hdd_cfg80211_set_nud_stats
12684 },
12685 {
12686 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12687 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
12688 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12689 WIPHY_VENDOR_CMD_NEED_NETDEV |
12690 WIPHY_VENDOR_CMD_NEED_RUNNING,
12691 .doit = wlan_hdd_cfg80211_get_nud_stats
12692 },
Qiwei Caie689a262018-07-26 15:50:22 +080012693
12694 FEATURE_BSS_TRANSITION_VENDOR_COMMANDS
Sandeep Puligilla063a4342018-01-10 02:50:14 -080012695 FEATURE_SPECTRAL_SCAN_VENDOR_COMMANDS
Paul Zhang3a210c52016-12-08 10:18:12 +080012696#ifdef WLAN_UMAC_CONVERGENCE
12697 COMMON_VENDOR_COMMANDS
12698#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080012699 FEATURE_11AX_VENDOR_COMMANDS
lifengd217d192017-05-09 19:44:16 +080012700
12701 {
12702 .info.vendor_id = QCA_NL80211_VENDOR_ID,
12703 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI,
12704 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
12705 WIPHY_VENDOR_CMD_NEED_NETDEV |
12706 WIPHY_VENDOR_CMD_NEED_RUNNING,
12707 .doit = wlan_hdd_cfg80211_get_chain_rssi
12708 },
Qiwei Caie689a262018-07-26 15:50:22 +080012709
12710 FEATURE_ACTIVE_TOS_VENDOR_COMMANDS
Nachiket Kukadea6a70a92018-10-09 20:07:21 +053012711 FEATURE_NAN_VENDOR_COMMANDS
Qun Zhangef655622019-02-25 10:48:10 +080012712 FEATURE_FW_STATE_COMMANDS
Jiani Liua5f17222019-03-04 16:22:33 +080012713 FEATURE_COEX_CONFIG_COMMANDS
stonez2d686482019-03-12 14:54:26 +080012714 FEATURE_MPTA_HELPER_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012715};
12716
Dustin Brown92bd8382018-10-31 15:49:46 -070012717struct hdd_context *hdd_cfg80211_wiphy_alloc(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012718{
12719 struct wiphy *wiphy;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012720 struct hdd_context *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080012721
Dustin Brown491d54b2018-03-14 12:39:11 -070012722 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012723
Dustin Brown92bd8382018-10-31 15:49:46 -070012724 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, sizeof(*hdd_ctx));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012725 if (!wiphy) {
Dustin Brown92bd8382018-10-31 15:49:46 -070012726 hdd_err("failed to allocate wiphy!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012727 return NULL;
12728 }
12729
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080012730 hdd_ctx = wiphy_priv(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080012731 hdd_ctx->wiphy = wiphy;
12732
12733 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012734}
12735
Jeff Johnson459d2732019-03-02 10:13:25 -080012736int wlan_hdd_cfg80211_update_band(struct hdd_context *hdd_ctx,
12737 struct wiphy *wiphy,
12738 enum band_info new_band)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012739{
12740 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070012741 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012742
Dustin Brown491d54b2018-03-14 12:39:11 -070012743 hdd_enter();
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070012744
12745 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012746
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012747 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012748 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012749
12750 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
12751 struct ieee80211_supported_band *band = wiphy->bands[i];
12752
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012753 channelEnabledState = wlan_reg_get_channel_state(
Dustin Brown07901ec2018-09-07 11:02:41 -070012754 hdd_ctx->pdev,
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012755 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012756
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012757 if (HDD_NL80211_BAND_2GHZ == i &&
Jeff Johnson459d2732019-03-02 10:13:25 -080012758 BAND_5G == new_band) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012759 /* 5G only */
12760#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
12761 /* Enable Social channels for P2P */
12762 if (WLAN_HDD_IS_SOCIAL_CHANNEL
12763 (band->channels[j].center_freq)
12764 && CHANNEL_STATE_ENABLE ==
12765 channelEnabledState)
12766 band->channels[j].flags &=
12767 ~IEEE80211_CHAN_DISABLED;
12768 else
12769#endif
12770 band->channels[j].flags |=
12771 IEEE80211_CHAN_DISABLED;
12772 continue;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012773 } else if (HDD_NL80211_BAND_5GHZ == i &&
Jeff Johnson459d2732019-03-02 10:13:25 -080012774 BAND_2G == new_band) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012775 /* 2G only */
12776 band->channels[j].flags |=
12777 IEEE80211_CHAN_DISABLED;
12778 continue;
12779 }
12780
Amar Singhal6842e8f2016-02-23 16:30:32 -080012781 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012782 band->channels[j].flags &=
12783 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012784 }
12785 }
12786 return 0;
12787}
12788
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053012789#if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \
12790 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
12791static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
12792{
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +053012793 wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
12794 wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053012795}
12796#else
12797static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
12798{
12799}
12800#endif
12801
Peng Xuacfdda12017-02-06 16:15:38 -080012802#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053012803
Liangwei Dong3abfe8f2018-09-20 02:25:44 -040012804#if defined(CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME) || \
12805 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
12806/**
12807 * wlan_hdd_cfg80211_action_frame_randomization_init() - Randomize SA of MA
12808 * frames
12809 * @wiphy: Pointer to wiphy
12810 *
12811 * This function is used to indicate the support of source mac address
12812 * randomization of management action frames
12813 *
12814 * Return: None
12815 */
12816static void
12817wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
12818{
12819 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA);
12820}
12821#else
12822static void
12823wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
12824{
12825}
12826#endif
12827
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053012828#if defined(WLAN_FEATURE_FILS_SK) && \
12829 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
12830 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053012831static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
12832{
12833 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
12834}
12835#else
12836static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
12837{
12838}
12839#endif
12840
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053012841#if defined (CFG80211_SCAN_DBS_CONTROL_SUPPORT) || \
12842 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
12843static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
12844{
12845 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
12846 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
12847 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
12848}
12849#else
12850static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
12851{
12852}
12853#endif
12854
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053012855#if defined(WLAN_FEATURE_SAE) && \
12856 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053012857/**
12858 * wlan_hdd_cfg80211_set_wiphy_sae_feature() - Indicates support of SAE feature
12859 * @wiphy: Pointer to wiphy
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053012860 *
12861 * This function is used to indicate the support of SAE
12862 *
12863 * Return: None
12864 */
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080012865static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053012866{
Manikandan Mohand350c192018-11-29 14:01:12 -080012867 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Manikandan Mohand350c192018-11-29 14:01:12 -080012868
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080012869 if (ucfg_fwol_get_sae_enable(hdd_ctx->psoc))
Manikandan Mohan5dba1c72019-01-07 16:57:03 -080012870 wiphy->features |= NL80211_FEATURE_SAE;
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053012871}
12872#else
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080012873static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053012874{
12875}
12876#endif
12877
Peng Xu8e8b0392018-04-30 11:32:34 -070012878#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
12879 defined(CFG80211_DFS_OFFLOAD_BACKPORT)
12880static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
12881{
12882 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
12883}
12884#else
12885static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
12886{
12887 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
12888}
12889#endif
12890
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070012891#ifdef WLAN_FEATURE_DSRC
12892static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
12893 int *num_ch, int *ch_len)
12894{
12895 *num_ch = QDF_ARRAY_SIZE(hdd_channels_dot11p);
12896 *ch_len = sizeof(hdd_channels_dot11p);
12897}
12898
12899static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
12900{
12901 if (!ch_arr_len)
12902 return;
12903 qdf_mem_copy(ch_ptr, &hdd_channels_dot11p[0], ch_arr_len);
12904}
12905
12906static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
12907 int *num_ch, int *ch_len)
12908{
12909 *num_ch = 0;
12910 *ch_len = 0;
12911}
12912
12913static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
12914{
12915}
12916
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053012917/**
12918 * wlan_hdd_populate_srd_chan_info() - Populate SRD chan info in hdd context
12919 * @hdd_ctx: pointer to hdd context
12920 * @index: SRD channel beginning index in chan_info of @hdd_ctx
12921 *
12922 * Return: Number of SRD channels populated
12923 */
12924static uint32_t
12925wlan_hdd_populate_srd_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
12926{
12927 return 0;
12928}
12929
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070012930#else
12931
12932static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
12933 int *num_ch, int *ch_len)
12934{
12935 *num_ch = 0;
12936 *ch_len = 0;
12937}
12938
12939static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
12940{
12941}
12942
12943static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
12944 int *num_ch, int *ch_len)
12945{
12946 *num_ch = QDF_ARRAY_SIZE(hdd_etsi13_srd_ch);
12947 *ch_len = sizeof(hdd_etsi13_srd_ch);
12948}
12949
12950static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
12951{
12952 if (!ch_arr_len)
12953 return;
12954 qdf_mem_copy(ch_ptr, &hdd_etsi13_srd_ch[0], ch_arr_len);
12955}
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053012956
12957/**
12958 * wlan_hdd_populate_srd_chan_info() - Populate SRD chan info in hdd context
12959 * @hdd_ctx: pointer to hdd context
12960 * @index: SRD channel beginning index in chan_info of @hdd_ctx
12961 *
12962 * Return: Number of SRD channels populated
12963 */
12964static uint32_t
12965wlan_hdd_populate_srd_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
12966{
12967 uint32_t num_srd_ch, i;
12968 struct scan_chan_info *chan_info;
12969
12970 num_srd_ch = QDF_ARRAY_SIZE(hdd_etsi13_srd_ch);
12971 chan_info = hdd_ctx->chan_info;
12972
12973 for (i = 0; i < num_srd_ch; i++)
12974 chan_info[index + i].freq = hdd_etsi13_srd_ch[i].center_freq;
12975
12976 return num_srd_ch;
12977}
12978
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070012979#endif
12980
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012981/*
12982 * FUNCTION: wlan_hdd_cfg80211_init
12983 * This function is called by hdd_wlan_startup()
12984 * during initialization.
12985 * This function is used to initialize and register wiphy structure.
12986 */
12987int wlan_hdd_cfg80211_init(struct device *dev,
Jeff Johnson30f5bba2019-03-08 11:58:08 -080012988 struct wiphy *wiphy, struct hdd_config *config)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012989{
Jeff Johnsonb8944722017-09-03 09:03:19 -070012990 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070012991 int len_5g_ch = 0, num_ch, ch_arr_size;
12992 int num_dsrc_ch, len_dsrc_ch, num_srd_ch, len_srd_ch;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053012993 uint32_t *cipher_suites;
Krunal Sonid2c33e12018-12-06 15:02:37 -080012994 uint8_t allow_mcc_go_diff_bi = 0, enable_mcc = 0;
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +053012995 bool mac_spoofing_enabled;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012996
Dustin Brown491d54b2018-03-14 12:39:11 -070012997 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012998
12999 /* Now bind the underlying wlan device with wiphy */
13000 set_wiphy_dev(wiphy, dev);
13001
13002 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
13003
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013004 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
13005 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
13006 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
13007#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
13008 | WIPHY_FLAG_4ADDR_STATION
13009#endif
13010 | WIPHY_FLAG_OFFCHAN_TX;
13011
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013012#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
13013 wiphy->wowlan = &wowlan_support_cfg80211_init;
13014#else
13015 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
13016 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
13017 wiphy->wowlan.pattern_min_len = 1;
13018 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
13019#endif
13020
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013021#ifdef FEATURE_WLAN_TDLS
13022 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
13023 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
13024#endif
13025
13026 wiphy->features |= NL80211_FEATURE_HT_IBSS;
13027
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013028#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
13029 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
13030#endif
13031
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053013032 wlan_hdd_cfg80211_set_wiphy_scan_flags(wiphy);
13033
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080013034 wlan_hdd_cfg80211_set_wiphy_sae_feature(wiphy);
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053013035
Pragaspathi Thilagaraj24789d32018-12-10 22:28:03 +053013036 wlan_scan_cfg80211_add_connected_pno_support(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013037
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013038 wiphy->max_scan_ssids = MAX_SCAN_SSID;
13039
13040 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
13041
13042 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
13043
Arun Khandavallifae92942016-08-01 13:31:08 +053013044 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
13045 | BIT(NL80211_IFTYPE_ADHOC)
13046 | BIT(NL80211_IFTYPE_P2P_CLIENT)
13047 | BIT(NL80211_IFTYPE_P2P_GO)
13048 | BIT(NL80211_IFTYPE_AP)
13049 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013050
Krunal Sonidf29bc42018-11-15 13:26:29 -080013051 if (QDF_STATUS_SUCCESS !=
13052 ucfg_policy_mgr_get_allow_mcc_go_diff_bi(hdd_ctx->psoc,
13053 &allow_mcc_go_diff_bi))
13054 hdd_err("can't get mcc_go_diff_bi value, use default");
Krunal Sonid2c33e12018-12-06 15:02:37 -080013055 if (QDF_STATUS_SUCCESS !=
13056 ucfg_mlme_get_mcc_feature(hdd_ctx->psoc, &enable_mcc))
13057 hdd_err("can't get enable_mcc value, use default");
Jeff Johnson30f5bba2019-03-08 11:58:08 -080013058 if (config->advertiseConcurrentOperation) {
Krunal Sonid2c33e12018-12-06 15:02:37 -080013059 if (enable_mcc) {
Arun Khandavallifae92942016-08-01 13:31:08 +053013060 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013061
Arun Khandavallifae92942016-08-01 13:31:08 +053013062 for (i = 0;
13063 i < ARRAY_SIZE(wlan_hdd_iface_combination);
13064 i++) {
Krunal Sonidf29bc42018-11-15 13:26:29 -080013065 if (!allow_mcc_go_diff_bi)
Arun Khandavallifae92942016-08-01 13:31:08 +053013066 wlan_hdd_iface_combination[i].
13067 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013068 }
13069 }
13070 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053013071 ARRAY_SIZE(wlan_hdd_iface_combination);
13072 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013073 }
13074
Abhishek Singhf512bf32016-05-04 16:47:46 +053013075 /*
13076 * In case of static linked driver at the time of driver unload,
13077 * module exit doesn't happens. Module cleanup helps in cleaning
13078 * of static memory.
13079 * If driver load happens statically, at the time of driver unload,
13080 * wiphy flags don't get reset because of static memory.
13081 * It's better not to store channel in static memory.
13082 */
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070013083 wiphy->bands[HDD_NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
13084 wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053013085 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Min Liu74a1a502018-10-10 19:59:07 +080013086 if (!wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels)
Abhishek Singhf512bf32016-05-04 16:47:46 +053013087 return -ENOMEM;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070013088 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053013089 &hdd_channels_2_4_ghz[0],
13090 sizeof(hdd_channels_2_4_ghz));
Jeff Johnsonb8944722017-09-03 09:03:19 -070013091 if ((hdd_is_5g_supported(hdd_ctx)) &&
Jeff Johnson30f5bba2019-03-08 11:58:08 -080013092 ((eHDD_DOT11_MODE_11b != config->dot11Mode) &&
13093 (eHDD_DOT11_MODE_11g != config->dot11Mode) &&
13094 (eHDD_DOT11_MODE_11b_ONLY != config->dot11Mode) &&
13095 (eHDD_DOT11_MODE_11g_ONLY != config->dot11Mode))) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070013096 wiphy->bands[HDD_NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Jeff Johnson30f5bba2019-03-08 11:58:08 -080013097 wlan_hdd_get_num_dsrc_ch_and_len(config, &num_dsrc_ch,
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070013098 &len_dsrc_ch);
Jeff Johnson30f5bba2019-03-08 11:58:08 -080013099 wlan_hdd_get_num_srd_ch_and_len(config, &num_srd_ch,
13100 &len_srd_ch);
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070013101 num_ch = QDF_ARRAY_SIZE(hdd_channels_5_ghz) + num_dsrc_ch +
13102 num_srd_ch;
13103 len_5g_ch = sizeof(hdd_channels_5_ghz);
13104 ch_arr_size = len_5g_ch + len_dsrc_ch + len_srd_ch;
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053013105
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070013106 wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels =
13107 qdf_mem_malloc(ch_arr_size);
13108 if (!wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels)
13109 goto mem_fail;
13110 wiphy->bands[HDD_NL80211_BAND_5GHZ]->n_channels = num_ch;
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053013111
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070013112 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels,
13113 &hdd_channels_5_ghz[0], len_5g_ch);
13114 if (num_dsrc_ch)
13115 wlan_hdd_copy_dsrc_ch((char *)wiphy->bands[
13116 HDD_NL80211_BAND_5GHZ]->channels +
13117 len_5g_ch, len_dsrc_ch);
13118 if (num_srd_ch)
13119 wlan_hdd_copy_srd_ch((char *)wiphy->bands[
13120 HDD_NL80211_BAND_5GHZ]->channels +
13121 len_5g_ch, len_srd_ch);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013122 }
13123
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013124 /*Initialise the supported cipher suite details */
Manikandan Mohan66df7fc2019-01-08 17:57:05 -080013125 if (ucfg_fwol_get_gcmp_enable(hdd_ctx->psoc)) {
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053013126 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites) +
13127 sizeof(hdd_gcmp_cipher_suits));
Min Liu74a1a502018-10-10 19:59:07 +080013128 if (!cipher_suites)
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053013129 return -ENOMEM;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053013130 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites) +
13131 QDF_ARRAY_SIZE(hdd_gcmp_cipher_suits);
13132 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
13133 sizeof(hdd_cipher_suites));
13134 qdf_mem_copy(cipher_suites + QDF_ARRAY_SIZE(hdd_cipher_suites),
13135 &hdd_gcmp_cipher_suits,
13136 sizeof(hdd_gcmp_cipher_suits));
13137 } else {
13138 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites));
Min Liu74a1a502018-10-10 19:59:07 +080013139 if (!cipher_suites)
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053013140 return -ENOMEM;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053013141 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites);
13142 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
13143 sizeof(hdd_cipher_suites));
13144 }
13145 wiphy->cipher_suites = cipher_suites;
13146 cipher_suites = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013147 /*signal strength in mBm (100*dBm) */
13148 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
13149 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
13150
Anurag Chouhan6d760662016-02-20 16:05:43 +053013151 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013152 wiphy->n_vendor_commands =
13153 ARRAY_SIZE(hdd_wiphy_vendor_commands);
13154 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
13155
13156 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
13157 wiphy->n_vendor_events =
13158 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
13159 }
13160
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013161#ifdef QCA_HT_2040_COEX
13162 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
13163#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053013164 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080013165
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053013166#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) || \
wadesonga75734c2017-02-07 16:03:25 +080013167 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
13168 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
13169 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
13170 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
13171#endif
13172
Abhishek Singh1bdb1572015-10-16 16:24:19 +053013173 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080013174 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Pragaspathi Thilagarajf37f3932019-01-11 00:25:43 +053013175 mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
13176 if (mac_spoofing_enabled)
Kiran Kumar Lokered547fdd2017-09-13 17:20:55 -070013177 wlan_hdd_cfg80211_scan_randomization_init(wiphy);
Liangwei Dong3abfe8f2018-09-20 02:25:44 -040013178 wlan_hdd_cfg80211_action_frame_randomization_init(wiphy);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053013179
Dustin Browne74003f2018-03-14 12:51:58 -070013180 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013181 return 0;
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053013182
13183mem_fail:
13184 hdd_err("Not enough memory to allocate channels");
13185 if (wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels != NULL) {
13186 qdf_mem_free(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels);
13187 wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels = NULL;
13188 }
13189 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013190}
13191
Abhishek Singhf512bf32016-05-04 16:47:46 +053013192/**
Yingying Tang80e15f32016-09-27 18:23:01 +080013193 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
13194 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053013195 *
13196 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053013197 * memory allocated in wlan_hdd_cfg80211_init also
13198 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053013199 *
13200 * Return: void
13201 */
13202void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
13203{
13204 int i;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053013205 const uint32_t *cipher_suites;
Abhishek Singhf512bf32016-05-04 16:47:46 +053013206
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070013207 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053013208 if (NULL != wiphy->bands[i] &&
13209 (NULL != wiphy->bands[i]->channels)) {
13210 qdf_mem_free(wiphy->bands[i]->channels);
13211 wiphy->bands[i]->channels = NULL;
13212 }
13213 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080013214
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053013215 cipher_suites = wiphy->cipher_suites;
13216 wiphy->cipher_suites = NULL;
13217 wiphy->n_cipher_suites = 0;
13218 qdf_mem_free((uint32_t *)cipher_suites);
13219 cipher_suites = NULL;
Abhishek Singh3e6172f2016-05-04 16:56:48 +053013220 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053013221}
13222
Yingying Tang80e15f32016-09-27 18:23:01 +080013223/**
13224 * wlan_hdd_update_band_cap() - update capabilities for supported bands
13225 * @hdd_ctx: HDD context
13226 *
13227 * this function will update capabilities for supported bands
13228 *
13229 * Return: void
13230 */
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053013231static void wlan_hdd_update_ht_cap(struct hdd_context *hdd_ctx)
Yingying Tang80e15f32016-09-27 18:23:01 +080013232{
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053013233 struct mlme_ht_capabilities_info ht_cap_info = {0};
Yingying Tang80e15f32016-09-27 18:23:01 +080013234 QDF_STATUS status;
Wu Gaoed616a12019-01-16 15:19:21 +080013235 uint32_t channel_bonding_mode;
Yingying Tang80e15f32016-09-27 18:23:01 +080013236
Dustin Brown76cd2932018-09-11 16:03:05 -070013237 status = ucfg_mlme_get_ht_cap_info(hdd_ctx->psoc, &ht_cap_info);
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053013238 if (QDF_STATUS_SUCCESS != status)
Yingying Tang80e15f32016-09-27 18:23:01 +080013239 hdd_err("could not get HT capability info");
Yingying Tang80e15f32016-09-27 18:23:01 +080013240
Vignesh Viswanathan78182502018-08-06 15:13:30 +053013241 if (ht_cap_info.tx_stbc) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070013242 if (NULL != hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ])
13243 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ]->ht_cap.cap |=
Yingying Tang80e15f32016-09-27 18:23:01 +080013244 IEEE80211_HT_CAP_TX_STBC;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070013245 if (NULL != hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ])
13246 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]->ht_cap.cap |=
Yingying Tang80e15f32016-09-27 18:23:01 +080013247 IEEE80211_HT_CAP_TX_STBC;
13248 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080013249
13250 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070013251 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ]->
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080013252 vht_cap.vht_supported = 0;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070013253 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ]->vht_cap.cap = 0;
13254 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]->
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080013255 vht_cap.vht_supported = 0;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070013256 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]->vht_cap.cap = 0;
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080013257 }
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053013258
Vignesh Viswanathan78182502018-08-06 15:13:30 +053013259 if (!ht_cap_info.short_gi_20_mhz) {
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053013260 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
13261 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
13262 }
13263
Vignesh Viswanathan78182502018-08-06 15:13:30 +053013264 if (!ht_cap_info.short_gi_40_mhz)
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053013265 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
Wu Gaoed616a12019-01-16 15:19:21 +080013266
13267 ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc, &channel_bonding_mode);
13268 if (!channel_bonding_mode)
13269 wlan_hdd_band_5_ghz.ht_cap.cap &=
13270 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
Yingying Tang80e15f32016-09-27 18:23:01 +080013271}
13272
Vignesh Viswanathanf97cc112018-10-03 19:17:07 +053013273/**
13274 * wlan_hdd_update_band_cap_in_wiphy() - update channel flags based on band cap
13275 * @hdd_ctx: HDD context
13276 *
13277 * This function updates the channel flags based on the band capability set
13278 * in the MLME CFG
13279 *
13280 * Return: void
13281 */
13282static void wlan_hdd_update_band_cap_in_wiphy(struct hdd_context *hdd_ctx)
13283{
13284 int i, j;
13285 uint8_t band_capability;
13286 QDF_STATUS status;
13287 struct ieee80211_supported_band *band;
13288
13289 status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
13290 if (QDF_IS_STATUS_ERROR(status)) {
13291 hdd_err("Failed to get MLME Band Capability");
13292 return;
13293 }
13294
13295 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
13296 if (NULL == hdd_ctx->wiphy->bands[i])
13297 continue;
13298
13299 for (j = 0; j < hdd_ctx->wiphy->bands[i]->n_channels; j++) {
13300 band = hdd_ctx->wiphy->bands[i];
13301
13302 if (HDD_NL80211_BAND_2GHZ == i &&
13303 BAND_5G == band_capability) {
13304 /* 5G only */
13305#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
13306 /* Enable social channels for P2P */
13307 if (WLAN_HDD_IS_SOCIAL_CHANNEL
13308 (band->channels[j].center_freq))
13309 band->channels[j].flags &=
13310 ~IEEE80211_CHAN_DISABLED;
13311 else
13312#endif
13313 band->channels[j].flags |=
13314 IEEE80211_CHAN_DISABLED;
13315 continue;
13316 } else if (HDD_NL80211_BAND_5GHZ == i &&
13317 BAND_2G == band_capability) {
13318 /* 2G only */
13319 band->channels[j].flags |=
13320 IEEE80211_CHAN_DISABLED;
13321 continue;
13322 }
13323 }
13324 }
13325}
13326
Wu Gao1ab05582018-11-08 16:22:49 +080013327#ifdef FEATURE_WLAN_ESE
13328/**
13329 * wlan_hdd_update_lfr_wiphy() - update LFR flag based on configures
13330 * @hdd_ctx: HDD context
13331 *
13332 * This function updates the LFR flag based on LFR configures
13333 *
13334 * Return: void
13335 */
13336static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
13337{
13338 bool fast_transition_enabled;
13339 bool lfr_enabled;
13340 bool ese_enabled;
13341
13342 ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
13343 &fast_transition_enabled);
13344 ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
13345 ucfg_mlme_is_ese_enabled(hdd_ctx->psoc, &ese_enabled);
13346 if (fast_transition_enabled || lfr_enabled || ese_enabled)
13347 hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
13348}
13349#else
13350static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
13351{
13352 bool fast_transition_enabled;
13353 bool lfr_enabled;
13354
13355 ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
13356 &fast_transition_enabled);
13357 ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
13358 if (fast_transition_enabled || lfr_enabled)
13359 hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
13360}
13361#endif
13362
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013363/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013364 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013365 * initialization. In wlan_hdd_cfg80211_init, only the
13366 * default values will be initialized. The final initialization
13367 * of all required members can be done here.
13368 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013369void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013370{
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053013371 int value;
Karthik Kantamneni2231a232018-09-11 15:45:55 +053013372 bool fils_enabled;
Arif Hussain88d1fdd2018-09-26 16:12:24 -070013373 bool dfs_master_capable = true;
Karthik Kantamneni2231a232018-09-11 15:45:55 +053013374 QDF_STATUS status;
Yingying Tang80e15f32016-09-27 18:23:01 +080013375
Dustin Brown05d81302018-09-11 16:49:22 -070013376 ucfg_mlme_get_sap_max_peers(hdd_ctx->psoc, &value);
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053013377 hdd_ctx->wiphy->max_ap_assoc_sta = value;
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053013378 wlan_hdd_update_ht_cap(hdd_ctx);
Vignesh Viswanathanf97cc112018-10-03 19:17:07 +053013379 wlan_hdd_update_band_cap_in_wiphy(hdd_ctx);
Wu Gao1ab05582018-11-08 16:22:49 +080013380 wlan_hdd_update_lfr_wiphy(hdd_ctx);
Karthik Kantamneni2231a232018-09-11 15:45:55 +053013381
13382 fils_enabled = 0;
Dustin Brown05d81302018-09-11 16:49:22 -070013383 status = ucfg_mlme_get_fils_enabled_info(hdd_ctx->psoc,
Karthik Kantamneni2231a232018-09-11 15:45:55 +053013384 &fils_enabled);
13385 if (QDF_IS_STATUS_ERROR(status))
13386 hdd_err("could not get fils enabled info");
13387 if (fils_enabled)
13388 wlan_hdd_cfg80211_set_wiphy_fils_feature(hdd_ctx->wiphy);
Arif Hussain88d1fdd2018-09-26 16:12:24 -070013389
13390 status = ucfg_mlme_get_dfs_master_capability(hdd_ctx->psoc,
13391 &dfs_master_capable);
13392 if (QDF_IS_STATUS_SUCCESS(status) && dfs_master_capable)
13393 wlan_hdd_cfg80211_set_dfs_offload_feature(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013394}
13395
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080013396/**
13397 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
13398 * @cfg: hdd cfg
13399 *
13400 * this function update 11n mode in hdd cfg
13401 *
13402 * Return: void
13403 */
Sandeep Puligilla34618782019-01-04 17:42:42 -080013404void wlan_hdd_update_11n_mode(struct hdd_context *hdd_ctx)
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080013405{
Sandeep Puligilla34618782019-01-04 17:42:42 -080013406 struct hdd_config *cfg = hdd_ctx->config;
13407
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080013408 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013409 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080013410 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013411 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080013412 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
13413 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
13414 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
Sandeep Puligilla34618782019-01-04 17:42:42 -080013415 ucfg_mlme_set_sap_11ac_override(hdd_ctx->psoc, 0);
13416 ucfg_mlme_set_go_11ac_override(hdd_ctx->psoc, 0);
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080013417 }
13418 }
13419}
13420
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013421/* In this function we are registering wiphy. */
13422int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
13423{
Dustin Brown491d54b2018-03-14 12:39:11 -070013424 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013425 /* Register our wiphy dev with cfg80211 */
13426 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070013427 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013428 return -EIO;
13429 }
13430
Dustin Browne74003f2018-03-14 12:51:58 -070013431 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013432 return 0;
13433}
13434
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013435/* This function registers for all frame which supplicant is interested in */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013436int wlan_hdd_cfg80211_register_frames(struct hdd_adapter *adapter)
Wu Gao84d120c2017-03-24 18:46:00 +080013437{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013438 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
Wu Gao84d120c2017-03-24 18:46:00 +080013439 /* Register for all P2P action, public action etc frames */
13440 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013441 QDF_STATUS status;
Wu Gao84d120c2017-03-24 18:46:00 +080013442
Dustin Brown491d54b2018-03-14 12:39:11 -070013443 hdd_enter();
Sourav Mohapatraa0943922018-11-21 21:26:29 +053013444 if (adapter->device_mode == QDF_FTM_MODE) {
13445 hdd_info("No need to register frames in FTM mode");
13446 return 0;
13447 }
Wu Gao84d120c2017-03-24 18:46:00 +080013448
13449 /* Register frame indication call back */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013450 status = sme_register_mgmt_frame_ind_callback(mac_handle,
13451 hdd_indicate_mgmt_frame);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013452 if (status != QDF_STATUS_SUCCESS) {
13453 hdd_err("Failed to register hdd_indicate_mgmt_frame");
13454 goto ret_status;
13455 }
Wu Gao84d120c2017-03-24 18:46:00 +080013456
Wu Gao84d120c2017-03-24 18:46:00 +080013457 /* Right now we are registering these frame when driver is getting
13458 * initialized. Once we will move to 2.6.37 kernel, in which we have
13459 * frame register ops, we will move this code as a part of that
13460 */
13461
13462 /* GAS Initial Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013463 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
13464 (uint8_t *) GAS_INITIAL_REQ,
13465 GAS_INITIAL_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013466 if (status != QDF_STATUS_SUCCESS) {
13467 hdd_err("Failed to register GAS_INITIAL_REQ");
13468 goto ret_status;
13469 }
Wu Gao84d120c2017-03-24 18:46:00 +080013470
13471 /* GAS Initial Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013472 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
13473 (uint8_t *) GAS_INITIAL_RSP,
13474 GAS_INITIAL_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013475 if (status != QDF_STATUS_SUCCESS) {
13476 hdd_err("Failed to register GAS_INITIAL_RSP");
13477 goto dereg_gas_initial_req;
13478 }
Wu Gao84d120c2017-03-24 18:46:00 +080013479
13480 /* GAS Comeback Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013481 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
13482 (uint8_t *) GAS_COMEBACK_REQ,
13483 GAS_COMEBACK_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013484 if (status != QDF_STATUS_SUCCESS) {
13485 hdd_err("Failed to register GAS_COMEBACK_REQ");
13486 goto dereg_gas_initial_rsp;
13487 }
Wu Gao84d120c2017-03-24 18:46:00 +080013488
13489 /* GAS Comeback Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013490 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
13491 (uint8_t *) GAS_COMEBACK_RSP,
13492 GAS_COMEBACK_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013493 if (status != QDF_STATUS_SUCCESS) {
13494 hdd_err("Failed to register GAS_COMEBACK_RSP");
13495 goto dereg_gas_comeback_req;
13496 }
Wu Gao84d120c2017-03-24 18:46:00 +080013497
13498 /* WNM BSS Transition Request frame */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013499 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
13500 (uint8_t *) WNM_BSS_ACTION_FRAME,
13501 WNM_BSS_ACTION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013502 if (status != QDF_STATUS_SUCCESS) {
13503 hdd_err("Failed to register WNM_BSS_ACTION_FRAME");
13504 goto dereg_gas_comeback_rsp;
13505 }
Wu Gao84d120c2017-03-24 18:46:00 +080013506
13507 /* WNM-Notification */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080013508 status = sme_register_mgmt_frame(mac_handle, adapter->vdev_id, type,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013509 (uint8_t *) WNM_NOTIFICATION_FRAME,
13510 WNM_NOTIFICATION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013511 if (status != QDF_STATUS_SUCCESS) {
13512 hdd_err("Failed to register WNM_NOTIFICATION_FRAME");
13513 goto dereg_wnm_bss_action_frm;
13514 }
13515
Dustin Brown237baee2018-05-10 13:22:18 -070013516 return 0;
13517
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013518dereg_wnm_bss_action_frm:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013519 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
13520 (uint8_t *) WNM_BSS_ACTION_FRAME,
13521 WNM_BSS_ACTION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013522dereg_gas_comeback_rsp:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013523 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
13524 (uint8_t *) GAS_COMEBACK_RSP,
13525 GAS_COMEBACK_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013526dereg_gas_comeback_req:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013527 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
13528 (uint8_t *) GAS_COMEBACK_REQ,
13529 GAS_COMEBACK_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013530dereg_gas_initial_rsp:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013531 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
13532 (uint8_t *) GAS_INITIAL_RSP,
13533 GAS_INITIAL_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013534dereg_gas_initial_req:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013535 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
13536 (uint8_t *) GAS_INITIAL_REQ,
13537 GAS_INITIAL_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053013538ret_status:
13539 return qdf_status_to_os_return(status);
Wu Gao84d120c2017-03-24 18:46:00 +080013540}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013541
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013542void wlan_hdd_cfg80211_deregister_frames(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013543{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013544 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
13545 /* Deregister for all P2P action, public action etc frames */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013546 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
13547
Dustin Brown491d54b2018-03-14 12:39:11 -070013548 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013549
13550 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013551 * initialized. Once we will move to 2.6.37 kernel, in which we have
13552 * frame register ops, we will move this code as a part of that
13553 */
13554
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013555 /* GAS Initial Request */
13556
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013557 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013558 (uint8_t *) GAS_INITIAL_REQ,
13559 GAS_INITIAL_REQ_SIZE);
13560
13561 /* GAS Initial Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013562 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013563 (uint8_t *) GAS_INITIAL_RSP,
13564 GAS_INITIAL_RSP_SIZE);
13565
13566 /* GAS Comeback Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013567 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013568 (uint8_t *) GAS_COMEBACK_REQ,
13569 GAS_COMEBACK_REQ_SIZE);
13570
13571 /* GAS Comeback Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013572 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013573 (uint8_t *) GAS_COMEBACK_RSP,
13574 GAS_COMEBACK_RSP_SIZE);
13575
13576 /* P2P Public Action */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013577 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013578 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
13579 P2P_PUBLIC_ACTION_FRAME_SIZE);
13580
13581 /* P2P Action */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013582 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013583 (uint8_t *) P2P_ACTION_FRAME,
13584 P2P_ACTION_FRAME_SIZE);
13585
13586 /* WNM-Notification */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080013587 sme_deregister_mgmt_frame(mac_handle, adapter->vdev_id, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013588 (uint8_t *) WNM_NOTIFICATION_FRAME,
13589 WNM_NOTIFICATION_FRAME_SIZE);
13590}
13591
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070013592#if defined(FEATURE_WLAN_WAPI) && !defined(CRYPTO_SET_KEY_CONVERGED)
Sourav Mohapatrad21fc6b2018-06-01 11:31:14 +053013593static void wlan_hdd_cfg80211_set_key_wapi(struct hdd_adapter *adapter,
13594 uint8_t key_index,
13595 const uint8_t *mac_addr,
13596 const uint8_t *key,
13597 int key_Len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013598{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013599 tCsrRoamSetKey setKey;
13600 bool isConnected = true;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013601 QDF_STATUS status;
Jeff Johnson29c78672019-02-26 21:05:53 -080013602 uint32_t roam_id = INVALID_ROAM_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013603 uint8_t *pKeyPtr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013604 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013605
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013606 hdd_debug("Device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070013607 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013608
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013609 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013610 setKey.keyId = key_index; /* Store Key ID */
13611 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
13612 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
13613 setKey.paeRole = 0; /* the PAE role */
Srinivas Girigowda576b2352017-08-25 14:44:26 -070013614 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
Anurag Chouhanc5548422016-02-24 18:33:27 +053013615 qdf_set_macaddr_broadcast(&setKey.peerMac);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070013616 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013617 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070013618
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013619 setKey.keyLength = key_Len;
13620 pKeyPtr = setKey.Key;
13621 memcpy(pKeyPtr, key, key_Len);
13622
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013623 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013624
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013625 if (isConnected) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013626 mac_handle = hdd_adapter_get_mac_handle(adapter);
13627 status = sme_roam_set_key(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080013628 adapter->vdev_id,
Jeff Johnson29c78672019-02-26 21:05:53 -080013629 &setKey, &roam_id);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013630 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonfee20aa2017-10-30 21:33:14 -070013631 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013632 }
13633}
13634#endif /* FEATURE_WLAN_WAPI */
13635
Krunal Soni364e0872017-05-10 21:24:34 -070013636bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
13637{
Naveen Rawat08db88f2017-09-08 15:07:48 -070013638 const uint8_t *vendor_ie;
Krunal Soni364e0872017-05-10 21:24:34 -070013639
13640 if (length < 2) {
13641 hdd_debug("bss size is less than expected");
13642 return true;
13643 }
13644 if (!ies) {
13645 hdd_debug("invalid IE pointer");
13646 return true;
13647 }
Naveen Rawat08db88f2017-09-08 15:07:48 -070013648 vendor_ie = wlan_get_vendor_ie_ptr_from_oui(VENDOR1_AP_OUI_TYPE,
Krunal Soni364e0872017-05-10 21:24:34 -070013649 VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
13650 if (vendor_ie) {
13651 hdd_debug("AP can't support immediate powersave. defer it");
13652 return false;
13653 }
13654 return true;
13655}
13656
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013657/*
13658 * FUNCTION: wlan_hdd_validate_operation_channel
13659 * called by wlan_hdd_cfg80211_start_bss() and
13660 * wlan_hdd_set_channel()
13661 * This function validates whether given channel is part of valid
13662 * channel list.
13663 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013664QDF_STATUS wlan_hdd_validate_operation_channel(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013665 int channel)
13666{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013667 uint32_t num_ch = 0;
Wu Gao0821b0d2019-01-11 17:31:11 +080013668 u8 valid_ch[CFG_VALID_CHANNEL_LIST_LEN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013669 u32 indx = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013670 uint8_t fValidChannel = false, count = 0;
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053013671 QDF_STATUS status;
13672 bool value;
13673 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013674
Wu Gao0821b0d2019-01-11 17:31:11 +080013675 num_ch = CFG_VALID_CHANNEL_LIST_LEN;
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053013676 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown05d81302018-09-11 16:49:22 -070013677 status = ucfg_mlme_get_sap_allow_all_channels(hdd_ctx->psoc, &value);
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053013678 if (status != QDF_STATUS_SUCCESS)
13679 hdd_err("Unable to fetch sap allow all channels");
13680 if (value) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013681 /* Validate the channel */
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070013682 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_173; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013683 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013684 fValidChannel = true;
13685 break;
13686 }
13687 }
13688 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013689 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013690 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013691 }
13692 } else {
Wu Gaof3cbeaf2019-01-15 18:26:25 +080013693 ucfg_mlme_get_valid_channel_list(hdd_ctx->psoc, valid_ch,
13694 &num_ch);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013695 for (indx = 0; indx < num_ch; indx++) {
Srinivas Girigowda576b2352017-08-25 14:44:26 -070013696 if (channel == valid_ch[indx])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013697 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013698 }
13699
13700 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013701 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013702 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013703 }
13704 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013705 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013706
13707}
13708
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013709static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
13710 struct net_device *dev,
13711 struct bss_parameters *params)
13712{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013713 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13714 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013715 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013716 QDF_STATUS qdf_ret_status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013717 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013718
Dustin Brown491d54b2018-03-14 12:39:11 -070013719 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013720
Anurag Chouhan6d760662016-02-20 16:05:43 +053013721 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070013722 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013723 return -EINVAL;
13724 }
13725
Jeff Johnson48363022019-02-24 16:26:51 -080013726 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013727 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013728
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053013729 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
13730 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080013731 adapter->vdev_id, params->ap_isolate);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053013732
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013733 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Dustin Brown458027c2018-10-19 12:26:27 -070013734 qdf_opmode_str(adapter->device_mode),
13735 adapter->device_mode, params->ap_isolate);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013736
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013737 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070013738 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013739 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013740 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013741
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013742 if (!(adapter->device_mode == QDF_SAP_MODE ||
13743 adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013744 return -EOPNOTSUPP;
13745 }
13746
13747 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013748 * want to update this parameter
13749 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013750 if (-1 != params->ap_isolate) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070013751 adapter->session.ap.disable_intrabss_fwd =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013752 !!params->ap_isolate;
13753
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013754 mac_handle = hdd_ctx->mac_handle;
13755 qdf_ret_status = sme_ap_disable_intra_bss_fwd(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080013756 adapter->vdev_id,
Jeff Johnsonb9424862017-10-30 08:49:35 -070013757 adapter->session.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013758 ap.
Jeff Johnson82ceb082017-10-27 14:52:42 -070013759 disable_intrabss_fwd);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070013760 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013761 ret = -EINVAL;
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +053013762
Dustin Brown07901ec2018-09-07 11:02:41 -070013763 ucfg_ipa_set_ap_ibss_fwd(hdd_ctx->pdev,
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +053013764 adapter->session.ap.
13765 disable_intrabss_fwd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013766 }
13767
Dustin Browne74003f2018-03-14 12:51:58 -070013768 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013769 return ret;
13770}
13771
Krunal Soni8c37e322016-02-03 16:08:37 -080013772/**
Dustin Brown56377e12018-10-10 17:04:04 -070013773 * hdd_change_adapter_mode() - change @adapter's operating mode to @new_mode
13774 * @adapter: the adapter to change modes on
13775 * @new_mode: the new operating mode to change to
Krunal Soni8c37e322016-02-03 16:08:37 -080013776 *
Dustin Brown56377e12018-10-10 17:04:04 -070013777 * Return: Errno
Krunal Soni8c37e322016-02-03 16:08:37 -080013778 */
Dustin Brown56377e12018-10-10 17:04:04 -070013779static int hdd_change_adapter_mode(struct hdd_adapter *adapter,
13780 enum QDF_OPMODE new_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013781{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013782 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown56377e12018-10-10 17:04:04 -070013783 struct net_device *netdev = adapter->dev;
Krunal Soni8c37e322016-02-03 16:08:37 -080013784 struct hdd_config *config = hdd_ctx->config;
Jeff Johnson20227a92018-03-13 09:41:05 -070013785 struct csr_roam_profile *roam_profile;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053013786 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013787
Dustin Brown491d54b2018-03-14 12:39:11 -070013788 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013789
Krunal Soni8c37e322016-02-03 16:08:37 -080013790 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Dustin Brown56377e12018-10-10 17:04:04 -070013791 hdd_warn("Can't change interface: ACS in progress");
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070013792 return -EBUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013793 }
13794
Dustin Browndb2a8be2017-12-20 11:49:56 -080013795 hdd_stop_adapter(hdd_ctx, adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080013796 hdd_deinit_adapter(hdd_ctx, adapter, true);
Dustin Brown194aeca2018-10-12 15:37:36 -070013797 adapter->device_mode = new_mode;
Jeff Johnsonb9424862017-10-30 08:49:35 -070013798 memset(&adapter->session, 0, sizeof(adapter->session));
Dustin Brown56377e12018-10-10 17:04:04 -070013799 hdd_set_station_ops(netdev);
Jeff Johnson20227a92018-03-13 09:41:05 -070013800
13801 roam_profile = hdd_roam_profile(adapter);
13802 roam_profile->pAddIEScan = adapter->scan_info.scan_add_ie.addIEdata;
Dustin Brown56377e12018-10-10 17:04:04 -070013803 roam_profile->nAddIEScanLength = adapter->scan_info.scan_add_ie.length;
13804
13805 if (new_mode == QDF_IBSS_MODE) {
Krunal Sonib51eec72017-11-20 21:53:01 -080013806 status = hdd_start_station_adapter(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070013807 roam_profile->BSSType = eCSR_BSS_TYPE_START_IBSS;
13808 roam_profile->phyMode =
Krunal Soni8c37e322016-02-03 16:08:37 -080013809 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
13810 }
Dustin Brown56377e12018-10-10 17:04:04 -070013811
Dustin Browne74003f2018-03-14 12:51:58 -070013812 hdd_exit();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070013813
13814 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013815}
13816
13817static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
13818 struct net_device *dev,
13819 struct bss_parameters *params)
13820{
Dustin Brown1d31b082018-11-22 14:41:20 +053013821 int errno;
13822 struct osif_vdev_sync *vdev_sync;
13823
13824 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
13825 if (errno)
13826 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013827
Dustin Brown1d31b082018-11-22 14:41:20 +053013828 errno = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013829
Dustin Brown1d31b082018-11-22 14:41:20 +053013830 osif_vdev_sync_op_stop(vdev_sync);
13831
13832 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013833}
13834
Rajeev Kumar98edb772016-01-19 12:42:19 -080013835/**
Dustin Brown63fe4922018-10-12 15:02:26 -070013836 * hdd_nl_to_policy_mgr_iface_type() - map nl80211_iftype to policy_mgr_con_mode
13837 * @type: the input NL80211 interface type to map
13838 *
13839 * Return: policy_mgr_con_mode
13840 */
13841static enum policy_mgr_con_mode
13842hdd_nl_to_policy_mgr_iface_type(enum nl80211_iftype type)
13843{
13844 switch (type) {
13845 case NL80211_IFTYPE_STATION:
13846 return PM_STA_MODE;
13847 case NL80211_IFTYPE_P2P_CLIENT:
13848 return PM_P2P_CLIENT_MODE;
13849 case NL80211_IFTYPE_P2P_GO:
13850 return PM_P2P_GO_MODE;
13851 case NL80211_IFTYPE_AP:
13852 return PM_SAP_MODE;
13853 case NL80211_IFTYPE_ADHOC:
13854 return PM_IBSS_MODE;
13855 default:
13856 hdd_err("Unsupported interface type: %d", type);
13857 return PM_MAX_NUM_OF_MODE;
13858 }
13859}
13860
13861static bool hdd_is_client_mode(enum QDF_OPMODE mode)
13862{
13863 switch (mode) {
13864 case QDF_STA_MODE:
13865 case QDF_P2P_CLIENT_MODE:
13866 case QDF_P2P_DEVICE_MODE:
13867 case QDF_IBSS_MODE:
13868 return true;
13869 default:
13870 return false;
13871 }
13872}
13873
13874static bool hdd_is_ap_mode(enum QDF_OPMODE mode)
13875{
13876 switch (mode) {
13877 case QDF_SAP_MODE:
13878 case QDF_P2P_GO_MODE:
13879 return true;
13880 default:
13881 return false;
13882 }
13883}
13884
13885/**
Rajeev Kumar98edb772016-01-19 12:42:19 -080013886 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
13887 * @wiphy: Pointer to the wiphy structure
13888 * @ndev: Pointer to the net device
13889 * @type: Interface type
13890 * @flags: Flags for change interface
13891 * @params: Pointer to change interface parameters
13892 *
13893 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013894 */
13895static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
13896 struct net_device *ndev,
13897 enum nl80211_iftype type,
13898 u32 *flags,
13899 struct vif_params *params)
13900{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013901 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070013902 struct hdd_context *hdd_ctx;
Dustin Brown56377e12018-10-10 17:04:04 -070013903 bool iff_up = ndev->flags & IFF_UP;
13904 enum QDF_OPMODE new_mode;
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053013905 bool ap_random_bssid_enabled;
Dustin Brown56377e12018-10-10 17:04:04 -070013906 QDF_STATUS status;
Dustin Brown63fe4922018-10-12 15:02:26 -070013907 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013908
Dustin Brown491d54b2018-03-14 12:39:11 -070013909 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013910
Dustin Brown63fe4922018-10-12 15:02:26 -070013911 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
Jeff Johnson77848112016-06-29 14:52:06 -070013912 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013913 return -EINVAL;
13914 }
13915
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013916 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown2ab5a972018-10-09 17:19:37 -070013917 errno = wlan_hdd_validate_context(hdd_ctx);
13918 if (errno)
13919 return errno;
Nachiket Kukade08b9f292017-11-17 18:27:37 +053013920
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053013921 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
13922 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080013923 adapter->vdev_id, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013924
Dustin Brown56377e12018-10-10 17:04:04 -070013925 status = hdd_nl_to_qdf_iface_type(type, &new_mode);
13926 if (QDF_IS_STATUS_ERROR(status))
13927 return qdf_status_to_os_return(status);
13928
Dustin Brown194aeca2018-10-12 15:37:36 -070013929 /* A userspace issue leads to it sending a 'change to station mode'
13930 * request on a "p2p" device, expecting the driver do execute a 'change
13931 * to p2p-device mode' request instead. The (unfortunate) work around
13932 * here is implemented by overriding the new mode if the net_device name
13933 * starts with "p2p" and the requested mode was station.
13934 */
13935 if (strnstr(ndev->name, "p2p", 3) && new_mode == QDF_STA_MODE)
13936 new_mode = QDF_P2P_DEVICE_MODE;
13937
Dustin Brown56377e12018-10-10 17:04:04 -070013938 hdd_debug("Changing mode for '%s' from %s to %s",
13939 ndev->name,
13940 qdf_opmode_str(adapter->device_mode),
13941 qdf_opmode_str(new_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013942
Dustin Brown3ecc8782018-09-19 16:37:13 -070013943 errno = hdd_psoc_idle_restart(hdd_ctx);
Dustin Brown2ab5a972018-10-09 17:19:37 -070013944 if (errno) {
Dustin Brown3ecc8782018-09-19 16:37:13 -070013945 hdd_err("Failed to restart psoc; errno:%d", errno);
Arun Khandavallifae92942016-08-01 13:31:08 +053013946 return -EINVAL;
13947 }
13948
Dustin Brown76cd2932018-09-11 16:03:05 -070013949 if (!policy_mgr_allow_concurrency(hdd_ctx->psoc,
Dustin Brown63fe4922018-10-12 15:02:26 -070013950 hdd_nl_to_policy_mgr_iface_type(type),
13951 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070013952 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013953 return -EINVAL;
13954 }
13955
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013956 /* Reset the current device mode bit mask */
Dustin Brown2ab5a972018-10-09 17:19:37 -070013957 policy_mgr_clear_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013958
Dustin Brown63fe4922018-10-12 15:02:26 -070013959 if (hdd_is_client_mode(adapter->device_mode)) {
13960 if (hdd_is_client_mode(new_mode)) {
Dustin Brown56377e12018-10-10 17:04:04 -070013961 if (new_mode == QDF_IBSS_MODE)
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013962 hdd_deregister_tx_flow_control(adapter);
Dustin Brown56377e12018-10-10 17:04:04 -070013963
13964 errno = hdd_change_adapter_mode(adapter, new_mode);
Liangwei Dong4d35cad2018-11-02 02:38:50 -040013965 if (errno) {
13966 hdd_err("change intf mode fail %d", errno);
13967 goto err;
13968 }
Dustin Brown63fe4922018-10-12 15:02:26 -070013969 } else if (hdd_is_ap_mode(new_mode)) {
13970 if (new_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013971 wlan_hdd_cancel_existing_remain_on_channel
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013972 (adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013973
Dustin Browndb2a8be2017-12-20 11:49:56 -080013974 hdd_stop_adapter(hdd_ctx, adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013975 hdd_deinit_adapter(hdd_ctx, adapter, true);
Dustin Brown2ab5a972018-10-09 17:19:37 -070013976 memset(&adapter->session, 0, sizeof(adapter->session));
Dustin Brown56377e12018-10-10 17:04:04 -070013977 adapter->device_mode = new_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013978
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053013979 status = ucfg_mlme_get_ap_random_bssid_enable(
13980 hdd_ctx->psoc,
13981 &ap_random_bssid_enabled);
13982 if (QDF_IS_STATUS_ERROR(status))
13983 return qdf_status_to_os_return(status);
13984
Dustin Brown2ab5a972018-10-09 17:19:37 -070013985 if (adapter->device_mode == QDF_SAP_MODE &&
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053013986 ap_random_bssid_enabled) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013987 /* To meet Android requirements create
13988 * a randomized MAC address of the
13989 * form 02:1A:11:Fx:xx:xx
13990 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013991 get_random_bytes(&ndev->dev_addr[3], 3);
13992 ndev->dev_addr[0] = 0x02;
13993 ndev->dev_addr[1] = 0x1A;
13994 ndev->dev_addr[2] = 0x11;
13995 ndev->dev_addr[3] |= 0xF0;
Dustin Brown2ab5a972018-10-09 17:19:37 -070013996 memcpy(adapter->mac_addr.bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013997 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013998 pr_info("wlan: Generated HotSpot BSSID "
13999 MAC_ADDRESS_STR "\n",
14000 MAC_ADDR_ARRAY(ndev->dev_addr));
14001 }
14002
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014003 hdd_set_ap_ops(adapter->dev);
Dustin Brown63fe4922018-10-12 15:02:26 -070014004 } else {
Dustin Brown56377e12018-10-10 17:04:04 -070014005 hdd_err("Changing to device mode '%s' is not supported",
14006 qdf_opmode_str(new_mode));
Liangwei Dong4d35cad2018-11-02 02:38:50 -040014007 errno = -EOPNOTSUPP;
14008 goto err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014009 }
Dustin Brown63fe4922018-10-12 15:02:26 -070014010 } else if (hdd_is_ap_mode(adapter->device_mode)) {
14011 if (hdd_is_client_mode(new_mode)) {
Dustin Brown56377e12018-10-10 17:04:04 -070014012 errno = hdd_change_adapter_mode(adapter, new_mode);
Liangwei Dong4d35cad2018-11-02 02:38:50 -040014013 if (errno) {
14014 hdd_err("change mode fail %d", errno);
14015 goto err;
14016 }
Dustin Brown63fe4922018-10-12 15:02:26 -070014017 } else if (hdd_is_ap_mode(new_mode)) {
Dustin Brown56377e12018-10-10 17:04:04 -070014018 adapter->device_mode = new_mode;
14019
Dustin Brown63fe4922018-10-12 15:02:26 -070014020 /* avoid starting the adapter, since it never stopped */
14021 iff_up = false;
14022 } else {
Dustin Brown56377e12018-10-10 17:04:04 -070014023 hdd_err("Changing to device mode '%s' is not supported",
14024 qdf_opmode_str(new_mode));
Liangwei Dong4d35cad2018-11-02 02:38:50 -040014025 errno = -EOPNOTSUPP;
14026 goto err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014027 }
14028 } else {
Dustin Brown56377e12018-10-10 17:04:04 -070014029 hdd_err("Changing from device mode '%s' is not supported",
14030 qdf_opmode_str(adapter->device_mode));
Liangwei Dong4d35cad2018-11-02 02:38:50 -040014031 errno = -EOPNOTSUPP;
14032 goto err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014033 }
Dustin Brown56377e12018-10-10 17:04:04 -070014034
Dustin Brown63fe4922018-10-12 15:02:26 -070014035 /* restart the adapter if it was up before the change iface request */
14036 if (iff_up) {
14037 errno = hdd_start_adapter(adapter);
14038 if (errno) {
14039 hdd_err("Failed to start adapter");
Liangwei Dong4d35cad2018-11-02 02:38:50 -040014040 errno = -EINVAL;
14041 goto err;
Dustin Brown63fe4922018-10-12 15:02:26 -070014042 }
14043 }
14044
14045 ndev->ieee80211_ptr->iftype = type;
Liangwei Dong4d35cad2018-11-02 02:38:50 -040014046 hdd_lpass_notify_mode_change(adapter);
14047err:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014048 /* Set bitmask based on updated value */
Dustin Brown2ab5a972018-10-09 17:19:37 -070014049 policy_mgr_set_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014050
Dustin Browne74003f2018-03-14 12:51:58 -070014051 hdd_exit();
Dustin Brown2ab5a972018-10-09 17:19:37 -070014052
Liangwei Dong4d35cad2018-11-02 02:38:50 -040014053 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014054}
14055
Dustin Brown0e1e1622019-01-17 11:00:22 -080014056static int _wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
14057 struct net_device *net_dev,
14058 enum nl80211_iftype type,
14059 u32 *flags,
14060 struct vif_params *params)
14061{
14062 int errno;
14063 struct osif_vdev_sync *vdev_sync;
14064
14065 errno = osif_vdev_sync_trans_start(net_dev, &vdev_sync);
14066 if (errno)
14067 return errno;
14068
Dustin Brown0e1e1622019-01-17 11:00:22 -080014069 errno = __wlan_hdd_cfg80211_change_iface(wiphy, net_dev, type,
14070 flags, params);
Dustin Brown0e1e1622019-01-17 11:00:22 -080014071
14072 osif_vdev_sync_trans_stop(vdev_sync);
14073
14074 return errno;
14075}
14076
Dustin Brown9ed30a52017-08-16 13:59:38 -070014077#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
Rajeev Kumar98edb772016-01-19 12:42:19 -080014078/**
14079 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
14080 * @wiphy: Pointer to the wiphy structure
14081 * @ndev: Pointer to the net device
14082 * @type: Interface type
14083 * @flags: Flags for change interface
14084 * @params: Pointer to change interface parameters
14085 *
14086 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014087 */
14088static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
14089 struct net_device *ndev,
14090 enum nl80211_iftype type,
14091 u32 *flags,
14092 struct vif_params *params)
14093{
Dustin Brown0e1e1622019-01-17 11:00:22 -080014094 return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
14095 flags, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014096}
Dustin Brown9ed30a52017-08-16 13:59:38 -070014097#else
14098static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
14099 struct net_device *ndev,
14100 enum nl80211_iftype type,
14101 struct vif_params *params)
14102{
Dustin Brown0e1e1622019-01-17 11:00:22 -080014103 return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
Dustin Brown9ed30a52017-08-16 13:59:38 -070014104 &params->flags, params);
Dustin Brown9ed30a52017-08-16 13:59:38 -070014105}
14106#endif /* KERNEL_VERSION(4, 12, 0) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014107
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053014108QDF_STATUS wlan_hdd_send_sta_authorized_event(
14109 struct hdd_adapter *adapter,
14110 struct hdd_context *hdd_ctx,
14111 const struct qdf_mac_addr *mac_addr)
14112{
14113 struct sk_buff *vendor_event;
14114 QDF_STATUS status;
14115 struct nl80211_sta_flag_update sta_flags;
14116
14117 hdd_enter();
14118 if (!hdd_ctx) {
14119 hdd_err("HDD context is null");
14120 return QDF_STATUS_E_INVAL;
14121 }
14122
14123 vendor_event =
14124 cfg80211_vendor_event_alloc(
14125 hdd_ctx->wiphy, &adapter->wdev, sizeof(sta_flags) +
14126 QDF_MAC_ADDR_SIZE + NLMSG_HDRLEN,
14127 QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX,
14128 GFP_KERNEL);
14129 if (!vendor_event) {
14130 hdd_err("cfg80211_vendor_event_alloc failed");
14131 return QDF_STATUS_E_FAILURE;
14132 }
14133
14134 sta_flags.mask |= BIT(NL80211_STA_FLAG_AUTHORIZED);
14135 sta_flags.set = true;
14136
14137 status = nla_put(vendor_event,
14138 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS,
14139 sizeof(struct nl80211_sta_flag_update),
14140 &sta_flags);
14141 if (status) {
14142 hdd_err("STA flag put fails");
14143 kfree_skb(vendor_event);
14144 return QDF_STATUS_E_FAILURE;
14145 }
14146 status = nla_put(vendor_event,
14147 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR,
14148 QDF_MAC_ADDR_SIZE, mac_addr->bytes);
14149 if (status) {
14150 hdd_err("STA MAC put fails");
14151 kfree_skb(vendor_event);
14152 return QDF_STATUS_E_FAILURE;
14153 }
14154
14155 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
14156
14157 hdd_exit();
14158 return QDF_STATUS_SUCCESS;
14159}
14160
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014161/**
14162 * __wlan_hdd_change_station() - change station
14163 * @wiphy: Pointer to the wiphy structure
14164 * @dev: Pointer to the net device.
14165 * @mac: bssid
14166 * @params: Pointer to station parameters
14167 *
14168 * Return: 0 for success, error number on failure.
14169 */
14170#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14171static int __wlan_hdd_change_station(struct wiphy *wiphy,
14172 struct net_device *dev,
14173 const uint8_t *mac,
14174 struct station_parameters *params)
14175#else
14176static int __wlan_hdd_change_station(struct wiphy *wiphy,
14177 struct net_device *dev,
14178 uint8_t *mac,
14179 struct station_parameters *params)
14180#endif
14181{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014182 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014183 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070014184 struct hdd_context *hdd_ctx;
Jeff Johnsond377dce2017-10-04 10:32:42 -070014185 struct hdd_station_ctx *sta_ctx;
Vignesh Viswanathan597d9012018-07-06 15:26:08 +053014186 struct hdd_ap_ctx *ap_ctx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053014187 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014188 int ret;
14189
Dustin Brown491d54b2018-03-14 12:39:11 -070014190 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014191
Anurag Chouhan6d760662016-02-20 16:05:43 +053014192 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014193 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014194 return -EINVAL;
14195 }
14196
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053014197 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
14198 TRACE_CODE_HDD_CHANGE_STATION,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080014199 adapter->vdev_id, params->listen_interval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200
Jeff Johnson48363022019-02-24 16:26:51 -080014201 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014202 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014203
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014204 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070014205 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014206 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014207 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014208
Jeff Johnsond377dce2017-10-04 10:32:42 -070014209 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014210
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014211 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014212
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014213 if ((adapter->device_mode == QDF_SAP_MODE) ||
14214 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014215 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
Vignesh Viswanathan597d9012018-07-06 15:26:08 +053014216 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
14217 /*
14218 * For Encrypted SAP session, this will be done as
14219 * part of eSAP_STA_SET_KEY_EVENT
14220 */
14221 if (ap_ctx->encryption_type !=
14222 eCSR_ENCRYPT_TYPE_NONE) {
14223 hdd_debug("Encrypt type %d, not setting peer authorized now",
14224 ap_ctx->encryption_type);
14225 return 0;
14226 }
14227
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014228 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014229 hdd_softap_change_sta_state(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014230 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080014231 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014232
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014233 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014234 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014235 return -EINVAL;
14236 }
Ashish Kumar Dhanotiya42b03782018-01-16 10:55:16 +053014237 status = wlan_hdd_send_sta_authorized_event(
14238 adapter,
14239 hdd_ctx,
14240 &STAMacAddress);
14241 if (status != QDF_STATUS_SUCCESS) {
14242 return -EINVAL;
14243 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014244 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014245 } else if ((adapter->device_mode == QDF_STA_MODE) ||
14246 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014247 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud1a28462017-09-06 22:55:48 +080014248#if defined(FEATURE_WLAN_TDLS)
Min Liu8c5d99e2018-09-10 17:18:44 +080014249 struct wlan_objmgr_vdev *vdev;
14250
14251 vdev = hdd_objmgr_get_vdev(adapter);
14252 if (!vdev)
14253 return -EINVAL;
14254 ret = wlan_cfg80211_tdls_update_peer(vdev, mac, params);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053014255 hdd_objmgr_put_vdev(vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014256#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080014257 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014258 }
Dustin Browne74003f2018-03-14 12:51:58 -070014259 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014260 return ret;
14261}
14262
14263/**
14264 * wlan_hdd_change_station() - cfg80211 change station handler function
14265 * @wiphy: Pointer to the wiphy structure
14266 * @dev: Pointer to the net device.
14267 * @mac: bssid
14268 * @params: Pointer to station parameters
14269 *
14270 * This is the cfg80211 change station handler function which invokes
14271 * the internal function @__wlan_hdd_change_station with
14272 * SSR protection.
14273 *
14274 * Return: 0 for success, error number on failure.
14275 */
14276#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
14277static int wlan_hdd_change_station(struct wiphy *wiphy,
14278 struct net_device *dev,
14279 const u8 *mac,
14280 struct station_parameters *params)
14281#else
14282static int wlan_hdd_change_station(struct wiphy *wiphy,
14283 struct net_device *dev,
14284 u8 *mac,
14285 struct station_parameters *params)
14286#endif
14287{
Dustin Brown1d31b082018-11-22 14:41:20 +053014288 int errno;
14289 struct osif_vdev_sync *vdev_sync;
14290
14291 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
14292 if (errno)
14293 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014294
Dustin Brown1d31b082018-11-22 14:41:20 +053014295 errno = __wlan_hdd_change_station(wiphy, dev, mac, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014296
Dustin Brown1d31b082018-11-22 14:41:20 +053014297 osif_vdev_sync_op_stop(vdev_sync);
14298
14299 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014300}
14301
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014302#ifdef CRYPTO_SET_KEY_CONVERGED
14303#ifdef FEATURE_WLAN_ESE
14304static bool hdd_is_krk_enc_type(uint32_t cipher_type)
14305{
14306 if (cipher_type == WLAN_CIPHER_SUITE_KRK)
14307 return true;
14308
14309 return false;
14310}
14311#else
14312static bool hdd_is_krk_enc_type(uint32_t cipher_type)
14313{
14314 return false;
14315}
14316#endif
14317
14318#if defined(FEATURE_WLAN_ESE) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
14319static bool hdd_is_btk_enc_type(uint32_t cipher_type)
14320{
14321 if (cipher_type == WLAN_CIPHER_SUITE_BTK)
14322 return true;
14323
14324 return false;
14325}
14326#else
14327static bool hdd_is_btk_enc_type(uint32_t cipher_type)
14328{
14329 return false;
14330}
14331#endif
14332#endif
14333
14334#ifdef CRYPTO_SET_KEY_CONVERGED
14335static int wlan_hdd_add_key_ibss(struct hdd_adapter *adapter,
14336 bool pairwise, u8 key_index,
14337 const u8 *mac_addr, struct key_params *params,
14338 bool *key_already_installed)
14339{
14340 struct wlan_objmgr_vdev *vdev;
14341 int errno;
14342
14343 if (pairwise)
14344 return 0;
14345 /* if a key is already installed, block all subsequent ones */
14346 if (adapter->session.station.ibss_enc_key_installed) {
14347 hdd_debug("IBSS key installed already");
14348 *key_already_installed = true;
14349 return 0;
14350 }
14351 /*Set the group key */
14352 vdev = hdd_objmgr_get_vdev(adapter);
14353 if (!vdev)
14354 return -EINVAL;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080014355 errno = wlan_cfg80211_crypto_add_key(vdev, WLAN_CRYPTO_KEY_TYPE_GROUP,
14356 key_index);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014357 if (errno) {
14358 hdd_err("add_ibss_key failed, errno: %d", errno);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053014359 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014360 return errno;
14361 }
14362 /* Save the keys here and call set_key for setting
14363 * the PTK after peer joins the IBSS network
14364 */
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080014365 wlan_cfg80211_store_key(vdev, key_index, WLAN_CRYPTO_KEY_TYPE_UNICAST,
14366 mac_addr, params);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053014367 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014368 adapter->session.station.ibss_enc_key_installed = 1;
14369
14370 return 0;
14371}
14372
14373static int wlan_hdd_add_key_sap(struct hdd_adapter *adapter,
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080014374 bool pairwise, u8 key_index,
14375 enum wlan_crypto_cipher_type cipher)
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014376{
14377 struct wlan_objmgr_vdev *vdev;
14378 int errno = 0;
14379 struct hdd_hostapd_state *hostapd_state =
14380 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
14381
14382 vdev = hdd_objmgr_get_vdev(adapter);
14383 if (!vdev)
14384 return -EINVAL;
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080014385 if (hostapd_state->bss_state == BSS_START) {
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080014386 errno =
14387 wlan_cfg80211_crypto_add_key(vdev, (pairwise ?
14388 WLAN_CRYPTO_KEY_TYPE_UNICAST :
14389 WLAN_CRYPTO_KEY_TYPE_GROUP),
14390 key_index);
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080014391 if (!errno)
14392 wma_update_set_key(adapter->vdev_id, pairwise,
14393 key_index, cipher);
14394 }
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053014395 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014396
14397 return errno;
14398}
14399
14400static int wlan_hdd_add_key_sta(struct hdd_adapter *adapter,
14401 bool pairwise, u8 key_index,
14402 mac_handle_t mac_handle, bool *ft_mode)
14403{
14404 struct wlan_objmgr_vdev *vdev;
14405 struct hdd_station_ctx *sta_ctx =
14406 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14407 int errno;
14408 QDF_STATUS status;
14409
14410 if (!pairwise) {
14411 /* set group key */
14412 if (sta_ctx->roam_info.defer_key_complete) {
14413 hdd_debug("Perform Set key Complete");
14414 hdd_perform_roam_set_key_complete(adapter);
14415 }
14416 }
14417 /* The supplicant may attempt to set the PTK once
14418 * pre-authentication is done. Save the key in the
14419 * UMAC and include it in the ADD BSS request
14420 */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080014421 status = sme_check_ft_status(mac_handle, adapter->vdev_id);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014422 if (status == QDF_STATUS_SUCCESS) {
14423 *ft_mode = true;
14424 return 0;
14425 }
14426 vdev = hdd_objmgr_get_vdev(adapter);
14427 if (!vdev)
14428 return -EINVAL;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080014429 errno = wlan_cfg80211_crypto_add_key(vdev, (pairwise ?
14430 WLAN_CRYPTO_KEY_TYPE_UNICAST :
14431 WLAN_CRYPTO_KEY_TYPE_GROUP),
14432 key_index);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053014433 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014434 if (!errno && adapter->send_mode_change) {
14435 wlan_hdd_send_mode_change_event();
14436 adapter->send_mode_change = false;
14437 }
14438
14439 return errno;
14440}
14441
14442static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
14443 struct net_device *ndev,
14444 u8 key_index, bool pairwise,
14445 const u8 *mac_addr,
14446 struct key_params *params)
14447{
14448 struct hdd_context *hdd_ctx;
14449 mac_handle_t mac_handle;
14450 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14451 struct wlan_objmgr_vdev *vdev;
14452 bool key_already_installed = false, ft_mode = false;
14453 enum wlan_crypto_cipher_type cipher;
14454 int errno;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080014455 struct qdf_mac_addr mac_address;
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014456
14457 hdd_enter();
14458
14459 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
14460 hdd_err("Command not allowed in FTM mode");
14461 return -EINVAL;
14462 }
14463
Jeff Johnson48363022019-02-24 16:26:51 -080014464 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014465 return -EINVAL;
14466
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053014467 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
14468 TRACE_CODE_HDD_CFG80211_ADD_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080014469 adapter->vdev_id, params->key_len);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053014470
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014471 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14472 errno = wlan_hdd_validate_context(hdd_ctx);
14473 if (errno)
14474 return errno;
14475
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080014476 hdd_debug("converged Device_mode %s(%d) index %d, pairwise %d",
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014477 qdf_opmode_str(adapter->device_mode),
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080014478 adapter->device_mode, key_index, pairwise);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014479 mac_handle = hdd_ctx->mac_handle;
14480
14481 if (hdd_is_btk_enc_type(params->cipher))
Jeff Johnsoncf07c312019-02-04 13:53:29 -080014482 return sme_add_key_btk(mac_handle, adapter->vdev_id,
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014483 params->key, params->key_len);
14484 if (hdd_is_krk_enc_type(params->cipher))
Jeff Johnsoncf07c312019-02-04 13:53:29 -080014485 return sme_add_key_krk(mac_handle, adapter->vdev_id,
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014486 params->key, params->key_len);
14487
14488 vdev = hdd_objmgr_get_vdev(adapter);
14489 if (!vdev)
14490 return -EINVAL;
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080014491 if (!pairwise && ((adapter->device_mode == QDF_STA_MODE) ||
14492 (adapter->device_mode == QDF_P2P_CLIENT_MODE))) {
14493 qdf_mem_copy(mac_address.bytes,
Jeff Johnsone04b6992019-02-27 14:06:55 -080014494 adapter->session.station.conn_info.bssid.bytes,
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080014495 QDF_MAC_ADDR_SIZE);
14496 } else {
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080014497 if (mac_addr)
14498 qdf_mem_copy(mac_address.bytes, mac_addr,
14499 QDF_MAC_ADDR_SIZE);
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080014500 }
14501 errno = wlan_cfg80211_store_key(vdev, key_index,
14502 (pairwise ?
14503 WLAN_CRYPTO_KEY_TYPE_UNICAST :
14504 WLAN_CRYPTO_KEY_TYPE_GROUP),
14505 mac_address.bytes, params);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053014506 hdd_objmgr_put_vdev(vdev);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014507 if (errno)
14508 return errno;
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080014509 cipher = osif_nl_to_crypto_cipher_type(params->cipher);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014510 switch (adapter->device_mode) {
14511 case QDF_IBSS_MODE:
14512 errno = wlan_hdd_add_key_ibss(adapter, pairwise, key_index,
14513 mac_addr, params,
14514 &key_already_installed);
14515 if (key_already_installed)
14516 return 0;
14517 break;
14518 case QDF_SAP_MODE:
14519 case QDF_P2P_GO_MODE:
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080014520 errno = wlan_hdd_add_key_sap(adapter, pairwise,
14521 key_index, cipher);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014522 break;
14523 case QDF_STA_MODE:
14524 case QDF_P2P_CLIENT_MODE:
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080014525 errno = wlan_hdd_add_key_sta(adapter, pairwise, key_index,
14526 mac_handle, &ft_mode);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014527 if (ft_mode)
14528 return 0;
14529 break;
14530 default:
14531 break;
14532 }
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080014533 if (!errno && (adapter->device_mode != QDF_SAP_MODE))
Jeff Johnsoncf07c312019-02-04 13:53:29 -080014534 wma_update_set_key(adapter->vdev_id, pairwise, key_index,
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014535 cipher);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014536 hdd_exit();
14537
14538 return errno;
14539}
14540#else /* !CRYPTO_SET_KEY_CONVERGED */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014541/*
14542 * FUNCTION: __wlan_hdd_cfg80211_add_key
14543 * This function is used to initialize the key information
14544 */
14545static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
14546 struct net_device *ndev,
14547 u8 key_index, bool pairwise,
14548 const u8 *mac_addr,
14549 struct key_params *params)
14550{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014551 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014552 tCsrRoamSetKey setKey;
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014553 int errno;
Jeff Johnson29c78672019-02-26 21:05:53 -080014554 uint32_t roam_id = INVALID_ROAM_ID;
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014555 QDF_STATUS status;
Jeff Johnsonb8944722017-09-03 09:03:19 -070014556 struct hdd_context *hdd_ctx;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014557 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014558
Dustin Brown491d54b2018-03-14 12:39:11 -070014559 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014560
Anurag Chouhan6d760662016-02-20 16:05:43 +053014561 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014562 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014563 return -EINVAL;
14564 }
14565
Jeff Johnson48363022019-02-24 16:26:51 -080014566 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014567 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014568
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053014569 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
14570 TRACE_CODE_HDD_CFG80211_ADD_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080014571 adapter->vdev_id, params->key_len);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053014572
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014573 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014574 errno = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014575
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014576 if (errno)
14577 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014578
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014579 hdd_debug("Device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070014580 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014581
14582 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014583 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014584
14585 return -EINVAL;
14586 }
14587
14588 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014589 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014590
14591 return -EINVAL;
14592 }
14593
Jeff Johnsonb05f4fd2017-10-18 15:08:21 -070014594 if (CSR_MAX_RSC_LEN < params->seq_len) {
14595 hdd_err("Invalid seq length %d", params->seq_len);
14596
14597 return -EINVAL;
14598 }
14599
14600 hdd_debug("key index %d, key length %d, seq length %d",
14601 key_index, params->key_len, params->seq_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014602
14603 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014604 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014605 setKey.keyId = key_index;
14606 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014607 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Jeff Johnsonb05f4fd2017-10-18 15:08:21 -070014608 qdf_mem_copy(&setKey.keyRsc[0], params->seq, params->seq_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014609
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014610 mac_handle = hdd_ctx->mac_handle;
14611
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014612 switch (params->cipher) {
14613 case WLAN_CIPHER_SUITE_WEP40:
14614 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14615 break;
14616
14617 case WLAN_CIPHER_SUITE_WEP104:
14618 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
14619 break;
14620
14621 case WLAN_CIPHER_SUITE_TKIP:
14622 {
14623 u8 *pKey = &setKey.Key[0];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014624
Srinivas Girigowda576b2352017-08-25 14:44:26 -070014625 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014626 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014627
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014628 /* Supplicant sends the 32bytes key in this order
14629 *
14630 * |--------------|----------|----------|
14631 * | Tk1 |TX-MIC | RX Mic |
14632 * |--------------|----------|----------|
14633 * <---16bytes---><--8bytes--><--8bytes-->
14634 *
14635 * Sme expects the 32 bytes key to be in the below order
14636 *
14637 * |--------------|----------|----------|
14638 * | Tk1 |RX-MIC | TX Mic |
14639 * |--------------|----------|----------|
14640 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014641 */
14642 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014643 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014644
14645 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014646 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014647
14648 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014649 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014650
14651 break;
14652 }
14653
14654 case WLAN_CIPHER_SUITE_CCMP:
14655 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
14656 break;
14657
14658#ifdef FEATURE_WLAN_WAPI
14659 case WLAN_CIPHER_SUITE_SMS4:
14660 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014661 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014662 wlan_hdd_cfg80211_set_key_wapi(adapter, key_index,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014663 mac_addr, params->key,
14664 params->key_len);
14665 return 0;
14666 }
14667#endif
14668
14669#ifdef FEATURE_WLAN_ESE
14670 case WLAN_CIPHER_SUITE_KRK:
14671 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
14672 break;
14673#ifdef WLAN_FEATURE_ROAM_OFFLOAD
14674 case WLAN_CIPHER_SUITE_BTK:
14675 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
14676 break;
14677#endif
14678#endif
14679
14680#ifdef WLAN_FEATURE_11W
14681 case WLAN_CIPHER_SUITE_AES_CMAC:
14682 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
14683 break;
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +053014684#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
14685 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
14686 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GMAC_128;
14687 break;
14688 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
14689 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GMAC_256;
14690 break;
14691#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014692#endif
Mukul Sharma05504ac2017-06-08 12:35:53 +053014693 case WLAN_CIPHER_SUITE_GCMP:
14694 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GCMP;
14695 break;
14696 case WLAN_CIPHER_SUITE_GCMP_256:
14697 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GCMP_256;
14698 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014699
14700 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014701 hdd_err("Unsupported cipher type: %u", params->cipher);
Ashish Kumar Dhanotiya02137932019-02-26 21:43:32 +053014702 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014703 return -EOPNOTSUPP;
14704 }
14705
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014706 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014707
14708 if (!pairwise) {
14709 /* set group key */
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070014710 hdd_debug("setting Broadcast key");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014711 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053014712 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014713 } else {
14714 /* set pairwise key */
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070014715 hdd_debug("setting pairwise key");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014716 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014717 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014718 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014719 if ((QDF_IBSS_MODE == adapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014720 /* if a key is already installed, block all subsequent ones */
Jeff Johnsonb9424862017-10-30 08:49:35 -070014721 if (adapter->session.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014722 hdd_debug("IBSS key installed already");
Ashish Kumar Dhanotiya02137932019-02-26 21:43:32 +053014723 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014724 return 0;
14725 }
14726
14727 setKey.keyDirection = eSIR_TX_RX;
14728 /*Set the group key */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014729 status = sme_roam_set_key(mac_handle,
Jeff Johnson29c78672019-02-26 21:05:53 -080014730 adapter->vdev_id, &setKey, &roam_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014731
14732 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014733 hdd_err("sme_roam_set_key failed, status: %d", status);
Ashish Kumar Dhanotiya02137932019-02-26 21:43:32 +053014734 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014735 return -EINVAL;
14736 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014737 /* Save the keys here and call sme_roam_set_key for setting
14738 * the PTK after peer joins the IBSS network
14739 */
Jeff Johnsonb9424862017-10-30 08:49:35 -070014740 qdf_mem_copy(&adapter->session.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014741 &setKey, sizeof(tCsrRoamSetKey));
14742
Jeff Johnsonb9424862017-10-30 08:49:35 -070014743 adapter->session.station.ibss_enc_key_installed = 1;
Ashish Kumar Dhanotiya02137932019-02-26 21:43:32 +053014744 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014745 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014746 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014747 if ((adapter->device_mode == QDF_SAP_MODE) ||
14748 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053014749 struct hdd_hostapd_state *hostapd_state =
14750 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
14751 struct hdd_ap_ctx *ap_ctx =
14752 WLAN_HDD_GET_AP_CTX_PTR(adapter);
14753
Jeff Johnson0f9f87b2017-10-28 09:21:06 -070014754 if (hostapd_state->bss_state == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070014755 status = wlansap_set_key_sta(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014756 WLAN_HDD_GET_SAP_CTX_PTR(adapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014757 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014758 hdd_err("wlansap_set_key_sta failed status: %d",
14759 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014760 }
14761 }
14762
Jeff Johnson413c15f2017-10-27 18:56:35 -070014763 /* Save the key in ap ctx for use on START_BSS and restart */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014764 if (pairwise ||
14765 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
14766 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Jeff Johnson3d731362017-10-27 19:06:41 -070014767 qdf_mem_copy(&ap_ctx->wep_key[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014768 sizeof(tCsrRoamSetKey));
14769 else
Jeff Johnson413c15f2017-10-27 18:56:35 -070014770 qdf_mem_copy(&ap_ctx->group_key, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014771 sizeof(tCsrRoamSetKey));
14772
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014773 } else if ((adapter->device_mode == QDF_STA_MODE) ||
14774 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Jeff Johnsond377dce2017-10-04 10:32:42 -070014775 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014776 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070014777 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014778
14779 if (!pairwise) {
14780 /* set group key */
Jeff Johnsonaf2ae4b2017-11-01 11:38:50 -070014781 if (sta_ctx->roam_info.defer_key_complete) {
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070014782 hdd_debug("Perform Set key Complete");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014783 hdd_perform_roam_set_key_complete(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014784 }
14785 }
14786
Jeff Johnson20227a92018-03-13 09:41:05 -070014787 roam_profile = hdd_roam_profile(adapter);
14788 roam_profile->Keys.KeyLength[key_index] = params->key_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014789
Jeff Johnson20227a92018-03-13 09:41:05 -070014790 roam_profile->Keys.defaultIndex = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014791
Jeff Johnson20227a92018-03-13 09:41:05 -070014792 qdf_mem_copy(&roam_profile->Keys.KeyMaterial[key_index][0],
14793 params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014794
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014795 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014796 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
14797 setKey.keyDirection);
14798
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014799 /* The supplicant may attempt to set the PTK once
14800 * pre-authentication is done. Save the key in the
14801 * UMAC and include it in the ADD BSS request
14802 */
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014803 status = sme_ft_update_key(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080014804 adapter->vdev_id, &setKey);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014805 if (status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014806 hdd_debug("Update PreAuth Key success");
Ashish Kumar Dhanotiya02137932019-02-26 21:43:32 +053014807 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014808 return 0;
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014809 } else if (status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014810 hdd_err("Update PreAuth Key failed");
Ashish Kumar Dhanotiya02137932019-02-26 21:43:32 +053014811 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014812 return -EINVAL;
14813 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014814
14815 /* issue set key request to SME */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014816 status = sme_roam_set_key(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080014817 adapter->vdev_id, &setKey,
Jeff Johnson29c78672019-02-26 21:05:53 -080014818 &roam_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014819
14820 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014821 hdd_err("sme_roam_set_key failed, status: %d", status);
Ashish Kumar Dhanotiya02137932019-02-26 21:43:32 +053014822 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014823 return -EINVAL;
14824 }
14825
Yeshwanth Sriram Guntuka4fe30bd2018-06-13 11:41:42 +053014826 if (adapter->send_mode_change) {
14827 wlan_hdd_send_mode_change_event();
14828 adapter->send_mode_change = false;
14829 }
14830
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014831 /* in case of IBSS as there was no information
14832 * available about WEP keys during IBSS join, group
Jeff Johnson5e19a942018-05-06 15:37:39 -070014833 * key initialized with NULL key, so re-initialize
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014834 * group key with correct value
14835 */
Jeff Johnson20227a92018-03-13 09:41:05 -070014836 if ((eCSR_BSS_TYPE_START_IBSS == roam_profile->BSSType) &&
Jeff Johnson37ecea42018-03-18 17:54:40 -070014837 !((HDD_AUTH_KEY_MGMT_802_1X ==
14838 (sta_ctx->auth_key_mgmt & HDD_AUTH_KEY_MGMT_802_1X))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014839 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
Jeff Johnson96e33512019-02-27 15:10:21 -080014840 sta_ctx->conn_info.auth_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014841 )
14842 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
14843 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
14844 )
14845 ) {
14846 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053014847 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014848
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014849 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014850 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
14851 setKey.keyDirection);
14852
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014853 status = sme_roam_set_key(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080014854 adapter->vdev_id, &setKey,
Jeff Johnson29c78672019-02-26 21:05:53 -080014855 &roam_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014856
14857 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014858 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Ashish Kumar Dhanotiya02137932019-02-26 21:43:32 +053014859 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014860 return -EINVAL;
14861 }
14862 }
14863 }
Ashish Kumar Dhanotiya02137932019-02-26 21:43:32 +053014864 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Dustin Browne74003f2018-03-14 12:51:58 -070014865 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014866 return 0;
14867}
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070014868#endif /* CRYPTO_SET_KEY_CONVERGED */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014869
14870static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
14871 struct net_device *ndev,
14872 u8 key_index, bool pairwise,
14873 const u8 *mac_addr,
14874 struct key_params *params)
14875{
Dustin Brown1d31b082018-11-22 14:41:20 +053014876 int errno;
14877 struct osif_vdev_sync *vdev_sync;
14878
14879 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
14880 if (errno)
14881 return errno;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070014882
Dustin Brown1d31b082018-11-22 14:41:20 +053014883 errno = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
14884 mac_addr, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014885
Dustin Brown1d31b082018-11-22 14:41:20 +053014886 osif_vdev_sync_op_stop(vdev_sync);
14887
14888 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014889}
14890
14891/*
14892 * FUNCTION: __wlan_hdd_cfg80211_get_key
14893 * This function is used to get the key information
14894 */
14895static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
14896 struct net_device *ndev,
14897 u8 key_index, bool pairwise,
14898 const u8 *mac_addr, void *cookie,
14899 void (*callback)(void *cookie,
14900 struct key_params *)
14901 )
14902{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014903 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070014904 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014905 struct key_params params;
14906
Dustin Brown491d54b2018-03-14 12:39:11 -070014907 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014908
Anurag Chouhan6d760662016-02-20 16:05:43 +053014909 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014910 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014911 return -EINVAL;
14912 }
14913
Jeff Johnson48363022019-02-24 16:26:51 -080014914 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Jiachao Wud58cfc92017-12-27 14:15:23 +080014915 return -EINVAL;
Jiachao Wud58cfc92017-12-27 14:15:23 +080014916
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014917 hdd_debug("Device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070014918 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014919
14920 memset(&params, 0, sizeof(params));
14921
14922 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014923 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014924 return -EINVAL;
14925 }
14926
Nachiket Kukaded9152832017-10-16 16:18:22 +053014927 if ((adapter->device_mode == QDF_SAP_MODE) ||
14928 (adapter->device_mode == QDF_P2P_GO_MODE)) {
14929 struct hdd_ap_ctx *ap_ctx =
14930 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070014931
Nachiket Kukaded9152832017-10-16 16:18:22 +053014932 roam_profile =
14933 wlan_sap_get_roam_profile(ap_ctx->sap_context);
14934 } else {
Jeff Johnson20227a92018-03-13 09:41:05 -070014935 roam_profile = hdd_roam_profile(adapter);
Nachiket Kukaded9152832017-10-16 16:18:22 +053014936 }
14937
Jiachao Wud58cfc92017-12-27 14:15:23 +080014938 if (roam_profile == NULL) {
14939 hdd_err("Get roam profile failed!");
14940 return -EINVAL;
14941 }
14942
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014943 switch (roam_profile->EncryptionType.encryptionType[0]) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014944 case eCSR_ENCRYPT_TYPE_NONE:
14945 params.cipher = IW_AUTH_CIPHER_NONE;
14946 break;
14947
14948 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
14949 case eCSR_ENCRYPT_TYPE_WEP40:
14950 params.cipher = WLAN_CIPHER_SUITE_WEP40;
14951 break;
14952
14953 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
14954 case eCSR_ENCRYPT_TYPE_WEP104:
14955 params.cipher = WLAN_CIPHER_SUITE_WEP104;
14956 break;
14957
14958 case eCSR_ENCRYPT_TYPE_TKIP:
14959 params.cipher = WLAN_CIPHER_SUITE_TKIP;
14960 break;
14961
14962 case eCSR_ENCRYPT_TYPE_AES:
14963 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
14964 break;
Mukul Sharma05504ac2017-06-08 12:35:53 +053014965 case eCSR_ENCRYPT_TYPE_AES_GCMP:
14966 params.cipher = WLAN_CIPHER_SUITE_GCMP;
14967 break;
14968 case eCSR_ENCRYPT_TYPE_AES_GCMP_256:
14969 params.cipher = WLAN_CIPHER_SUITE_GCMP_256;
14970 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014971 default:
14972 params.cipher = IW_AUTH_CIPHER_NONE;
14973 break;
14974 }
14975
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053014976 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
14977 TRACE_CODE_HDD_CFG80211_GET_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080014978 adapter->vdev_id, params.cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014979
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014980 params.key_len = roam_profile->Keys.KeyLength[key_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014981 params.seq_len = 0;
14982 params.seq = NULL;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014983 params.key = &roam_profile->Keys.KeyMaterial[key_index][0];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014984 callback(cookie, &params);
14985
Dustin Browne74003f2018-03-14 12:51:58 -070014986 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014987 return 0;
14988}
14989
14990static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
14991 struct net_device *ndev,
14992 u8 key_index, bool pairwise,
14993 const u8 *mac_addr, void *cookie,
14994 void (*callback)(void *cookie,
14995 struct key_params *)
14996 )
14997{
Dustin Brown1d31b082018-11-22 14:41:20 +053014998 int errno;
14999 struct osif_vdev_sync *vdev_sync;
15000
15001 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
15002 if (errno)
15003 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015004
Dustin Brown1d31b082018-11-22 14:41:20 +053015005 errno = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
15006 mac_addr, cookie, callback);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015007
Dustin Brown1d31b082018-11-22 14:41:20 +053015008 osif_vdev_sync_op_stop(vdev_sync);
15009
15010 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015011}
15012
15013/**
15014 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
15015 * @wiphy: wiphy interface context
15016 * @ndev: pointer to net device
15017 * @key_index: Key index used in 802.11 frames
15018 * @unicast: true if it is unicast key
15019 * @multicast: true if it is multicast key
15020 *
15021 * This function is required for cfg80211_ops API.
15022 * It is used to delete the key information
15023 * Underlying hardware implementation does not have API to delete the
15024 * encryption key. It is automatically deleted when the peer is
15025 * removed. Hence this function currently does nothing.
15026 * Future implementation may interprete delete key operation to
15027 * replacing the key with a random junk value, effectively making it
15028 * useless.
15029 *
15030 * Return: status code, always 0.
15031 */
15032
15033static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
15034 struct net_device *ndev,
15035 u8 key_index,
15036 bool pairwise, const u8 *mac_addr)
15037{
Dustin Browne74003f2018-03-14 12:51:58 -070015038 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015039 return 0;
15040}
15041
15042/**
15043 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
15044 * @wiphy: Pointer to wiphy structure.
15045 * @dev: Pointer to net_device structure.
15046 * @key_index: key index
15047 * @pairwise: pairwise
15048 * @mac_addr: mac address
15049 *
15050 * This is the cfg80211 delete key handler function which invokes
15051 * the internal function @__wlan_hdd_cfg80211_del_key with
15052 * SSR protection.
15053 *
15054 * Return: 0 for success, error number on failure.
15055 */
15056static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
15057 struct net_device *dev,
15058 u8 key_index,
15059 bool pairwise, const u8 *mac_addr)
15060{
Dustin Brown1d31b082018-11-22 14:41:20 +053015061 int errno;
15062 struct osif_vdev_sync *vdev_sync;
15063
15064 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
15065 if (errno)
15066 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015067
Dustin Brown1d31b082018-11-22 14:41:20 +053015068 errno = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
15069 pairwise, mac_addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015070
Dustin Brown1d31b082018-11-22 14:41:20 +053015071 osif_vdev_sync_op_stop(vdev_sync);
15072
15073 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015074}
15075
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015076#ifndef CRYPTO_SET_KEY_CONVERGED
Hu Wangc3148842017-06-20 19:03:29 +080015077#ifdef FEATURE_WLAN_WAPI
Jeff Johnsonb1959842019-02-27 13:04:04 -080015078static bool hdd_is_wapi_enc_type(eCsrEncryptionType encrypt_type)
Hu Wangc3148842017-06-20 19:03:29 +080015079{
Jeff Johnsonb1959842019-02-27 13:04:04 -080015080 if (encrypt_type == eCSR_ENCRYPT_TYPE_WPI)
Hu Wangc3148842017-06-20 19:03:29 +080015081 return true;
15082
15083 return false;
15084}
15085#else
Jeff Johnsonb1959842019-02-27 13:04:04 -080015086static bool hdd_is_wapi_enc_type(eCsrEncryptionType encrypt_type)
Hu Wangc3148842017-06-20 19:03:29 +080015087{
15088 return false;
15089}
15090#endif
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015091#endif
Hu Wangc3148842017-06-20 19:03:29 +080015092
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015093#ifdef CRYPTO_SET_KEY_CONVERGED
15094static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
15095 struct net_device *ndev,
15096 u8 key_index,
15097 bool unicast, bool multicast)
15098{
15099 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
15100 struct hdd_context *hdd_ctx;
15101 struct qdf_mac_addr bssid = QDF_MAC_ADDR_BCAST_INIT;
15102 struct hdd_station_ctx *sta_ctx;
15103 struct wlan_crypto_key *crypto_key;
15104 int ret;
15105 QDF_STATUS status;
15106
15107 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15108 hdd_err("Command not allowed in FTM mode");
15109 return -EINVAL;
15110 }
15111
Jeff Johnson48363022019-02-24 16:26:51 -080015112 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015113 return -EINVAL;
15114
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053015115 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
15116 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080015117 adapter->vdev_id, key_index);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015118
15119 hdd_debug("Device_mode %s(%d) key_index = %d",
15120 qdf_opmode_str(adapter->device_mode),
15121 adapter->device_mode, key_index);
15122
15123 if (CSR_MAX_NUM_KEY <= key_index) {
15124 hdd_err("Invalid key index: %d", key_index);
15125 return -EINVAL;
15126 }
15127
15128 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
15129 ret = wlan_hdd_validate_context(hdd_ctx);
15130
15131 if (0 != ret)
15132 return ret;
15133 crypto_key = wlan_crypto_get_key(adapter->vdev, key_index);
15134 hdd_debug("unicast %d, cipher %d", unicast, crypto_key->cipher_type);
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080015135 if (!IS_WEP_CIPHER(crypto_key->cipher_type))
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015136 return 0;
15137 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15138 if (unicast)
15139 status =
15140 wlan_cfg80211_set_default_key(adapter->vdev, key_index,
Jeff Johnsone04b6992019-02-27 14:06:55 -080015141 &sta_ctx->conn_info.bssid);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015142 else
15143 status = wlan_cfg80211_set_default_key(adapter->vdev, key_index,
15144 &bssid);
15145 if (QDF_STATUS_SUCCESS != status) {
15146 hdd_err("ret fail status %d", ret);
15147 return -EINVAL;
15148 }
15149 if ((adapter->device_mode == QDF_STA_MODE) ||
15150 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Kiran Kumar Lokere47d0dac2019-01-24 18:38:33 -080015151 ret =
15152 wlan_cfg80211_crypto_add_key(adapter->vdev, (unicast ?
15153 WLAN_CRYPTO_KEY_TYPE_UNICAST :
15154 WLAN_CRYPTO_KEY_TYPE_GROUP),
15155 key_index);
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080015156 wma_update_set_key(adapter->vdev_id, unicast, key_index,
15157 crypto_key->cipher_type);
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015158 }
15159
15160 return ret;
15161}
15162#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015163/*
15164 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
15165 * This function is used to set the default tx key index
15166 */
15167static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
15168 struct net_device *ndev,
15169 u8 key_index,
15170 bool unicast, bool multicast)
15171{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015172 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070015173 struct hdd_context *hdd_ctx;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015174 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015175 int status;
15176
Dustin Brown491d54b2018-03-14 12:39:11 -070015177 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015178
Anurag Chouhan6d760662016-02-20 16:05:43 +053015179 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070015180 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015181 return -EINVAL;
15182 }
15183
Jeff Johnson48363022019-02-24 16:26:51 -080015184 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015185 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015186
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053015187 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
15188 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080015189 adapter->vdev_id, key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015190
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015191 hdd_debug("Device_mode %s(%d) key_index = %d",
Dustin Brown458027c2018-10-19 12:26:27 -070015192 qdf_opmode_str(adapter->device_mode),
15193 adapter->device_mode, key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015194
15195 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015196 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015197 return -EINVAL;
15198 }
15199
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015200 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070015201 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015202
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015203 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015204 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015205
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015206 mac_handle = hdd_ctx->mac_handle;
15207
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015208 if ((adapter->device_mode == QDF_STA_MODE) ||
15209 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053015210 struct hdd_station_ctx *sta_ctx =
15211 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070015212 struct csr_roam_profile *roam_profile;
15213
15214 roam_profile = hdd_roam_profile(adapter);
Nachiket Kukaded9152832017-10-16 16:18:22 +053015215
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015216 if ((eCSR_ENCRYPT_TYPE_TKIP !=
Jeff Johnsonb1959842019-02-27 13:04:04 -080015217 sta_ctx->conn_info.uc_encrypt_type) &&
Hu Wangc3148842017-06-20 19:03:29 +080015218 !hdd_is_wapi_enc_type(
Jeff Johnsonb1959842019-02-27 13:04:04 -080015219 sta_ctx->conn_info.uc_encrypt_type) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015220 (eCSR_ENCRYPT_TYPE_AES !=
Jeff Johnsonb1959842019-02-27 13:04:04 -080015221 sta_ctx->conn_info.uc_encrypt_type) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053015222 (eCSR_ENCRYPT_TYPE_AES_GCMP !=
Jeff Johnsonb1959842019-02-27 13:04:04 -080015223 sta_ctx->conn_info.uc_encrypt_type) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053015224 (eCSR_ENCRYPT_TYPE_AES_GCMP_256 !=
Jeff Johnsonb1959842019-02-27 13:04:04 -080015225 sta_ctx->conn_info.uc_encrypt_type)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015226 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015227 * then update the default key index
15228 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015229
15230 tCsrRoamSetKey setKey;
Jeff Johnson29c78672019-02-26 21:05:53 -080015231 uint32_t roam_id = INVALID_ROAM_ID;
Jeff Johnson20227a92018-03-13 09:41:05 -070015232 tCsrKeys *Keys = &roam_profile->Keys;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015233
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015234 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015235 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015236 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015237 setKey.keyId = key_index;
15238 setKey.keyLength = Keys->KeyLength[key_index];
15239
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015240 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015241 &Keys->KeyMaterial[key_index][0],
15242 Keys->KeyLength[key_index]);
15243
15244 setKey.keyDirection = eSIR_TX_RX;
15245
Anurag Chouhanc5548422016-02-24 18:33:27 +053015246 qdf_copy_macaddr(&setKey.peerMac,
Jeff Johnsone04b6992019-02-27 14:06:55 -080015247 &sta_ctx->conn_info.bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015248
15249 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
Jeff Johnson20227a92018-03-13 09:41:05 -070015250 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015251 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015252 /* In the case of dynamic wep
15253 * supplicant hardcodes DWEP type to
15254 * eCSR_ENCRYPT_TYPE_WEP104 even
15255 * though ap is configured for WEP-40
15256 * encryption. In this canse the key
15257 * length is 5 but the encryption type
15258 * is 104 hence checking the key
Jeff Johnsonfe8e9492018-05-06 15:40:52 -070015259 * length(5) and encryption type(104)
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015260 * and switching encryption type to 40
15261 */
Jeff Johnson20227a92018-03-13 09:41:05 -070015262 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015263 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
Jeff Johnson20227a92018-03-13 09:41:05 -070015264 roam_profile->mcEncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015265 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
15266 }
15267
15268 setKey.encType =
Jeff Johnson20227a92018-03-13 09:41:05 -070015269 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015270 encryptionType[0];
15271
15272 /* Issue set key request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015273 status = sme_roam_set_key(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080015274 adapter->vdev_id, &setKey,
Jeff Johnson29c78672019-02-26 21:05:53 -080015275 &roam_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015276
15277 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015278 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015279 status);
15280 return -EINVAL;
15281 }
15282 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015283 } else if (QDF_SAP_MODE == adapter->device_mode) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053015284 struct hdd_ap_ctx *ap_ctx =
15285 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnson61b5e982018-03-15 11:33:31 -070015286 struct csr_roam_profile *profile =
Nachiket Kukaded9152832017-10-16 16:18:22 +053015287 wlan_sap_get_roam_profile(ap_ctx->sap_context);
15288
15289 if (!profile) {
15290 hdd_err("Failed to get SAP Roam Profile");
15291 return -EINVAL;
15292 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015293 /* In SoftAp mode setting key direction for default mode */
15294 if ((eCSR_ENCRYPT_TYPE_TKIP !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053015295 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053015296 (eCSR_ENCRYPT_TYPE_AES !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053015297 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053015298 (eCSR_ENCRYPT_TYPE_AES_GCMP !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053015299 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053015300 (eCSR_ENCRYPT_TYPE_AES_GCMP_256 !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053015301 profile->EncryptionType.encryptionType[0])) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015302 /* Saving key direction for default key index to TX default */
Nachiket Kukaded9152832017-10-16 16:18:22 +053015303 ap_ctx->wep_key[key_index].keyDirection =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015304 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015305 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053015306 key_index);
Nachiket Kukaded9152832017-10-16 16:18:22 +053015307 ap_ctx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015308 }
15309 }
15310
Dustin Browne74003f2018-03-14 12:51:58 -070015311 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015312 return status;
15313}
Kiran Kumar Lokere7d6e4c92018-09-19 13:45:47 -070015314#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015315
15316static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
15317 struct net_device *ndev,
15318 u8 key_index,
15319 bool unicast, bool multicast)
15320{
Dustin Brown1d31b082018-11-22 14:41:20 +053015321 int errno;
15322 struct osif_vdev_sync *vdev_sync;
15323
15324 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
15325 if (errno)
15326 return errno;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -070015327
Dustin Brown1d31b082018-11-22 14:41:20 +053015328 errno = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index,
15329 unicast, multicast);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015330
Dustin Brown1d31b082018-11-22 14:41:20 +053015331 osif_vdev_sync_op_stop(vdev_sync);
15332
15333 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015334}
15335
Abhishek Singh85283ae2019-03-08 12:00:51 +053015336void wlan_hdd_cfg80211_unlink_bss(struct hdd_adapter *adapter,
15337 tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015338{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015339 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015340 struct wireless_dev *wdev = dev->ieee80211_ptr;
15341 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015342 struct cfg80211_bss *bss = NULL;
15343
Abhishek Singh59cdca12019-03-08 13:48:20 +053015344 bss = wlan_cfg80211_get_bss(wiphy, NULL, bssid, NULL, 0);
Abhishek Singh85283ae2019-03-08 12:00:51 +053015345 if (!bss) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070015346 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015347 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015348 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053015349 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015350 cfg80211_unlink_bss(wiphy, bss);
Abhishek Singh85283ae2019-03-08 12:00:51 +053015351 /* cfg80211_get_bss get bss with ref count so release it */
15352 cfg80211_put_bss(wiphy, bss);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015353 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015354}
15355
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015356#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015357static inline int
15358wlan_hdd_get_frame_len(struct bss_description *bss_desc)
15359{
15360 return GET_IE_LEN_IN_BSS(bss_desc->length) + sizeof(qcom_ie_age);
15361}
15362
15363static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053015364 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015365{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015366 qcom_ie_age *qie_age = NULL;
Nachiket Kukade348ede72017-04-28 16:34:24 +053015367
15368 /*
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015369 * GPS Requirement: need age ie per entry. Using vendor specific.
15370 * Assuming this is the last IE, copy at the end
Nachiket Kukade348ede72017-04-28 16:34:24 +053015371 */
Abhishek Singhf1c16762018-03-07 10:48:46 +053015372 *ie_length -= sizeof(qcom_ie_age);
15373 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + *ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015374 qie_age->element_id = QCOM_VENDOR_IE_ID;
15375 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
15376 qie_age->oui_1 = QCOM_OUI1;
15377 qie_age->oui_2 = QCOM_OUI2;
15378 qie_age->oui_3 = QCOM_OUI3;
15379 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053015380 /*
15381 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
15382 * all bss related timestamp is in units of ms. Due to this when scan
15383 * results are sent to lowi the scan age is high.To address this,
15384 * send age in units of 1/10 ms.
15385 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015386 qie_age->age = (uint32_t)(qdf_mc_timer_get_system_time() -
15387 bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015388 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070015389 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
15390 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070015391 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
15392 sizeof(qie_age->seq_ctrl));
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015393}
15394#else
15395static inline int
15396wlan_hdd_get_frame_len(struct bss_description *bss_desc)
15397{
15398 return GET_IE_LEN_IN_BSS(bss_desc->length);
15399}
15400static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053015401 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015402{
15403}
15404#endif /* WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015405
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015406
15407struct cfg80211_bss *
15408wlan_hdd_inform_bss_frame(struct hdd_adapter *adapter,
15409 struct bss_description *bss_desc)
15410{
15411 struct wireless_dev *wdev = adapter->dev->ieee80211_ptr;
15412 struct wiphy *wiphy = wdev->wiphy;
Abhishek Singhf1c16762018-03-07 10:48:46 +053015413 uint32_t ie_length = wlan_hdd_get_frame_len(bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015414 const char *ie =
15415 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
15416 uint32_t freq, i;
15417 struct cfg80211_bss *bss_status = NULL;
15418 struct hdd_context *hdd_ctx;
15419 struct timespec ts;
15420 struct hdd_config *cfg_param;
15421 struct wlan_cfg80211_inform_bss bss_data = {0};
15422
15423 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
15424 /*
15425 * wlan_hdd_validate_context should not be used here, In validate ctx
15426 * start_modules_in_progress or stop_modules_in_progress is validated,
15427 * If the start_modules_in_progress is set to true means the interface
15428 * is not UP yet if the stop_modules_in_progress means that interface
15429 * is already down. So in both the two scenario's driver should not be
15430 * informing bss to kernel. Hence removing the validate context.
15431 */
15432
15433 if (!hdd_ctx || !hdd_ctx->config) {
15434 hdd_debug("HDD context is Null");
15435 return NULL;
15436 }
15437
15438 if (cds_is_driver_recovering() ||
15439 cds_is_load_or_unload_in_progress()) {
15440 hdd_debug("Recovery or load/unload in progress. State: 0x%x",
15441 cds_get_driver_state());
15442 return NULL;
15443 }
15444
15445 cfg_param = hdd_ctx->config;
15446 bss_data.frame_len = ie_length + offsetof(struct ieee80211_mgmt,
15447 u.probe_resp.variable);
15448 bss_data.mgmt = qdf_mem_malloc(bss_data.frame_len);
Min Liu74a1a502018-10-10 19:59:07 +080015449 if (!bss_data.mgmt)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015450 return NULL;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015451
15452 memcpy(bss_data.mgmt->bssid, bss_desc->bssId, ETH_ALEN);
15453
15454 /* Android does not want the timestamp from the frame.
15455 * Instead it wants a monotonic increasing value
15456 */
15457 get_monotonic_boottime(&ts);
15458 bss_data.mgmt->u.probe_resp.timestamp =
15459 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
15460
15461 bss_data.mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
15462 bss_data.mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
15463
Abhishek Singhf1c16762018-03-07 10:48:46 +053015464 wlan_hdd_add_age_ie(bss_data.mgmt, &ie_length, bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015465
15466 memcpy(bss_data.mgmt->u.probe_resp.variable, ie, ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015467 if (bss_desc->fProbeRsp) {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015468 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015469 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
15470 } else {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015471 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015472 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
15473 }
15474
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015475 if (bss_desc->channelId <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015476 (wiphy->bands[HDD_NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015477 freq =
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015478 ieee80211_channel_to_frequency(bss_desc->channelId,
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -070015479 HDD_NL80211_BAND_2GHZ);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015480 } else if ((bss_desc->channelId > ARRAY_SIZE(hdd_channels_2_4_ghz))
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015481 && (wiphy->bands[HDD_NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015482 freq =
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015483 ieee80211_channel_to_frequency(bss_desc->channelId,
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -070015484 HDD_NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015485 } else {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015486 hdd_err("Invalid channel: %d", bss_desc->channelId);
15487 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015488 return NULL;
15489 }
15490
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015491 bss_data.chan = ieee80211_get_channel(wiphy, freq);
15492 if (!bss_data.chan) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053015493 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015494 bss_desc->channelId, freq);
15495 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015496 return NULL;
15497 }
15498
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015499 /*
15500 * Based on .ini configuration, raw rssi can be reported for bss.
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070015501 * Raw rssi is typically used for estimating power.
15502 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015503 bss_data.rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070015504 bss_desc->rssi;
15505
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015506 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015507 bss_data.rssi = QDF_MIN(bss_data.rssi, 0) * 100;
15508
15509 bss_data.boottime_ns = bss_desc->scansystimensec;
15510
15511 /* Set all per chain rssi as invalid */
15512 for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++)
Yeshwanth Sriram Guntuka14ab04c2018-09-21 15:06:49 +053015513 bss_data.per_chain_rssi[i] = WLAN_INVALID_PER_CHAIN_RSSI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015514
Abhishek Singhef6f38c2018-12-20 13:51:29 +053015515 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u seq %d",
15516 MAC_ADDR_ARRAY(bss_data.mgmt->bssid),
15517 bss_data.chan->center_freq, (int)(bss_data.rssi / 100),
15518 bss_desc->timeStamp[0], ((bss_desc->seq_ctrl.seqNumHi <<
15519 HIGH_SEQ_NUM_OFFSET) | bss_desc->seq_ctrl.seqNumLo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015520
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015521 bss_status = wlan_cfg80211_inform_bss_frame_data(wiphy, &bss_data);
Jeff Johnsonb8944722017-09-03 09:03:19 -070015522 hdd_ctx->beacon_probe_rsp_cnt_per_scan++;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015523 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015524 return bss_status;
15525}
15526
15527/**
15528 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015529 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070015530 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015531 *
15532 * This function is used to update the BSS data base of CFG8011
15533 *
15534 * Return: struct cfg80211_bss pointer
15535 */
Jeff Johnson172237b2017-11-07 15:32:59 -080015536struct cfg80211_bss *
15537wlan_hdd_cfg80211_update_bss_db(struct hdd_adapter *adapter,
15538 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015539{
15540 tCsrRoamConnectedProfile roamProfile;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015541 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015542 struct cfg80211_bss *bss = NULL;
15543
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015544 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
Jeff Johnsoncf07c312019-02-04 13:53:29 -080015545 sme_roam_get_connect_profile(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070015546 &roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015547
15548 if (NULL != roamProfile.pBssDesc) {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015549 bss = wlan_hdd_inform_bss_frame(adapter, roamProfile.pBssDesc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015550
15551 if (NULL == bss)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053015552 hdd_debug("wlan_hdd_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015553
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080015554 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015555 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070015556 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015557 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015558 return bss;
15559}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015560
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015561/**
15562 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015563 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070015564 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015565 * @index: Index
15566 * @preauth: Preauth flag
15567 *
15568 * This function is used to notify the supplicant of a new PMKSA candidate.
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080015569 * PMK value is notified to supplicant whether PMK caching or OKC is enabled
15570 * in firmware or not. Supplicant needs this value becaue it uses PMK caching
15571 * by default.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015572 *
15573 * Return: 0 for success, non-zero for failure
15574 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015575int wlan_hdd_cfg80211_pmksa_candidate_notify(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080015576 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015577 int index, bool preauth)
15578{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015579 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015580
Dustin Brown491d54b2018-03-14 12:39:11 -070015581 hdd_enter();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015582 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015583
Jeff Johnsonfd060852017-10-04 10:50:51 -070015584 if (NULL == roam_info) {
15585 hdd_err("roam_info is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015586 return -EINVAL;
15587 }
15588
Dustin Brown5e89ef82018-03-14 11:50:23 -070015589 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080015590 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnsonfd060852017-10-04 10:50:51 -070015591 roam_info->bssid.bytes,
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080015592 preauth, GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015593 return 0;
15594}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015595
15596#ifdef FEATURE_WLAN_LFR_METRICS
15597/**
15598 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015599 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070015600 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015601 *
15602 * 802.11r/LFR metrics reporting function to report preauth initiation
15603 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053015604 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015605 */
15606#define MAX_LFR_METRICS_EVENT_LENGTH 100
Jeff Johnson172237b2017-11-07 15:32:59 -080015607QDF_STATUS
15608wlan_hdd_cfg80211_roam_metrics_preauth(struct hdd_adapter *adapter,
15609 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015610{
15611 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
15612 union iwreq_data wrqu;
15613
Dustin Brown491d54b2018-03-14 12:39:11 -070015614 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015615
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015616 if (NULL == adapter) {
15617 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015618 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015619 }
15620
15621 /* create the event */
15622 memset(&wrqu, 0, sizeof(wrqu));
15623 memset(metrics_notification, 0, sizeof(metrics_notification));
15624
15625 wrqu.data.pointer = metrics_notification;
15626 wrqu.data.length = scnprintf(metrics_notification,
15627 sizeof(metrics_notification),
15628 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
Jeff Johnsonfd060852017-10-04 10:50:51 -070015629 MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015630
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015631 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015632 metrics_notification);
15633
Dustin Browne74003f2018-03-14 12:51:58 -070015634 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015635
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015636 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015637}
15638
15639/**
15640 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015641 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070015642 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015643 * @preauth_status: Preauth status
15644 *
15645 * 802.11r/LFR metrics reporting function to report handover initiation
15646 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053015647 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015648 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015649QDF_STATUS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015650wlan_hdd_cfg80211_roam_metrics_preauth_status(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080015651 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015652 bool preauth_status)
15653{
15654 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
15655 union iwreq_data wrqu;
15656
Dustin Brown491d54b2018-03-14 12:39:11 -070015657 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015658
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015659 if (NULL == adapter) {
15660 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015661 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015662 }
15663
15664 /* create the event */
15665 memset(&wrqu, 0, sizeof(wrqu));
15666 memset(metrics_notification, 0, sizeof(metrics_notification));
15667
15668 scnprintf(metrics_notification, sizeof(metrics_notification),
15669 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
Jeff Johnsonfd060852017-10-04 10:50:51 -070015670 MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015671
15672 if (1 == preauth_status)
15673 strlcat(metrics_notification, " true",
15674 sizeof(metrics_notification));
15675 else
15676 strlcat(metrics_notification, " false",
15677 sizeof(metrics_notification));
15678
15679 wrqu.data.pointer = metrics_notification;
15680 wrqu.data.length = strlen(metrics_notification);
15681
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015682 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015683 metrics_notification);
15684
Dustin Browne74003f2018-03-14 12:51:58 -070015685 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015686
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015687 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015688}
15689
15690/**
15691 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015692 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070015693 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015694 *
15695 * 802.11r/LFR metrics reporting function to report handover initiation
15696 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053015697 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015698 */
Jeff Johnson172237b2017-11-07 15:32:59 -080015699QDF_STATUS
15700wlan_hdd_cfg80211_roam_metrics_handover(struct hdd_adapter *adapter,
15701 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015702{
15703 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
15704 union iwreq_data wrqu;
15705
Dustin Brown491d54b2018-03-14 12:39:11 -070015706 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015707
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015708 if (NULL == adapter) {
15709 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015710 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015711 }
15712
15713 /* create the event */
15714 memset(&wrqu, 0, sizeof(wrqu));
15715 memset(metrics_notification, 0, sizeof(metrics_notification));
15716
15717 wrqu.data.pointer = metrics_notification;
15718 wrqu.data.length = scnprintf(metrics_notification,
15719 sizeof(metrics_notification),
15720 "QCOM: LFR_PREAUTH_HANDOVER "
15721 MAC_ADDRESS_STR,
Jeff Johnsonfd060852017-10-04 10:50:51 -070015722 MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015723
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015724 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015725 metrics_notification);
15726
Dustin Browne74003f2018-03-14 12:51:58 -070015727 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015728
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015729 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015730}
15731#endif
15732
Nirav Shah73713f72018-05-17 14:50:41 +053015733#ifdef FEATURE_MONITOR_MODE_SUPPORT
15734static
15735void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
15736 uint8_t operationChannel,
15737 struct ch_params *ch_params)
15738{
15739 struct hdd_station_ctx *station_ctx =
15740 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15741 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
15742 enum hdd_dot11_mode hdd_dot11_mode;
15743 uint8_t ini_dot11_mode =
15744 (WLAN_HDD_GET_CTX(adapter))->config->dot11Mode;
15745
15746 hdd_debug("Dot11Mode is %u", ini_dot11_mode);
15747 switch (ini_dot11_mode) {
15748 case eHDD_DOT11_MODE_AUTO:
15749 case eHDD_DOT11_MODE_11ax:
15750 case eHDD_DOT11_MODE_11ax_ONLY:
15751 if (sme_is_feature_supported_by_fw(DOT11AX))
15752 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
15753 else if (sme_is_feature_supported_by_fw(DOT11AC))
15754 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
15755 else
15756 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
15757 break;
15758 case eHDD_DOT11_MODE_11ac:
15759 case eHDD_DOT11_MODE_11ac_ONLY:
15760 if (sme_is_feature_supported_by_fw(DOT11AC))
15761 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
15762 else
15763 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
15764 break;
15765 case eHDD_DOT11_MODE_11n:
15766 case eHDD_DOT11_MODE_11n_ONLY:
15767 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
15768 break;
15769 default:
15770 hdd_dot11_mode = ini_dot11_mode;
15771 break;
15772 }
15773 ch_info->channel_width = ch_params->ch_width;
15774 ch_info->phy_mode =
15775 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
15776 ch_info->channel = operationChannel;
15777 ch_info->cb_mode = ch_params->ch_width;
15778 hdd_debug("ch_info width %d, phymode %d channel %d",
15779 ch_info->channel_width, ch_info->phy_mode,
15780 ch_info->channel);
15781}
15782#else
15783static
15784void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
15785 uint8_t operationChannel,
15786 struct ch_params *ch_params)
15787{
15788}
15789#endif
15790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015791/**
15792 * hdd_select_cbmode() - select channel bonding mode
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015793 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015794 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015795 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015796 *
15797 * Return: none
15798 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015799void hdd_select_cbmode(struct hdd_adapter *adapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080015800 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015801{
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015802 uint8_t sec_ch = 0;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015803 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Chaoli Zhou75b062f2018-06-11 12:36:54 +080015804 struct hdd_station_ctx *station_ctx =
15805 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15806 eConnectionState connstate;
15807 bool cbmode_select = false;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015808
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015809 /*
15810 * CDS api expects secondary channel for calculating
15811 * the channel params
15812 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015813 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070015814 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015815 if (operationChannel >= 1 && operationChannel <= 5)
15816 sec_ch = operationChannel + 4;
15817 else if (operationChannel >= 6 && operationChannel <= 13)
15818 sec_ch = operationChannel - 4;
15819 }
15820
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015821 /* This call decides required channel bonding mode */
Dustin Brown07901ec2018-09-07 11:02:41 -070015822 wlan_reg_set_channel_params(hdd_ctx->pdev, operationChannel,
15823 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015824
Chaoli Zhou75b062f2018-06-11 12:36:54 +080015825 if (adapter->device_mode == QDF_STA_MODE &&
Pragaspathi Thilagaraja8893752019-02-06 19:58:59 +053015826 ucfg_mlme_is_change_channel_bandwidth_enabled(hdd_ctx->psoc)) {
Jeff Johnsone7951512019-02-27 10:02:51 -080015827 connstate = station_ctx->conn_info.conn_state;
Chaoli Zhou75b062f2018-06-11 12:36:54 +080015828 if (!(eConnectionState_Associated == connstate ||
15829 eConnectionState_Connecting == connstate)) {
15830 cbmode_select = true;
15831 }
15832 }
15833
15834 if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE || cbmode_select)
Nirav Shah73713f72018-05-17 14:50:41 +053015835 hdd_mon_select_cbmode(adapter, operationChannel, ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015836}
15837
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070015838/**
15839 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
15840 * @adapter: STA adapter
15841 * @roam_profile: STA roam profile
15842 *
15843 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
15844 *
15845 * Return: false if sta-sap conc is not allowed, else return true
15846 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070015847static
15848bool wlan_hdd_handle_sap_sta_dfs_conc(struct hdd_adapter *adapter,
15849 struct csr_roam_profile *roam_profile)
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070015850{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015851 struct hdd_context *hdd_ctx;
Jeff Johnsone5006672017-08-29 14:39:02 -070015852 struct hdd_adapter *ap_adapter;
Jeff Johnson87251032017-08-29 13:31:11 -070015853 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070015854 struct hdd_hostapd_state *hostapd_state;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070015855 uint8_t channel = 0;
15856 QDF_STATUS status;
15857
15858 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
15859 if (!hdd_ctx) {
15860 hdd_err("HDD context is NULL");
15861 return true;
15862 }
15863
15864 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
15865 /* probably no sap running, no handling required */
15866 if (ap_adapter == NULL)
15867 return true;
15868
15869 /*
15870 * sap is not in started state, so it is fine to go ahead with sta.
15871 * if sap is currently doing CAC then don't allow sta to go further.
15872 */
15873 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
15874 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
15875 return true;
15876
15877 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
15878 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
15879 return false;
15880 }
15881
15882 /*
15883 * log and return error, if we allow STA to go through, we don't
15884 * know what is going to happen better stop sta connection
15885 */
15886 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
15887 if (NULL == hdd_ap_ctx) {
15888 hdd_err("AP context not found");
15889 return false;
15890 }
15891
15892 /* sap is on non-dfs channel, nothing to handle */
Dustin Brown07901ec2018-09-07 11:02:41 -070015893 if (!wlan_reg_is_dfs_ch(hdd_ctx->pdev,
Jeff Johnson01206862017-10-27 20:55:59 -070015894 hdd_ap_ctx->operating_channel)) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070015895 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070015896 return true;
15897 }
15898 /*
15899 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053015900 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070015901 */
Dustin Brown76cd2932018-09-11 16:03:05 -070015902 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070015903 roam_profile, &channel);
15904
Nitesh Shah59774522016-09-16 15:14:21 +053015905 /*
15906 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
15907 * channels for roaming case.
15908 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070015909 if (WLAN_REG_IS_24GHZ_CH(channel)) {
15910 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053015911 return true;
15912 }
15913
15914 /*
Jeff Johnsondcf84ce2017-10-05 09:26:24 -070015915 * If channel is 0 or DFS or LTE unsafe then better to call pcl and
Tushnim Bhattacharyya9a929992017-06-18 00:59:09 -070015916 * find out the best channel. If channel is non-dfs 5 GHz then
15917 * better move SAP to STA's channel to make scc, so we have room
15918 * for 3port MCC scenario.
Nitesh Shah59774522016-09-16 15:14:21 +053015919 */
Dustin Brown07901ec2018-09-07 11:02:41 -070015920 if (!channel || wlan_reg_is_dfs_ch(hdd_ctx->pdev, channel) ||
Dustin Brown76cd2932018-09-11 16:03:05 -070015921 !policy_mgr_is_safe_channel(hdd_ctx->psoc, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015922 channel = policy_mgr_get_nondfs_preferred_channel(
Dustin Brown76cd2932018-09-11 16:03:05 -070015923 hdd_ctx->psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070015924
15925 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
15926 qdf_event_reset(&hostapd_state->qdf_event);
15927 status = wlansap_set_channel_change_with_csa(
15928 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
Jeff Johnson91df29d2017-10-27 19:29:50 -070015929 hdd_ap_ctx->sap_config.ch_width_orig, false);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070015930
15931 if (QDF_STATUS_SUCCESS != status) {
15932 hdd_err("Set channel with CSA IE failed, can't allow STA");
15933 return false;
15934 }
15935
15936 /*
15937 * wait here for SAP to finish the channel switch. When channel
15938 * switch happens, SAP sends few beacons with CSA_IE. After
15939 * successfully Transmission of those beacons, it will move its
15940 * state from started to disconnected and move to new channel.
15941 * once it moves to new channel, sap again moves its state
15942 * machine from disconnected to started and set this event.
15943 * wait for 10 secs to finish this.
15944 */
Nachiket Kukade0396b732017-11-14 16:35:16 +053015945 status = qdf_wait_for_event_completion(&hostapd_state->qdf_event, 10000);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070015946 if (!QDF_IS_STATUS_SUCCESS(status)) {
15947 hdd_err("wait for qdf_event failed, STA not allowed!!");
15948 return false;
15949 }
15950
15951 return true;
15952}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015953
Abhishek Singhcfb44482017-03-10 12:42:37 +053015954#ifdef WLAN_FEATURE_11W
15955/**
15956 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
15957 * @roam_profile: pointer to roam profile
15958 *
15959 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
15960 * or pmf=2 is an explicit configuration in the supplicant
15961 * configuration, drop the connection request.
15962 *
15963 * Return: 0 if check result is valid, otherwise return error code
15964 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070015965static
15966int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053015967{
15968 if (roam_profile->MFPEnabled &&
Jeff Johnson20227a92018-03-13 09:41:05 -070015969 !(roam_profile->MFPRequired || roam_profile->MFPCapable)) {
Abhishek Singhcfb44482017-03-10 12:42:37 +053015970 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
15971 roam_profile->MFPEnabled,
15972 roam_profile->MFPRequired,
15973 roam_profile->MFPCapable);
15974 return -EINVAL;
15975 }
15976 return 0;
15977}
15978#else
15979static inline
Jeff Johnson61b5e982018-03-15 11:33:31 -070015980int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053015981{
15982 return 0;
15983}
15984#endif
15985
Krunal Soni31949422016-07-29 17:17:53 -070015986/**
15987 * wlan_hdd_cfg80211_connect_start() - to start the association process
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015988 * @adapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070015989 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015990 * @ssid_len: Length of ssid
15991 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070015992 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015993 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015994 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015995 *
15996 * This function is used to start the association process
15997 *
15998 * Return: 0 for success, non-zero for failure
15999 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016000static int wlan_hdd_cfg80211_connect_start(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016001 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070016002 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016003 u8 operatingChannel,
16004 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016005{
16006 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080016007 QDF_STATUS qdf_status;
Jeff Johnsonb8944722017-09-03 09:03:19 -070016008 struct hdd_context *hdd_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070016009 struct hdd_station_ctx *hdd_sta_ctx;
Jeff Johnson29c78672019-02-26 21:05:53 -080016010 uint32_t roam_id = INVALID_ROAM_ID;
Jeff Johnson61b5e982018-03-15 11:33:31 -070016011 struct csr_roam_profile *roam_profile;
Jeff Johnson784efe22019-03-09 18:31:13 -080016012 eCsrAuthType rsn_auth_type;
Jeff Johnson46b4f0e2019-03-08 10:48:35 -080016013 struct sme_config_params *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053016014 uint8_t channel = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016015 mac_handle_t mac_handle;
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +053016016 uint8_t wmm_mode = 0;
16017 uint8_t value = 0;
Min Liu8c5d99e2018-09-10 17:18:44 +080016018 struct wlan_objmgr_vdev *vdev;
Wu Gaoed616a12019-01-16 15:19:21 +080016019 uint32_t channel_bonding_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016020
Dustin Brown491d54b2018-03-14 12:39:11 -070016021 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016022
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016023 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16024 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016025
Jeff Johnsonb8944722017-09-03 09:03:19 -070016026 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016027 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016028 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016029
16030 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016031 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016032 status = -EINVAL;
16033 goto ret_status;
16034 }
16035
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016036 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016037 hdd_err("Connection refused: conn in progress");
16038 status = -EINVAL;
16039 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016040 }
16041
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053016042 /* Disable roaming on all other adapters before connect start */
16043 wlan_hdd_disable_roaming(adapter);
16044
Min Liu8c5d99e2018-09-10 17:18:44 +080016045 vdev = hdd_objmgr_get_vdev(adapter);
16046 if (!vdev) {
16047 status = -EINVAL;
16048 goto ret_status;
16049 }
16050 hdd_notify_teardown_tdls_links(vdev);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053016051 hdd_objmgr_put_vdev(vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053016052
Anurag Chouhand939d3d2016-07-20 17:45:48 +053016053 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
16054 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016055
Jeff Johnson20227a92018-03-13 09:41:05 -070016056 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016057 if (roam_profile) {
Jeff Johnsond377dce2017-10-04 10:32:42 -070016058 struct hdd_station_ctx *sta_ctx;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070016059
Jeff Johnsond377dce2017-10-04 10:32:42 -070016060 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016061
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016062 /* Restart the opportunistic timer
16063 *
16064 * If hw_mode_change_in_progress is true, then wait
16065 * till firmware sends the callback for hw_mode change.
16066 *
16067 * Else set connect_in_progress as true and proceed.
16068 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016069 policy_mgr_restart_opportunistic_timer(
Dustin Brown76cd2932018-09-11 16:03:05 -070016070 hdd_ctx->psoc, false);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016071 if (policy_mgr_is_hw_mode_change_in_progress(
Dustin Brown76cd2932018-09-11 16:03:05 -070016072 hdd_ctx->psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053016073 qdf_status = policy_mgr_wait_for_connection_update(
Dustin Brown76cd2932018-09-11 16:03:05 -070016074 hdd_ctx->psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053016075 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016076 hdd_err("qdf wait for event failed!!");
16077 status = -EINVAL;
16078 goto ret_status;
16079 }
16080 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016081 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016082
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +053016083 status = ucfg_mlme_get_wmm_mode(hdd_ctx->psoc, &wmm_mode);
16084 if (!QDF_IS_STATUS_SUCCESS(status)) {
16085 hdd_err("Get wmm_mode failed");
16086 status = -EINVAL;
16087 goto ret_status;
16088 }
16089 if (HDD_WMM_USER_MODE_NO_QOS == wmm_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016090 /*QoS not enabled in cfg file */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016091 roam_profile->uapsd_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016092 } else {
16093 /*QoS enabled, update uapsd mask from cfg file */
Abhinav Kumar7d6f1ac2018-09-01 18:33:56 +053016094 status = ucfg_mlme_get_wmm_uapsd_mask(hdd_ctx->psoc,
16095 &value);
16096 if (!QDF_IS_STATUS_SUCCESS(status)) {
16097 hdd_err("Get uapsd_mask failed");
16098 status = -EINVAL;
16099 goto ret_status;
16100 }
16101 roam_profile->uapsd_mask = value;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016102 }
16103
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016104 roam_profile->SSIDs.numOfSSIDs = 1;
16105 roam_profile->SSIDs.SSIDList->SSID.length = ssid_len;
16106 qdf_mem_zero(roam_profile->SSIDs.SSIDList->SSID.ssId,
16107 sizeof(roam_profile->SSIDs.SSIDList->SSID.ssId));
16108 qdf_mem_copy((void *)(roam_profile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016109 ssid, ssid_len);
16110
Abhishek Singh3c9910e2017-01-06 17:56:47 +053016111 /* cleanup bssid hint */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016112 qdf_mem_zero(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053016113 QDF_MAC_ADDR_SIZE);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016114 qdf_mem_zero((void *)(roam_profile->BSSIDs.bssid),
Abhishek Singh3c9910e2017-01-06 17:56:47 +053016115 QDF_MAC_ADDR_SIZE);
16116
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016117 if (bssid) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016118 roam_profile->BSSIDs.numOfBSSIDs = 1;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016119 qdf_mem_copy((void *)(roam_profile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053016120 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070016121 /*
Jeff Johnsonfa7d9602018-05-06 11:25:31 -070016122 * Save BSSID in separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016123 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070016124 * association process. In case of join failure
16125 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016126 */
Jeff Johnson731bc322017-10-14 19:53:44 -070016127 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
16128 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016129 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016130 } else if (bssid_hint) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016131 qdf_mem_copy(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053016132 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070016133 /*
16134 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016135 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070016136 * association process. In case of join failure
16137 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016138 */
Jeff Johnson731bc322017-10-14 19:53:44 -070016139 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053016140 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016141 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070016142 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016143 }
16144
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016145 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016146 roam_profile->SSIDs.SSIDList->SSID.length,
16147 roam_profile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016148 operatingChannel);
16149
Jeff Johnsonce4a8342017-10-14 13:12:22 -070016150 if (hdd_sta_ctx->wpa_versions) {
Jeff Johnson784efe22019-03-09 18:31:13 -080016151 hdd_set_genie_to_csr(adapter, &rsn_auth_type);
16152 hdd_set_csr_auth_type(adapter, rsn_auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016153 }
16154#ifdef FEATURE_WLAN_WAPI
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070016155 if (adapter->wapi_info.wapi_mode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016156 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070016157 switch (adapter->wapi_info.wapi_auth_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016158 case WAPI_AUTH_MODE_PSK:
16159 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016160 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070016161 adapter->wapi_info.wapi_auth_mode);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016162 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016163 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
16164 break;
16165 }
16166 case WAPI_AUTH_MODE_CERT:
16167 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016168 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070016169 adapter->wapi_info.wapi_auth_mode);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016170 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016171 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
16172 break;
16173 }
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070016174 default:
16175 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016176 } /* End of switch */
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070016177 if (adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016178 WAPI_AUTH_MODE_PSK
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070016179 || adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016180 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016181 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016182 roam_profile->AuthType.numEntries = 1;
16183 roam_profile->EncryptionType.numEntries = 1;
16184 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016185 eCSR_ENCRYPT_TYPE_WPI;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016186 roam_profile->mcEncryptionType.numEntries = 1;
16187 roam_profile->mcEncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016188 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
16189 }
16190 }
Krunal Soni31949422016-07-29 17:17:53 -070016191#endif
Min Liu8c5d99e2018-09-10 17:18:44 +080016192 vdev = hdd_objmgr_get_vdev(adapter);
16193 if (!vdev) {
16194 status = -EINVAL;
16195 goto conn_failure;
16196 }
16197 ucfg_pmo_flush_gtk_offload_req(vdev);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053016198 hdd_objmgr_put_vdev(vdev);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016199 roam_profile->csrPersona = adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016200
16201 if (operatingChannel) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016202 roam_profile->ChannelInfo.ChannelList =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016203 &operatingChannel;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016204 roam_profile->ChannelInfo.numOfChannels = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016205 } else {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016206 roam_profile->ChannelInfo.ChannelList = NULL;
16207 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016208 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016209 if ((QDF_IBSS_MODE == adapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016210 && operatingChannel) {
16211 /*
16212 * Need to post the IBSS power save parameters
16213 * to WMA. WMA will configure this parameters
16214 * to firmware if power save is enabled by the
16215 * firmware.
16216 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016217 qdf_status = hdd_set_ibss_power_save_params(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016218
Abhishek Singh471652b2017-04-14 12:28:32 +053016219 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016220 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016221 status = -EINVAL;
16222 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016223 }
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016224 roam_profile->ch_params.ch_width =
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016225 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053016226 /*
16227 * In IBSS mode while operating in 2.4 GHz,
16228 * the device supports only 20 MHz.
16229 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016230 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016231 roam_profile->ch_params.ch_width =
Nitesh Shah87335a52016-09-05 15:47:32 +053016232 CH_WIDTH_20MHZ;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016233 hdd_select_cbmode(adapter, operatingChannel,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016234 &roam_profile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016235 }
16236
Jeff Johnson20227a92018-03-13 09:41:05 -070016237 if (wlan_hdd_cfg80211_check_pmf_valid(roam_profile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016238 status = -EINVAL;
16239 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016240 }
16241
Krunal Soni31949422016-07-29 17:17:53 -070016242 /*
16243 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016244 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070016245 * enhancements, the supplicant is not issuing the scan command
16246 * now. So the unicast frames which are sent from the host are
16247 * not having the additional IEs. If it is P2P CLIENT and there
16248 * is no additional IE present in roamProfile, then use the
16249 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016250 */
16251
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016252 if ((adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016253 (!roam_profile->pAddIEScan)) {
16254 roam_profile->pAddIEScan =
Jeff Johnson37fa0402017-10-28 12:42:29 -070016255 &adapter->scan_info.scan_add_ie.addIEdata[0];
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016256 roam_profile->nAddIEScanLength =
Jeff Johnson37fa0402017-10-28 12:42:29 -070016257 adapter->scan_info.scan_add_ie.length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016258 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016259
Dustin Brown76cd2932018-09-11 16:03:05 -070016260 if ((policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) == true)
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016261 && (false == wlan_hdd_handle_sap_sta_dfs_conc(adapter,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016262 roam_profile))) {
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070016263 hdd_err("sap-sta conc will fail, can't allow sta");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016264 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070016265 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016266 status = -ENOMEM;
16267 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070016268 }
16269
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016270 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016271 if (!sme_config) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016272 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070016273 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016274 status = -ENOMEM;
16275 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016276 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016277
16278 mac_handle = hdd_ctx->mac_handle;
16279 sme_get_config_param(mac_handle, sme_config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016280 /* These values are not sessionized. So, any change in these SME
16281 * configs on an older or parallel interface will affect the
16282 * cb mode. So, restoring the default INI params before starting
16283 * interfaces such as sta, cli etc.,
16284 */
Wu Gaoed616a12019-01-16 15:19:21 +080016285 ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc,
16286 &channel_bonding_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016287 sme_config->csrConfig.channelBondingMode5GHz =
Wu Gaoed616a12019-01-16 15:19:21 +080016288 channel_bonding_mode;
16289 ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
16290 &channel_bonding_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016291 sme_config->csrConfig.channelBondingMode24GHz =
Wu Gaoed616a12019-01-16 15:19:21 +080016292 channel_bonding_mode;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016293 sme_update_config(mac_handle, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016294 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053016295 /*
16296 * Change conn_state to connecting before sme_roam_connect(),
16297 * because sme_roam_connect() has a direct path to call
16298 * hdd_sme_roam_callback(), which will change the conn_state
16299 * If direct path, conn_state will be accordingly changed to
16300 * NotConnected or Associated by either
16301 * hdd_association_completion_handler() or
16302 * hdd_dis_connect_handler() in sme_RoamCallback()if
16303 * sme_RomConnect is to be queued,
16304 * Connecting state will remain until it is completed.
16305 *
16306 * If connection state is not changed, connection state will
16307 * remain in eConnectionState_NotConnected state.
16308 * In hdd_association_completion_handler, "hddDisconInProgress"
16309 * is set to true if conn state is
16310 * eConnectionState_NotConnected.
16311 * If "hddDisconInProgress" is set to true then cfg80211 layer
16312 * is not informed of connect result indication which
16313 * is an issue.
16314 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016315 if (QDF_STA_MODE == adapter->device_mode ||
16316 QDF_P2P_CLIENT_MODE == adapter->device_mode)
16317 hdd_conn_set_connection_state(adapter,
Agrawal Ashish6b015762016-05-05 11:22:18 +053016318 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016319
Alok Kumarb64650c2018-03-23 17:05:11 +053016320 hdd_set_disconnect_status(adapter, false);
16321
Jingxiang Geb49aa302018-01-17 20:54:15 +080016322 qdf_runtime_pm_prevent_suspend(
16323 &hdd_ctx->runtime_context.connect);
Padma, Santhosh Kumarc88de482018-04-09 16:17:04 +053016324 hdd_prevent_suspend_timeout(HDD_WAKELOCK_CONNECT_COMPLETE,
Dustin Brownceed67e2017-05-26 11:57:31 -070016325 WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016326 qdf_status = sme_roam_connect(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016327 adapter->vdev_id, roam_profile,
Jeff Johnson29c78672019-02-26 21:05:53 -080016328 &roam_id);
Abhishek Singh471652b2017-04-14 12:28:32 +053016329 if (QDF_IS_STATUS_ERROR(qdf_status))
16330 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016331
Rajeev Kumard31e1542017-01-13 14:37:42 -080016332 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016333 (QDF_STA_MODE == adapter->device_mode ||
16334 QDF_P2P_CLIENT_MODE == adapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016335 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080016336 "qdf_status %d. -> NotConnected",
Jeff Johnsoncf07c312019-02-04 13:53:29 -080016337 adapter->vdev_id, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016338 /* change back to NotAssociated */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016339 hdd_conn_set_connection_state(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016340 eConnectionState_NotConnected);
Jingxiang Geb49aa302018-01-17 20:54:15 +080016341 qdf_runtime_pm_allow_suspend(
16342 &hdd_ctx->runtime_context.connect);
Dustin Brownceed67e2017-05-26 11:57:31 -070016343 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016344 }
16345
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016346 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016347 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016348
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016349 roam_profile->ChannelInfo.ChannelList = NULL;
16350 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016351
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016352 if ((QDF_STA_MODE == adapter->device_mode)
Dustin Brown76cd2932018-09-11 16:03:05 -070016353 && policy_mgr_is_current_hwmode_dbs(hdd_ctx->psoc)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016354 && !policy_mgr_is_hw_dbs_2x2_capable(
Dustin Brown76cd2932018-09-11 16:03:05 -070016355 hdd_ctx->psoc)) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016356 policy_mgr_get_channel_from_scan_result(
Dustin Brown76cd2932018-09-11 16:03:05 -070016357 hdd_ctx->psoc,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016358 roam_profile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080016359 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053016360 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016361 policy_mgr_checkn_update_hw_mode_single_mac_mode(
Dustin Brown76cd2932018-09-11 16:03:05 -070016362 hdd_ctx->psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053016363 }
16364
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016365 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016366 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016367 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016368 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016369 goto ret_status;
16370
16371conn_failure:
16372 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016373 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053016374
16375ret_status:
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053016376 /*
16377 * Enable roaming on other STA adapter for failure case.
16378 * For success case, it is enabled in assoc completion handler
16379 */
16380 if (status)
16381 wlan_hdd_enable_roaming(adapter);
16382
Dustin Browne74003f2018-03-14 12:51:58 -070016383 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016384 return status;
16385}
16386
16387/**
16388 * wlan_hdd_cfg80211_set_auth_type() - set auth type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016389 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016390 * @auth_type: Auth type
16391 *
16392 * This function is used to set the authentication type (OPEN/SHARED).
16393 *
16394 * Return: 0 for success, non-zero for failure
16395 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016396static int wlan_hdd_cfg80211_set_auth_type(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016397 enum nl80211_auth_type auth_type)
16398{
Jeff Johnsond377dce2017-10-04 10:32:42 -070016399 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016400 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016401 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016402
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016403 /*set authentication type */
16404 switch (auth_type) {
16405 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016406 hdd_debug("set authentication type to AUTOSWITCH");
Jeff Johnson96e33512019-02-27 15:10:21 -080016407 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_AUTOSWITCH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016408 break;
16409
16410 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016411 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016412 hdd_debug("set authentication type to OPEN");
Jeff Johnson96e33512019-02-27 15:10:21 -080016413 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016414 break;
16415
16416 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016417 hdd_debug("set authentication type to SHARED");
Jeff Johnson96e33512019-02-27 15:10:21 -080016418 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_SHARED_KEY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016419 break;
16420#ifdef FEATURE_WLAN_ESE
16421 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016422 hdd_debug("set authentication type to CCKM WPA");
Jeff Johnson96e33512019-02-27 15:10:21 -080016423 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_CCKM_WPA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016424 break;
16425#endif
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053016426#if defined(WLAN_FEATURE_FILS_SK) && \
16427 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
16428 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016429 case NL80211_AUTHTYPE_FILS_SK:
Dustin Brown5e89ef82018-03-14 11:50:23 -070016430 hdd_debug("set authentication type to FILS SHARED");
Jeff Johnson96e33512019-02-27 15:10:21 -080016431 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016432 break;
16433#endif
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053016434 case NL80211_AUTHTYPE_SAE:
16435 hdd_debug("set authentication type to SAE");
Jeff Johnson96e33512019-02-27 15:10:21 -080016436 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_SAE;
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053016437 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016438 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016439 hdd_err("Unsupported authentication type: %d", auth_type);
Jeff Johnson96e33512019-02-27 15:10:21 -080016440 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_UNKNOWN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016441 return -EINVAL;
16442 }
16443
Jeff Johnson20227a92018-03-13 09:41:05 -070016444 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson96e33512019-02-27 15:10:21 -080016445 roam_profile->AuthType.authType[0] = sta_ctx->conn_info.auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016446 return 0;
16447}
16448
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053016449#if defined(WLAN_FEATURE_FILS_SK) && \
16450 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
16451 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Jeff Johnson20227a92018-03-13 09:41:05 -070016452static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016453{
16454 struct cds_fils_connection_info *fils_con_info;
16455
Jeff Johnson20227a92018-03-13 09:41:05 -070016456 fils_con_info = roam_profile->fils_con_info;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016457 if (!fils_con_info) {
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070016458 hdd_err("No valid Roam profile");
16459 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016460 }
16461
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070016462 return true;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016463}
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070016464
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016465static enum eAniAuthType wlan_hdd_get_fils_auth_type(
16466 enum nl80211_auth_type auth)
16467{
16468 switch (auth) {
16469 case NL80211_AUTHTYPE_FILS_SK:
16470 return SIR_FILS_SK_WITHOUT_PFS;
16471 case NL80211_AUTHTYPE_FILS_SK_PFS:
16472 return SIR_FILS_SK_WITH_PFS;
16473 case NL80211_AUTHTYPE_FILS_PK:
16474 return SIR_FILS_PK_AUTH;
16475 default:
16476 return eSIR_DONOT_USE_AUTH_TYPE;
16477 }
16478}
16479
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080016480static bool wlan_hdd_fils_data_in_limits(struct cfg80211_connect_params *req)
16481{
16482 hdd_debug("seq=%d auth=%d lengths: user=%zu rrk=%zu realm=%zu",
16483 req->fils_erp_next_seq_num, req->auth_type,
16484 req->fils_erp_username_len, req->fils_erp_rrk_len,
16485 req->fils_erp_realm_len);
16486 if (!req->fils_erp_rrk_len || !req->fils_erp_realm_len ||
16487 !req->fils_erp_username_len ||
16488 req->fils_erp_rrk_len > FILS_MAX_RRK_LENGTH ||
16489 req->fils_erp_realm_len > FILS_MAX_REALM_LEN ||
16490 req->fils_erp_username_len > FILS_MAX_KEYNAME_NAI_LENGTH) {
16491 hdd_err("length incorrect, user=%zu rrk=%zu realm=%zu",
16492 req->fils_erp_username_len, req->fils_erp_rrk_len,
16493 req->fils_erp_realm_len);
16494 return false;
16495 }
16496
bings77a35ac2018-06-01 15:10:44 +080016497 if (!req->fils_erp_rrk || !req->fils_erp_realm ||
16498 !req->fils_erp_username) {
16499 hdd_err("buffer incorrect, user=%pK rrk=%pK realm=%pK",
16500 req->fils_erp_username, req->fils_erp_rrk,
16501 req->fils_erp_realm);
16502 return false;
16503 }
16504
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080016505 return true;
16506}
16507
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016508/**
16509 * wlan_hdd_cfg80211_set_fils_config() - set fils config params during connect
16510 * @adapter: Pointer to adapter
16511 * @req: Pointer to fils parameters
16512 *
16513 * Return: 0 for success, non-zero for failure
16514 */
16515static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
16516 struct cfg80211_connect_params *req)
16517{
Jeff Johnson61b5e982018-03-15 11:33:31 -070016518 struct csr_roam_profile *roam_profile;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016519 enum eAniAuthType auth_type;
16520 uint8_t *buf;
Karthik Kantamneni2231a232018-09-11 15:45:55 +053016521 bool value;
16522 QDF_STATUS status;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016523 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16524
Jeff Johnson20227a92018-03-13 09:41:05 -070016525 roam_profile = hdd_roam_profile(adapter);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016526
Karthik Kantamneni2231a232018-09-11 15:45:55 +053016527 value = 0;
Dustin Brown05d81302018-09-11 16:49:22 -070016528 status = ucfg_mlme_get_fils_enabled_info(hdd_ctx->psoc, &value);
Karthik Kantamneni2231a232018-09-11 15:45:55 +053016529 if (QDF_IS_STATUS_ERROR(status) || !value) {
16530 hdd_err("get_fils_enabled status: %d fils_enabled: %d",
16531 status, value);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016532 return -EINVAL;
16533 }
Karthik Kantamneni2231a232018-09-11 15:45:55 +053016534
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016535 hdd_clear_fils_connection_info(adapter);
16536 roam_profile->fils_con_info =
16537 qdf_mem_malloc(sizeof(*roam_profile->fils_con_info));
16538
Min Liu74a1a502018-10-10 19:59:07 +080016539 if (!roam_profile->fils_con_info)
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016540 return -EINVAL;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016541 /*
16542 * The initial connection for FILS may happen with an OPEN
16543 * auth type. Hence we need to allow the connection to go
16544 * through in that case as well. Below is_fils_connection
16545 * flag is propagated down to CSR and PE sessions through
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080016546 * the JOIN request. As the flag is used, do not free the
16547 * memory allocated to fils_con_info and return success.
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016548 */
16549 if (req->auth_type != NL80211_AUTHTYPE_FILS_SK) {
16550 roam_profile->fils_con_info->is_fils_connection = false;
16551 return 0;
16552 }
16553
16554 /*
16555 * Once above check is done, then we can check for valid FILS
16556 * auth types. Currently only NL80211_AUTHTYPE_FILS_SK is
16557 * supported. Once all auth types are supported, then we can
16558 * merge these 2 conditions into one.
16559 */
16560 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
16561 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
16562 hdd_err("invalid auth type for fils %d", req->auth_type);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070016563 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016564 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080016565 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080016566 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016567
16568 roam_profile->fils_con_info->is_fils_connection = true;
16569 roam_profile->fils_con_info->sequence_number =
Pragaspathi Thilagaraj87a60af2019-02-20 20:42:47 +053016570 (req->fils_erp_next_seq_num + 1);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016571 roam_profile->fils_con_info->auth_type = auth_type;
16572
16573 roam_profile->fils_con_info->r_rk_length =
16574 req->fils_erp_rrk_len;
16575 if (req->fils_erp_rrk_len)
16576 qdf_mem_copy(roam_profile->fils_con_info->r_rk,
16577 req->fils_erp_rrk,
16578 roam_profile->fils_con_info->r_rk_length);
16579
16580 roam_profile->fils_con_info->realm_len = req->fils_erp_realm_len;
16581 if (req->fils_erp_realm_len)
16582 qdf_mem_copy(roam_profile->fils_con_info->realm,
16583 req->fils_erp_realm,
16584 roam_profile->fils_con_info->realm_len);
16585
16586 roam_profile->fils_con_info->key_nai_length =
16587 req->fils_erp_username_len + sizeof(char) +
16588 req->fils_erp_realm_len;
16589 hdd_debug("key_nai_length = %d",
16590 roam_profile->fils_con_info->key_nai_length);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070016591 if (roam_profile->fils_con_info->key_nai_length >
16592 FILS_MAX_KEYNAME_NAI_LENGTH) {
16593 hdd_err("Do not allow FILS conn due to excess NAI Length %d",
16594 roam_profile->fils_con_info->key_nai_length);
16595 goto fils_conn_fail;
16596 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080016597 buf = roam_profile->fils_con_info->keyname_nai;
16598 qdf_mem_copy(buf, req->fils_erp_username, req->fils_erp_username_len);
16599 buf += req->fils_erp_username_len;
16600 *buf++ = '@';
16601 qdf_mem_copy(buf, req->fils_erp_realm, req->fils_erp_realm_len);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016602
16603 return 0;
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070016604
16605fils_conn_fail:
16606 if (roam_profile->fils_con_info) {
16607 qdf_mem_free(roam_profile->fils_con_info);
16608 roam_profile->fils_con_info = NULL;
16609 }
16610 return -EINVAL;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016611}
16612
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070016613static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
16614{
16615 switch (key_mgmt) {
16616 case WLAN_AKM_SUITE_FILS_SHA256:
16617 case WLAN_AKM_SUITE_FILS_SHA384:
16618 case WLAN_AKM_SUITE_FT_FILS_SHA256:
16619 case WLAN_AKM_SUITE_FT_FILS_SHA384:
16620 return true;
16621 default:
16622 return false;
16623 }
16624}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016625
16626static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
16627{
16628 enum nl80211_auth_type auth_type = req->auth_type;
16629 /*
16630 * Below n_akm_suites is defined as int in the kernel, even though it
16631 * is supposed to be unsigned.
16632 */
16633 int num_akm_suites = req->crypto.n_akm_suites;
16634 uint32_t key_mgmt = req->crypto.akm_suites[0];
16635 enum eAniAuthType fils_auth_type =
16636 wlan_hdd_get_fils_auth_type(req->auth_type);
16637
16638 hdd_debug("Num of AKM suites = %d", num_akm_suites);
16639 if (num_akm_suites <= 0)
16640 return false;
16641
16642 /*
16643 * Auth type will be either be OPEN or FILS type for a FILS connection
16644 */
16645 if ((auth_type != NL80211_AUTHTYPE_OPEN_SYSTEM) &&
16646 (fils_auth_type == eSIR_DONOT_USE_AUTH_TYPE)) {
16647 hdd_debug("Not a FILS auth type, auth = %d, fils auth = %d",
16648 auth_type, fils_auth_type);
16649 return false;
16650 }
16651
16652 if (!wlan_hdd_is_akm_suite_fils(key_mgmt)) {
16653 hdd_debug("Not a FILS AKM SUITE %d", key_mgmt);
16654 return false;
16655 }
16656
16657 return true;
16658}
16659
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070016660#else
Jeff Johnson20227a92018-03-13 09:41:05 -070016661static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016662{
16663 return true;
16664}
16665
16666static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
16667 struct cfg80211_connect_params *req)
16668{
16669 return 0;
16670}
16671
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070016672static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
16673{
16674 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016675}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016676
16677static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
16678{
16679 return false;
16680}
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016681#endif
16682
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016683/**
16684 * wlan_hdd_set_akm_suite() - set key management type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016685 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016686 * @key_mgmt: Key management type
16687 *
16688 * This function is used to set the key mgmt type(PSK/8021x).
16689 *
16690 * Return: 0 for success, non-zero for failure
16691 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016692static int wlan_hdd_set_akm_suite(struct hdd_adapter *adapter, u32 key_mgmt)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016693{
Jeff Johnson37ecea42018-03-18 17:54:40 -070016694 struct hdd_station_ctx *sta_ctx;
Jeff Johnson61b5e982018-03-15 11:33:31 -070016695 struct csr_roam_profile *roam_profile;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016696
Jeff Johnson20227a92018-03-13 09:41:05 -070016697 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016698
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070016699 if (wlan_hdd_is_akm_suite_fils(key_mgmt) &&
Jeff Johnson20227a92018-03-13 09:41:05 -070016700 !hdd_validate_fils_info_ptr(roam_profile))
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070016701 return -EINVAL;
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053016702#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016703#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053016704#endif
16705#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016706#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053016707#endif
Jeff Johnson37ecea42018-03-18 17:54:40 -070016708
16709 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16710
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016711 /*set key mgmt type */
16712 switch (key_mgmt) {
16713 case WLAN_AKM_SUITE_PSK:
16714 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016715 case WLAN_AKM_SUITE_FT_PSK:
Abhishek Singh02cb9e02017-08-30 17:39:50 +053016716 case WLAN_AKM_SUITE_DPP_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016717 hdd_debug("setting key mgmt type to PSK");
Jeff Johnson37ecea42018-03-18 17:54:40 -070016718 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_PSK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016719 break;
16720
16721 case WLAN_AKM_SUITE_8021X_SHA256:
16722 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016723 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016724 hdd_debug("setting key mgmt type to 8021x");
Jeff Johnson37ecea42018-03-18 17:54:40 -070016725 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016726 break;
16727#ifdef FEATURE_WLAN_ESE
16728#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016729 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016730 hdd_debug("setting key mgmt type to CCKM");
Jeff Johnson37ecea42018-03-18 17:54:40 -070016731 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_CCKM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016732 break;
16733#endif
16734#ifndef WLAN_AKM_SUITE_OSEN
16735#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
16736#endif
16737 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016738 hdd_debug("setting key mgmt type to OSEN");
Jeff Johnson37ecea42018-03-18 17:54:40 -070016739 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016740 break;
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053016741#if defined(WLAN_FEATURE_FILS_SK) && \
16742 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
16743 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053016744 case WLAN_AKM_SUITE_FILS_SHA256:
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016745 hdd_debug("setting key mgmt type to FILS SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070016746 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016747 roam_profile->fils_con_info->akm_type =
16748 eCSR_AUTH_TYPE_FILS_SHA256;
16749 break;
16750
16751 case WLAN_AKM_SUITE_FILS_SHA384:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070016752 hdd_debug("setting key mgmt type to FILS SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070016753 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016754 roam_profile->fils_con_info->akm_type =
16755 eCSR_AUTH_TYPE_FILS_SHA384;
16756 break;
16757
16758 case WLAN_AKM_SUITE_FT_FILS_SHA256:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070016759 hdd_debug("setting key mgmt type to FILS FT SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070016760 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016761 roam_profile->fils_con_info->akm_type =
16762 eCSR_AUTH_TYPE_FT_FILS_SHA256;
16763 break;
16764
16765 case WLAN_AKM_SUITE_FT_FILS_SHA384:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070016766 hdd_debug("setting key mgmt type to FILS FT SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070016767 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016768 roam_profile->fils_con_info->akm_type =
16769 eCSR_AUTH_TYPE_FT_FILS_SHA384;
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053016770 break;
16771#endif
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053016772
16773 case WLAN_AKM_SUITE_OWE:
16774 hdd_debug("setting key mgmt type to OWE");
Jeff Johnson37ecea42018-03-18 17:54:40 -070016775 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053016776 break;
16777
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053016778 case WLAN_AKM_SUITE_EAP_SHA256:
16779 hdd_debug("setting key mgmt type to EAP_SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070016780 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053016781 break;
16782 case WLAN_AKM_SUITE_EAP_SHA384:
16783 hdd_debug("setting key mgmt type to EAP_SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070016784 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053016785 break;
16786
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053016787 case WLAN_AKM_SUITE_SAE:
16788 hdd_debug("setting key mgmt type to SAE");
Jeff Johnson37ecea42018-03-18 17:54:40 -070016789 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053016790 break;
16791
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016792 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016793 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016794 return -EINVAL;
16795
16796 }
16797 return 0;
16798}
16799
16800/**
16801 * wlan_hdd_cfg80211_set_cipher() - set encryption type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016802 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016803 * @cipher: Cipher type
16804 * @ucast: Unicast flag
16805 *
16806 * This function is used to set the encryption type
16807 * (NONE/WEP40/WEP104/TKIP/CCMP).
16808 *
16809 * Return: 0 for success, non-zero for failure
16810 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016811static int wlan_hdd_cfg80211_set_cipher(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016812 u32 cipher, bool ucast)
16813{
16814 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Jeff Johnsond377dce2017-10-04 10:32:42 -070016815 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016816 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016817 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016818
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016819 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016820 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016821 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
16822 } else {
16823
16824 /*set encryption method */
16825 switch (cipher) {
16826 case IW_AUTH_CIPHER_NONE:
16827 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
16828 break;
16829
16830 case WLAN_CIPHER_SUITE_WEP40:
16831 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
16832 break;
16833
16834 case WLAN_CIPHER_SUITE_WEP104:
16835 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
16836 break;
16837
16838 case WLAN_CIPHER_SUITE_TKIP:
16839 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
16840 break;
16841
16842 case WLAN_CIPHER_SUITE_CCMP:
16843 encryptionType = eCSR_ENCRYPT_TYPE_AES;
16844 break;
16845#ifdef FEATURE_WLAN_WAPI
16846 case WLAN_CIPHER_SUITE_SMS4:
16847 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
16848 break;
16849#endif
16850
16851#ifdef FEATURE_WLAN_ESE
16852 case WLAN_CIPHER_SUITE_KRK:
16853 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
16854 break;
16855#ifdef WLAN_FEATURE_ROAM_OFFLOAD
16856 case WLAN_CIPHER_SUITE_BTK:
16857 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
16858 break;
16859#endif
16860#endif
Mukul Sharma05504ac2017-06-08 12:35:53 +053016861 case WLAN_CIPHER_SUITE_GCMP:
16862 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP;
16863 break;
16864 case WLAN_CIPHER_SUITE_GCMP_256:
16865 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP_256;
16866 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016867 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016868 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016869 return -EOPNOTSUPP;
16870 }
16871 }
16872
Jeff Johnson20227a92018-03-13 09:41:05 -070016873 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016874 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016875 hdd_debug("setting unicast cipher type to %d", encryptionType);
Jeff Johnsonb1959842019-02-27 13:04:04 -080016876 sta_ctx->conn_info.uc_encrypt_type = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070016877 roam_profile->EncryptionType.numEntries = 1;
16878 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016879 encryptionType;
16880 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016881 hdd_debug("setting mcast cipher type to %d", encryptionType);
Jeff Johnsonb1959842019-02-27 13:04:04 -080016882 sta_ctx->conn_info.mc_encrypt_type = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070016883 roam_profile->mcEncryptionType.numEntries = 1;
16884 roam_profile->mcEncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016885 encryptionType;
16886 }
16887
16888 return 0;
16889}
16890
16891/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053016892 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
Jeff Johnson20227a92018-03-13 09:41:05 -070016893 * @adapter: Pointer to adapter
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053016894 * @gen_ie: Pointer to IE data
16895 * @len: length of IE data
16896 *
16897 * Return: 0 for success, non-zero for failure
16898 */
Jeff Johnson20227a92018-03-13 09:41:05 -070016899static int wlan_hdd_add_assoc_ie(struct hdd_adapter *adapter,
16900 const uint8_t *gen_ie, uint16_t len)
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053016901{
Jeff Johnson20227a92018-03-13 09:41:05 -070016902 struct csr_roam_profile *roam_profile;
16903 tSirAddie *assoc_add_ie;
16904 uint16_t cur_add_ie_len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053016905
Jeff Johnson20227a92018-03-13 09:41:05 -070016906 assoc_add_ie = hdd_assoc_additional_ie(adapter);
16907 cur_add_ie_len = assoc_add_ie->length;
16908 if (SIR_MAC_MAX_ADD_IE_LENGTH < (cur_add_ie_len + len)) {
16909 hdd_err("current len %u, new ie of len %u will overflow",
16910 cur_add_ie_len, len);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053016911 return -ENOMEM;
16912 }
Jeff Johnson20227a92018-03-13 09:41:05 -070016913 memcpy(assoc_add_ie->addIEdata + cur_add_ie_len, gen_ie, len);
16914 assoc_add_ie->length += len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053016915
Jeff Johnson20227a92018-03-13 09:41:05 -070016916 roam_profile = hdd_roam_profile(adapter);
16917 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
16918 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
16919
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053016920 return 0;
16921}
16922
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053016923#ifdef WLAN_FEATURE_FILS_SK
16924/**
16925 * wlan_hdd_save_hlp_ie - API to save HLP IE
16926 * @roam_profile: Pointer to roam profile
16927 * @gen_ie: IE buffer to store
16928 * @len: length of the IE buffer @gen_ie
16929 * @flush: Flush the older saved HLP if any
16930 *
16931 * Return: None
16932 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070016933static void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070016934 const uint8_t *gen_ie, uint16_t len,
16935 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053016936{
16937 uint8_t *hlp_ie = roam_profile->hlp_ie;
16938
16939 if (flush) {
16940 roam_profile->hlp_ie_len = 0;
16941 if (hlp_ie) {
16942 qdf_mem_free(hlp_ie);
16943 roam_profile->hlp_ie = NULL;
16944 }
16945 }
16946
16947 if ((roam_profile->hlp_ie_len +
16948 len) > FILS_MAX_HLP_DATA_LEN) {
16949 hdd_err("HLP len exceeds: hlp_ie_len %d len %d",
16950 roam_profile->hlp_ie_len, len);
16951 return;
16952 }
16953
16954 if (!roam_profile->hlp_ie) {
16955 roam_profile->hlp_ie =
16956 qdf_mem_malloc(FILS_MAX_HLP_DATA_LEN);
16957 hlp_ie = roam_profile->hlp_ie;
Min Liu74a1a502018-10-10 19:59:07 +080016958 if (!hlp_ie)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053016959 return;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053016960 }
16961
16962 qdf_mem_copy(hlp_ie + roam_profile->hlp_ie_len, gen_ie, len);
16963 roam_profile->hlp_ie_len += len;
16964}
16965#else
Jeff Johnson61b5e982018-03-15 11:33:31 -070016966static inline void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070016967 const uint8_t *gen_ie, uint16_t len,
16968 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053016969{}
16970#endif
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080016971
16972#ifdef WLAN_CONV_CRYPTO_SUPPORTED
16973/**
16974 * hdd_populate_crypto_auth_type() - populate auth type for crypto
16975 * @vdev: pointed to vdev obmgr
16976 * @auth_type: legacy auth_type
16977 *
16978 * set the crypto auth type for corresponding auth type received
16979 * from NL
16980 *
16981 * Return: None
16982 */
16983static void hdd_populate_crypto_auth_type(struct wlan_objmgr_vdev *vdev,
16984 enum nl80211_auth_type auth_type)
16985{
16986 QDF_STATUS status;
16987 uint32_t set_val = 0;
16988 wlan_crypto_auth_mode crypto_auth_type =
16989 osif_nl_to_crypto_auth_type(auth_type);
16990
16991 hdd_debug("set auth type %d to crypto component", crypto_auth_type);
16992 HDD_SET_BIT(set_val, crypto_auth_type);
16993 status = wlan_crypto_set_vdev_param(vdev,
16994 WLAN_CRYPTO_PARAM_AUTH_MODE,
16995 set_val);
16996 if (QDF_IS_STATUS_ERROR(status))
16997 hdd_err("Failed to set auth type %0X to crypto component",
16998 set_val);
16999}
17000
17001/**
17002 * hdd_populate_crypto_akm_type() - populate akm type for crypto
17003 * @vdev: pointed to vdev obmgr
17004 * @akm_type: legacy akm_type
17005 *
17006 * set the crypto akm type for corresponding akm type received
17007 * from NL
17008 *
17009 * Return: None
17010 */
17011static void hdd_populate_crypto_akm_type(struct wlan_objmgr_vdev *vdev,
17012 u32 key_mgmt)
17013{
17014 QDF_STATUS status;
17015 uint32_t set_val = 0;
17016 wlan_crypto_key_mgmt crypto_akm_type =
17017 osif_nl_to_crypto_akm_type(key_mgmt);
17018
17019 hdd_debug("set akm type %d to crypto component", crypto_akm_type);
17020 HDD_SET_BIT(set_val, crypto_akm_type);
17021
17022 status = wlan_crypto_set_vdev_param(vdev,
17023 WLAN_CRYPTO_PARAM_KEY_MGMT,
17024 set_val);
17025 if (QDF_IS_STATUS_ERROR(status))
17026 hdd_err("Failed to set akm type %0x to crypto component",
17027 set_val);
17028}
17029
17030/**
17031 * hdd_populate_crypto_cipher_type() - populate cipher type for crypto
17032 * @cipher: legacy cipher type
17033 * @vdev: pointed to vdev obmgr
17034 * @cipher_param_type: param type, UCST/MCAST
17035 *
17036 * set the crypto cipher type for corresponding cipher type received
17037 * from NL
17038 *
17039 * Return: None
17040 */
17041static void hdd_populate_crypto_cipher_type(u32 cipher,
17042 struct wlan_objmgr_vdev *vdev,
17043 wlan_crypto_param_type
17044 cipher_param_type)
17045{
17046 QDF_STATUS status;
17047 uint32_t set_val = 0;
17048 wlan_crypto_cipher_type crypto_cipher_type =
17049 osif_nl_to_crypto_cipher_type(cipher);
17050
17051 hdd_debug("set cipher params %d type %d to crypto",
17052 cipher_param_type, crypto_cipher_type);
17053 HDD_SET_BIT(set_val, crypto_cipher_type);
17054 status = wlan_crypto_set_vdev_param(vdev, cipher_param_type, set_val);
17055 if (QDF_IS_STATUS_ERROR(status))
17056 hdd_err("Failed to set cipher params %d type %0x to crypto",
17057 cipher_param_type, set_val);
17058}
17059
17060/**
17061 * hdd_populate_crypto_params() - set crypto params
17062 * @vdev: Pointer to vdev obh mgr
17063 * @req: Pointer to security parameters
17064 *
17065 * Set Auth, Akm and Cipher type for crypto
17066 *
17067 * Return: None
17068 */
17069static void hdd_populate_crypto_params(struct wlan_objmgr_vdev *vdev,
17070 struct cfg80211_connect_params *req)
17071{
17072 hdd_populate_crypto_auth_type(vdev, req->auth_type);
17073
17074 if (req->crypto.n_akm_suites)
17075 hdd_populate_crypto_akm_type(vdev, req->crypto.akm_suites[0]);
17076
17077 if (req->crypto.n_ciphers_pairwise) {
17078 hdd_populate_crypto_cipher_type(req->crypto.ciphers_pairwise[0],
17079 vdev,
17080 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
17081 } else {
17082 /* Reset previous cipher suite to none */
17083 hdd_populate_crypto_cipher_type(0, vdev,
17084 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
17085 }
17086
17087 hdd_populate_crypto_cipher_type(req->crypto.cipher_group,
17088 vdev,
17089 WLAN_CRYPTO_PARAM_MCAST_CIPHER);
17090}
17091
17092/**
17093 * hdd_set_crypto_key_mgmt_param() - Set key mgmt param.
17094 * @adapter: Pointer to adapter.
17095 *
17096 * Return: None
17097 */
17098static void hdd_set_crypto_key_mgmt_param(struct hdd_adapter *adapter)
17099{
17100 uint32_t key_mgmt = 0;
17101 struct wlan_objmgr_vdev *vdev;
17102
17103 if (!adapter) {
17104 hdd_err("adapter is null");
17105 return;
17106 }
17107
17108 vdev = hdd_objmgr_get_vdev(adapter);
17109 if (!vdev)
17110 return;
17111
17112 if (adapter->wapi_info.wapi_auth_mode == WAPI_AUTH_MODE_PSK)
17113 HDD_SET_BIT(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK);
17114 if (adapter->wapi_info.wapi_auth_mode == WAPI_AUTH_MODE_CERT)
17115 HDD_SET_BIT(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT);
17116
17117 wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT, key_mgmt);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053017118 hdd_objmgr_put_vdev(vdev);
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080017119}
17120
17121#else
17122
17123static inline
17124void hdd_populate_crypto_auth_type(struct wlan_objmgr_vdev *vdev,
17125 enum nl80211_auth_type auth_type)
17126{
17127}
17128
17129static inline
17130void hdd_populate_crypto_akm_type(struct wlan_objmgr_vdev *vdev,
17131 u32 key_mgmt)
17132{
17133}
17134
17135static inline
17136void hdd_populate_crypto_cipher_type(u32 cipher,
17137 struct wlan_objmgr_vdev *vdev,
17138 wlan_crypto_param_type
17139 cipher_param_type)
17140{
17141}
17142
17143static inline
17144void hdd_populate_crypto_params(struct wlan_objmgr_vdev *vdev,
17145 struct cfg80211_connect_params *req)
17146{
17147}
17148
17149static inline void hdd_set_crypto_key_mgmt_param(struct hdd_adapter *adapter)
17150{
17151}
17152
17153#endif
17154
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053017155/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017156 * wlan_hdd_cfg80211_set_ie() - set IEs
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017157 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017158 * @ie: Pointer ot ie
17159 * @ie: IE length
17160 *
17161 * Return: 0 for success, non-zero for failure
17162 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017163static int wlan_hdd_cfg80211_set_ie(struct hdd_adapter *adapter,
Jeff Johnson2a722002017-09-30 20:02:35 -070017164 const uint8_t *ie,
17165 size_t ie_len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017166{
Jeff Johnson20227a92018-03-13 09:41:05 -070017167 struct csr_roam_profile *roam_profile;
17168 tSirAddie *assoc_add_ie;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017169 const uint8_t *genie = ie;
17170 uint16_t remLen = ie_len;
17171#ifdef FEATURE_WLAN_WAPI
17172 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
tinlin8a44b642018-04-25 13:56:06 +080017173 uint8_t *tmp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017174 uint16_t akmsuiteCount;
tinlin8a44b642018-04-25 13:56:06 +080017175 uint32_t *akmlist;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017176#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053017177 int status;
Jeff Johnson20227a92018-03-13 09:41:05 -070017178 uint8_t *security_ie;
17179
17180 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017181
17182 /* clear previous assocAddIE */
Jeff Johnson20227a92018-03-13 09:41:05 -070017183 assoc_add_ie = hdd_assoc_additional_ie(adapter);
17184 assoc_add_ie->length = 0;
17185 roam_profile->bWPSAssociation = false;
17186 roam_profile->bOSENAssociation = false;
17187 security_ie = hdd_security_ie(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017188
17189 while (remLen >= 2) {
17190 uint16_t eLen = 0;
17191 uint8_t elementId;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070017192
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017193 elementId = *genie++;
17194 eLen = *genie++;
17195 remLen -= 2;
17196
Nachiket Kukade4bea8b42017-06-13 11:53:19 +053017197 /* Sanity check on eLen */
17198 if (eLen > remLen) {
17199 hdd_err("%s: Invalid IE length[%d] for IE[0x%X]",
17200 __func__, eLen, elementId);
17201 QDF_ASSERT(0);
17202 return -EINVAL;
17203 }
17204
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017205 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017206
17207 switch (elementId) {
17208 case DOT11F_EID_WPA:
17209 if (4 > eLen) { /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017210 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017211 return -EINVAL;
17212 } else if (0 ==
17213 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
Jeff Johnson20227a92018-03-13 09:41:05 -070017214 uint16_t curAddIELen = assoc_add_ie->length;
17215
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017216 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017217
17218 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070017219 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017220 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017221 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017222 return -ENOMEM;
17223 }
17224 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070017225 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017226 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070017227 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017228
Jeff Johnson20227a92018-03-13 09:41:05 -070017229 roam_profile->bWPSAssociation = true;
17230 roam_profile->pAddIEAssoc =
17231 assoc_add_ie->addIEdata;
17232 roam_profile->nAddIEAssocLength =
17233 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017234 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Nachiket Kukade2f6509f2017-06-13 17:45:46 +053017235 if (eLen > (MAX_WPA_RSN_IE_LEN - 2)) {
17236 hdd_err("%s: Invalid WPA IE length[%d]",
17237 __func__, eLen);
17238 QDF_ASSERT(0);
17239 return -EINVAL;
17240 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017241 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070017242 memset(security_ie, 0, MAX_WPA_RSN_IE_LEN);
17243 memcpy(security_ie, genie - 2, (eLen + 2));
17244 roam_profile->pWPAReqIE = security_ie;
17245 roam_profile->nWPAReqIELength = eLen + 2; /* ie_len; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017246 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
17247 P2P_OUI_TYPE_SIZE))) {
17248 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070017249 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017250 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017251
17252 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070017253 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017254 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017255 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017256 return -ENOMEM;
17257 }
17258 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070017259 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017260 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070017261 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017262
Jeff Johnson20227a92018-03-13 09:41:05 -070017263 roam_profile->pAddIEAssoc =
17264 assoc_add_ie->addIEdata;
17265 roam_profile->nAddIEAssocLength =
17266 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017267 }
17268#ifdef WLAN_FEATURE_WFD
17269 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
17270 WFD_OUI_TYPE_SIZE)) &&
17271 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080017272 (QDF_P2P_CLIENT_MODE ==
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017273 adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017274 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070017275 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017276 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017277
17278 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070017279 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017280 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017281 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017282 return -ENOMEM;
17283 }
17284 /* WFD IE is saved to Additional IE ; it should
17285 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080017286 * WFD IE
17287 */
Jeff Johnson20227a92018-03-13 09:41:05 -070017288 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017289 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070017290 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017291
Jeff Johnson20227a92018-03-13 09:41:05 -070017292 roam_profile->pAddIEAssoc =
17293 assoc_add_ie->addIEdata;
17294 roam_profile->nAddIEAssocLength =
17295 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017296 }
17297#endif
17298 /* Appending HS 2.0 Indication Element in Assiciation Request */
17299 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
17300 HS20_OUI_TYPE_SIZE))) {
17301 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070017302 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017303 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017304
17305 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070017306 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017307 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017308 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017309 return -ENOMEM;
17310 }
Jeff Johnson20227a92018-03-13 09:41:05 -070017311 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017312 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070017313 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017314
Jeff Johnson20227a92018-03-13 09:41:05 -070017315 roam_profile->pAddIEAssoc =
17316 assoc_add_ie->addIEdata;
17317 roam_profile->nAddIEAssocLength =
17318 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017319 }
17320 /* Appending OSEN Information Element in Assiciation Request */
17321 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
17322 OSEN_OUI_TYPE_SIZE))) {
17323 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070017324 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017325 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017326
17327 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070017328 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017329 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017330 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017331 return -ENOMEM;
17332 }
Jeff Johnson20227a92018-03-13 09:41:05 -070017333 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017334 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070017335 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017336
Jeff Johnson20227a92018-03-13 09:41:05 -070017337 roam_profile->bOSENAssociation = true;
17338 roam_profile->pAddIEAssoc =
17339 assoc_add_ie->addIEdata;
17340 roam_profile->nAddIEAssocLength =
17341 assoc_add_ie->length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053017342 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
17343 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017344 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070017345 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053017346 genie - 2, eLen + 2);
17347 if (status)
17348 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017349 } else {
17350 uint16_t add_ie_len =
Jeff Johnson20227a92018-03-13 09:41:05 -070017351 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017352
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017353 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017354
17355 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070017356 (assoc_add_ie->length + eLen)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017357 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017358 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017359 return -ENOMEM;
17360 }
17361
Jeff Johnson20227a92018-03-13 09:41:05 -070017362 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017363 add_ie_len, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070017364 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017365
Jeff Johnson20227a92018-03-13 09:41:05 -070017366 roam_profile->pAddIEAssoc =
17367 assoc_add_ie->addIEdata;
17368 roam_profile->nAddIEAssocLength =
17369 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017370 }
17371 break;
17372 case DOT11F_EID_RSN:
tinlin8a44b642018-04-25 13:56:06 +080017373 if (eLen > DOT11F_IE_RSN_MAX_LEN) {
Vignesh Viswanathan96e0e702017-12-05 19:42:46 +053017374 hdd_err("%s: Invalid WPA RSN IE length[%d]",
tinlin8a44b642018-04-25 13:56:06 +080017375 __func__, eLen);
Vignesh Viswanathan96e0e702017-12-05 19:42:46 +053017376 return -EINVAL;
17377 }
Jeff Johnson20227a92018-03-13 09:41:05 -070017378 memset(security_ie, 0, MAX_WPA_RSN_IE_LEN);
17379 memcpy(security_ie, genie - 2, (eLen + 2));
17380 roam_profile->pRSNReqIE = security_ie;
17381 roam_profile->nRSNReqIELength = eLen + 2; /* ie_len; */
tinlin8a44b642018-04-25 13:56:06 +080017382 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017383 break;
17384 /*
17385 * Appending Extended Capabilities with Interworking bit set
17386 * in Assoc Req.
17387 *
17388 * In assoc req this EXT Cap will only be taken into account if
17389 * interworkingService bit is set to 1. Currently
17390 * driver is only interested in interworkingService capability
17391 * from supplicant. If in future any other EXT Cap info is
17392 * required from supplicat, it needs to be handled while
17393 * sending Assoc Req in LIM.
17394 */
17395 case DOT11F_EID_EXTCAP:
17396 {
17397 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070017398 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017399 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017400
17401 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070017402 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017403 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017404 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017405 return -ENOMEM;
17406 }
Jeff Johnson20227a92018-03-13 09:41:05 -070017407 memcpy(assoc_add_ie->addIEdata + curAddIELen, genie - 2, eLen + 2);
17408 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017409
Jeff Johnson20227a92018-03-13 09:41:05 -070017410 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
17411 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017412 break;
17413 }
17414#ifdef FEATURE_WLAN_WAPI
17415 case WLAN_EID_WAPI:
17416 /* Setting WAPI Mode to ON=1 */
tinlin8a44b642018-04-25 13:56:06 +080017417 adapter->wapi_info.wapi_mode = 1;
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017418 hdd_debug("WAPI MODE IS %u", adapter->wapi_info.wapi_mode);
Abhinav Kumarf56c81f2018-06-06 16:07:01 +053017419 /* genie is pointing to data field of WAPI IE's buffer */
17420 tmp = (uint8_t *)genie;
17421 /* Validate length for Version(2 bytes) and Number
17422 * of AKM suite (2 bytes) in WAPI IE buffer, coming from
17423 * supplicant*/
17424 if (eLen < 4) {
17425 hdd_err("Invalid IE Len: %u", eLen);
17426 return -EINVAL;
17427 }
17428 tmp = tmp + 2; /* Skip Version */
tinlin8a44b642018-04-25 13:56:06 +080017429 /* Get the number of AKM suite */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017430 akmsuiteCount = WPA_GET_LE16(tmp);
tinlin8a44b642018-04-25 13:56:06 +080017431 /* Skip the number of AKM suite */
17432 tmp = tmp + 2;
Abhinav Kumarf56c81f2018-06-06 16:07:01 +053017433 /* Validate total length for WAPI IE's buffer */
17434 if (eLen < (4 + (akmsuiteCount * sizeof(uint32_t)))) {
17435 hdd_err("Invalid IE Len: %u", eLen);
17436 return -EINVAL;
17437 }
tinlin8a44b642018-04-25 13:56:06 +080017438 /* AKM suite list, each OUI contains 4 bytes */
17439 akmlist = (uint32_t *)(tmp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017440 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
Vignesh Viswanathan845bd472018-06-11 18:45:45 +053017441 qdf_mem_copy(akmsuite, akmlist,
17442 sizeof(uint32_t) * akmsuiteCount);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017443 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017444 hdd_err("Invalid akmSuite count: %u",
17445 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017446 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017447 return -EINVAL;
17448 }
17449
17450 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017451 hdd_debug("WAPI AUTH MODE SET TO PSK");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017452 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017453 WAPI_AUTH_MODE_PSK;
17454 }
17455 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017456 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017457 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017458 WAPI_AUTH_MODE_CERT;
17459 }
Arif Hussainf8f6b3b2019-01-10 19:42:09 -080017460
17461 hdd_set_crypto_key_mgmt_param(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017462 break;
17463#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053017464 case DOT11F_EID_SUPPOPERATINGCLASSES:
17465 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017466 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070017467 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053017468 genie - 2, eLen + 2);
17469 if (status)
17470 return status;
17471 break;
17472 }
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053017473 case SIR_MAC_REQUEST_EID_MAX:
17474 {
17475 if (genie[0] == SIR_FILS_HLP_EXT_EID) {
17476 hdd_debug("Set HLP EXT IE(len %d)",
17477 eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070017478 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053017479 genie - 2, eLen + 2,
17480 true);
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053017481 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070017482 adapter, genie - 2,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053017483 eLen + 2);
17484 if (status)
17485 return status;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053017486 } else if (genie[0] ==
17487 SIR_DH_PARAMETER_ELEMENT_EXT_EID) {
17488 hdd_debug("Set DH EXT IE(len %d)",
17489 eLen + 2);
17490 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070017491 adapter, genie - 2,
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053017492 eLen + 2);
17493 if (status)
17494 return status;
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053017495 } else {
17496 hdd_err("UNKNOWN EID: %X", genie[0]);
17497 }
17498 break;
17499 }
17500 case DOT11F_EID_FRAGMENT_IE:
17501 {
17502 hdd_debug("Set Fragment IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070017503 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053017504 genie - 2, eLen + 2,
17505 false);
Jeff Johnson20227a92018-03-13 09:41:05 -070017506 status = wlan_hdd_add_assoc_ie(adapter,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053017507 genie - 2, eLen + 2);
17508 if (status)
17509 return status;
17510 break;
17511 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017512 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017513 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080017514 /* when Unknown IE is received we break
17515 * and continue to the next IE in the buffer
17516 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017517 break;
17518 }
17519 genie += eLen;
17520 remLen -= eLen;
17521 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017522 return 0;
17523}
17524
17525/**
17526 * hdd_is_wpaie_present() - check for WPA ie
17527 * @ie: Pointer to ie
17528 * @ie_len: Ie length
17529 *
17530 * Parse the received IE to find the WPA IE
17531 *
17532 * Return: true if wpa ie is found else false
17533 */
17534static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
17535{
17536 uint8_t eLen = 0;
17537 uint16_t remLen = ie_len;
17538 uint8_t elementId = 0;
17539
17540 while (remLen >= 2) {
17541 elementId = *ie++;
17542 eLen = *ie++;
17543 remLen -= 2;
17544 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017545 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017546 return false;
17547 }
17548 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
17549 /* OUI - 0x00 0X50 0XF2
17550 * WPA Information Element - 0x01
17551 * WPA version - 0x01
17552 */
17553 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
17554 return true;
17555 }
17556 ie += eLen;
17557 remLen -= eLen;
17558 }
17559 return false;
17560}
17561
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017562#ifdef CRYPTO_SET_KEY_CONVERGED
17563static void wlan_hdd_cfg80211_store_wep_key(struct hdd_adapter *adapter,
17564 struct wlan_objmgr_vdev *vdev,
17565 struct cfg80211_connect_params *req)
17566{
17567 struct key_params params;
17568
17569 qdf_mem_zero(&params, sizeof(params));
17570 params.cipher = req->crypto.ciphers_pairwise[0];
17571 params.key_len = req->key_len;
17572 params.key = req->key;
17573 wlan_cfg80211_store_key(vdev, req->key_idx,
17574 WLAN_CRYPTO_KEY_TYPE_UNICAST,
17575 NULL, &params);
17576}
17577#else
17578static void wlan_hdd_cfg80211_store_wep_key(struct hdd_adapter *adapter,
17579 struct wlan_objmgr_vdev *vdev,
17580 struct cfg80211_connect_params *req)
17581{
17582 struct csr_roam_profile *roam_profile;
17583
17584 roam_profile = hdd_roam_profile(adapter);
17585 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
17586 req->key_idx, req->key_len);
17587 qdf_mem_copy(&roam_profile->Keys.KeyMaterial[req->key_idx][0],
17588 req->key, req->key_len);
17589 roam_profile->Keys.KeyLength[req->key_idx] = req->key_len;
17590 roam_profile->Keys.defaultIndex = req->key_idx;
17591}
17592#endif /* !CRYPTO_SET_KEY_CONVERGED */
17593
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070017594/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017595 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017596 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017597 * @req: Pointer to security parameters
17598 *
17599 * Return: 0 for success, non-zero for failure
17600 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017601static int wlan_hdd_cfg80211_set_privacy(struct hdd_adapter *adapter,
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070017602 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017603{
17604 int status = 0;
Jeff Johnsonce4a8342017-10-14 13:12:22 -070017605 struct hdd_station_ctx *sta_ctx;
Jeff Johnson20227a92018-03-13 09:41:05 -070017606 struct csr_roam_profile *roam_profile;
Min Liu8c5d99e2018-09-10 17:18:44 +080017607 struct wlan_objmgr_vdev *vdev;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070017608
Dustin Brown491d54b2018-03-14 12:39:11 -070017609 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017610
Jeff Johnsonce4a8342017-10-14 13:12:22 -070017611 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17612 sta_ctx->wpa_versions = req->crypto.wpa_versions;
17613 hdd_debug("set wpa version to %d", sta_ctx->wpa_versions);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017614
Jeff Johnson20227a92018-03-13 09:41:05 -070017615 roam_profile = hdd_roam_profile(adapter);
17616
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070017617 /* populate auth,akm and cipher params for crypto */
Min Liu8c5d99e2018-09-10 17:18:44 +080017618 vdev = hdd_objmgr_get_vdev(adapter);
17619 if (!vdev)
17620 return -EINVAL;
17621 hdd_populate_crypto_params(vdev, req);
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070017622
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017623 /*set authentication type */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017624 status = wlan_hdd_cfg80211_set_auth_type(adapter, req->auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017625
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070017626 if (wlan_hdd_is_conn_type_fils(req)) {
17627 status = wlan_hdd_cfg80211_set_fils_config(adapter, req);
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053017628
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070017629 if (0 > status) {
17630 hdd_err("Failed to set fils config");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017631 goto release_vdev_ref;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070017632 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017633 }
17634
17635 /*set key mgmt type */
17636 if (req->crypto.n_akm_suites) {
17637 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017638 wlan_hdd_set_akm_suite(adapter, req->crypto.akm_suites[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017639 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017640 hdd_err("Failed to set akm suite");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017641 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017642 }
17643 }
17644
17645 /*set pairwise cipher type */
17646 if (req->crypto.n_ciphers_pairwise) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017647 status = wlan_hdd_cfg80211_set_cipher(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017648 req->crypto.
17649 ciphers_pairwise[0],
17650 true);
17651 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017652 hdd_err("Failed to set unicast cipher type");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017653 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017654 }
17655 } else {
17656 /*Reset previous cipher suite to none */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017657 status = wlan_hdd_cfg80211_set_cipher(adapter, 0, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017658 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017659 hdd_err("Failed to set unicast cipher type");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017660 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017661 }
17662 }
17663
17664 /*set group cipher type */
17665 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017666 wlan_hdd_cfg80211_set_cipher(adapter, req->crypto.cipher_group,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017667 false);
17668
17669 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017670 hdd_err("Failed to set mcast cipher type");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017671 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017672 }
17673#ifdef WLAN_FEATURE_11W
Jeff Johnson20227a92018-03-13 09:41:05 -070017674 roam_profile->MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017675#endif
17676
17677 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
17678 if (req->ie_len) {
17679 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017680 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017681 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017682 hdd_err("Failed to parse the WPA/RSN IE");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017683 goto release_vdev_ref;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017684 }
17685 }
17686
17687 /*incase of WEP set default key information */
17688 if (req->key && req->key_len) {
Jeff Johnson37ecea42018-03-18 17:54:40 -070017689 u32 cipher = req->crypto.ciphers_pairwise[0];
Jeff Johnson68755312017-02-10 11:46:55 -080017690
Jeff Johnson37ecea42018-03-18 17:54:40 -070017691 if ((WLAN_CIPHER_SUITE_WEP40 == cipher) ||
17692 (WLAN_CIPHER_SUITE_WEP104 == cipher)) {
17693 enum hdd_auth_key_mgmt key_mgmt =
17694 sta_ctx->auth_key_mgmt;
17695
17696 if (key_mgmt & HDD_AUTH_KEY_MGMT_802_1X) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017697 hdd_err("Dynamic WEP not supported");
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017698 status = -EOPNOTSUPP;
17699 goto release_vdev_ref;
Jeff Johnson68755312017-02-10 11:46:55 -080017700 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017701
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017702 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
17703 req->key_len) && (CSR_MAX_NUM_KEY > req->key_idx))
17704 wlan_hdd_cfg80211_store_wep_key(adapter,
17705 vdev, req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017706 }
17707 }
Varun Reddy Yeturuff4c9982019-02-15 15:59:24 -080017708release_vdev_ref:
17709 hdd_objmgr_put_vdev(vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017710
17711 return status;
17712}
17713
wadesongcaad7c72018-08-06 13:26:27 +080017714/**
17715 * wlan_hdd_clear_wapi_privacy() - reset WAPI settings in HDD layer
17716 * @adapter: pointer to HDD adapter object
17717 *
17718 * This function resets all WAPI related parameters imposed before STA
17719 * connection starts. It's invoked when privacy checking against concurrency
17720 * fails, to make sure no improper WAPI settings are still populated before
17721 * returning an error to the upper layer requester.
17722 *
17723 * Return: none
17724 */
17725#ifdef FEATURE_WLAN_WAPI
17726static inline void wlan_hdd_clear_wapi_privacy(struct hdd_adapter *adapter)
17727{
17728 adapter->wapi_info.wapi_mode = 0;
17729 adapter->wapi_info.wapi_auth_mode = WAPI_AUTH_MODE_OPEN;
17730}
17731#else
17732static inline void wlan_hdd_clear_wapi_privacy(struct hdd_adapter *adapter)
17733{
17734}
17735#endif
17736
17737/**
17738 * wlan_hdd_cfg80211_clear_privacy() - reset STA security parameters
17739 * @adapter: pointer to HDD adapter object
17740 *
17741 * This function resets all privacy related parameters imposed
17742 * before STA connection starts. It's invoked when privacy checking
17743 * against concurrency fails, to make sure no improper settings are
17744 * still populated before returning an error to the upper layer requester.
17745 *
17746 * Return: none
17747 */
17748static void wlan_hdd_cfg80211_clear_privacy(struct hdd_adapter *adapter)
17749{
17750 struct hdd_station_ctx *hdd_sta_ctx =
17751 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17752
17753 hdd_debug("resetting all privacy configurations");
17754
17755 hdd_sta_ctx->wpa_versions = 0;
17756
Jeff Johnson96e33512019-02-27 15:10:21 -080017757 hdd_sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_NONE;
wadesongcaad7c72018-08-06 13:26:27 +080017758 hdd_sta_ctx->roam_profile.AuthType.authType[0] = eCSR_AUTH_TYPE_NONE;
17759
Jeff Johnsonb1959842019-02-27 13:04:04 -080017760 hdd_sta_ctx->conn_info.uc_encrypt_type = eCSR_ENCRYPT_TYPE_NONE;
wadesongcaad7c72018-08-06 13:26:27 +080017761 hdd_sta_ctx->roam_profile.EncryptionType.numEntries = 0;
Jeff Johnsonb1959842019-02-27 13:04:04 -080017762 hdd_sta_ctx->conn_info.mc_encrypt_type = eCSR_ENCRYPT_TYPE_NONE;
wadesongcaad7c72018-08-06 13:26:27 +080017763 hdd_sta_ctx->roam_profile.mcEncryptionType.numEntries = 0;
17764
17765 wlan_hdd_clear_wapi_privacy(adapter);
17766}
17767
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017768int wlan_hdd_try_disconnect(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017769{
17770 unsigned long rc;
Jeff Johnsond377dce2017-10-04 10:32:42 -070017771 struct hdd_station_ctx *sta_ctx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053017772 int status, result = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017773 mac_handle_t mac_handle;
Abhishek Singhd1f21c72019-01-21 15:16:34 +053017774 uint32_t wait_time = SME_DISCONNECT_TIMEOUT;
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053017775 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017776
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053017777 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsond377dce2017-10-04 10:32:42 -070017778 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017779 mac_handle = hdd_adapter_get_mac_handle(adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017780 if (adapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017781 hdd_debug("Stop firmware roaming");
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017782 sme_stop_roaming(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017783 eCsrForcedDisassoc);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017784
Abhishek Singh533c9da2017-05-04 10:23:34 +053017785 /*
17786 * If firmware has already started roaming process, driver
17787 * needs to wait for processing of this disconnect request.
17788 *
17789 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017790 INIT_COMPLETION(adapter->roaming_comp_var);
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053017791 if (hdd_is_roaming_in_progress(hdd_ctx)) {
Abhishek Singh533c9da2017-05-04 10:23:34 +053017792 rc = wait_for_completion_timeout(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017793 &adapter->roaming_comp_var,
Abhishek Singh533c9da2017-05-04 10:23:34 +053017794 msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));
17795 if (!rc) {
Jeff Johnson55d2ab42019-03-06 11:43:49 -080017796 hdd_err("roaming comp var timed out vdev id: %d",
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017797 adapter->vdev_id);
Abhishek Singh533c9da2017-05-04 10:23:34 +053017798 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017799 if (adapter->roam_ho_fail) {
17800 INIT_COMPLETION(adapter->disconnect_comp_var);
17801 hdd_conn_set_connection_state(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053017802 eConnectionState_Disconnecting);
17803 }
17804 }
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017805 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017806
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017807 if ((QDF_IBSS_MODE == adapter->device_mode) ||
Jeff Johnsone7951512019-02-27 10:02:51 -080017808 (eConnectionState_Associated == sta_ctx->conn_info.conn_state) ||
17809 (eConnectionState_Connecting == sta_ctx->conn_info.conn_state) ||
17810 (eConnectionState_IbssConnected == sta_ctx->conn_info.conn_state)) {
Abhishek Singh0edeba02018-06-05 10:04:08 +053017811 eConnectionState prev_conn_state;
17812
Jeff Johnsone7951512019-02-27 10:02:51 -080017813 prev_conn_state = sta_ctx->conn_info.conn_state;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017814 hdd_conn_set_connection_state(adapter,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017815 eConnectionState_Disconnecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017816 /* Issue disconnect to CSR */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017817 INIT_COMPLETION(adapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053017818
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017819 status = sme_roam_disconnect(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017820 adapter->vdev_id,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053017821 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Abhishek Singh0edeba02018-06-05 10:04:08 +053017822
17823 if ((status == QDF_STATUS_CMD_NOT_QUEUED) &&
17824 prev_conn_state != eConnectionState_Connecting) {
17825 hdd_debug("Already disconnect in progress");
17826 result = 0;
17827 /*
17828 * Wait here instead of returning directly. This will
17829 * block the connect command and allow processing
17830 * of the disconnect in SME. As disconnect is already
17831 * in progress, wait here for 1 sec instead of 5 sec.
17832 */
17833 wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS;
17834 } else if (status == QDF_STATUS_CMD_NOT_QUEUED) {
17835 /*
17836 * Wait here instead of returning directly, this will
17837 * block the connect command and allow processing
17838 * of the scan for ssid and the previous connect command
17839 * in CSR.
17840 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017841 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053017842 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017843 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053017844 (int)status);
Jeff Johnson8380f232017-10-25 12:39:44 -070017845 sta_ctx->sta_debug_state = status;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053017846 result = -EINVAL;
17847 goto disconnected;
17848 }
17849
Abhishek Singh0edeba02018-06-05 10:04:08 +053017850 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
17851 msecs_to_jiffies(wait_time));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017852 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson55d2ab42019-03-06 11:43:49 -080017853 hdd_err("Sme disconnect event timed out vdev id: %d sta_debug_state: %d",
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017854 adapter->vdev_id, sta_ctx->sta_debug_state);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053017855 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017856 }
17857 } else if (eConnectionState_Disconnecting ==
Jeff Johnsone7951512019-02-27 10:02:51 -080017858 sta_ctx->conn_info.conn_state) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017859 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Abhishek Singh0edeba02018-06-05 10:04:08 +053017860 msecs_to_jiffies(wait_time));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017861 if (!rc) {
Jeff Johnson55d2ab42019-03-06 11:43:49 -080017862 hdd_err("Disconnect event timed out vdev id: %d sta_debug_state: %d",
Jeff Johnsoncf07c312019-02-04 13:53:29 -080017863 adapter->vdev_id, sta_ctx->sta_debug_state);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053017864 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017865 }
17866 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053017867disconnected:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017868 hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053017869 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017870}
17871
17872/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070017873 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
17874 * @adapter: Pointer to the HDD adapter
17875 * @req: Pointer to the structure cfg_connect_params receieved from user space
17876 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053017877 * This function will start reassociation if prev_bssid is set and bssid/
17878 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070017879 *
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053017880 * Return: 0 if connect was for ReAssociation, non-zero error code otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070017881 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053017882#if defined(CFG80211_CONNECT_PREV_BSSID) || \
17883 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053017884static int wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
17885 struct cfg80211_connect_params *req)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070017886{
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053017887 int status = -EINVAL;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053017888 const uint8_t *bssid = NULL;
17889 uint16_t channel = 0;
Jeff Johnson731bc322017-10-14 19:53:44 -070017890 struct hdd_station_ctx *sta_ctx;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053017891
17892 if (req->bssid)
17893 bssid = req->bssid;
17894 else if (req->bssid_hint)
17895 bssid = req->bssid_hint;
17896
17897 if (req->channel)
17898 channel = req->channel->hw_value;
17899 else if (req->channel_hint)
17900 channel = req->channel_hint->hw_value;
17901
17902 if (bssid && channel && req->prev_bssid) {
Dustin Brownbacc48f2018-03-14 14:48:44 -070017903 hdd_debug("REASSOC Attempt on channel %d to " MAC_ADDRESS_STR,
17904 channel, MAC_ADDR_ARRAY(bssid));
Arif Hussain43354e62017-05-24 11:24:25 -070017905 /*
17906 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017907 * roam_profile's BSSID is getting zeroed out in the
Arif Hussain43354e62017-05-24 11:24:25 -070017908 * association process. In case of join failure
17909 * we should send valid BSSID to supplicant
17910 */
Jeff Johnson731bc322017-10-14 19:53:44 -070017911 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17912 qdf_mem_copy(sta_ctx->requested_bssid.bytes, bssid,
Arif Hussain43354e62017-05-24 11:24:25 -070017913 QDF_MAC_ADDR_SIZE);
17914
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053017915 status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070017916 CONNECT_CMD_USERSPACE);
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053017917 hdd_debug("hdd_reassoc: status: %d", status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070017918 }
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053017919 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070017920}
17921#else
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053017922static int wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
17923 struct cfg80211_connect_params *req)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070017924{
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053017925 return -ENOTSUPP;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070017926}
17927#endif
17928
Abhishek Singhb59f8d42017-07-31 14:42:47 +053017929
17930/**
17931 * wlan_hdd_check_ht20_ht40_ind() - check if Supplicant has indicated to
17932 * connect in HT20 mode
17933 * @hdd_ctx: hdd context
17934 * @adapter: Pointer to the HDD adapter
17935 * @req: Pointer to the structure cfg_connect_params receieved from user space
17936 *
17937 * This function will check if supplicant has indicated to to connect in HT20
17938 * mode. this is currently applicable only for 2.4Ghz mode only.
17939 * if feature is enabled and supplicant indicate HT20 set
17940 * force_24ghz_in_ht20 to true to force 2.4Ghz in HT20 else set it to false.
17941 *
17942 * Return: void
17943 */
17944#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
Jeff Johnson20227a92018-03-13 09:41:05 -070017945static void
17946wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
17947 struct hdd_adapter *adapter,
17948 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053017949{
Jeff Johnson61b5e982018-03-15 11:33:31 -070017950 struct csr_roam_profile *roam_profile;
Wu Gaofc81ecf2018-11-22 11:38:41 +080017951 bool is_override_ht20_40_24g;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053017952
Jeff Johnson20227a92018-03-13 09:41:05 -070017953 roam_profile = hdd_roam_profile(adapter);
17954
Abhishek Singhb59f8d42017-07-31 14:42:47 +053017955 roam_profile->force_24ghz_in_ht20 = false;
17956
Wu Gaofc81ecf2018-11-22 11:38:41 +080017957 ucfg_mlme_is_override_ht20_40_24g(hdd_ctx->psoc,
17958 &is_override_ht20_40_24g);
17959 if (is_override_ht20_40_24g &&
Jeff Johnson20227a92018-03-13 09:41:05 -070017960 !(req->ht_capa.cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
Abhishek Singhb59f8d42017-07-31 14:42:47 +053017961 roam_profile->force_24ghz_in_ht20 = true;
17962
17963 hdd_debug("req->ht_capa.cap_info %x override_ht20_40_24g %d",
17964 req->ht_capa.cap_info,
Wu Gaofc81ecf2018-11-22 11:38:41 +080017965 is_override_ht20_40_24g);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053017966}
17967#else
Jeff Johnson20227a92018-03-13 09:41:05 -070017968static inline void
17969wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
17970 struct hdd_adapter *adapter,
17971 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053017972{
Jeff Johnson61b5e982018-03-15 11:33:31 -070017973 struct csr_roam_profile *roam_profile;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053017974
Jeff Johnson20227a92018-03-13 09:41:05 -070017975 roam_profile = hdd_roam_profile(adapter);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053017976
17977 roam_profile->force_24ghz_in_ht20 = false;
17978}
17979#endif
17980
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070017981/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017982 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
17983 * @wiphy: Pointer to wiphy
17984 * @dev: Pointer to network device
17985 * @req: Pointer to cfg80211 connect request
17986 *
17987 * This function is used to start the association process
17988 *
17989 * Return: 0 for success, non-zero for failure
17990 */
17991static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
17992 struct net_device *ndev,
17993 struct cfg80211_connect_params *req)
17994{
17995 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053017996 u16 channel;
Arif Hussainee677012017-01-26 17:50:13 -080017997 const u8 *bssid = NULL;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053017998#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
17999 const u8 *bssid_hint = req->bssid_hint;
18000#else
18001 const u8 *bssid_hint = NULL;
18002#endif
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018003 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070018004 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018005
Dustin Brown491d54b2018-03-14 12:39:11 -070018006 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018007
Anurag Chouhan6d760662016-02-20 16:05:43 +053018008 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018009 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018010 return -EINVAL;
18011 }
18012
Jeff Johnson48363022019-02-24 16:26:51 -080018013 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018014 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018015
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053018016 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
18017 TRACE_CODE_HDD_CFG80211_CONNECT,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018018 adapter->vdev_id, adapter->device_mode);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053018019
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018020 hdd_debug("Device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070018021 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018022
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018023 if (adapter->device_mode != QDF_STA_MODE &&
Dustin Brown458027c2018-10-19 12:26:27 -070018024 adapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018025 hdd_err("Device_mode %s(%d) is not supported",
Dustin Brown458027c2018-10-19 12:26:27 -070018026 qdf_opmode_str(adapter->device_mode),
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018027 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018028 return -EINVAL;
18029 }
18030
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018031 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070018032 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018033 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018034 return -EINVAL;
18035 }
18036
Jeff Johnsonb8944722017-09-03 09:03:19 -070018037 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018038 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018039 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070018040
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053018041 /*
18042 * Disable NAN Discovery if incoming connection is P2P or if a STA
18043 * connection already exists and if this is a case of STA+STA.
18044 */
18045 if (adapter->device_mode == QDF_P2P_CLIENT_MODE ||
18046 policy_mgr_mode_specific_connection_count(hdd_ctx->psoc,
18047 PM_STA_MODE, NULL))
Nachiket Kukade089b9832018-12-12 16:38:17 +053018048 ucfg_nan_disable_concurrency(hdd_ctx->psoc);
18049
Nachiket Kukade413c5fa2019-02-19 17:57:19 +053018050 /*
18051 * STA+NDI concurrency gets preference over NDI+NDI. Disable
18052 * first NDI in case an NDI+NDI concurrency exists.
18053 */
18054 ucfg_nan_check_and_disable_unsupported_ndi(hdd_ctx->psoc);
18055
Arif Hussainee677012017-01-26 17:50:13 -080018056 if (req->bssid)
18057 bssid = req->bssid;
18058 else if (bssid_hint)
18059 bssid = bssid_hint;
18060
Jeff Johnsonb8944722017-09-03 09:03:19 -070018061 if (bssid && hdd_get_adapter_by_macaddr(hdd_ctx, (uint8_t *)bssid)) {
Arif Hussain7631afa2017-02-08 14:35:00 -080018062 hdd_err("adapter exist with same mac address " MAC_ADDRESS_STR,
18063 MAC_ADDR_ARRAY(bssid));
18064 return -EINVAL;
Arif Hussainee677012017-01-26 17:50:13 -080018065 }
18066
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053018067 /*
18068 * Check if this is reassoc to same bssid, if reassoc is success, return
18069 */
18070 status = wlan_hdd_reassoc_bssid_hint(adapter, req);
Padma, Santhosh Kumar41552782018-06-29 15:31:25 +053018071 if (!status) {
18072 hdd_set_roaming_in_progress(true);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070018073 return status;
Padma, Santhosh Kumar41552782018-06-29 15:31:25 +053018074 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070018075
Agrawal Ashishf156e942016-08-04 14:54:47 +053018076 /* Try disconnecting if already in connected state */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018077 status = wlan_hdd_try_disconnect(adapter);
Agrawal Ashishf156e942016-08-04 14:54:47 +053018078 if (0 > status) {
18079 hdd_err("Failed to disconnect the existing connection");
18080 return -EALREADY;
18081 }
18082
Liangwei Dong3fa5cba2018-07-16 06:41:55 -040018083 /*initialise security parameters */
18084 status = wlan_hdd_cfg80211_set_privacy(adapter, req);
18085
18086 if (status < 0) {
18087 hdd_err("Failed to set security params");
18088 return status;
18089 }
18090
18091 /*
18092 * Check for max concurrent connections after doing disconnect if any,
18093 * must be called after the invocation of wlan_hdd_cfg80211_set_privacy
18094 * so privacy is already set for the current adapter before it's
18095 * checked against concurrency.
18096 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018097 if (req->channel) {
Min Liuab6ed4f2018-01-09 13:13:57 +080018098 bool ok = false;
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053018099
18100 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
Dustin Brown76cd2932018-09-11 16:03:05 -070018101 hdd_ctx->psoc,
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053018102 req->channel->hw_value,
18103 &ok)) {
18104 hdd_warn("Unable to get channel:%d eligibility for DNBS",
18105 req->channel->hw_value);
18106 return -EINVAL;
18107 }
18108 /**
18109 * Send connection timedout, so that Android framework does not
18110 * blacklist us.
18111 */
18112 if (!ok) {
18113 struct ieee80211_channel *chan =
Dustin Brown2eb1e452017-08-15 12:40:34 -070018114 ieee80211_get_channel(wiphy,
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053018115 wlan_chan_to_freq(req->channel->hw_value));
18116 struct cfg80211_bss *bss;
18117
18118 hdd_warn("Channel:%d not OK for DNBS",
18119 req->channel->hw_value);
18120 if (chan) {
Abhishek Singh59cdca12019-03-08 13:48:20 +053018121 bss = wlan_cfg80211_get_bss(wiphy, chan,
18122 req->bssid,
18123 req->ssid,
18124 req->ssid_len);
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053018125 if (bss) {
18126 cfg80211_assoc_timeout(ndev, bss);
18127 return -ETIMEDOUT;
18128 }
18129 }
18130 return -EINVAL;
18131 }
18132
Dustin Brown76cd2932018-09-11 16:03:05 -070018133 if (!policy_mgr_allow_concurrency(hdd_ctx->psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018134 policy_mgr_convert_device_mode_to_qdf_type(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018135 adapter->device_mode),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018136 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018137 hdd_warn("This concurrency combination is not allowed");
wadesongcaad7c72018-08-06 13:26:27 +080018138 status = -ECONNREFUSED;
18139 goto con_chk_failed;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018140 }
18141 } else {
Dustin Brown76cd2932018-09-11 16:03:05 -070018142 if (!policy_mgr_allow_concurrency(hdd_ctx->psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018143 policy_mgr_convert_device_mode_to_qdf_type(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018144 adapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018145 hdd_warn("This concurrency combination is not allowed");
wadesongcaad7c72018-08-06 13:26:27 +080018146 status = -ECONNREFUSED;
18147 goto con_chk_failed;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018148 }
18149 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070018150
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053018151 if (req->channel)
18152 channel = req->channel->hw_value;
18153 else
18154 channel = 0;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053018155
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018156 wlan_hdd_check_ht20_ht40_ind(hdd_ctx, adapter, req);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053018157
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018158 status = wlan_hdd_cfg80211_connect_start(adapter, req->ssid,
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053018159 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070018160 bssid_hint, channel, 0);
Srinivas Girigowdad2412882018-09-07 15:42:04 -070018161 if (0 > status)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018162 hdd_err("connect failed");
Srinivas Girigowdad2412882018-09-07 15:42:04 -070018163
wadesongcaad7c72018-08-06 13:26:27 +080018164 return status;
18165
18166con_chk_failed:
18167 wlan_hdd_cfg80211_clear_privacy(adapter);
Dustin Browne74003f2018-03-14 12:51:58 -070018168 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018169 return status;
18170}
18171
18172/**
18173 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
18174 * @wiphy: Pointer to wiphy
18175 * @dev: Pointer to network device
18176 * @req: Pointer to cfg80211 connect request
18177 *
18178 * Return: 0 for success, non-zero for failure
18179 */
18180static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
18181 struct net_device *ndev,
18182 struct cfg80211_connect_params *req)
18183{
Dustin Brown1d31b082018-11-22 14:41:20 +053018184 int errno;
18185 struct osif_vdev_sync *vdev_sync;
18186
18187 errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
18188 if (errno)
18189 return errno;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070018190
Dustin Brown1d31b082018-11-22 14:41:20 +053018191 errno = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018192
Dustin Brown1d31b082018-11-22 14:41:20 +053018193 osif_vdev_sync_op_stop(vdev_sync);
18194
18195 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018196}
18197
Himanshu Agarwal6c3607a2018-01-12 12:04:19 +053018198int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018199{
Dundi Ravitejacc95c562018-07-27 12:30:24 +053018200 QDF_STATUS status;
18201 int result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018202 unsigned long rc;
Jeff Johnsond377dce2017-10-04 10:32:42 -070018203 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018204 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053018205 eConnectionState prev_conn_state;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018206 mac_handle_t mac_handle;
Abhishek Singhd1f21c72019-01-21 15:16:34 +053018207 uint32_t wait_time = SME_DISCONNECT_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018208
Dustin Brown491d54b2018-03-14 12:39:11 -070018209 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018210
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018211 mac_handle = hdd_ctx->mac_handle;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018212 if (adapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018213 hdd_debug("Stop firmware roaming");
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018214 status = sme_stop_roaming(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018215 eCsrForcedDisassoc);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080018216 /*
Abhishek Singh533c9da2017-05-04 10:23:34 +053018217 * If firmware has already started roaming process, driver
18218 * needs to wait for processing of this disconnect request.
18219 *
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080018220 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018221 INIT_COMPLETION(adapter->roaming_comp_var);
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053018222 if (hdd_is_roaming_in_progress(hdd_ctx)) {
Abhishek Singh533c9da2017-05-04 10:23:34 +053018223 rc = wait_for_completion_timeout(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018224 &adapter->roaming_comp_var,
Abhishek Singh533c9da2017-05-04 10:23:34 +053018225 msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));
18226 if (!rc) {
Jeff Johnson55d2ab42019-03-06 11:43:49 -080018227 hdd_err("roaming comp var timed out vdev id: %d",
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018228 adapter->vdev_id);
Abhishek Singh533c9da2017-05-04 10:23:34 +053018229 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018230 if (adapter->roam_ho_fail) {
18231 INIT_COMPLETION(adapter->disconnect_comp_var);
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -070018232 hdd_debug("Disabling queues");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018233 wlan_hdd_netif_queue_control(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053018234 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
18235 WLAN_CONTROL_PATH);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018236 hdd_conn_set_connection_state(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053018237 eConnectionState_Disconnecting);
18238 goto wait_for_disconnect;
18239 }
18240 }
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080018241 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018242
Jeff Johnsone7951512019-02-27 10:02:51 -080018243 prev_conn_state = sta_ctx->conn_info.conn_state;
Srinivas Girigowda6598eea2017-07-06 19:26:19 -070018244 /*stop tx queues */
18245 hdd_info("Disabling queues");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018246 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053018247 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Jeff Johnsone7951512019-02-27 10:02:51 -080018248 hdd_debug("Set HDD conn_state to eConnectionState_Disconnecting");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018249 hdd_conn_set_connection_state(adapter, eConnectionState_Disconnecting);
Varun Reddy Yeturu9e0032c2017-07-12 18:39:59 -070018250
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018251 INIT_COMPLETION(adapter->disconnect_comp_var);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018252
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080018253 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018254
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018255 status = sme_roam_disconnect(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018256 adapter->vdev_id, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053018257 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
18258 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018259 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053018260 result = 0;
Abhishek Singhe9706cc2017-10-12 17:25:06 +053018261 /*
18262 * Wait here instead of returning directly. This will block the
18263 * next connect command and allow processing of the disconnect
18264 * in SME else we might hit some race conditions leading to SME
18265 * and HDD out of sync. As disconnect is already in progress,
18266 * wait here for 1 sec instead of 5 sec.
18267 */
18268 wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS;
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053018269 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
18270 /*
18271 * Wait here instead of returning directly, this will block the
18272 * next connect command and allow processing of the scan for
18273 * ssid and the previous connect command in CSR. Else we might
18274 * hit some race conditions leading to SME and HDD out of sync.
18275 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018276 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018277 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018278 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Jeff Johnson8380f232017-10-25 12:39:44 -070018279 sta_ctx->sta_debug_state = status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018280 result = -EINVAL;
18281 goto disconnected;
18282 }
Abhishek Singh533c9da2017-05-04 10:23:34 +053018283wait_for_disconnect:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018284 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Abhishek Singhe9706cc2017-10-12 17:25:06 +053018285 msecs_to_jiffies(wait_time));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018286
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053018287 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018288 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018289 result = -ETIMEDOUT;
18290 }
18291disconnected:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018292 hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018293#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
18294 /* Sending disconnect event to userspace for kernel version < 3.11
18295 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
18296 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018297 hdd_debug("Send disconnected event to userspace");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018298 wlan_hdd_cfg80211_indicate_disconnect(adapter->dev, true,
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053018299 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018300#endif
18301
18302 return result;
18303}
18304
18305/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080018306 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
18307 * @reason: ieee80211 reason code.
18308 *
18309 * This utility function helps log string conversion of reason code.
18310 *
18311 * Return: string conversion of reason code, if match found;
18312 * "Unknown" otherwise.
18313 */
18314static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
18315{
18316 switch (reason) {
18317 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
18318 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
18319 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
18320 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
18321 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
18322 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
18323 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
18324 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
18325 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
18326 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
18327 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
18328 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
18329 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
18330 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
18331 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
18332 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
18333 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
18334 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
18335 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
18336 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
18337 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
18338 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
18339 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
18340 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
18341 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
18342 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
18343 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
18344 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
18345 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
18346 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
18347 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
18348 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
18349 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
18350 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
18351 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
18352 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
18353 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
18354 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
18355 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
18356 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
18357 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
18358 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
18359 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
18360 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
18361 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
18362 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
18363 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
18364 default:
18365 return "Unknown";
18366 }
18367}
18368
18369/**
Srinivas Girigowda44cff5c2018-04-16 15:49:30 -070018370 * hdd_print_netdev_txq_status() - print netdev tx queue status
18371 * @dev: Pointer to network device
18372 *
18373 * This function is used to print netdev tx queue status
18374 *
18375 * Return: none
18376 */
18377static void hdd_print_netdev_txq_status(struct net_device *dev)
18378{
18379 unsigned int i;
18380
18381 if (!dev)
18382 return;
18383
18384 for (i = 0; i < dev->num_tx_queues; i++) {
18385 struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
18386
Dustin Brown1e3ec6b2018-08-07 11:18:47 -070018387 hdd_debug("netdev tx queue[%u] state: 0x%lx", i, txq->state);
Srinivas Girigowda44cff5c2018-04-16 15:49:30 -070018388 }
18389}
18390
18391/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018392 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
18393 * @wiphy: Pointer to wiphy
18394 * @dev: Pointer to network device
18395 * @reason: Disconnect reason code
18396 *
18397 * This function is used to issue a disconnect request to SME
18398 *
18399 * Return: 0 for success, non-zero for failure
18400 */
18401static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
18402 struct net_device *dev, u16 reason)
18403{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018404 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018405 int status;
Jeff Johnsond377dce2017-10-04 10:32:42 -070018406 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018407 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
18408 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Min Liu8c5d99e2018-09-10 17:18:44 +080018409 struct wlan_objmgr_vdev *vdev;
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053018410 bool enable_deauth_to_disassoc_map;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018411
Dustin Brown491d54b2018-03-14 12:39:11 -070018412 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018413
Anurag Chouhan6d760662016-02-20 16:05:43 +053018414 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018415 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018416 return -EINVAL;
18417 }
18418
Jeff Johnson48363022019-02-24 16:26:51 -080018419 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018420 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018421
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053018422 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
18423 TRACE_CODE_HDD_CFG80211_DISCONNECT,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018424 adapter->vdev_id, reason);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053018425
Srinivas Girigowda44cff5c2018-04-16 15:49:30 -070018426 hdd_print_netdev_txq_status(dev);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018427 hdd_debug("Device_mode %s(%d) reason code(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070018428 qdf_opmode_str(adapter->device_mode),
18429 adapter->device_mode, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018430
Jeff Johnsonb8944722017-09-03 09:03:19 -070018431 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018432
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018433 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018434 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018435
Alok Kumarb64650c2018-03-23 17:05:11 +053018436 qdf_mutex_acquire(&adapter->disconnection_status_lock);
18437 if (adapter->disconnection_in_progress) {
18438 qdf_mutex_release(&adapter->disconnection_status_lock);
18439 hdd_debug("Disconnect is already in progress");
18440 return 0;
18441 }
18442 adapter->disconnection_in_progress = true;
18443 qdf_mutex_release(&adapter->disconnection_status_lock);
18444
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018445 /* Issue disconnect request to SME, if station is in connected state */
Jeff Johnsone7951512019-02-27 10:02:51 -080018446 if ((sta_ctx->conn_info.conn_state == eConnectionState_Associated) ||
18447 (sta_ctx->conn_info.conn_state == eConnectionState_Connecting)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018448 eCsrRoamDisconnectReason reasonCode =
18449 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018450
18451 switch (reason) {
18452 case WLAN_REASON_MIC_FAILURE:
18453 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
18454 break;
18455
18456 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
18457 case WLAN_REASON_DISASSOC_AP_BUSY:
18458 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
18459 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
18460 break;
18461
18462 case WLAN_REASON_PREV_AUTH_NOT_VALID:
18463 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
18464 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
18465 break;
18466
18467 case WLAN_REASON_DEAUTH_LEAVING:
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053018468 status = ucfg_mlme_get_enable_deauth_to_disassoc_map(
18469 hdd_ctx->psoc,
18470 &enable_deauth_to_disassoc_map);
18471 if (QDF_IS_STATUS_ERROR(status))
18472 return -EINVAL;
18473
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018474 reasonCode =
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +053018475 enable_deauth_to_disassoc_map ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018476 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
18477 eCSR_DISCONNECT_REASON_DEAUTH;
Mohit Khannaceb97782017-04-05 16:27:08 -070018478 qdf_dp_trace_dump_all(
18479 WLAN_DEAUTH_DPTRACE_DUMP_COUNT,
18480 QDF_TRACE_DEFAULT_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018481 break;
18482 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
18483 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
18484 break;
18485 default:
18486 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
18487 break;
18488 }
Min Liu8c5d99e2018-09-10 17:18:44 +080018489
18490 vdev = hdd_objmgr_get_vdev(adapter);
18491 if (!vdev)
18492 return -EINVAL;
18493 if (ucfg_scan_get_vdev_status(vdev) !=
Sandeep Puligilla5f86d992017-10-29 14:58:53 -070018494 SCAN_NOT_IN_PROGRESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018495 hdd_debug("Disconnect is in progress, Aborting Scan");
Dustin Brown07901ec2018-09-07 11:02:41 -070018496 wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018497 adapter->vdev_id, INVALID_SCAN_ID,
Dustin Brown07901ec2018-09-07 11:02:41 -070018498 false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018499 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018500 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018501 /* First clean up the tdls peers if any */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018502 hdd_notify_sta_disconnect(adapter->vdev_id,
Min Liu8c5d99e2018-09-10 17:18:44 +080018503 false, true, vdev);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053018504 hdd_objmgr_put_vdev(vdev);
Kabilan Kannanb6153b12017-07-13 17:54:02 -070018505
Dustin Browna7bb6ae2018-08-16 16:51:50 -070018506 hdd_info("Disconnect from userspace; reason:%d (%s)",
18507 reason, hdd_ieee80211_reason_code_to_str(reason));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018508 status = wlan_hdd_disconnect(adapter, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018509 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018510 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Alok Kumarb64650c2018-03-23 17:05:11 +053018511 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018512 return -EINVAL;
18513 }
18514 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018515 hdd_err("Unexpected cfg disconnect called while in state: %d",
Jeff Johnsone7951512019-02-27 10:02:51 -080018516 sta_ctx->conn_info.conn_state);
Alok Kumarb64650c2018-03-23 17:05:11 +053018517 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018518 }
18519
18520 return status;
18521}
18522
18523/**
18524 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
18525 * @wiphy: Pointer to wiphy
18526 * @dev: Pointer to network device
18527 * @reason: Disconnect reason code
18528 *
18529 * Return: 0 for success, non-zero for failure
18530 */
18531static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
18532 struct net_device *dev, u16 reason)
18533{
Dustin Brown1d31b082018-11-22 14:41:20 +053018534 int errno;
18535 struct osif_vdev_sync *vdev_sync;
18536
18537 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
18538 if (errno)
18539 return errno;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070018540
Dustin Brown1d31b082018-11-22 14:41:20 +053018541 errno = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018542
Dustin Brown1d31b082018-11-22 14:41:20 +053018543 osif_vdev_sync_op_stop(vdev_sync);
18544
18545 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018546}
18547
18548/**
18549 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018550 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018551 * @param: Pointer to IBSS parameters
18552 *
18553 * This function is used to initialize the security settings in IBSS mode
18554 *
18555 * Return: 0 for success, non-zero for failure
18556 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018557static int wlan_hdd_cfg80211_set_privacy_ibss(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018558 struct cfg80211_ibss_params
18559 *params)
18560{
Naveen Rawat72475db2017-12-13 18:07:35 -080018561 uint32_t ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018562 int status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018563 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Jeff Johnsond377dce2017-10-04 10:32:42 -070018564 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018565 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070018566 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018567
Dustin Brown491d54b2018-03-14 12:39:11 -070018568 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018569
Jeff Johnsonce4a8342017-10-14 13:12:22 -070018570 sta_ctx->wpa_versions = 0;
Jeff Johnsond377dce2017-10-04 10:32:42 -070018571 qdf_mem_zero(&sta_ctx->ibss_enc_key, sizeof(tCsrRoamSetKey));
18572 sta_ctx->ibss_enc_key_installed = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018573
18574 if (params->ie_len && (NULL != params->ie)) {
Naveen Rawat08db88f2017-09-08 15:07:48 -070018575 if (wlan_get_ie_ptr_from_eid(WLAN_EID_RSN, params->ie,
18576 params->ie_len)) {
Jeff Johnsonce4a8342017-10-14 13:12:22 -070018577 sta_ctx->wpa_versions = NL80211_WPA_VERSION_2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018578 encryptionType = eCSR_ENCRYPT_TYPE_AES;
18579 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
Jeff Johnson6a2c0ca2019-03-09 22:08:45 -080018580 tDot11fIEWPA dot11_wpa_ie;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018581 mac_handle_t mac_handle =
18582 hdd_adapter_get_mac_handle(adapter);
Naveen Rawat08db88f2017-09-08 15:07:48 -070018583 const u8 *ie;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018584
Jeff Johnson6a2c0ca2019-03-09 22:08:45 -080018585 memset(&dot11_wpa_ie, 0, sizeof(dot11_wpa_ie));
Naveen Rawat08db88f2017-09-08 15:07:48 -070018586 ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_WPA,
18587 params->ie, params->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018588 if (NULL != ie) {
Jeff Johnsonce4a8342017-10-14 13:12:22 -070018589 sta_ctx->wpa_versions = NL80211_WPA_VERSION_1;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080018590 /* Unpack the WPA IE
18591 * Skip past the EID byte and length byte
18592 * and four byte WiFi OUI
18593 */
Hanumanth Reddy Pothulaf6e3db32018-01-24 17:54:15 +053018594 if (ie[1] < DOT11F_IE_WPA_MIN_LEN ||
18595 ie[1] > DOT11F_IE_WPA_MAX_LEN) {
18596 hdd_err("invalid ie len:%d", ie[1]);
18597 return -EINVAL;
18598 }
Naveen Rawat72475db2017-12-13 18:07:35 -080018599 ret = dot11f_unpack_ie_wpa(
Jeff Johnson034f3c92018-11-09 10:46:21 -080018600 MAC_CONTEXT(mac_handle),
Naveen Rawat72475db2017-12-13 18:07:35 -080018601 (uint8_t *)&ie[2 + 4],
Jeff Johnson6a2c0ca2019-03-09 22:08:45 -080018602 ie[1] - 4, &dot11_wpa_ie, false);
Naveen Rawat72475db2017-12-13 18:07:35 -080018603 if (DOT11F_FAILED(ret)) {
18604 hdd_err("unpack failed ret: 0x%x", ret);
18605 return -EINVAL;
18606 }
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053018607 /*
18608 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080018609 * encType for unicast cipher for
18610 * wpa-none is none
18611 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018612 encryptionType =
18613 hdd_translate_wpa_to_csr_encryption_type
Jeff Johnson6a2c0ca2019-03-09 22:08:45 -080018614 (dot11_wpa_ie.multicast_cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018615 }
18616 }
18617
18618 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018619 wlan_hdd_cfg80211_set_ie(adapter, params->ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018620 params->ie_len);
18621
18622 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018623 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018624 return status;
18625 }
18626 }
18627
Jeff Johnson20227a92018-03-13 09:41:05 -070018628 roam_profile = hdd_roam_profile(adapter);
18629 roam_profile->AuthType.authType[0] =
Jeff Johnson96e33512019-02-27 15:10:21 -080018630 sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018631
18632 if (params->privacy) {
18633 /* Security enabled IBSS, At this time there is no information
Jeff Johnson60ed45a2018-05-06 15:28:49 -070018634 * available about the security parameters, so initialise the
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018635 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
18636 * The correct security parameters will be updated later in
18637 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
18638 * set inorder enable privacy bit in beacons
18639 */
18640
18641 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
18642 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018643 hdd_debug("encryptionType=%d", encryptionType);
Jeff Johnsonb1959842019-02-27 13:04:04 -080018644 sta_ctx->conn_info.uc_encrypt_type = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070018645 roam_profile->EncryptionType.numEntries = 1;
18646 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018647 encryptionType;
18648 return status;
18649}
18650
18651/**
18652 * __wlan_hdd_cfg80211_join_ibss() - join ibss
18653 * @wiphy: Pointer to wiphy
18654 * @dev: Pointer to network device
18655 * @param: Pointer to IBSS join parameters
18656 *
18657 * This function is used to create/join an IBSS network
18658 *
18659 * Return: 0 for success, non-zero for failure
18660 */
18661static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
18662 struct net_device *dev,
18663 struct cfg80211_ibss_params *params)
18664{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018665 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070018666 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018667 int status;
Jeff Johnsond377dce2017-10-04 10:32:42 -070018668 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018669 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
18670 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053018671 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018672 u8 channelNum = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018673 mac_handle_t mac_handle;
Manikandan Mohan2bd09772018-11-28 18:27:32 -080018674 struct wlan_mlme_ibss_cfg ibss_cfg = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018675
Dustin Brown491d54b2018-03-14 12:39:11 -070018676 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018677
Anurag Chouhan6d760662016-02-20 16:05:43 +053018678 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018679 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018680 return -EINVAL;
18681 }
18682
Jeff Johnson48363022019-02-24 16:26:51 -080018683 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018684 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018685
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053018686 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
18687 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018688 adapter->vdev_id, adapter->device_mode);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053018689
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018690 hdd_debug("Device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070018691 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018692
Jeff Johnsonb8944722017-09-03 09:03:19 -070018693 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018694
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018695 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018696 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018697
Manikandan Mohan2bd09772018-11-28 18:27:32 -080018698 if (QDF_IS_STATUS_ERROR(ucfg_mlme_get_ibss_cfg(hdd_ctx->psoc,
18699 &ibss_cfg))) {
18700 return -EINVAL;
18701 }
18702
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018703 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018704 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053018705 params->chandef.chan) {
Wu Gao0821b0d2019-01-11 17:31:11 +080018706 uint32_t numChans = CFG_VALID_CHANNEL_LIST_LEN;
18707 uint8_t validChan[CFG_VALID_CHANNEL_LIST_LEN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018708 int indx;
18709
18710 /* Get channel number */
18711 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018712 params->
18713 chandef.
18714 chan->
18715 center_freq);
Wu Gaof3cbeaf2019-01-15 18:26:25 +080018716 ucfg_mlme_get_valid_channel_list(hdd_ctx->psoc, validChan,
18717 &numChans);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018718
18719 for (indx = 0; indx < numChans; indx++) {
Srinivas Girigowda576b2352017-08-25 14:44:26 -070018720 if (channelNum == validChan[indx])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018721 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018722 }
18723 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018724 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018725 return -EINVAL;
18726 }
18727 }
18728
Nachiket Kukade089b9832018-12-12 16:38:17 +053018729 /* Disable NAN Discovery if enabled */
18730 ucfg_nan_disable_concurrency(hdd_ctx->psoc);
18731
Dustin Brown76cd2932018-09-11 16:03:05 -070018732 if (!policy_mgr_allow_concurrency(hdd_ctx->psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018733 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018734 hdd_err("This concurrency combination is not allowed");
18735 return -ECONNREFUSED;
18736 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018737
Dustin Brown76cd2932018-09-11 16:03:05 -070018738 status = policy_mgr_reset_connection_update(hdd_ctx->psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070018739 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018740 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070018741
Dustin Brown76cd2932018-09-11 16:03:05 -070018742 status = policy_mgr_current_connections_update(hdd_ctx->psoc,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018743 adapter->vdev_id, channelNum,
Tushnim Bhattacharyya3b99f4b2018-03-26 14:19:24 -070018744 POLICY_MGR_UPDATE_REASON_JOIN_IBSS);
Krunal Soni3091bcc2016-06-23 12:28:21 -070018745 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018746 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070018747 return -EINVAL;
18748 }
18749
18750 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018751 status = policy_mgr_wait_for_connection_update(
Dustin Brown76cd2932018-09-11 16:03:05 -070018752 hdd_ctx->psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070018753 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018754 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018755 return -EINVAL;
18756 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018757 }
18758
18759 /*Try disconnecting if already in connected state */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018760 status = wlan_hdd_try_disconnect(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018761 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018762 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018763 return -EALREADY;
18764 }
18765
Jeff Johnson20227a92018-03-13 09:41:05 -070018766 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018767
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018768 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018769 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018770 return -EINVAL;
18771 }
18772
18773 /* enable selected protection checks in IBSS mode */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018774 roam_profile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018775
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018776 /* BSSID is provided by upper layers hence no need to AUTO generate */
18777 if (NULL != params->bssid) {
Manikandan Mohan2bd09772018-11-28 18:27:32 -080018778 if (ucfg_mlme_set_ibss_auto_bssid(hdd_ctx->psoc, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053018779 == QDF_STATUS_E_FAILURE) {
Manikandan Mohan2bd09772018-11-28 18:27:32 -080018780 hdd_err("Unable to update MLME IBSS Auto BSSID config");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018781 return -EIO;
18782 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053018783 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Manikandan Mohan2bd09772018-11-28 18:27:32 -080018784 } else if (ibss_cfg.coalesing_enable == 0) {
18785 if (ucfg_mlme_set_ibss_auto_bssid(hdd_ctx->psoc, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053018786 == QDF_STATUS_E_FAILURE) {
Manikandan Mohan2bd09772018-11-28 18:27:32 -080018787 hdd_err("Unable to update MLME IBSS Auto BSSID config");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018788 return -EIO;
18789 }
Manikandan Mohan2bd09772018-11-28 18:27:32 -080018790 qdf_copy_macaddr(&bssid, &ibss_cfg.bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018791 }
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053018792
18793 if (cfg_in_range(CFG_BEACON_INTERVAL, params->beacon_interval))
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018794 roam_profile->beaconInterval = params->beacon_interval;
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053018795 else
Dustin Brown05d81302018-09-11 16:49:22 -070018796 roam_profile->beaconInterval = cfg_get(hdd_ctx->psoc,
Bala Venkatesh2fde2c62018-09-11 20:33:24 +053018797 CFG_BEACON_INTERVAL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018798
18799 /* Set Channel */
18800 if (channelNum) {
18801 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018802 hdd_debug("set channel %d", channelNum);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018803 roam_profile->ChannelInfo.numOfChannels = 1;
Jeff Johnson8626e932019-02-27 18:35:22 -080018804 sta_ctx->conn_info.channel = channelNum;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018805 roam_profile->ChannelInfo.ChannelList =
Jeff Johnson8626e932019-02-27 18:35:22 -080018806 &sta_ctx->conn_info.channel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018807 }
18808
18809 /* Initialize security parameters */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018810 status = wlan_hdd_cfg80211_set_privacy_ibss(adapter, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018811 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018812 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018813 return status;
18814 }
18815
18816 /* Issue connect start */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018817 status = wlan_hdd_cfg80211_connect_start(adapter, params->ssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018818 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070018819 bssid.bytes, NULL,
Jeff Johnsond377dce2017-10-04 10:32:42 -070018820 sta_ctx->conn_info.
Jeff Johnson8626e932019-02-27 18:35:22 -080018821 channel,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070018822 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018823
18824 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018825 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018826 return status;
18827 }
Dustin Browne74003f2018-03-14 12:51:58 -070018828 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018829 return 0;
18830}
18831
18832/**
18833 * wlan_hdd_cfg80211_join_ibss() - join ibss
18834 * @wiphy: Pointer to wiphy
18835 * @dev: Pointer to network device
18836 * @param: Pointer to IBSS join parameters
18837 *
18838 * This function is used to create/join an IBSS network
18839 *
18840 * Return: 0 for success, non-zero for failure
18841 */
18842static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
18843 struct net_device *dev,
18844 struct cfg80211_ibss_params *params)
18845{
Dustin Brown1d31b082018-11-22 14:41:20 +053018846 int errno;
18847 struct osif_vdev_sync *vdev_sync;
18848
18849 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
18850 if (errno)
18851 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018852
Dustin Brown1d31b082018-11-22 14:41:20 +053018853 errno = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018854
Dustin Brown1d31b082018-11-22 14:41:20 +053018855 osif_vdev_sync_op_stop(vdev_sync);
18856
18857 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018858}
18859
18860/**
18861 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
18862 * @wiphy: Pointer to wiphy
18863 * @dev: Pointer to network device
18864 *
18865 * This function is used to leave an IBSS network
18866 *
18867 * Return: 0 for success, non-zero for failure
18868 */
18869static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
18870 struct net_device *dev)
18871{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018872 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070018873 struct csr_roam_profile *roam_profile;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018874 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018875 int status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018876 mac_handle_t mac_handle;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053018877 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080018878 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018879
Dustin Brown491d54b2018-03-14 12:39:11 -070018880 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018881
Anurag Chouhan6d760662016-02-20 16:05:43 +053018882 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018883 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018884 return -EINVAL;
18885 }
18886
Jeff Johnson48363022019-02-24 16:26:51 -080018887 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018888 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018889
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053018890 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
18891 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018892 adapter->vdev_id, eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053018893
Jeff Johnsonb8944722017-09-03 09:03:19 -070018894 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018895 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018896 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018897
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018898 hdd_debug("Device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070018899 qdf_opmode_str(adapter->device_mode), adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018900
Jeff Johnson20227a92018-03-13 09:41:05 -070018901 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018902
18903 /* Issue disconnect only if interface type is set to IBSS */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018904 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018905 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018906 return -EINVAL;
18907 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080018908 /* Clearing add IE of beacon */
Jeff Johnson1e851a12017-10-28 14:36:12 -070018909 qdf_mem_copy(updateIE.bssid.bytes, adapter->mac_addr.bytes,
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080018910 sizeof(tSirMacAddr));
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018911 updateIE.smeSessionId = adapter->vdev_id;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080018912 updateIE.ieBufferlength = 0;
18913 updateIE.pAdditionIEBuffer = NULL;
18914 updateIE.append = true;
18915 updateIE.notify = true;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018916 mac_handle = hdd_ctx->mac_handle;
18917 if (sme_update_add_ie(mac_handle,
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080018918 &updateIE,
18919 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018920 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080018921 }
18922
18923 /* Reset WNI_CFG_PROBE_RSP Flags */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018924 wlan_hdd_reset_prob_rspies(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018925
18926 /* Issue Disconnect request */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018927 INIT_COMPLETION(adapter->disconnect_comp_var);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018928 status = sme_roam_disconnect(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080018929 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018930 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
18931 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018932 hdd_err("sme_roam_disconnect failed status: %d",
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018933 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018934 return -EAGAIN;
18935 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053018936
18937 /* wait for mc thread to cleanup and then return to upper stack
18938 * so by the time upper layer calls the change interface, we are
18939 * all set to proceed further
18940 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018941 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Abhishek Singhd1f21c72019-01-21 15:16:34 +053018942 msecs_to_jiffies(SME_DISCONNECT_TIMEOUT));
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053018943 if (!rc) {
18944 hdd_err("Failed to disconnect, timed out");
18945 return -ETIMEDOUT;
18946 }
18947
Dustin Browne74003f2018-03-14 12:51:58 -070018948 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018949 return 0;
18950}
18951
18952/**
18953 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
18954 * @wiphy: Pointer to wiphy
18955 * @dev: Pointer to network device
18956 *
18957 * This function is used to leave an IBSS network
18958 *
18959 * Return: 0 for success, non-zero for failure
18960 */
18961static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
18962 struct net_device *dev)
18963{
Dustin Brown1d31b082018-11-22 14:41:20 +053018964 int errno;
18965 struct osif_vdev_sync *vdev_sync;
18966
18967 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
18968 if (errno)
18969 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018970
Dustin Brown1d31b082018-11-22 14:41:20 +053018971 errno = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018972
Dustin Brown1d31b082018-11-22 14:41:20 +053018973 osif_vdev_sync_op_stop(vdev_sync);
18974
18975 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018976}
18977
18978/**
18979 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
18980 * @wiphy: Pointer to wiphy
18981 * @changed: Parameters changed
18982 *
18983 * This function is used to set the phy parameters. RTS Threshold/FRAG
18984 * Threshold/Retry Count etc.
18985 *
18986 * Return: 0 for success, non-zero for failure
18987 */
18988static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
18989 u32 changed)
18990{
Jeff Johnsonb8944722017-09-03 09:03:19 -070018991 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018992 int status;
18993
Dustin Brown491d54b2018-03-14 12:39:11 -070018994 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018995
Anurag Chouhan6d760662016-02-20 16:05:43 +053018996 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018997 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018998 return -EINVAL;
18999 }
19000
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053019001 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
19002 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
19003 NO_SESSION, wiphy->rts_threshold);
19004
Jeff Johnsonb8944722017-09-03 09:03:19 -070019005 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019006
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019007 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019008 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019009
19010 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
19011 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
Harprit Chhabadabec6de42018-09-10 10:21:15 -070019012 cfg_max(CFG_RTS_THRESHOLD) :
19013 wiphy->rts_threshold;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019014
Harprit Chhabadabec6de42018-09-10 10:21:15 -070019015 if ((cfg_min(CFG_RTS_THRESHOLD) > rts_threshold) ||
19016 (cfg_max(CFG_RTS_THRESHOLD) < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019017 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019018 rts_threshold);
19019 return -EINVAL;
19020 }
19021
Harprit Chhabadabec6de42018-09-10 10:21:15 -070019022 if (0 != ucfg_mlme_set_rts_threshold(hdd_ctx->psoc,
19023 rts_threshold)) {
19024 hdd_err("mlme_set_rts_threshold failed for val %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019025 rts_threshold);
19026 return -EIO;
19027 }
19028
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019029 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019030 }
19031
19032 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
19033 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
Harprit Chhabadabec6de42018-09-10 10:21:15 -070019034 cfg_max(CFG_FRAG_THRESHOLD) :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019035 wiphy->frag_threshold;
19036
Harprit Chhabadabec6de42018-09-10 10:21:15 -070019037 if ((cfg_min(CFG_FRAG_THRESHOLD) > frag_threshold) ||
19038 (cfg_max(CFG_FRAG_THRESHOLD) < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019039 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019040 frag_threshold);
19041 return -EINVAL;
19042 }
19043
Harprit Chhabadabec6de42018-09-10 10:21:15 -070019044 if (0 != ucfg_mlme_set_frag_threshold(hdd_ctx->psoc,
19045 frag_threshold)) {
19046 hdd_err("mlme_set_frag_threshold failed for val %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019047 frag_threshold);
19048 return -EIO;
19049 }
19050
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019051 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019052 }
19053
Dustin Browne74003f2018-03-14 12:51:58 -070019054 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019055 return 0;
19056}
19057
19058/**
19059 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
19060 * @wiphy: Pointer to wiphy
19061 * @changed: Parameters changed
19062 *
19063 * Return: 0 for success, non-zero for failure
19064 */
19065static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
19066{
Dustin Brown363b4792019-02-05 16:11:55 -080019067 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080019068 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +053019069
Dustin Brown363b4792019-02-05 16:11:55 -080019070 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080019071 if (errno)
19072 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019073
Dustin Brownf0f00612019-01-31 16:02:24 -080019074 errno = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019075
Dustin Brown363b4792019-02-05 16:11:55 -080019076 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080019077
19078 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019079}
19080
19081/**
19082 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
19083 * key
19084 * @wiphy: Pointer to wiphy
19085 * @dev: Pointer to network device
19086 * @key_index: Key index
19087 *
19088 * Return: 0
19089 */
19090static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
19091 struct net_device *netdev,
19092 u8 key_index)
19093{
Dustin Brown491d54b2018-03-14 12:39:11 -070019094 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019095 return 0;
19096}
19097
19098/**
19099 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
19100 * wlan_hdd_set_default_mgmt_key
19101 * @wiphy: pointer to wiphy
19102 * @netdev: pointer to net_device structure
19103 * @key_index: key index
19104 *
19105 * Return: 0 on success, error number on failure
19106 */
19107static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
19108 struct net_device *netdev,
19109 u8 key_index)
19110{
Dustin Brown1d31b082018-11-22 14:41:20 +053019111 int errno;
19112 struct osif_vdev_sync *vdev_sync;
19113
19114 errno = osif_vdev_sync_op_start(netdev, &vdev_sync);
19115 if (errno)
19116 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019117
Dustin Brown1d31b082018-11-22 14:41:20 +053019118 errno = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019119
Dustin Brown1d31b082018-11-22 14:41:20 +053019120 osif_vdev_sync_op_stop(vdev_sync);
19121
19122 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019123}
19124
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019125/**
19126 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
19127 * @wiphy: Pointer to wiphy
19128 * @dev: Pointer to network device
19129 * @params: Pointer to tx queue parameters
19130 *
19131 * Return: 0
19132 */
19133static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
19134 struct net_device *dev,
19135 struct ieee80211_txq_params *params)
19136{
Dustin Brown491d54b2018-03-14 12:39:11 -070019137 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019138 return 0;
19139}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019140
19141/**
19142 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
19143 * @wiphy: pointer to wiphy
19144 * @netdev: pointer to net_device structure
19145 * @params: pointer to ieee80211_txq_params
19146 *
19147 * Return: 0 on success, error number on failure
19148 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019149static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
19150 struct net_device *dev,
19151 struct ieee80211_txq_params *params)
19152{
Dustin Brown1d31b082018-11-22 14:41:20 +053019153 int errno;
19154 struct osif_vdev_sync *vdev_sync;
19155
19156 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
19157 if (errno)
19158 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019159
Dustin Brown1d31b082018-11-22 14:41:20 +053019160 errno = __wlan_hdd_set_txq_params(wiphy, dev, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019161
Dustin Brown1d31b082018-11-22 14:41:20 +053019162 osif_vdev_sync_op_stop(vdev_sync);
19163
19164 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019165}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019166
19167/**
19168 * __wlan_hdd_cfg80211_del_station() - delete station v2
19169 * @wiphy: Pointer to wiphy
Jeff Johnson50e37e92019-03-08 11:32:25 -080019170 * @dev: Underlying net device
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019171 * @param: Pointer to delete station parameter
19172 *
19173 * Return: 0 for success, non-zero for failure
19174 */
19175static
19176int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
19177 struct net_device *dev,
Jeff Johnson50e37e92019-03-08 11:32:25 -080019178 struct csr_del_sta_params *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019179{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019180 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070019181 struct hdd_context *hdd_ctx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053019182 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070019183 struct hdd_hostapd_state *hapd_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019184 int status;
Jeff Johnson0a082d92019-03-04 12:25:49 -080019185 uint8_t sta_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019186 uint8_t *mac;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019187 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019188
Dustin Brown491d54b2018-03-14 12:39:11 -070019189 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019190
Anurag Chouhan6d760662016-02-20 16:05:43 +053019191 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019192 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019193 return -EINVAL;
19194 }
19195
Jeff Johnson48363022019-02-24 16:26:51 -080019196 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019197 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019198
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053019199 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
19200 TRACE_CODE_HDD_CFG80211_DEL_STA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019201 adapter->vdev_id, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019202
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019203 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070019204 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019205
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019206 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019207 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019208
Jeff Johnson50e37e92019-03-08 11:32:25 -080019209 mac = (uint8_t *) param->peerMacAddr.bytes;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019210 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019211
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019212 if ((QDF_SAP_MODE == adapter->device_mode) ||
19213 (QDF_P2P_GO_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019214
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019215 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019216 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019217 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019218 return 0;
19219 }
19220
Anurag Chouhanc5548422016-02-24 18:33:27 +053019221 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019222 uint16_t i;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019223
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019224 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070019225 if ((adapter->sta_info[i].in_use) &&
19226 (!adapter->sta_info[i].
Jeff Johnsone4f5d932017-10-21 13:21:15 -070019227 is_deauth_in_progress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053019228 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019229 mac,
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070019230 adapter->sta_info[i].
Jeff Johnsonf2356512017-10-21 16:04:12 -070019231 sta_mac.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053019232 QDF_MAC_ADDR_SIZE);
Yun Parka4bb37c2017-12-08 16:14:22 -080019233
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019234 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019235 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019236 MAC_ADDR_ARRAY(mac));
19237
Jeff Johnsonb8944722017-09-03 09:03:19 -070019238 if (hdd_ctx->dev_dfs_cac_status ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019239 DFS_CAC_IN_PROGRESS)
19240 goto fn_end;
19241
Wei Song2f76f642016-11-18 16:32:53 +080019242 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019243 qdf_status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019244 hdd_softap_sta_deauth(adapter,
Jeff Johnson50e37e92019-03-08 11:32:25 -080019245 param);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019246 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070019247 adapter->sta_info[i].
Jeff Johnsone4f5d932017-10-21 13:21:15 -070019248 is_deauth_in_progress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053019249 qdf_status =
Nachiket Kukade0396b732017-11-14 16:35:16 +053019250 qdf_wait_for_event_completion(
Naveen Rawatb56880c2016-12-13 17:56:03 -080019251 &hapd_state->
19252 qdf_sta_disassoc_event,
Abhishek Singhd1f21c72019-01-21 15:16:34 +053019253 SME_PEER_DISCONNECT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +053019254 if (!QDF_IS_STATUS_SUCCESS(
19255 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019256 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019257 }
19258 }
19259 }
19260 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019261 qdf_status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019262 hdd_softap_get_sta_id(adapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053019263 (struct qdf_mac_addr *) mac,
Jeff Johnson0a082d92019-03-04 12:25:49 -080019264 &sta_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019265 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019266 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019267 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019268 MAC_ADDR_ARRAY(mac));
19269 return -ENOENT;
19270 }
19271
Jeff Johnson0a082d92019-03-04 12:25:49 -080019272 if (adapter->sta_info[sta_id].is_deauth_in_progress ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019273 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019274 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019275 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019276 MAC_ADDR_ARRAY(mac));
19277 return -ENOENT;
19278 }
19279
Jeff Johnson0a082d92019-03-04 12:25:49 -080019280 adapter->sta_info[sta_id].is_deauth_in_progress = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019281
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019282 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019283 MAC_ADDR_ARRAY(mac));
19284
19285 /* Case: SAP in ACS selected DFS ch and client connected
19286 * Now Radar detected. Then if random channel is another
19287 * DFS ch then new CAC is initiated and no TX allowed.
19288 * So do not send any mgmt frames as it will timeout
19289 * during CAC.
19290 */
19291
Jeff Johnsonb8944722017-09-03 09:03:19 -070019292 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019293 goto fn_end;
19294
Wei Song2f76f642016-11-18 16:32:53 +080019295 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019296 sme_send_disassoc_req_frame(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019297 adapter->vdev_id,
Jeff Johnson50e37e92019-03-08 11:32:25 -080019298 (uint8_t *)&param->peerMacAddr,
19299 param->reason_code, 0);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019300 qdf_status = hdd_softap_sta_deauth(adapter,
Jeff Johnson50e37e92019-03-08 11:32:25 -080019301 param);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019302 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson0a082d92019-03-04 12:25:49 -080019303 adapter->sta_info[sta_id].is_deauth_in_progress =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019304 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019305 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019306 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019307 MAC_ADDR_ARRAY(mac));
19308 return -ENOENT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019309 }
Nachiket Kukade0396b732017-11-14 16:35:16 +053019310 qdf_status = qdf_wait_for_event_completion(
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019311 &hapd_state->
19312 qdf_sta_disassoc_event,
Abhishek Singhd1f21c72019-01-21 15:16:34 +053019313 SME_PEER_DISCONNECT_TIMEOUT);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019314 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
19315 hdd_warn("Deauth wait time expired");
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +053019316
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019317 }
19318 }
19319
19320fn_end:
Dustin Browne74003f2018-03-14 12:51:58 -070019321 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019322 return 0;
19323}
19324
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080019325#if defined(USE_CFG80211_DEL_STA_V2)
19326/**
19327 * wlan_hdd_del_station() - delete station wrapper
19328 * @adapter: pointer to the hdd adapter
19329 *
19330 * Return: None
19331 */
Jeff Johnsone5006672017-08-29 14:39:02 -070019332void wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080019333{
19334 struct station_del_parameters del_sta;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019335
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080019336 del_sta.mac = NULL;
19337 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
19338 del_sta.reason_code = eCsrForcedDeauthSta;
19339
19340 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
19341 &del_sta);
19342}
19343#else
Jeff Johnsone5006672017-08-29 14:39:02 -070019344void wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080019345{
19346 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
19347}
19348#endif
19349
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019350/**
Dustin Brown1d31b082018-11-22 14:41:20 +053019351 * wlan_hdd_cfg80211_del_station() - delete station entry handler
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019352 * @wiphy: Pointer to wiphy
Dustin Brown1d31b082018-11-22 14:41:20 +053019353 * @dev: net_device to operate against
19354 * @mac: binary mac address
19355 * @reason_code: reason for the deauthorization/disassociation
19356 * @subtype: management frame subtype to indicate removal
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019357 *
Dustin Brown1d31b082018-11-22 14:41:20 +053019358 * Return: Errno
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019359 */
Dustin Brown1d31b082018-11-22 14:41:20 +053019360static int _wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
19361 struct net_device *dev,
19362 const uint8_t *mac,
19363 uint16_t reason_code,
19364 uint8_t subtype)
19365{
19366 int errno;
19367 struct csr_del_sta_params delStaParams;
19368 struct osif_vdev_sync *vdev_sync;
19369
19370 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
19371 if (errno)
19372 return errno;
19373
Dustin Brown1d31b082018-11-22 14:41:20 +053019374 wlansap_populate_del_sta_params(mac, reason_code, subtype,
19375 &delStaParams);
19376 errno = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
Dustin Brown1d31b082018-11-22 14:41:20 +053019377
19378 osif_vdev_sync_op_stop(vdev_sync);
19379
19380 return errno;
19381}
19382
19383#ifdef USE_CFG80211_DEL_STA_V2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019384int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
19385 struct net_device *dev,
19386 struct station_del_parameters *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019387{
Dustin Brown1d31b082018-11-22 14:41:20 +053019388 if (!param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019389 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019390
Dustin Brown1d31b082018-11-22 14:41:20 +053019391 return _wlan_hdd_cfg80211_del_station(wiphy, dev, param->mac,
19392 param->reason_code,
19393 param->subtype);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019394}
Dustin Brown1d31b082018-11-22 14:41:20 +053019395#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
19396int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
19397 const uint8_t *mac)
19398{
19399 uint16_t reason = eSIR_MAC_DEAUTH_LEAVING_BSS_REASON;
19400 uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
19401
19402 return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
19403}
19404#else
19405int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
19406 uint8_t *mac)
19407{
19408 uint16_t reason = eSIR_MAC_DEAUTH_LEAVING_BSS_REASON;
19409 uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
19410
19411 return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
19412}
19413#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019414
19415/**
19416 * __wlan_hdd_cfg80211_add_station() - add station
19417 * @wiphy: Pointer to wiphy
19418 * @mac: Pointer to station mac address
19419 * @pmksa: Pointer to add station parameter
19420 *
19421 * Return: 0 for success, non-zero for failure
19422 */
19423static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
19424 struct net_device *dev,
19425 const uint8_t *mac,
19426 struct station_parameters *params)
19427{
19428 int status = -EPERM;
19429#ifdef FEATURE_WLAN_TDLS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019430 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070019431 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019432 u32 mask, set;
19433
Dustin Brown491d54b2018-03-14 12:39:11 -070019434 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019435
Anurag Chouhan6d760662016-02-20 16:05:43 +053019436 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019437 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019438 return -EINVAL;
19439 }
19440
Jeff Johnson48363022019-02-24 16:26:51 -080019441 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019442 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019443
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053019444 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
19445 TRACE_CODE_HDD_CFG80211_ADD_STA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019446 adapter->vdev_id, params->listen_interval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019447
Jeff Johnsonb8944722017-09-03 09:03:19 -070019448 if (0 != wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019449 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019450
19451 mask = params->sta_flags_mask;
19452
19453 set = params->sta_flags_set;
19454
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019455 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019456 MAC_ADDR_ARRAY(mac));
19457
19458 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Min Liu8c5d99e2018-09-10 17:18:44 +080019459 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
19460 struct wlan_objmgr_vdev *vdev;
19461
19462 vdev = hdd_objmgr_get_vdev(adapter);
19463 if (vdev) {
19464 status = wlan_cfg80211_tdls_add_peer(vdev,
19465 mac);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053019466 hdd_objmgr_put_vdev(vdev);
Min Liu8c5d99e2018-09-10 17:18:44 +080019467 }
19468 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019469 }
19470#endif
Dustin Browne74003f2018-03-14 12:51:58 -070019471 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019472 return status;
19473}
19474
19475/**
19476 * wlan_hdd_cfg80211_add_station() - add station
19477 * @wiphy: Pointer to wiphy
19478 * @mac: Pointer to station mac address
19479 * @pmksa: Pointer to add station parameter
19480 *
19481 * Return: 0 for success, non-zero for failure
19482 */
19483#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
19484static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
19485 struct net_device *dev,
19486 const uint8_t *mac,
19487 struct station_parameters *params)
19488#else
19489static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
19490 struct net_device *dev, uint8_t *mac,
19491 struct station_parameters *params)
19492#endif
19493{
Dustin Brown1d31b082018-11-22 14:41:20 +053019494 int errno;
19495 struct osif_vdev_sync *vdev_sync;
19496
19497 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
19498 if (errno)
19499 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019500
Dustin Brown1d31b082018-11-22 14:41:20 +053019501 errno = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019502
Dustin Brown1d31b082018-11-22 14:41:20 +053019503 osif_vdev_sync_op_stop(vdev_sync);
19504
19505 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019506}
19507
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053019508#if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
19509 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019510/*
19511 * wlan_hdd_is_pmksa_valid: API to validate pmksa
19512 * @pmksa: pointer to cfg80211_pmksa structure
19513 *
19514 * Return: True if valid else false
19515 */
19516static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
19517{
19518 if (!pmksa->bssid) {
Vignesh Viswanathanfa90d622017-12-22 13:13:26 +053019519 hdd_warn("bssid (%pK) is NULL",
19520 pmksa->bssid);
19521 if (!pmksa->ssid || !pmksa->cache_id) {
19522 hdd_err("either ssid (%pK) or cache_id (%pK) are NULL",
19523 pmksa->ssid, pmksa->cache_id);
19524 return false;
19525 }
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019526 }
19527 return true;
19528}
19529
19530/*
19531 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
gaurank kathpalia99d06c12018-05-16 16:28:35 +053019532 * @adapter: Pointer to hdd adapter
19533 * @pmk_cache: pmk that needs to be udated
19534 * @pmksa: pmk from supplicant
19535 * @is_delete: Bool to decide set or delete PMK
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019536 * Return: None
19537 */
gaurank kathpalia99d06c12018-05-16 16:28:35 +053019538static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
19539 tPmkidCacheInfo *pmk_cache,
19540 struct cfg80211_pmksa *pmksa, bool is_delete)
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019541{
19542 if (pmksa->bssid) {
19543 hdd_debug("%s PMKSA for " MAC_ADDRESS_STR,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019544 is_delete ? "Delete" : "Set",
19545 MAC_ADDR_ARRAY(pmksa->bssid));
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019546 qdf_mem_copy(pmk_cache->BSSID.bytes,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019547 pmksa->bssid, QDF_MAC_ADDR_SIZE);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019548 } else {
Jeff Johnson9c749db2018-05-07 12:50:46 -070019549 qdf_mem_copy(pmk_cache->ssid, pmksa->ssid, pmksa->ssid_len);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019550 qdf_mem_copy(pmk_cache->cache_id, pmksa->cache_id,
19551 CACHE_ID_LEN);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019552 pmk_cache->ssid_len = pmksa->ssid_len;
19553 hdd_debug("%s PMKSA for ssid %*.*s cache_id %x %x",
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019554 is_delete ? "Delete" : "Set",
19555 pmk_cache->ssid_len, pmk_cache->ssid_len,
19556 pmk_cache->ssid, pmk_cache->cache_id[0],
19557 pmk_cache->cache_id[1]);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019558 }
19559
19560 if (is_delete)
19561 return;
19562
19563 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
19564 if (pmksa->pmk_len && (pmksa->pmk_len <= CSR_RSN_MAX_PMK_LEN)) {
19565 qdf_mem_copy(pmk_cache->pmk, pmksa->pmk, pmksa->pmk_len);
19566 pmk_cache->pmk_len = pmksa->pmk_len;
19567 } else
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053019568 hdd_debug("pmk len is %zu", pmksa->pmk_len);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019569}
19570#else
19571/*
19572 * wlan_hdd_is_pmksa_valid: API to validate pmksa
19573 * @pmksa: pointer to cfg80211_pmksa structure
19574 *
19575 * Return: True if valid else false
19576 */
19577static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
19578{
19579 if (!pmksa->bssid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070019580 hdd_err("both bssid is NULL %pK", pmksa->bssid);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019581 return false;
19582 }
19583 return true;
19584}
19585
19586/*
19587 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
gaurank kathpalia99d06c12018-05-16 16:28:35 +053019588 * @adapter: Pointer to hdd adapter
19589 * @pmk_cache: pmk which needs to be updated
19590 * @pmksa: pmk from supplicant
19591 * @is_delete: Bool to decide whether to set or delete PMK
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019592 *
19593 * Return: None
19594 */
gaurank kathpalia99d06c12018-05-16 16:28:35 +053019595static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
19596 tPmkidCacheInfo *pmk_cache,
19597 struct cfg80211_pmksa *pmksa, bool is_delete)
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019598{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019599 mac_handle_t mac_handle;
Srinivas Girigowda50335342018-09-07 15:21:01 -070019600
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019601 hdd_debug("%s PMKSA for " MAC_ADDRESS_STR, is_delete ? "Delete" : "Set",
19602 MAC_ADDR_ARRAY(pmksa->bssid));
19603 qdf_mem_copy(pmk_cache->BSSID.bytes,
19604 pmksa->bssid, QDF_MAC_ADDR_SIZE);
19605
19606 if (is_delete)
19607 return;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019608 mac_handle = hdd_adapter_get_mac_handle(adapter);
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019609 sme_get_pmk_info(mac_handle, adapter->vdev_id, pmk_cache);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019610 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
19611}
19612#endif
19613
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019614/**
19615 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
19616 * @wiphy: Pointer to wiphy
19617 * @dev: Pointer to network device
19618 * @pmksa: Pointer to set pmksa parameter
19619 *
19620 * Return: 0 for success, non-zero for failure
19621 */
19622static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
19623 struct net_device *dev,
19624 struct cfg80211_pmksa *pmksa)
19625{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019626 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19627 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019628 mac_handle_t mac_handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019629 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019630 int status;
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019631 tPmkidCacheInfo pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019632
Dustin Brown491d54b2018-03-14 12:39:11 -070019633 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019634
Anurag Chouhan6d760662016-02-20 16:05:43 +053019635 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019636 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019637 return -EINVAL;
19638 }
19639
Jeff Johnson48363022019-02-24 16:26:51 -080019640 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019641 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019642
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019643 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019644 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019645 return -EINVAL;
19646 }
19647
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019648 if (!pmksa->pmkid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070019649 hdd_err("pmksa->pmkid(%pK) is NULL",
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019650 pmksa->pmkid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019651 return -EINVAL;
19652 }
19653
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019654 if (!wlan_hdd_is_pmksa_valid(pmksa))
19655 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019656
Jeff Johnsonb8944722017-09-03 09:03:19 -070019657 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019658
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019659 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019660 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019661
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019662 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019663
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019664 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019665
gaurank kathpalia99d06c12018-05-16 16:28:35 +053019666 hdd_fill_pmksa_info(adapter, &pmk_cache, pmksa, false);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019667
19668 /*
19669 * Add to the PMKSA Cache in CSR
19670 * PMKSA cache will be having following
19671 * 1. pmkid id
19672 * 2. pmk
19673 * 3. bssid or cache identifier
19674 */
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019675 result = sme_roam_set_pmkid_cache(mac_handle, adapter->vdev_id,
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019676 &pmk_cache, 1, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019677
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053019678 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
19679 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019680 adapter->vdev_id, result);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019681
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019682 sme_set_del_pmkid_cache(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019683 &pmk_cache, true);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019684
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +053019685 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
Dustin Browne74003f2018-03-14 12:51:58 -070019686 hdd_exit();
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +053019687
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019688 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019689}
19690
19691/**
19692 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
19693 * @wiphy: Pointer to wiphy
19694 * @dev: Pointer to network device
19695 * @pmksa: Pointer to set pmksa parameter
19696 *
19697 * Return: 0 for success, non-zero for failure
19698 */
19699static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
19700 struct net_device *dev,
19701 struct cfg80211_pmksa *pmksa)
19702{
Dustin Brown1d31b082018-11-22 14:41:20 +053019703 int errno;
19704 struct osif_vdev_sync *vdev_sync;
19705
19706 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
19707 if (errno)
19708 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019709
Dustin Brown1d31b082018-11-22 14:41:20 +053019710 errno = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019711
Dustin Brown1d31b082018-11-22 14:41:20 +053019712 osif_vdev_sync_op_stop(vdev_sync);
19713
19714 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019715}
19716
19717/**
19718 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
19719 * @wiphy: Pointer to wiphy
19720 * @dev: Pointer to network device
19721 * @pmksa: Pointer to pmksa parameter
19722 *
19723 * Return: 0 for success, non-zero for failure
19724 */
19725static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
19726 struct net_device *dev,
19727 struct cfg80211_pmksa *pmksa)
19728{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019729 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19730 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019731 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019732 int status = 0;
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019733 tPmkidCacheInfo pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019734
Dustin Brown491d54b2018-03-14 12:39:11 -070019735 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019736
Anurag Chouhan6d760662016-02-20 16:05:43 +053019737 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019738 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019739 return -EINVAL;
19740 }
19741
Jeff Johnson48363022019-02-24 16:26:51 -080019742 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019743 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019744
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019745 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019746 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019747 return -EINVAL;
19748 }
19749
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019750 if (!wlan_hdd_is_pmksa_valid(pmksa))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019751 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019752
Jeff Johnsonb8944722017-09-03 09:03:19 -070019753 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019754
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019755 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019756 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019757
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019758 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019759
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053019760 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
19761 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019762 adapter->vdev_id, 0);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019763
19764 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
19765
gaurank kathpalia99d06c12018-05-16 16:28:35 +053019766 hdd_fill_pmksa_info(adapter, &pmk_cache, pmksa, true);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053019767
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019768 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019769 if (QDF_STATUS_SUCCESS !=
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019770 sme_roam_del_pmkid_from_cache(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019771 adapter->vdev_id, &pmk_cache,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019772 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019773 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019774 MAC_ADDR_ARRAY(pmksa->bssid));
19775 status = -EINVAL;
19776 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019777
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019778 sme_set_del_pmkid_cache(mac_handle, adapter->vdev_id, &pmk_cache,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019779 false);
Ashish Kumar Dhanotiya36510832019-02-20 22:13:25 +053019780 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
19781
Dustin Browne74003f2018-03-14 12:51:58 -070019782 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019783 return status;
19784}
19785
19786/**
19787 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
19788 * @wiphy: Pointer to wiphy
19789 * @dev: Pointer to network device
19790 * @pmksa: Pointer to pmksa parameter
19791 *
19792 * Return: 0 for success, non-zero for failure
19793 */
19794static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
19795 struct net_device *dev,
19796 struct cfg80211_pmksa *pmksa)
19797{
Dustin Brown1d31b082018-11-22 14:41:20 +053019798 int errno;
19799 struct osif_vdev_sync *vdev_sync;
19800
19801 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
19802 if (errno)
19803 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019804
Dustin Brown1d31b082018-11-22 14:41:20 +053019805 errno = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019806
Dustin Brown1d31b082018-11-22 14:41:20 +053019807 osif_vdev_sync_op_stop(vdev_sync);
19808
19809 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019810
19811}
19812
19813/**
19814 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
19815 * @wiphy: Pointer to wiphy
19816 * @dev: Pointer to network device
19817 *
19818 * Return: 0 for success, non-zero for failure
19819 */
19820static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
19821 struct net_device *dev)
19822{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019823 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19824 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019825 mac_handle_t mac_handle;
19826 int errno;
19827 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019828
Dustin Brown491d54b2018-03-14 12:39:11 -070019829 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019830
Anurag Chouhan6d760662016-02-20 16:05:43 +053019831 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019832 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019833 return -EINVAL;
19834 }
19835
Jeff Johnson48363022019-02-24 16:26:51 -080019836 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019837 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019838
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019839 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019840
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019841 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019842 errno = wlan_hdd_validate_context(hdd_ctx);
19843 if (errno)
19844 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019845
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019846 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019847
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019848 status = sme_roam_del_pmkid_from_cache(mac_handle,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019849 adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019850 NULL, true);
19851 if (QDF_IS_STATUS_ERROR(status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019852 hdd_err("Cannot flush PMKIDCache");
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019853 errno = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019854 }
Vignesh Viswanathane8a26b22017-10-11 20:38:47 +053019855
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019856 sme_set_del_pmkid_cache(mac_handle, adapter->vdev_id, NULL, false);
Dustin Browne74003f2018-03-14 12:51:58 -070019857 hdd_exit();
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019858 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019859}
19860
19861/**
19862 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
19863 * @wiphy: Pointer to wiphy
19864 * @dev: Pointer to network device
19865 *
19866 * Return: 0 for success, non-zero for failure
19867 */
19868static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
19869 struct net_device *dev)
19870{
Dustin Brown1d31b082018-11-22 14:41:20 +053019871 int errno;
19872 struct osif_vdev_sync *vdev_sync;
19873
19874 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
19875 if (errno)
19876 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019877
Dustin Brown1d31b082018-11-22 14:41:20 +053019878 errno = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019879
Dustin Brown1d31b082018-11-22 14:41:20 +053019880 osif_vdev_sync_op_stop(vdev_sync);
19881
19882 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019883}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019884
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080019885#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019886/**
19887 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
19888 * @wiphy: Pointer to wiphy
19889 * @dev: Pointer to network device
19890 * @ftie: Pointer to fast transition ie parameter
19891 *
19892 * Return: 0 for success, non-zero for failure
19893 */
19894static int
19895__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
19896 struct net_device *dev,
19897 struct cfg80211_update_ft_ies_params *ftie)
19898{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070019899 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019900 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsond377dce2017-10-04 10:32:42 -070019901 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019902 int status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019903 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019904
Dustin Brown491d54b2018-03-14 12:39:11 -070019905 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019907 status = wlan_hdd_validate_context(hdd_ctx);
19908 if (status)
19909 return status;
19910
Anurag Chouhan6d760662016-02-20 16:05:43 +053019911 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019912 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019913 return -EINVAL;
19914 }
19915
Jeff Johnson48363022019-02-24 16:26:51 -080019916 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019917 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019918
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053019919 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
19920 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
Jeff Johnsone7951512019-02-27 10:02:51 -080019921 adapter->vdev_id, sta_ctx->conn_info.conn_state);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053019922
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019923 /* Added for debug on reception of Re-assoc Req. */
Jeff Johnsone7951512019-02-27 10:02:51 -080019924 if (eConnectionState_Associated != sta_ctx->conn_info.conn_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019925 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019926 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019927 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019928 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019929 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019930 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019931
19932 /* Pass the received FT IEs to SME */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019933 mac_handle = hdd_ctx->mac_handle;
Jeff Johnsoncf07c312019-02-04 13:53:29 -080019934 sme_set_ft_ies(mac_handle, adapter->vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019935 (const u8 *)ftie->ie, ftie->ie_len);
Dustin Browne74003f2018-03-14 12:51:58 -070019936 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019937 return 0;
19938}
19939
19940/**
19941 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
19942 * @wiphy: Pointer to wiphy
19943 * @dev: Pointer to network device
19944 * @ftie: Pointer to fast transition ie parameter
19945 *
19946 * Return: 0 for success, non-zero for failure
19947 */
19948static int
19949wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
19950 struct net_device *dev,
19951 struct cfg80211_update_ft_ies_params *ftie)
19952{
Dustin Brown1d31b082018-11-22 14:41:20 +053019953 int errno;
19954 struct osif_vdev_sync *vdev_sync;
19955
19956 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
19957 if (errno)
19958 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019959
Dustin Brown1d31b082018-11-22 14:41:20 +053019960 errno = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019961
Dustin Brown1d31b082018-11-22 14:41:20 +053019962 osif_vdev_sync_op_stop(vdev_sync);
19963
19964 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019965}
19966#endif
19967
Min Liu0daa0982019-02-01 17:50:44 +080019968#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
19969/**
19970 * __wlan_hdd_cfg80211_update_owe_info() - update OWE info
19971 * @wiphy: Pointer to wiphy
19972 * @dev: Pointer to network device
19973 * @owe_info: Pointer to OWE info
19974 *
19975 * Return: 0 for success, non-zero for failure
19976 */
19977static int
19978__wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
19979 struct net_device *dev,
19980 struct cfg80211_update_owe_info *owe_info)
19981{
19982 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
19983 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19984 QDF_STATUS status;
Dustin Brown96b98dd2019-03-06 12:39:37 -080019985 int errno;
Min Liu0daa0982019-02-01 17:50:44 +080019986
19987 hdd_enter_dev(dev);
19988
19989 errno = wlan_hdd_validate_context(hdd_ctx);
19990 if (errno)
19991 return errno;
19992
19993 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19994 hdd_err("Command not allowed in FTM mode");
19995 return -EINVAL;
19996 }
19997
Jeff Johnsona6b398d2019-02-24 16:26:51 -080019998 if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) {
19999 hdd_err("invalid vdev id: %d", adapter->vdev_id);
Min Liu0daa0982019-02-01 17:50:44 +080020000 return -EINVAL;
20001 }
20002
20003 hdd_debug("owe_status %d", owe_info->status);
20004
20005 status = wlansap_update_owe_info(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
20006 owe_info->bssid, owe_info->ie,
20007 owe_info->ie_len, owe_info->status);
20008 if (QDF_IS_STATUS_ERROR(status)) {
20009 hdd_err("Failed to update OWE info");
20010 errno = qdf_status_to_os_return(status);
20011 }
20012
20013 hdd_exit();
20014 return errno;
20015}
20016
20017/**
20018 * wlan_hdd_cfg80211_update_owe_info() - update OWE info
20019 * @wiphy: Pointer to wiphy
20020 * @dev: Pointer to network device
20021 * @owe_info: Pointer to OWE info
20022 *
20023 * Return: 0 for success, non-zero for failure
20024 */
20025static int
20026wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
Dustin Brown96b98dd2019-03-06 12:39:37 -080020027 struct net_device *net_dev,
Min Liu0daa0982019-02-01 17:50:44 +080020028 struct cfg80211_update_owe_info *owe_info)
20029{
Dustin Brown96b98dd2019-03-06 12:39:37 -080020030 struct osif_vdev_sync *vdev_sync;
20031 int errno;
Min Liu0daa0982019-02-01 17:50:44 +080020032
Dustin Brown96b98dd2019-03-06 12:39:37 -080020033 errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
20034 if (errno)
20035 return errno;
Min Liu0daa0982019-02-01 17:50:44 +080020036
Dustin Brown96b98dd2019-03-06 12:39:37 -080020037 errno = __wlan_hdd_cfg80211_update_owe_info(wiphy, net_dev, owe_info);
20038
20039 osif_vdev_sync_op_stop(vdev_sync);
20040
20041 return errno;
Min Liu0daa0982019-02-01 17:50:44 +080020042}
20043#endif
20044
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +053020045void wlan_hdd_cfg80211_update_replay_counter_cb(
Mukul Sharma3d36c392017-01-18 18:39:12 +053020046 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
20047
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020048{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020049 struct hdd_adapter *adapter = (struct hdd_adapter *)cb_ctx;
Mukul Sharma3d36c392017-01-18 18:39:12 +053020050 uint8_t temp_replay_counter[8];
20051 int i;
20052 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020053
Dustin Brown491d54b2018-03-14 12:39:11 -070020054 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020055
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020056 if (!adapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020057 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053020058 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020059 }
20060
Mukul Sharma3d36c392017-01-18 18:39:12 +053020061 if (!gtk_rsp_param) {
20062 hdd_err("gtk_rsp_param is Null");
20063 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020064 }
20065
Mukul Sharma3d36c392017-01-18 18:39:12 +053020066 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020067 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053020068 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020069 }
20070
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020071 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053020072 gtk_rsp_param->replay_counter);
20073 /* convert little to big endian since supplicant works on big endian */
20074 p = (uint8_t *)&gtk_rsp_param->replay_counter;
20075 for (i = 0; i < 8; i++)
20076 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020077
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020078 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020079 /* Update replay counter to NL */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020080 cfg80211_gtk_rekey_notify(adapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053020081 gtk_rsp_param->bssid.bytes,
20082 temp_replay_counter, GFP_KERNEL);
20083out:
Dustin Browne74003f2018-03-14 12:51:58 -070020084 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053020085
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020086}
20087
Wu Gaoa9d336b2018-05-30 14:48:04 +080020088#ifdef WLAN_FEATURE_GTK_OFFLOAD
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020089/**
20090 * wlan_hdd_copy_gtk_kek - Copy the KEK from GTK rekey data to GTK request
20091 * @gtk_req: Pointer to GTK request
20092 * @data: Pointer to rekey data
20093 *
20094 * Return: none
20095 */
20096#ifdef CFG80211_REKEY_DATA_KEK_LEN
20097static
20098void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
20099 struct cfg80211_gtk_rekey_data *data)
20100{
20101 qdf_mem_copy(gtk_req->kek, data->kek, data->kek_len);
20102 gtk_req->kek_len = data->kek_len;
20103}
20104#else
20105static
20106void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
20107 struct cfg80211_gtk_rekey_data *data)
20108{
20109 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
20110 gtk_req->kek_len = NL80211_KEK_LEN;
20111}
20112#endif
20113
20114/**
20115 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
20116 * @wiphy: Pointer to wiphy
20117 * @dev: Pointer to network device
20118 * @data: Pointer to rekey data
20119 *
20120 * This function is used to offload GTK rekeying job to the firmware.
20121 *
20122 * Return: 0 for success, non-zero for failure
20123 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070020124static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020125int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053020126 struct net_device *dev,
20127 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020128{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020129 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053020130 int result, i;
20131 struct pmo_gtk_req *gtk_req = NULL;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020132 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharma3d36c392017-01-18 18:39:12 +053020133 uint8_t *buf;
Min Liu8c5d99e2018-09-10 17:18:44 +080020134 struct wlan_objmgr_vdev *vdev;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020135 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020136
Dustin Brown491d54b2018-03-14 12:39:11 -070020137 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020138
Anurag Chouhan6d760662016-02-20 16:05:43 +053020139 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020140 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053020141 result = -EINVAL;
20142 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020143 }
20144
Jeff Johnson48363022019-02-24 16:26:51 -080020145 if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) {
Mukul Sharma3d36c392017-01-18 18:39:12 +053020146 result = -EINVAL;
20147 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020148 }
20149
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020150 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
20151 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020152 adapter->vdev_id, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020153
Mukul Sharma3d36c392017-01-18 18:39:12 +053020154 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020155 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053020156 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020157
Mukul Sharma3d36c392017-01-18 18:39:12 +053020158 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
20159 if (!gtk_req) {
Mukul Sharma3d36c392017-01-18 18:39:12 +053020160 result = -ENOMEM;
20161 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020162 }
20163
Mukul Sharma3d36c392017-01-18 18:39:12 +053020164 /* convert big to little endian since driver work on little endian */
20165 buf = (uint8_t *)&gtk_req->replay_counter;
20166 for (i = 0; i < 8; i++)
20167 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020168
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020169 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053020170 gtk_req->replay_counter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020171
20172 wlan_hdd_copy_gtk_kek(gtk_req, data);
Mukul Sharma3d36c392017-01-18 18:39:12 +053020173 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
gaurank kathpalia82a1b2b2018-07-10 16:49:10 +053020174 gtk_req->is_fils_connection = hdd_is_fils_connection(adapter);
Min Liu8c5d99e2018-09-10 17:18:44 +080020175 vdev = hdd_objmgr_get_vdev(adapter);
20176 if (!vdev) {
20177 result = -EINVAL;
20178 goto out;
20179 }
20180 status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
Rajeev Kumar Sirasanagandla25bdfad2019-02-15 19:15:49 +053020181 hdd_objmgr_put_vdev(vdev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053020182 if (status != QDF_STATUS_SUCCESS) {
20183 hdd_err("Failed to cache GTK Offload");
20184 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020185 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053020186out:
20187 if (gtk_req)
20188 qdf_mem_free(gtk_req);
Dustin Browne74003f2018-03-14 12:51:58 -070020189 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053020190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020191 return result;
20192}
20193
20194/**
20195 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
20196 * @wiphy: Pointer to wiphy
20197 * @dev: Pointer to network device
20198 * @data: Pointer to rekey data
20199 *
20200 * This function is used to offload GTK rekeying job to the firmware.
20201 *
20202 * Return: 0 for success, non-zero for failure
20203 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070020204static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020205int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
20206 struct net_device *dev,
20207 struct cfg80211_gtk_rekey_data *data)
20208{
Dustin Brown1d31b082018-11-22 14:41:20 +053020209 int errno;
20210 struct osif_vdev_sync *vdev_sync;
20211
20212 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
20213 if (errno)
20214 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020215
Dustin Brown1d31b082018-11-22 14:41:20 +053020216 errno = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020217
Dustin Brown1d31b082018-11-22 14:41:20 +053020218 osif_vdev_sync_op_stop(vdev_sync);
20219
20220 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020221}
Wu Gaoa9d336b2018-05-30 14:48:04 +080020222#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020223
20224/**
20225 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
20226 * @wiphy: Pointer to wiphy
20227 * @dev: Pointer to network device
20228 * @param: Pointer to access control parameter
20229 *
20230 * Return: 0 for success, non-zero for failure
20231 */
20232static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
20233 struct net_device *dev,
20234 const struct cfg80211_acl_data *params)
20235{
20236 int i;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020237 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson5c19ade2017-10-04 09:52:12 -070020238 struct hdd_hostapd_state *hostapd_state;
Jeff Johnson954903d2019-03-07 20:41:27 -080020239 tsap_config_t *config;
Jeff Johnsonb8944722017-09-03 09:03:19 -070020240 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020241 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020242 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020243
Dustin Brown491d54b2018-03-14 12:39:11 -070020244 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020245
Anurag Chouhan6d760662016-02-20 16:05:43 +053020246 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020247 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020248 return -EINVAL;
20249 }
20250
20251 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020252 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020253 return -EINVAL;
20254 }
20255
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020256 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020257 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020258
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020259 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020260 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020261
Jeff Johnson5c19ade2017-10-04 09:52:12 -070020262 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020263
Jeff Johnson5c19ade2017-10-04 09:52:12 -070020264 if (NULL == hostapd_state) {
20265 hdd_err("hostapd_state is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020266 return -EINVAL;
20267 }
20268
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020269 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020270 params->n_acl_entries);
20271
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020272 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
20273 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020274 adapter->vdev_id, adapter->device_mode);
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020275
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020276 if (QDF_SAP_MODE == adapter->device_mode) {
Jeff Johnson954903d2019-03-07 20:41:27 -080020277 config = &adapter->session.ap.sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020278
20279 /* default value */
Jeff Johnson954903d2019-03-07 20:41:27 -080020280 config->num_accept_mac = 0;
20281 config->num_deny_mac = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020282
20283 /**
20284 * access control policy
20285 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
20286 * listed in hostapd.deny file.
20287 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
20288 * listed in hostapd.accept file.
20289 */
20290 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
Jeff Johnson954903d2019-03-07 20:41:27 -080020291 config->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020292 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
20293 params->acl_policy) {
Jeff Johnson954903d2019-03-07 20:41:27 -080020294 config->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020295 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020296 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020297 params->acl_policy);
20298 return -ENOTSUPP;
20299 }
20300
Jeff Johnson954903d2019-03-07 20:41:27 -080020301 if (eSAP_DENY_UNLESS_ACCEPTED == config->SapMacaddr_acl) {
20302 config->num_accept_mac = params->n_acl_entries;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020303 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020304 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020305 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020306 MAC_ADDR_ARRAY(
20307 params->mac_addrs[i].addr));
20308
Jeff Johnson954903d2019-03-07 20:41:27 -080020309 qdf_mem_copy(&config->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020310 params->mac_addrs[i].addr,
20311 sizeof(qcmacaddr));
20312 }
Jeff Johnson954903d2019-03-07 20:41:27 -080020313 } else if (eSAP_ACCEPT_UNLESS_DENIED == config->SapMacaddr_acl) {
20314 config->num_deny_mac = params->n_acl_entries;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020315 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020316 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020317 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020318 MAC_ADDR_ARRAY(
20319 params->mac_addrs[i].addr));
20320
Jeff Johnson954903d2019-03-07 20:41:27 -080020321 qdf_mem_copy(&config->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020322 params->mac_addrs[i].addr,
20323 sizeof(qcmacaddr));
20324 }
20325 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070020326 qdf_status = wlansap_set_mac_acl(
Jeff Johnson954903d2019-03-07 20:41:27 -080020327 WLAN_HDD_GET_SAP_CTX_PTR(adapter), config);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020328 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020329 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020330 return -EINVAL;
20331 }
20332 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020333 hdd_debug("Invalid device_mode %s(%d)",
Dustin Brown458027c2018-10-19 12:26:27 -070020334 qdf_opmode_str(adapter->device_mode),
20335 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020336 return -EINVAL;
20337 }
Dustin Browne74003f2018-03-14 12:51:58 -070020338 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020339 return 0;
20340}
20341
20342/**
20343 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
20344 * __wlan_hdd_cfg80211_set_mac_acl
20345 * @wiphy: pointer to wiphy structure
20346 * @dev: pointer to net_device
20347 * @params: pointer to cfg80211_acl_data
20348 *
20349 * Return; 0 on success, error number otherwise
20350 */
20351static int
20352wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
20353 struct net_device *dev,
20354 const struct cfg80211_acl_data *params)
20355{
Dustin Brown1d31b082018-11-22 14:41:20 +053020356 int errno;
20357 struct osif_vdev_sync *vdev_sync;
20358
20359 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
20360 if (errno)
20361 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020362
Dustin Brown1d31b082018-11-22 14:41:20 +053020363 errno = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020364
Dustin Brown1d31b082018-11-22 14:41:20 +053020365 osif_vdev_sync_op_stop(vdev_sync);
20366
20367 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020368}
20369
20370#ifdef WLAN_NL80211_TESTMODE
20371#ifdef FEATURE_WLAN_LPHB
20372/**
20373 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
Jeff Johnsonb8944722017-09-03 09:03:19 -070020374 * @hdd_ctx: Pointer to hdd context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020375 * @lphbInd: Pointer to low power heart beat indication parameter
20376 *
20377 * Return: none
20378 */
Jeff Johnsonb8944722017-09-03 09:03:19 -070020379static void wlan_hdd_cfg80211_lphb_ind_handler(void *hdd_ctx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053020380 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020381{
20382 struct sk_buff *skb;
20383
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020384 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020385
Jeff Johnsonb8944722017-09-03 09:03:19 -070020386 if (0 != wlan_hdd_validate_context((struct hdd_context *) hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020387 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020388
Mukul Sharmafcd57f52017-03-20 18:18:59 +053020389 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020390 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020391 return;
20392 }
20393
Jeff Johnsonb8944722017-09-03 09:03:19 -070020394 skb = cfg80211_testmode_alloc_event_skb(((struct hdd_context *) hdd_ctx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053020395 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020396 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020397 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020398 return;
20399 }
20400
20401 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020402 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020403 goto nla_put_failure;
20404 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053020405 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020406 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020407 goto nla_put_failure;
20408 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053020409 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
20410 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020411 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020412 goto nla_put_failure;
20413 }
20414 cfg80211_testmode_event(skb, GFP_ATOMIC);
20415 return;
20416
20417nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020418 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020419 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020420}
20421#endif /* FEATURE_WLAN_LPHB */
20422
20423/**
20424 * __wlan_hdd_cfg80211_testmode() - test mode
20425 * @wiphy: Pointer to wiphy
20426 * @data: Data pointer
20427 * @len: Data length
20428 *
20429 * Return: 0 for success, non-zero for failure
20430 */
20431static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
20432 void *data, int len)
20433{
20434 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
20435 int err;
Jeff Johnsonb8944722017-09-03 09:03:19 -070020436 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020437
Dustin Brown491d54b2018-03-14 12:39:11 -070020438 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020439
Jeff Johnsonb8944722017-09-03 09:03:19 -070020440 err = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020441 if (err)
20442 return err;
20443
Ryan Hsu4df41382018-06-15 15:45:22 -070020444 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
20445 hdd_err("Driver Modules are closed");
20446 return -EINVAL;
20447 }
20448
Dustin Brown4ea21db2018-01-05 14:13:17 -080020449 err = wlan_cfg80211_nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
20450 len, wlan_hdd_tm_policy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020451 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020452 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020453 return err;
20454 }
20455
20456 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020457 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020458 return -EINVAL;
20459 }
20460
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +053020461 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
20462 TRACE_CODE_HDD_CFG80211_TESTMODE,
20463 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
20464
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020465 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
20466#ifdef FEATURE_WLAN_LPHB
20467 /* Low Power Heartbeat configuration request */
20468 case WLAN_HDD_TM_CMD_WLAN_HB:
20469 {
20470 int buf_len;
20471 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053020472 struct pmo_lphb_req *hb_params = NULL;
20473 struct pmo_lphb_req *hb_params_temp = NULL;
20474 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020475
20476 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020477 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020478 return -EINVAL;
20479 }
20480
20481 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
20482 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
20483
Mukul Sharmafcd57f52017-03-20 18:18:59 +053020484 hb_params_temp = (struct pmo_lphb_req *) buf;
20485 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
20486 && (hb_params_temp->params.lphb_tcp_params.
20487 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020488 return -EINVAL;
20489
Manjeet Singh00b2a562017-01-03 12:08:10 +053020490 if (buf_len > sizeof(*hb_params)) {
20491 hdd_err("buf_len=%d exceeded hb_params size limit",
20492 buf_len);
20493 return -ERANGE;
20494 }
20495
Mukul Sharmafcd57f52017-03-20 18:18:59 +053020496 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
20497 sizeof(*hb_params));
Min Liu74a1a502018-10-10 19:59:07 +080020498 if (!hb_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020499 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020500
Ashish Kumar Dhanotiya0fa8ee02017-07-13 14:04:31 +053020501 qdf_mem_zero(hb_params, sizeof(*hb_params));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053020502 qdf_mem_copy(hb_params, buf, buf_len);
Wu Gaod7dd6e42018-10-16 17:22:56 +080020503 status = ucfg_pmo_lphb_config_req(
20504 hdd_ctx->psoc,
Jeff Johnsonb8944722017-09-03 09:03:19 -070020505 hb_params, (void *)hdd_ctx,
Wu Gaod7dd6e42018-10-16 17:22:56 +080020506 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053020507 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020508 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053020509
20510 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020511 return 0;
20512 }
20513#endif /* FEATURE_WLAN_LPHB */
20514
20515#if defined(QCA_WIFI_FTM)
20516 case WLAN_HDD_TM_CMD_WLAN_FTM:
20517 {
Ryan Hsu4df41382018-06-15 15:45:22 -070020518 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam()) {
20519 hdd_err("Command not allowed in FTM mode, mode %d",
20520 hdd_get_conparam());
20521 return -EINVAL;
20522 }
20523
Dustin Brown07901ec2018-09-07 11:02:41 -070020524 err = wlan_cfg80211_ftm_testmode_cmd(hdd_ctx->pdev,
Ryan Hsuc8b27a42018-01-02 13:57:56 -080020525 data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020526 break;
20527 }
20528#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020529 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020530 hdd_err("command: %d not supported",
Ryan Hsuc8b27a42018-01-02 13:57:56 -080020531 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020532 return -EOPNOTSUPP;
20533 }
Ryan Hsuc8b27a42018-01-02 13:57:56 -080020534
Dustin Browne74003f2018-03-14 12:51:58 -070020535 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020536 return err;
20537}
20538
20539/**
20540 * wlan_hdd_cfg80211_testmode() - test mode
20541 * @wiphy: Pointer to wiphy
20542 * @dev: Pointer to network device
20543 * @data: Data pointer
20544 * @len: Data length
20545 *
20546 * Return: 0 for success, non-zero for failure
20547 */
20548static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
20549#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
20550 struct wireless_dev *wdev,
20551#endif
20552 void *data, int len)
20553{
Dustin Brown363b4792019-02-05 16:11:55 -080020554 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080020555 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +053020556
Dustin Brown363b4792019-02-05 16:11:55 -080020557 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080020558 if (errno)
20559 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020560
Dustin Brownf0f00612019-01-31 16:02:24 -080020561 errno = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020562
Dustin Brown363b4792019-02-05 16:11:55 -080020563 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080020564
20565 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020566}
20567
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020568#endif /* CONFIG_NL80211_TESTMODE */
20569
20570#ifdef QCA_HT_2040_COEX
20571/**
20572 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
20573 * @wiphy: Pointer to wiphy
20574 * @dev: Pointer to network device
20575 * @chandef: Pointer to channel definition parameter
20576 *
20577 * Return: 0 for success, non-zero for failure
20578 */
20579static int
20580__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
20581 struct net_device *dev,
20582 struct cfg80211_chan_def *chandef)
20583{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020584 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020585 struct hdd_context *hdd_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020586 QDF_STATUS status;
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053020587 int retval = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020588
Anurag Chouhan6d760662016-02-20 16:05:43 +053020589 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020590 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020591 return -EINVAL;
20592 }
20593
Jeff Johnson48363022019-02-24 16:26:51 -080020594 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020595 return -EINVAL;
Dustin Brown63500612018-08-07 11:36:09 -070020596
Abhishek Singh9d5f4582017-10-11 17:59:48 +053020597 if (!(adapter->device_mode == QDF_SAP_MODE ||
20598 adapter->device_mode == QDF_P2P_GO_MODE))
20599 return -EOPNOTSUPP;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020600
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020601 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020602 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053020603 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020604 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020605
Abhishek Singh9d5f4582017-10-11 17:59:48 +053020606 hdd_debug("Channel width changed to %d ",
20607 cfg80211_get_chandef_type(chandef));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020608
20609 /* Change SAP ht2040 mode */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020610 status = hdd_set_sap_ht2040_mode(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020611 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020612 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020613 hdd_err("Cannot set SAP HT20/40 mode!");
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053020614 retval = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020615 }
20616
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053020617 return retval;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020618}
20619
20620/**
20621 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
20622 * @wiphy: Pointer to wiphy
20623 * @dev: Pointer to network device
20624 * @chandef: Pointer to channel definition parameter
20625 *
20626 * Return: 0 for success, non-zero for failure
20627 */
20628static int
20629wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
20630 struct net_device *dev,
20631 struct cfg80211_chan_def *chandef)
20632{
Dustin Brown1d31b082018-11-22 14:41:20 +053020633 int errno;
20634 struct osif_vdev_sync *vdev_sync;
20635
20636 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
20637 if (errno)
20638 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020639
Dustin Brown1d31b082018-11-22 14:41:20 +053020640 errno = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020641
Dustin Brown1d31b082018-11-22 14:41:20 +053020642 osif_vdev_sync_op_stop(vdev_sync);
20643
20644 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020645}
20646#endif
20647
Abhishek Singh1bdb1572015-10-16 16:24:19 +053020648#ifdef CHANNEL_SWITCH_SUPPORTED
20649/**
20650 * __wlan_hdd_cfg80211_channel_switch()- function to switch
20651 * channel in SAP/GO
20652 * @wiphy: wiphy pointer
20653 * @dev: dev pointer.
20654 * @csa_params: Change channel params
20655 *
20656 * This function is called to switch channel in SAP/GO
20657 *
20658 * Return: 0 if success else return non zero
20659 */
20660static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
20661 struct net_device *dev,
20662 struct cfg80211_csa_settings *csa_params)
20663{
Jeff Johnsone5006672017-08-29 14:39:02 -070020664 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070020665 struct hdd_context *hdd_ctx;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053020666 uint8_t channel;
20667 uint16_t freq;
20668 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080020669 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053020670
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020671 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053020672 csa_params->chandef.chan->center_freq);
20673
Jeff Johnson48363022019-02-24 16:26:51 -080020674 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020675 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020676
Abhishek Singh1bdb1572015-10-16 16:24:19 +053020677 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
20678 ret = wlan_hdd_validate_context(hdd_ctx);
20679
20680 if (0 != ret)
20681 return ret;
20682
Krunal Sonib4326f22016-03-10 13:05:51 -080020683 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
20684 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053020685 return -ENOTSUPP;
20686
20687 freq = csa_params->chandef.chan->center_freq;
20688 channel = cds_freq_to_chan(freq);
20689
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053020690 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
20691
Min Liu2fef5792018-01-19 17:59:42 +080020692 ret = hdd_softap_set_channel_change(dev, channel, ch_width, false);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053020693 return ret;
20694}
20695
20696/**
20697 * wlan_hdd_cfg80211_channel_switch()- function to switch
20698 * channel in SAP/GO
20699 * @wiphy: wiphy pointer
20700 * @dev: dev pointer.
20701 * @csa_params: Change channel params
20702 *
20703 * This function is called to switch channel in SAP/GO
20704 *
20705 * Return: 0 if success else return non zero
20706 */
20707static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
20708 struct net_device *dev,
20709 struct cfg80211_csa_settings *csa_params)
20710{
Dustin Brown1d31b082018-11-22 14:41:20 +053020711 int errno;
20712 struct osif_vdev_sync *vdev_sync;
20713
20714 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
20715 if (errno)
20716 return errno;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053020717
Dustin Brown1d31b082018-11-22 14:41:20 +053020718 errno = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
Dustin Brown1d31b082018-11-22 14:41:20 +053020719
20720 osif_vdev_sync_op_stop(vdev_sync);
20721
20722 return errno;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053020723}
20724#endif
20725
Krunal Sonied3bc8e2018-01-26 12:13:34 -080020726int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter,
20727 uint8_t channel,
20728 enum policy_mgr_conn_update_reason reason)
20729{
20730 QDF_STATUS status;
20731 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
20732
Dustin Brown491d54b2018-03-14 12:39:11 -070020733 hdd_enter();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080020734 if (0 != wlan_hdd_validate_context(hdd_ctx))
20735 return -EINVAL;
20736
Dustin Brown76cd2932018-09-11 16:03:05 -070020737 status = policy_mgr_reset_connection_update(hdd_ctx->psoc);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080020738 if (!QDF_IS_STATUS_SUCCESS(status))
20739 hdd_err("clearing event failed");
20740
Dustin Brown76cd2932018-09-11 16:03:05 -070020741 status = policy_mgr_current_connections_update(hdd_ctx->psoc,
Jeff Johnsoncf07c312019-02-04 13:53:29 -080020742 adapter->vdev_id, channel, reason);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080020743 switch (status) {
20744 case QDF_STATUS_E_FAILURE:
20745 /*
Jeff Johnson11d7c9d2018-05-06 15:44:09 -070020746 * QDF_STATUS_E_FAILURE indicates that some error has occurred
Krunal Sonied3bc8e2018-01-26 12:13:34 -080020747 * while changing the hw mode
20748 */
20749 hdd_err("ERROR: connections update failed!!");
20750 return -EINVAL;
20751
20752 case QDF_STATUS_SUCCESS:
20753 /*
20754 * QDF_STATUS_SUCCESS indicates that HW mode change has been
20755 * triggered and wait for it to finish.
20756 */
20757 status = policy_mgr_wait_for_connection_update(
Dustin Brown76cd2932018-09-11 16:03:05 -070020758 hdd_ctx->psoc);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080020759 if (!QDF_IS_STATUS_SUCCESS(status)) {
20760 hdd_err("ERROR: qdf wait for event failed!!");
20761 return -EINVAL;
20762 }
20763 if (QDF_MONITOR_MODE == adapter->device_mode)
20764 hdd_info("Monitor mode:channel:%d (SMM->DBS)", channel);
20765 break;
20766
20767 default:
20768 /*
20769 * QDF_STATUS_E_NOSUPPORT indicates that no HW mode change is
20770 * required, so caller can proceed further.
20771 */
20772 break;
20773
20774 }
Dustin Browne74003f2018-03-14 12:51:58 -070020775 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080020776
20777 return 0;
20778}
20779
Nirav Shah73713f72018-05-17 14:50:41 +053020780#ifdef FEATURE_MONITOR_MODE_SUPPORT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020781/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020782 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
20783 * @wiphy: Handle to struct wiphy to get handle to module context.
20784 * @chandef: Contains information about the capture channel to be set.
20785 *
20786 * This interface is called if and only if monitor mode interface alone is
20787 * active.
20788 *
20789 * Return: 0 success or error code on failure.
20790 */
20791static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
20792 struct cfg80211_chan_def *chandef)
20793{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070020794 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsone5006672017-08-29 14:39:02 -070020795 struct hdd_adapter *adapter;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070020796 struct hdd_station_ctx *sta_ctx;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020797 struct hdd_mon_set_ch_info *ch_info;
20798 QDF_STATUS status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070020799 mac_handle_t mac_handle;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020800 struct qdf_mac_addr bssid;
Jeff Johnson61b5e982018-03-15 11:33:31 -070020801 struct csr_roam_profile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080020802 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070020803 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020804 int ret;
20805 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
20806
Dustin Brown491d54b2018-03-14 12:39:11 -070020807 hdd_enter();
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020808
20809 ret = wlan_hdd_validate_context(hdd_ctx);
20810 if (ret)
20811 return ret;
20812
Jeff Johnson34fc63a2018-06-14 10:10:02 -070020813 mac_handle = hdd_ctx->mac_handle;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020814
20815 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
20816 if (!adapter)
20817 return -EIO;
20818
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020819 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020820 adapter->dev->name, chan_num, chandef->chan->center_freq);
20821
20822 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
20823 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020824 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
20825 roam_profile.ChannelInfo.numOfChannels = 1;
20826 roam_profile.phyMode = ch_info->phy_mode;
Naveen Rawat3184dd82017-07-05 14:58:18 -070020827 roam_profile.ch_params.ch_width = hdd_map_nl_chan_width(chandef->width);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070020828 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020829
Jeff Johnson1e851a12017-10-28 14:36:12 -070020830 qdf_mem_copy(bssid.bytes, adapter->mac_addr.bytes,
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020831 QDF_MAC_ADDR_SIZE);
20832
Naveen Rawat3184dd82017-07-05 14:58:18 -070020833 ch_params.ch_width = hdd_map_nl_chan_width(chandef->width);
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070020834 /*
20835 * CDS api expects secondary channel for calculating
20836 * the channel params
20837 */
20838 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070020839 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070020840 if (chan_num >= 1 && chan_num <= 5)
20841 sec_ch = chan_num + 4;
20842 else if (chan_num >= 6 && chan_num <= 13)
20843 sec_ch = chan_num - 4;
20844 }
Dustin Brown07901ec2018-09-07 11:02:41 -070020845 wlan_reg_set_channel_params(hdd_ctx->pdev, chan_num,
20846 sec_ch, &ch_params);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080020847 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, chan_num,
20848 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
20849 hdd_err("Failed to change hw mode");
20850 return -EINVAL;
20851 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -070020852 status = sme_roam_channel_change_req(mac_handle, bssid, &ch_params,
20853 &roam_profile);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020854 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020855 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020856 status);
20857 ret = qdf_status_to_os_return(status);
20858 return ret;
20859 }
Dustin Browne74003f2018-03-14 12:51:58 -070020860 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080020861
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020862 return 0;
20863}
20864
20865/**
20866 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
20867 * @wiphy: Handle to struct wiphy to get handle to module context.
20868 * @chandef: Contains information about the capture channel to be set.
20869 *
20870 * This interface is called if and only if monitor mode interface alone is
20871 * active.
20872 *
20873 * Return: 0 success or error code on failure.
20874 */
20875static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
20876 struct cfg80211_chan_def *chandef)
20877{
Dustin Brown363b4792019-02-05 16:11:55 -080020878 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -080020879 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +053020880
Dustin Brown363b4792019-02-05 16:11:55 -080020881 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080020882 if (errno)
20883 return errno;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020884
Dustin Brownf0f00612019-01-31 16:02:24 -080020885 errno = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
Arunk Khandavalli447837f2018-11-08 14:32:53 +053020886
Dustin Brown363b4792019-02-05 16:11:55 -080020887 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -080020888
20889 return errno;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020890}
Nirav Shah73713f72018-05-17 14:50:41 +053020891#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070020892
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053020893#define CNT_DIFF(cur, prev) \
20894 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
20895#define MAX_COUNT 0xffffffff
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070020896static void hdd_update_chan_info(struct hdd_context *hdd_ctx,
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053020897 struct scan_chan_info *chan,
20898 struct scan_chan_info *info, uint32_t cmd_flag)
20899{
20900 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
20901 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
20902 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
20903
20904 mutex_lock(&hdd_ctx->chan_info_lock);
20905
20906 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
20907 qdf_mem_zero(chan, sizeof(*chan));
20908
20909 chan->freq = info->freq;
20910 chan->noise_floor = info->noise_floor;
20911 chan->clock_freq = info->clock_freq;
20912 chan->cmd_flag = info->cmd_flag;
20913 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
20914
20915 chan->rx_clear_count =
20916 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
20917
20918 chan->tx_frame_count =
20919 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
20920
20921 mutex_unlock(&hdd_ctx->chan_info_lock);
20922
20923}
20924#undef CNT_DIFF
20925#undef MAX_COUNT
20926
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020927#if defined(WLAN_FEATURE_FILS_SK) &&\
Sridhar Selvaraje5260442017-08-19 10:12:03 +053020928 defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) &&\
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020929 (defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
20930 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
20931
20932#ifndef UPDATE_FILS_ERP_INFO
20933#define UPDATE_FILS_ERP_INFO BIT(1)
20934#endif
20935
20936#ifndef UPDATE_FILS_AUTH_TYPE
20937#define UPDATE_FILS_AUTH_TYPE BIT(2)
20938#endif
20939
20940/**
20941 * __wlan_hdd_cfg80211_update_connect_params - update connect params
20942 * @wiphy: Handle to struct wiphy to get handle to module context.
20943 * @dev: Pointer to network device
20944 * @req: Pointer to connect params
20945 * @changed: Bitmap used to indicate the changed params
20946 *
20947 * Update the connect parameters while connected to a BSS. The updated
20948 * parameters can be used by driver/firmware for subsequent BSS selection
20949 * (roaming) decisions and to form the Authentication/(Re)Association
20950 * Request frames. This call does not request an immediate disassociation
20951 * or reassociation with the current BSS, i.e., this impacts only
20952 * subsequent (re)associations. The bits in changed are defined in enum
20953 * cfg80211_connect_params_changed
20954 *
20955 * Return: zero for success, non-zero for failure
20956 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070020957static int
20958__wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
20959 struct net_device *dev,
20960 struct cfg80211_connect_params *req,
20961 uint32_t changed)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020962{
Jeff Johnson61b5e982018-03-15 11:33:31 -070020963 struct csr_roam_profile *roam_profile;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020964 uint8_t *buf;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070020965 int ret;
20966 enum eAniAuthType auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020967 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
20968 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
20969 QDF_STATUS status;
20970 struct cds_fils_connection_info *fils_info;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070020971 mac_handle_t mac_handle;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020972
Dustin Brownfdf17c12018-03-14 12:55:34 -070020973 hdd_enter_dev(dev);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020974
Jeff Johnson48363022019-02-24 16:26:51 -080020975 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020976 return -EINVAL;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020977
20978 ret = wlan_hdd_validate_context(hdd_ctx);
20979 if (ret)
20980 return -EINVAL;
20981
Jeff Johnson20227a92018-03-13 09:41:05 -070020982 roam_profile = hdd_roam_profile(adapter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020983 fils_info = roam_profile->fils_con_info;
20984
20985 if (!fils_info) {
20986 hdd_err("No valid FILS conn info");
20987 return -EINVAL;
20988 }
20989
20990 if (req->ie_len)
20991 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
20992
20993 if (changed)
20994 fils_info->is_fils_connection = true;
20995
20996 if (changed & UPDATE_FILS_ERP_INFO) {
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080020997 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080020998 return -EINVAL;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020999 fils_info->key_nai_length = req->fils_erp_username_len +
21000 sizeof(char) +
21001 req->fils_erp_realm_len;
Dundi Raviteja170d2872018-03-23 15:49:54 +053021002 if (fils_info->key_nai_length >
21003 FILS_MAX_KEYNAME_NAI_LENGTH) {
21004 hdd_err("Key NAI Length %d",
21005 fils_info->key_nai_length);
21006 return -EINVAL;
21007 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021008 if (req->fils_erp_username_len && req->fils_erp_username) {
21009 buf = fils_info->keyname_nai;
21010 qdf_mem_copy(buf, req->fils_erp_username,
21011 req->fils_erp_username_len);
21012 buf += req->fils_erp_username_len;
21013 *buf++ = '@';
21014 qdf_mem_copy(buf, req->fils_erp_realm,
21015 req->fils_erp_realm_len);
21016 }
21017
Pragaspathi Thilagaraj87a60af2019-02-20 20:42:47 +053021018 fils_info->sequence_number = req->fils_erp_next_seq_num + 1;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021019 fils_info->r_rk_length = req->fils_erp_rrk_len;
21020
21021 if (req->fils_erp_rrk_len && req->fils_erp_rrk)
21022 qdf_mem_copy(fils_info->r_rk, req->fils_erp_rrk,
21023 fils_info->r_rk_length);
21024
21025 fils_info->realm_len = req->fils_erp_realm_len;
21026 if (req->fils_erp_realm_len && req->fils_erp_realm)
21027 qdf_mem_copy(fils_info->realm, req->fils_erp_realm,
21028 fils_info->realm_len);
21029 }
21030
21031 if (changed & UPDATE_FILS_AUTH_TYPE) {
21032 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070021033 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021034 hdd_err("invalid auth type for fils %d",
21035 req->auth_type);
21036 return -EINVAL;
21037 }
21038
21039 roam_profile->fils_con_info->auth_type = auth_type;
21040 }
21041
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080021042 hdd_debug("fils conn update: changed %x is_fils %d keyname nai len %d",
21043 changed, roam_profile->fils_con_info->is_fils_connection,
21044 roam_profile->fils_con_info->key_nai_length);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021045
Abhishek Singh1f217ec2017-12-22 11:48:27 +053021046 if (!hdd_ctx->is_fils_roaming_supported) {
21047 hdd_debug("FILS roaming support %d",
Vignesh Viswanathan731186f2017-09-18 13:47:37 +053021048 hdd_ctx->is_fils_roaming_supported);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021049 return 0;
21050 }
21051
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021052 mac_handle = hdd_ctx->mac_handle;
Jeff Johnsoncf07c312019-02-04 13:53:29 -080021053 status = sme_update_fils_config(mac_handle, adapter->vdev_id,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021054 roam_profile);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021055 if (QDF_IS_STATUS_ERROR(status))
21056 hdd_err("Update FILS connect params to Fw failed %d", status);
21057
21058 return 0;
21059}
21060
21061/**
21062 * wlan_hdd_cfg80211_update_connect_params - SSR wrapper for
21063 * __wlan_hdd_cfg80211_update_connect_params
21064 * @wiphy: Pointer to wiphy structure
21065 * @dev: Pointer to net_device
21066 * @req: Pointer to connect params
21067 * @changed: flags used to indicate the changed params
21068 *
21069 * Return: zero for success, non-zero for failure
21070 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021071static int
21072wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
21073 struct net_device *dev,
21074 struct cfg80211_connect_params *req,
21075 uint32_t changed)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021076{
Dustin Brown1d31b082018-11-22 14:41:20 +053021077 int errno;
21078 struct osif_vdev_sync *vdev_sync;
21079
21080 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21081 if (errno)
21082 return errno;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021083
Dustin Brown1d31b082018-11-22 14:41:20 +053021084 errno = __wlan_hdd_cfg80211_update_connect_params(wiphy, dev,
21085 req, changed);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021086
Dustin Brown1d31b082018-11-22 14:41:20 +053021087 osif_vdev_sync_op_stop(vdev_sync);
21088
21089 return errno;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021090}
21091#endif
21092
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053021093#if defined(WLAN_FEATURE_SAE) && \
21094 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
Srinivas Dasari29186ca2019-02-11 18:45:48 +053021095#if defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT)
21096/**
21097 * wlan_hdd_extauth_cache_pmkid() - Extract and cache pmkid
21098 * @adapter: hdd vdev/net_device context
21099 * @mac_handle: Handle to the MAC
21100 * @params: Pointer to external auth params.
21101 *
21102 * Extract the PMKID and BSS from external auth params and add to the
21103 * PMKSA Cache in CSR.
21104 */
21105static void
21106wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
21107 mac_handle_t mac_handle,
21108 struct cfg80211_external_auth_params *params)
21109{
21110 tPmkidCacheInfo pmk_cache;
21111 QDF_STATUS result;
21112 if (params->pmkid) {
21113 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
21114 qdf_mem_copy(pmk_cache.BSSID.bytes, params->bssid,
21115 QDF_MAC_ADDR_SIZE);
21116 qdf_mem_copy(pmk_cache.PMKID, params->pmkid,
21117 CSR_RSN_PMKID_SIZE);
21118 result = sme_roam_set_pmkid_cache(mac_handle, adapter->vdev_id,
21119 &pmk_cache, 1, false);
21120 if (!QDF_IS_STATUS_SUCCESS(result))
21121 hdd_debug("external_auth: Failed to cache PMKID");
21122 }
21123}
21124#else
21125static void
21126wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
21127 mac_handle_t mac_handle,
21128 struct cfg80211_external_auth_params *params)
21129{}
21130#endif
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053021131/**
21132 * __wlan_hdd_cfg80211_external_auth() - Handle external auth
Srinivas Dasari29186ca2019-02-11 18:45:48 +053021133 *
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053021134 * @wiphy: Pointer to wireless phy
21135 * @dev: net device
Srinivas Dasari29186ca2019-02-11 18:45:48 +053021136 * @params: Pointer to external auth params.
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053021137 * Return: 0 on success, negative errno on failure
Srinivas Dasari29186ca2019-02-11 18:45:48 +053021138 *
21139 * Userspace sends status of the external authentication(e.g., SAE) with a peer.
21140 * The message carries BSSID of the peer and auth status (WLAN_STATUS_SUCCESS/
21141 * WLAN_STATUS_UNSPECIFIED_FAILURE) in params.
21142 * Userspace may send PMKID in params, which can be used for
21143 * further connections.
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053021144 */
21145static int
21146__wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
21147 struct net_device *dev,
21148 struct cfg80211_external_auth_params *params)
21149{
21150 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
21151 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21152 int ret;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021153 mac_handle_t mac_handle;
Srinivas Dasarie854ff02019-02-11 17:24:48 +053021154 struct qdf_mac_addr peer_mac_addr;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053021155
21156 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
21157 hdd_err("Command not allowed in FTM mode");
21158 return -EPERM;
21159 }
21160
Jeff Johnson48363022019-02-24 16:26:51 -080021161 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053021162 return -EINVAL;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053021163
21164 ret = wlan_hdd_validate_context(hdd_ctx);
21165 if (ret)
21166 return ret;
21167
Srinivas Dasarie854ff02019-02-11 17:24:48 +053021168 hdd_debug("external_auth status: %d peer mac: " QDF_MAC_ADDR_STR,
21169 params->status, QDF_MAC_ADDR_ARRAY(params->bssid));
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021170 mac_handle = hdd_ctx->mac_handle;
Srinivas Dasarie854ff02019-02-11 17:24:48 +053021171 qdf_mem_copy(peer_mac_addr.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Srinivas Dasari29186ca2019-02-11 18:45:48 +053021172
21173 wlan_hdd_extauth_cache_pmkid(adapter, mac_handle, params);
21174
Srinivas Dasarie854ff02019-02-11 17:24:48 +053021175 sme_handle_sae_msg(mac_handle, adapter->vdev_id, params->status,
21176 peer_mac_addr);
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053021177
21178 return ret;
21179}
21180
21181/**
21182 * wlan_hdd_cfg80211_external_auth() - Handle external auth
21183 * @wiphy: Pointer to wireless phy
21184 * @dev: net device
21185 * @params: Pointer to external auth params
21186 *
21187 * Return: 0 on success, negative errno on failure
21188 */
21189static int
21190wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
21191 struct net_device *dev,
21192 struct cfg80211_external_auth_params *params)
21193{
Dustin Brown1d31b082018-11-22 14:41:20 +053021194 int errno;
21195 struct osif_vdev_sync *vdev_sync;
21196
21197 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
21198 if (errno)
21199 return errno;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053021200
Dustin Brown1d31b082018-11-22 14:41:20 +053021201 errno = __wlan_hdd_cfg80211_external_auth(wiphy, dev, params);
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053021202
Dustin Brown1d31b082018-11-22 14:41:20 +053021203 osif_vdev_sync_op_stop(vdev_sync);
21204
21205 return errno;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053021206}
21207#endif
21208
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021209/**
21210 * wlan_hdd_chan_info_cb() - channel info callback
21211 * @chan_info: struct scan_chan_info
21212 *
21213 * Store channel info into HDD context
21214 *
21215 * Return: None.
21216 */
21217static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
21218{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070021219 struct hdd_context *hdd_ctx;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021220 struct scan_chan_info *chan;
21221 uint8_t idx;
21222
Dustin Brown491d54b2018-03-14 12:39:11 -070021223 hdd_enter();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021224
21225 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
21226 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
21227 hdd_err("hdd_ctx is invalid");
21228 return;
21229 }
21230
21231 if (!hdd_ctx->chan_info) {
21232 hdd_err("chan_info is NULL");
21233 return;
21234 }
21235
21236 chan = hdd_ctx->chan_info;
21237 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
21238 if (chan[idx].freq == info->freq) {
21239 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
21240 info->cmd_flag);
Rajeev Kumareb6ec172018-09-26 20:45:36 -070021241 hdd_debug("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
21242 chan[idx].cmd_flag, chan[idx].freq,
21243 chan[idx].noise_floor,
21244 chan[idx].cycle_count,
21245 chan[idx].rx_clear_count,
21246 chan[idx].clock_freq, chan[idx].cmd_flag,
21247 chan[idx].tx_frame_count, idx);
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021248 if (chan[idx].freq == 0)
21249 break;
21250
21251 }
21252 }
21253
Dustin Browne74003f2018-03-14 12:51:58 -070021254 hdd_exit();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021255}
21256
21257/**
21258 * wlan_hdd_init_chan_info() - init chan info in hdd context
21259 * @hdd_ctx: HDD context pointer
21260 *
21261 * Return: none
21262 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070021263void wlan_hdd_init_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021264{
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053021265 uint32_t num_2g, num_5g, index = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021266 mac_handle_t mac_handle;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021267
Kapil Gupta63e75282017-05-18 20:55:10 +053021268 hdd_ctx->chan_info = NULL;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021269 if (!hdd_ctx->config->fEnableSNRMonitoring) {
Dustin Brown31116772018-08-15 14:59:21 -070021270 hdd_debug("SNR monitoring is disabled");
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021271 return;
21272 }
21273
21274 hdd_ctx->chan_info =
21275 qdf_mem_malloc(sizeof(struct scan_chan_info)
21276 * QDF_MAX_NUM_CHAN);
Min Liu74a1a502018-10-10 19:59:07 +080021277 if (!hdd_ctx->chan_info)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021278 return;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021279 mutex_init(&hdd_ctx->chan_info_lock);
21280
21281 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
21282 for (; index < num_2g; index++) {
21283 hdd_ctx->chan_info[index].freq =
21284 hdd_channels_2_4_ghz[index].center_freq;
21285 }
21286
21287 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
21288 for (; (index - num_2g) < num_5g; index++) {
Dustin Brown07901ec2018-09-07 11:02:41 -070021289 if (wlan_reg_is_dsrc_chan(hdd_ctx->pdev,
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070021290 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021291 continue;
21292 hdd_ctx->chan_info[index].freq =
21293 hdd_channels_5_ghz[index - num_2g].center_freq;
21294 }
Rajeev Kumar Sirasanagandla9770bba2018-09-24 20:12:28 +053021295
21296 index = num_2g + num_5g;
21297 index = wlan_hdd_populate_srd_chan_info(hdd_ctx, index);
21298
Jeff Johnson34fc63a2018-06-14 10:10:02 -070021299 mac_handle = hdd_ctx->mac_handle;
21300 sme_set_chan_info_callback(mac_handle,
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021301 &wlan_hdd_chan_info_cb);
21302}
21303
21304/**
21305 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
21306 * @hdd_ctx: hdd context pointer
21307 *
21308 * Return: none
21309 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070021310void wlan_hdd_deinit_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053021311{
21312 struct scan_chan_info *chan;
21313
21314 chan = hdd_ctx->chan_info;
21315 hdd_ctx->chan_info = NULL;
21316 if (chan)
21317 qdf_mem_free(chan);
21318}
21319
Dustin Brown32cb4792017-06-15 15:33:42 -070021320#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
21321static enum rate_info_bw hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
21322{
21323 switch (hdd_bw) {
21324 case HDD_RATE_BW_5:
21325 return RATE_INFO_BW_5;
21326 case HDD_RATE_BW_10:
21327 return RATE_INFO_BW_10;
21328 case HDD_RATE_BW_20:
21329 return RATE_INFO_BW_20;
21330 case HDD_RATE_BW_40:
21331 return RATE_INFO_BW_40;
21332 case HDD_RATE_BW_80:
21333 return RATE_INFO_BW_80;
21334 case HDD_RATE_BW_160:
21335 return RATE_INFO_BW_160;
21336 }
21337
21338 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
21339
21340 return RATE_INFO_BW_20;
21341}
21342
21343void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
21344{
21345 info->bw = hdd_map_hdd_bw_to_os(hdd_bw);
21346}
21347#else
21348static enum rate_info_flags hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
21349{
21350 switch (hdd_bw) {
21351 case HDD_RATE_BW_5:
21352 case HDD_RATE_BW_10:
21353 case HDD_RATE_BW_20:
21354 return (enum rate_info_flags)0;
21355 case HDD_RATE_BW_40:
21356 return RATE_INFO_FLAGS_40_MHZ_WIDTH;
21357 case HDD_RATE_BW_80:
21358 return RATE_INFO_FLAGS_80_MHZ_WIDTH;
21359 case HDD_RATE_BW_160:
21360 return RATE_INFO_FLAGS_160_MHZ_WIDTH;
21361 }
21362
21363 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
21364
21365 return (enum rate_info_flags)0;
21366}
21367
21368void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
21369{
21370 const enum rate_info_flags all_bws =
21371 RATE_INFO_FLAGS_40_MHZ_WIDTH |
21372 RATE_INFO_FLAGS_80_MHZ_WIDTH |
21373 RATE_INFO_FLAGS_80P80_MHZ_WIDTH |
21374 RATE_INFO_FLAGS_160_MHZ_WIDTH;
21375
21376 info->flags &= ~all_bws;
21377 info->flags |= hdd_map_hdd_bw_to_os(hdd_bw);
21378}
21379#endif
21380
Min Liue34708a2019-02-01 15:00:34 +080021381#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
21382void hdd_send_update_owe_info_event(struct hdd_adapter *adapter,
21383 uint8_t sta_addr[],
21384 uint8_t *owe_ie,
21385 uint32_t owe_ie_len)
21386{
21387 struct cfg80211_update_owe_info owe_info;
21388 struct net_device *dev = adapter->dev;
21389
21390 hdd_enter_dev(dev);
21391
21392 qdf_mem_copy(owe_info.bssid, sta_addr, ETH_ALEN);
21393 owe_info.ie = owe_ie;
21394 owe_info.ie_len = owe_ie_len;
21395
21396 cfg80211_update_owe_info_event(dev, &owe_info, GFP_KERNEL);
21397
21398 hdd_exit();
21399}
21400#endif
21401
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053021402/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021403 * struct cfg80211_ops - cfg80211_ops
21404 *
21405 * @add_virtual_intf: Add virtual interface
21406 * @del_virtual_intf: Delete virtual interface
21407 * @change_virtual_intf: Change virtual interface
21408 * @change_station: Change station
21409 * @add_beacon: Add beacon in sap mode
21410 * @del_beacon: Delete beacon in sap mode
21411 * @set_beacon: Set beacon in sap mode
21412 * @start_ap: Start ap
21413 * @change_beacon: Change beacon
21414 * @stop_ap: Stop ap
21415 * @change_bss: Change bss
21416 * @add_key: Add key
21417 * @get_key: Get key
21418 * @del_key: Delete key
21419 * @set_default_key: Set default key
21420 * @set_channel: Set channel
21421 * @scan: Scan
21422 * @connect: Connect
21423 * @disconnect: Disconnect
21424 * @join_ibss = Join ibss
21425 * @leave_ibss = Leave ibss
21426 * @set_wiphy_params = Set wiphy params
21427 * @set_tx_power = Set tx power
21428 * @get_tx_power = get tx power
21429 * @remain_on_channel = Remain on channel
21430 * @cancel_remain_on_channel = Cancel remain on channel
21431 * @mgmt_tx = Tx management frame
21432 * @mgmt_tx_cancel_wait = Cancel management tx wait
21433 * @set_default_mgmt_key = Set default management key
21434 * @set_txq_params = Set tx queue parameters
21435 * @get_station = Get station
21436 * @set_power_mgmt = Set power management
21437 * @del_station = Delete station
21438 * @add_station = Add station
21439 * @set_pmksa = Set pmksa
21440 * @del_pmksa = Delete pmksa
21441 * @flush_pmksa = Flush pmksa
21442 * @update_ft_ies = Update FT IEs
21443 * @tdls_mgmt = Tdls management
21444 * @tdls_oper = Tdls operation
21445 * @set_rekey_data = Set rekey data
21446 * @sched_scan_start = Scheduled scan start
21447 * @sched_scan_stop = Scheduled scan stop
21448 * @resume = Resume wlan
21449 * @suspend = Suspend wlan
21450 * @set_mac_acl = Set mac acl
21451 * @testmode_cmd = Test mode command
21452 * @set_ap_chanwidth = Set AP channel bandwidth
21453 * @dump_survey = Dump survey
21454 * @key_mgmt_set_pmk = Set pmk key management
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021455 * @update_connect_params = Update connect params
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021456 */
21457static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
21458 .add_virtual_intf = wlan_hdd_add_virtual_intf,
21459 .del_virtual_intf = wlan_hdd_del_virtual_intf,
21460 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
21461 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021462 .start_ap = wlan_hdd_cfg80211_start_ap,
21463 .change_beacon = wlan_hdd_cfg80211_change_beacon,
21464 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021465 .change_bss = wlan_hdd_cfg80211_change_bss,
21466 .add_key = wlan_hdd_cfg80211_add_key,
21467 .get_key = wlan_hdd_cfg80211_get_key,
21468 .del_key = wlan_hdd_cfg80211_del_key,
21469 .set_default_key = wlan_hdd_cfg80211_set_default_key,
21470 .scan = wlan_hdd_cfg80211_scan,
21471 .connect = wlan_hdd_cfg80211_connect,
21472 .disconnect = wlan_hdd_cfg80211_disconnect,
21473 .join_ibss = wlan_hdd_cfg80211_join_ibss,
21474 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
21475 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
21476 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
21477 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
21478 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
21479 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
21480 .mgmt_tx = wlan_hdd_mgmt_tx,
21481 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
21482 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
21483 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053021484 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021485 .get_station = wlan_hdd_cfg80211_get_station,
21486 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
21487 .del_station = wlan_hdd_cfg80211_del_station,
21488 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021489 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
21490 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
21491 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080021492#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021493 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
21494#endif
Min Liu0daa0982019-02-01 17:50:44 +080021495#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
21496 .update_owe_info = wlan_hdd_cfg80211_update_owe_info,
21497#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021498#ifdef FEATURE_WLAN_TDLS
21499 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
21500 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
21501#endif
21502#ifdef WLAN_FEATURE_GTK_OFFLOAD
21503 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
21504#endif /* WLAN_FEATURE_GTK_OFFLOAD */
21505#ifdef FEATURE_WLAN_SCAN_PNO
21506 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
21507 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
21508#endif /*FEATURE_WLAN_SCAN_PNO */
21509 .resume = wlan_hdd_cfg80211_resume_wlan,
21510 .suspend = wlan_hdd_cfg80211_suspend_wlan,
21511 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
21512#ifdef WLAN_NL80211_TESTMODE
21513 .testmode_cmd = wlan_hdd_cfg80211_testmode,
21514#endif
21515#ifdef QCA_HT_2040_COEX
21516 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
21517#endif
21518 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021519#ifdef CHANNEL_SWITCH_SUPPORTED
21520 .channel_switch = wlan_hdd_cfg80211_channel_switch,
21521#endif
Nirav Shah73713f72018-05-17 14:50:41 +053021522#ifdef FEATURE_MONITOR_MODE_SUPPORT
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070021523 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Nirav Shah73713f72018-05-17 14:50:41 +053021524#endif
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053021525#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
Srinivas Girigowda576b2352017-08-25 14:44:26 -070021526 defined(CFG80211_ABORT_SCAN)
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053021527 .abort_scan = wlan_hdd_cfg80211_abort_scan,
21528#endif
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021529#if defined(WLAN_FEATURE_FILS_SK) &&\
Sridhar Selvaraje5260442017-08-19 10:12:03 +053021530 defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) &&\
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021531 (defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
21532 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
21533 .update_connect_params = wlan_hdd_cfg80211_update_connect_params,
21534#endif
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053021535#if defined(WLAN_FEATURE_SAE) && \
21536 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
21537 .external_auth = wlan_hdd_cfg80211_external_auth,
21538#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021539};