blob: 694e0403bb04044c94d9f0322bcce67cb9d7fd02 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Vignesh Viswanathanfa90d622017-12-22 13:13:26 +05302 * Copyright (c) 2012-2018 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>
32#include <wlan_hdd_includes.h>
33#include <net/arp.h>
34#include <net/cfg80211.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080035#include <wlan_hdd_wowl.h>
36#include <ani_global.h>
37#include "sir_params.h"
38#include "dot11f.h"
39#include "wlan_hdd_assoc.h"
40#include "wlan_hdd_wext.h"
41#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070042#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080043#include "wlan_hdd_p2p.h"
44#include "wlan_hdd_cfg80211.h"
45#include "wlan_hdd_hostapd.h"
46#include "wlan_hdd_softap_tx_rx.h"
47#include "wlan_hdd_main.h"
48#include "wlan_hdd_power.h"
49#include "wlan_hdd_trace.h"
Dustin Brownd4241942018-02-26 12:51:37 -080050#include "qdf_str.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053051#include "qdf_trace.h"
Dustin Brownd4241942018-02-26 12:51:37 -080052#include "qdf_types.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "cds_utils.h"
54#include "cds_sched.h"
55#include "wlan_hdd_scan.h"
56#include <qc_sap_ioctl.h>
57#include "wlan_hdd_tdls.h"
58#include "wlan_hdd_wmm.h"
59#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053060#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080061#include "wlan_hdd_misc.h"
62#include "wlan_hdd_nan.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080063#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053064#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053065#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053066#include "pld_common.h"
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070067#include "wmi_unified_param.h"
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070068
Paul Zhang3a210c52016-12-08 10:18:12 +080069#ifdef WLAN_UMAC_CONVERGENCE
70#include "wlan_cfg80211.h"
71#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080072#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080073#include <wlan_cfg80211_scan.h>
Ryan Hsuc8b27a42018-01-02 13:57:56 -080074#include <wlan_cfg80211_ftm.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080075
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080076#include "wlan_hdd_ext_scan.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080078#include "wlan_hdd_stats.h"
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080079#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080080#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081#include "qwlan_version.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080082
83#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070084#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080085
Ravi Joshideb5a8d2015-11-09 19:11:43 -080086#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053087#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070088#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070089#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053090#include "wlan_hdd_disa.h"
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070091#include "wlan_osif_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080092#include "wlan_hdd_he.h"
Nachiket Kukade177b5b02018-05-22 20:52:17 +053093#ifdef FEATURE_WLAN_APF
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053094#include "wlan_hdd_apf.h"
Nachiket Kukade177b5b02018-05-22 20:52:17 +053095#endif
Ravi Joshideb5a8d2015-11-09 19:11:43 -080096
Leo Changfdb45c32016-10-28 11:09:23 -070097#include <cdp_txrx_cmn.h>
98#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080099#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530100#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800101#include "os_if_wifi_pos.h"
Ajit Pal Singh90a45a42017-04-18 18:53:46 +0530102#include "wlan_utility.h"
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -0700103#include "wlan_reg_ucfg_api.h"
Naveen Rawatd2657be2017-10-10 14:31:23 -0700104#include "wifi_pos_api.h"
Sandeep Puligilla063a4342018-01-10 02:50:14 -0800105#include "wlan_hdd_spectralscan.h"
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +0530106#include "wlan_ipa_ucfg_api.h"
Naveen Rawate8b1b822018-01-30 09:46:16 -0800107#include <wlan_cfg80211_mc_cp_stats.h>
Yu Wang157d1472018-03-09 16:05:01 +0800108#include <wlan_cp_stats_mc_ucfg_api.h>
Wu Gaobdb7f272018-07-05 19:33:26 +0800109#include "wlan_tdls_cfg_api.h"
Qiwei Caie689a262018-07-26 15:50:22 +0800110#include <wlan_hdd_bss_transition.h>
111#include <wlan_hdd_concurrency_matrix.h>
112#include <wlan_hdd_p2p_listen_offload.h>
113#include <wlan_hdd_rssi_monitor.h>
114#include <wlan_hdd_sap_cond_chan_switch.h>
115#include <wlan_hdd_station_info.h>
116#include <wlan_hdd_tx_power.h>
117#include <wlan_hdd_active_tos.h>
118#include <wlan_hdd_sar_limits.h>
119#include <wlan_hdd_ota_test.h>
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +0530120#include "wlan_mlme_ucfg_api.h"
121#include "wlan_mlme_public_struct.h"
Harprit Chhabadae8155d32018-08-22 16:19:34 -0700122#include "wlan_extscan_ucfg_api.h"
Wu Gao93816212018-08-31 16:49:54 +0800123#include "wlan_mlme_ucfg_api.h"
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +0530124
Harprit Chhabada6c641ba2018-06-28 14:45:10 -0700125#include "wlan_crypto_global_api.h"
126#include "wlan_nl_to_crypto_params.h"
127#include "wlan_crypto_global_def.h"
128
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800129#define g_mode_rates_size (12)
130#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800131
132/*
133 * Android CTS verifier needs atleast this much wait time (in msec)
134 */
135#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
136
137/*
138 * Refer @tCfgProtection structure for definition of the bit map.
139 * below value is obtained by setting the following bit-fields.
140 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
141 */
142#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
143
144#define HDD2GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700145 .band = HDD_NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800146 .center_freq = (freq), \
147 .hw_value = (chan), \
148 .flags = (flag), \
149 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800150 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151}
152
153#define HDD5GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700154 .band = HDD_NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800155 .center_freq = (freq), \
156 .hw_value = (chan), \
157 .flags = (flag), \
158 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800159 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160}
161
162#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
163 { \
164 .bitrate = rate, \
165 .hw_value = rate_id, \
166 .flags = flag, \
167 }
168
Dustin Brown5f7d38e2017-08-16 11:30:08 -0700169#ifndef WLAN_AKM_SUITE_FT_8021X
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
Dustin Brown5f7d38e2017-08-16 11:30:08 -0700171#endif
172
Dustin Brown234d45f2017-08-16 11:45:05 -0700173#ifndef WLAN_AKM_SUITE_FT_PSK
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800174#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Dustin Brown234d45f2017-08-16 11:45:05 -0700175#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800176
177#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800178
Agrawal Ashish65634612016-08-18 13:24:32 +0530179#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
180 mode <= DFS_MODE_DEPRIORITIZE))
Mohit Khannaceb97782017-04-05 16:27:08 -0700181/*
182 * Number of DPTRACE records to dump when a cfg80211 disconnect with reason
183 * WLAN_REASON_DEAUTH_LEAVING DEAUTH is received from user-space.
184 */
185#define WLAN_DEAUTH_DPTRACE_DUMP_COUNT 100
Mukul Sharma05504ac2017-06-08 12:35:53 +0530186#ifndef WLAN_CIPHER_SUITE_GCMP
187#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
188#endif
189#ifndef WLAN_CIPHER_SUITE_GCMP_256
190#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09
191#endif
Mohit Khannaceb97782017-04-05 16:27:08 -0700192
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +0530193static const u32 hdd_gcmp_cipher_suits[] = {
194 WLAN_CIPHER_SUITE_GCMP,
195 WLAN_CIPHER_SUITE_GCMP_256,
196};
197
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800198static const u32 hdd_cipher_suites[] = {
199 WLAN_CIPHER_SUITE_WEP40,
200 WLAN_CIPHER_SUITE_WEP104,
201 WLAN_CIPHER_SUITE_TKIP,
202#ifdef FEATURE_WLAN_ESE
203#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
204#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
205 WLAN_CIPHER_SUITE_BTK,
206 WLAN_CIPHER_SUITE_KRK,
207 WLAN_CIPHER_SUITE_CCMP,
208#else
209 WLAN_CIPHER_SUITE_CCMP,
210#endif
211#ifdef FEATURE_WLAN_WAPI
212 WLAN_CIPHER_SUITE_SMS4,
213#endif
214#ifdef WLAN_FEATURE_11W
215 WLAN_CIPHER_SUITE_AES_CMAC,
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +0530216#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
217 WLAN_CIPHER_SUITE_BIP_GMAC_128,
218 WLAN_CIPHER_SUITE_BIP_GMAC_256,
219#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800220#endif
221};
222
Abhishek Singhf512bf32016-05-04 16:47:46 +0530223static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224 HDD2GHZCHAN(2412, 1, 0),
225 HDD2GHZCHAN(2417, 2, 0),
226 HDD2GHZCHAN(2422, 3, 0),
227 HDD2GHZCHAN(2427, 4, 0),
228 HDD2GHZCHAN(2432, 5, 0),
229 HDD2GHZCHAN(2437, 6, 0),
230 HDD2GHZCHAN(2442, 7, 0),
231 HDD2GHZCHAN(2447, 8, 0),
232 HDD2GHZCHAN(2452, 9, 0),
233 HDD2GHZCHAN(2457, 10, 0),
234 HDD2GHZCHAN(2462, 11, 0),
235 HDD2GHZCHAN(2467, 12, 0),
236 HDD2GHZCHAN(2472, 13, 0),
237 HDD2GHZCHAN(2484, 14, 0),
238};
239
Abhishek Singhf512bf32016-05-04 16:47:46 +0530240static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800241 HDD5GHZCHAN(5180, 36, 0),
242 HDD5GHZCHAN(5200, 40, 0),
243 HDD5GHZCHAN(5220, 44, 0),
244 HDD5GHZCHAN(5240, 48, 0),
245 HDD5GHZCHAN(5260, 52, 0),
246 HDD5GHZCHAN(5280, 56, 0),
247 HDD5GHZCHAN(5300, 60, 0),
248 HDD5GHZCHAN(5320, 64, 0),
249 HDD5GHZCHAN(5500, 100, 0),
250 HDD5GHZCHAN(5520, 104, 0),
251 HDD5GHZCHAN(5540, 108, 0),
252 HDD5GHZCHAN(5560, 112, 0),
253 HDD5GHZCHAN(5580, 116, 0),
254 HDD5GHZCHAN(5600, 120, 0),
255 HDD5GHZCHAN(5620, 124, 0),
256 HDD5GHZCHAN(5640, 128, 0),
257 HDD5GHZCHAN(5660, 132, 0),
258 HDD5GHZCHAN(5680, 136, 0),
259 HDD5GHZCHAN(5700, 140, 0),
260 HDD5GHZCHAN(5720, 144, 0),
261 HDD5GHZCHAN(5745, 149, 0),
262 HDD5GHZCHAN(5765, 153, 0),
263 HDD5GHZCHAN(5785, 157, 0),
264 HDD5GHZCHAN(5805, 161, 0),
265 HDD5GHZCHAN(5825, 165, 0),
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +0530266};
267
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -0700268#ifdef WLAN_FEATURE_DSRC
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +0530269static const struct ieee80211_channel hdd_channels_dot11p[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800270 HDD5GHZCHAN(5852, 170, 0),
271 HDD5GHZCHAN(5855, 171, 0),
272 HDD5GHZCHAN(5860, 172, 0),
273 HDD5GHZCHAN(5865, 173, 0),
274 HDD5GHZCHAN(5870, 174, 0),
275 HDD5GHZCHAN(5875, 175, 0),
276 HDD5GHZCHAN(5880, 176, 0),
277 HDD5GHZCHAN(5885, 177, 0),
278 HDD5GHZCHAN(5890, 178, 0),
279 HDD5GHZCHAN(5895, 179, 0),
280 HDD5GHZCHAN(5900, 180, 0),
281 HDD5GHZCHAN(5905, 181, 0),
282 HDD5GHZCHAN(5910, 182, 0),
283 HDD5GHZCHAN(5915, 183, 0),
284 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800285};
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -0700286#else
287static const struct ieee80211_channel hdd_etsi13_srd_ch[] = {
288 HDD5GHZCHAN(5845, 169, 0),
289 HDD5GHZCHAN(5865, 173, 0),
290};
291#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292
293static struct ieee80211_rate g_mode_rates[] = {
294 HDD_G_MODE_RATETAB(10, 0x1, 0),
295 HDD_G_MODE_RATETAB(20, 0x2, 0),
296 HDD_G_MODE_RATETAB(55, 0x4, 0),
297 HDD_G_MODE_RATETAB(110, 0x8, 0),
298 HDD_G_MODE_RATETAB(60, 0x10, 0),
299 HDD_G_MODE_RATETAB(90, 0x20, 0),
300 HDD_G_MODE_RATETAB(120, 0x40, 0),
301 HDD_G_MODE_RATETAB(180, 0x80, 0),
302 HDD_G_MODE_RATETAB(240, 0x100, 0),
303 HDD_G_MODE_RATETAB(360, 0x200, 0),
304 HDD_G_MODE_RATETAB(480, 0x400, 0),
305 HDD_G_MODE_RATETAB(540, 0x800, 0),
306};
307
308static struct ieee80211_rate a_mode_rates[] = {
309 HDD_G_MODE_RATETAB(60, 0x10, 0),
310 HDD_G_MODE_RATETAB(90, 0x20, 0),
311 HDD_G_MODE_RATETAB(120, 0x40, 0),
312 HDD_G_MODE_RATETAB(180, 0x80, 0),
313 HDD_G_MODE_RATETAB(240, 0x100, 0),
314 HDD_G_MODE_RATETAB(360, 0x200, 0),
315 HDD_G_MODE_RATETAB(480, 0x400, 0),
316 HDD_G_MODE_RATETAB(540, 0x800, 0),
317};
318
319static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530320 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800321 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700322 .band = HDD_NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800323 .bitrates = g_mode_rates,
324 .n_bitrates = g_mode_rates_size,
325 .ht_cap.ht_supported = 1,
326 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
327 | IEEE80211_HT_CAP_GRN_FLD
328 | IEEE80211_HT_CAP_DSSSCCK40
329 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
330 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
331 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
332 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
333 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
334 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
335 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
336};
337
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800338static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530339 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800340 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700341 .band = HDD_NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800342 .bitrates = a_mode_rates,
343 .n_bitrates = a_mode_rates_size,
344 .ht_cap.ht_supported = 1,
345 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
346 | IEEE80211_HT_CAP_GRN_FLD
347 | IEEE80211_HT_CAP_DSSSCCK40
348 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
349 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
350 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
351 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
352 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
353 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
354 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
355 .vht_cap.vht_supported = 1,
356};
357
358/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800359 * TX/RX direction for each kind of interface
360 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800361static const struct ieee80211_txrx_stypes
362 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
363 [NL80211_IFTYPE_STATION] = {
364 .tx = 0xffff,
365 .rx = BIT(SIR_MAC_MGMT_ACTION) |
Padma, Santhosh Kumar1ccc1332017-09-13 17:39:01 +0530366 BIT(SIR_MAC_MGMT_PROBE_REQ) |
367 BIT(SIR_MAC_MGMT_AUTH),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800368 },
369 [NL80211_IFTYPE_AP] = {
370 .tx = 0xffff,
371 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
372 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
373 BIT(SIR_MAC_MGMT_PROBE_REQ) |
374 BIT(SIR_MAC_MGMT_DISASSOC) |
375 BIT(SIR_MAC_MGMT_AUTH) |
376 BIT(SIR_MAC_MGMT_DEAUTH) |
377 BIT(SIR_MAC_MGMT_ACTION),
378 },
379 [NL80211_IFTYPE_ADHOC] = {
380 .tx = 0xffff,
381 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
382 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
383 BIT(SIR_MAC_MGMT_PROBE_REQ) |
384 BIT(SIR_MAC_MGMT_DISASSOC) |
385 BIT(SIR_MAC_MGMT_AUTH) |
386 BIT(SIR_MAC_MGMT_DEAUTH) |
387 BIT(SIR_MAC_MGMT_ACTION),
388 },
389 [NL80211_IFTYPE_P2P_CLIENT] = {
390 .tx = 0xffff,
391 .rx = BIT(SIR_MAC_MGMT_ACTION) |
392 BIT(SIR_MAC_MGMT_PROBE_REQ),
393 },
394 [NL80211_IFTYPE_P2P_GO] = {
395 /* This is also same as for SoftAP */
396 .tx = 0xffff,
397 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
398 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
399 BIT(SIR_MAC_MGMT_PROBE_REQ) |
400 BIT(SIR_MAC_MGMT_DISASSOC) |
401 BIT(SIR_MAC_MGMT_AUTH) |
402 BIT(SIR_MAC_MGMT_DEAUTH) |
403 BIT(SIR_MAC_MGMT_ACTION),
404 },
405};
406
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800407/* Interface limits and combinations registered by the driver */
408
409/* STA ( + STA ) combination */
410static const struct ieee80211_iface_limit
411 wlan_hdd_sta_iface_limit[] = {
412 {
413 .max = 3, /* p2p0 is a STA as well */
414 .types = BIT(NL80211_IFTYPE_STATION),
415 },
416};
417
418/* ADHOC (IBSS) limit */
419static const struct ieee80211_iface_limit
420 wlan_hdd_adhoc_iface_limit[] = {
421 {
422 .max = 1,
423 .types = BIT(NL80211_IFTYPE_STATION),
424 },
425 {
426 .max = 1,
427 .types = BIT(NL80211_IFTYPE_ADHOC),
428 },
429};
430
431/* AP ( + AP ) combination */
432static const struct ieee80211_iface_limit
433 wlan_hdd_ap_iface_limit[] = {
434 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530435 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800436 .types = BIT(NL80211_IFTYPE_AP),
437 },
438};
439
440/* P2P limit */
441static const struct ieee80211_iface_limit
442 wlan_hdd_p2p_iface_limit[] = {
443 {
444 .max = 1,
445 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
446 },
447 {
448 .max = 1,
449 .types = BIT(NL80211_IFTYPE_P2P_GO),
450 },
451};
452
453static const struct ieee80211_iface_limit
454 wlan_hdd_sta_ap_iface_limit[] = {
455 {
456 /* We need 1 extra STA interface for OBSS scan when SAP starts
457 * with HT40 in STA+SAP concurrency mode
458 */
459 .max = (1 + SAP_MAX_OBSS_STA_CNT),
460 .types = BIT(NL80211_IFTYPE_STATION),
461 },
462 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530463 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800464 .types = BIT(NL80211_IFTYPE_AP),
465 },
466};
467
468/* STA + P2P combination */
469static const struct ieee80211_iface_limit
470 wlan_hdd_sta_p2p_iface_limit[] = {
471 {
472 /* One reserved for dedicated P2PDEV usage */
473 .max = 2,
474 .types = BIT(NL80211_IFTYPE_STATION)
475 },
476 {
477 /* Support for two identical (GO + GO or CLI + CLI)
478 * or dissimilar (GO + CLI) P2P interfaces
479 */
480 .max = 2,
481 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
482 },
483};
484
485/* STA + AP + P2PGO combination */
486static const struct ieee80211_iface_limit
487wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
488 /* Support for AP+P2PGO interfaces */
489 {
490 .max = 2,
491 .types = BIT(NL80211_IFTYPE_STATION)
492 },
493 {
494 .max = 1,
495 .types = BIT(NL80211_IFTYPE_P2P_GO)
496 },
497 {
498 .max = 1,
499 .types = BIT(NL80211_IFTYPE_AP)
500 }
501};
502
503/* SAP + P2P combination */
504static const struct ieee80211_iface_limit
505wlan_hdd_sap_p2p_iface_limit[] = {
506 {
507 /* 1 dedicated for p2p0 which is a STA type */
508 .max = 1,
509 .types = BIT(NL80211_IFTYPE_STATION)
510 },
511 {
512 /* The p2p interface in SAP+P2P can be GO/CLI.
513 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
514 */
515 .max = 1,
516 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
517 },
518 {
519 /* SAP+GO to support only one SAP interface */
520 .max = 1,
521 .types = BIT(NL80211_IFTYPE_AP)
522 }
523};
524
525/* P2P + P2P combination */
526static const struct ieee80211_iface_limit
527wlan_hdd_p2p_p2p_iface_limit[] = {
528 {
529 /* 1 dedicated for p2p0 which is a STA type */
530 .max = 1,
531 .types = BIT(NL80211_IFTYPE_STATION)
532 },
533 {
534 /* The p2p interface in P2P+P2P can be GO/CLI.
535 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
536 */
537 .max = 2,
538 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
539 },
540};
541
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700542static const struct ieee80211_iface_limit
543 wlan_hdd_mon_iface_limit[] = {
544 {
545 .max = 3, /* Monitor interface */
546 .types = BIT(NL80211_IFTYPE_MONITOR),
547 },
548};
549
550static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800551 wlan_hdd_iface_combination[] = {
552 /* STA */
553 {
554 .limits = wlan_hdd_sta_iface_limit,
555 .num_different_channels = 2,
556 .max_interfaces = 3,
557 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
558 },
559 /* ADHOC */
560 {
561 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700562 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800563 .max_interfaces = 2,
564 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
565 },
566 /* AP */
567 {
568 .limits = wlan_hdd_ap_iface_limit,
569 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530570 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800571 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
hqu3c4ed3d2017-09-19 11:42:35 +0800572#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
573 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
574 .beacon_int_min_gcd = 1,
575#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800576 },
577 /* P2P */
578 {
579 .limits = wlan_hdd_p2p_iface_limit,
580 .num_different_channels = 2,
581 .max_interfaces = 2,
582 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
583 },
584 /* STA + AP */
585 {
586 .limits = wlan_hdd_sta_ap_iface_limit,
587 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530588 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800589 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
590 .beacon_int_infra_match = true,
hqu3c4ed3d2017-09-19 11:42:35 +0800591#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
592 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
593 .beacon_int_min_gcd = 1,
594#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800595 },
596 /* STA + P2P */
597 {
598 .limits = wlan_hdd_sta_p2p_iface_limit,
599 .num_different_channels = 2,
600 /* one interface reserved for P2PDEV dedicated usage */
601 .max_interfaces = 4,
602 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
603 .beacon_int_infra_match = true,
604 },
605 /* STA + P2P GO + SAP */
606 {
607 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
608 /* we can allow 3 channels for three different persona
609 * but due to firmware limitation, allow max 2 concrnt channels.
610 */
611 .num_different_channels = 2,
612 /* one interface reserved for P2PDEV dedicated usage */
613 .max_interfaces = 4,
614 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
615 .beacon_int_infra_match = true,
616 },
617 /* SAP + P2P */
618 {
619 .limits = wlan_hdd_sap_p2p_iface_limit,
620 .num_different_channels = 2,
621 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
622 .max_interfaces = 3,
623 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
624 .beacon_int_infra_match = true,
625 },
626 /* P2P + P2P */
627 {
628 .limits = wlan_hdd_p2p_p2p_iface_limit,
629 .num_different_channels = 2,
630 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
631 .max_interfaces = 3,
632 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
633 .beacon_int_infra_match = true,
634 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530635 /* Monitor */
636 {
637 .limits = wlan_hdd_mon_iface_limit,
638 .max_interfaces = 3,
639 .num_different_channels = 2,
640 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
641 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800642};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800643
644static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800645
646#ifdef WLAN_NL80211_TESTMODE
647enum wlan_hdd_tm_attr {
648 WLAN_HDD_TM_ATTR_INVALID = 0,
649 WLAN_HDD_TM_ATTR_CMD = 1,
650 WLAN_HDD_TM_ATTR_DATA = 2,
651 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
652 WLAN_HDD_TM_ATTR_TYPE = 4,
653 /* keep last */
654 WLAN_HDD_TM_ATTR_AFTER_LAST,
655 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
656};
657
658enum wlan_hdd_tm_cmd {
659 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
660 WLAN_HDD_TM_CMD_WLAN_HB = 1,
661};
662
663#define WLAN_HDD_TM_DATA_MAX_LEN 5000
664
665static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
666 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
667 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
668 .len = WLAN_HDD_TM_DATA_MAX_LEN},
669};
670#endif /* WLAN_NL80211_TESTMODE */
671
Lin Baia016e9a2017-08-29 19:10:42 +0800672enum wlan_hdd_vendor_ie_access_policy {
673 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
674 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
675};
676
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
678static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
679 .flags = WIPHY_WOWLAN_MAGIC_PKT,
680 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
681 .pattern_min_len = 1,
682 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
683};
684#endif
685
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530687 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
688 * @flags: Pointer to the flags to Add channel switch flag.
689 *
690 * This Function adds Channel Switch support flag, if channel switch is
691 * supported by kernel.
692 * Return: void.
693 */
694#ifdef CHANNEL_SWITCH_SUPPORTED
695static inline void hdd_add_channel_switch_support(uint32_t *flags)
696{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800697 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530698}
699#else
700static inline void hdd_add_channel_switch_support(uint32_t *flags)
701{
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530702}
703#endif
704
Manikandan Mohan22b83722015-12-15 15:03:23 -0800705#ifdef FEATURE_WLAN_TDLS
706
707/* TDLS capabilities params */
708#define PARAM_MAX_TDLS_SESSION \
709 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
710#define PARAM_TDLS_FEATURE_SUPPORT \
711 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
712
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530713/**
Jeff Johnson118a4a02018-05-06 00:14:15 -0700714 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800715 * @wiphy: WIPHY structure pointer
716 * @wdev: Wireless device structure pointer
717 * @data: Pointer to the data received
718 * @data_len: Length of the data received
719 *
720 * This function provides TDLS capabilities
721 *
722 * Return: 0 on success and errno on failure
723 */
724static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
725 struct wireless_dev *wdev,
726 const void *data,
727 int data_len)
728{
729 int status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -0700730 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800731 struct sk_buff *skb;
732 uint32_t set = 0;
Frank Liu5c63dc82017-09-07 14:49:05 +0800733 uint32_t max_num_tdls_sta = 0;
Wu Gaobdb7f272018-07-05 19:33:26 +0800734 bool tdls_support;
735 bool tdls_external_control;
736 bool tdls_sleep_sta_enable;
737 bool tdls_buffer_sta;
738 bool tdls_off_channel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800739
Dustin Brownfdf17c12018-03-14 12:55:34 -0700740 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -0800741
Anurag Chouhan6d760662016-02-20 16:05:43 +0530742 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800743 hdd_err("Command not allowed in FTM mode");
744 return -EPERM;
745 }
746
747 status = wlan_hdd_validate_context(hdd_ctx);
748 if (status)
749 return status;
750
751 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
752 NLMSG_HDRLEN);
753 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700754 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800755 goto fail;
756 }
757
Wu Gaobdb7f272018-07-05 19:33:26 +0800758 if ((cfg_tdls_get_support_enable(hdd_ctx->hdd_psoc, &tdls_support) ==
759 QDF_STATUS_SUCCESS) && tdls_support) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800760 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800761 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
762 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700763 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764 goto fail;
765 }
766 } else {
Wu Gaobdb7f272018-07-05 19:33:26 +0800767 cfg_tdls_get_external_control(hdd_ctx->hdd_psoc,
768 &tdls_external_control);
769 cfg_tdls_get_sleep_sta_enable(hdd_ctx->hdd_psoc,
770 &tdls_sleep_sta_enable);
771 cfg_tdls_get_buffer_sta_enable(hdd_ctx->hdd_psoc,
772 &tdls_buffer_sta);
773 cfg_tdls_get_off_channel_enable(hdd_ctx->hdd_psoc,
774 &tdls_off_channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 set = set | WIFI_TDLS_SUPPORT;
Wu Gaobdb7f272018-07-05 19:33:26 +0800776 set = set | (tdls_external_control ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800777 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
Wu Gaobdb7f272018-07-05 19:33:26 +0800778 set = set | (tdls_off_channel ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800779 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Wu Gaobdb7f272018-07-05 19:33:26 +0800780 if (tdls_sleep_sta_enable || tdls_buffer_sta ||
781 tdls_off_channel)
Frank Liu5c63dc82017-09-07 14:49:05 +0800782 max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA_P_UAPSD_OFFCHAN;
783 else
784 max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA;
785
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800786 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800787 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
Frank Liu5c63dc82017-09-07 14:49:05 +0800788 max_num_tdls_sta) ||
789 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700790 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800791 goto fail;
792 }
793 }
794 return cfg80211_vendor_cmd_reply(skb);
795fail:
796 if (skb)
797 kfree_skb(skb);
798 return -EINVAL;
799}
800
801/**
Jeff Johnson118a4a02018-05-06 00:14:15 -0700802 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800803 * @wiphy: WIPHY structure pointer
804 * @wdev: Wireless device structure pointer
805 * @data: Pointer to the data received
806 * @data_len: Length of the data received
807 *
808 * This function provides TDLS capabilities
809 *
810 * Return: 0 on success and errno on failure
811 */
812static int
813wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
814 struct wireless_dev *wdev,
815 const void *data,
816 int data_len)
817{
818 int ret;
819
820 cds_ssr_protect(__func__);
821 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
822 data, data_len);
823 cds_ssr_unprotect(__func__);
824
825 return ret;
826}
827#endif
828
829#ifdef QCA_HT_2040_COEX
830static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
831#endif
832
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700833int wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type *destFreqList,
834 struct ch_avoid_ind_type *srcFreqList)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530835{
836 int i;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700837 struct ch_avoid_freq_type *avoid_range =
838 &destFreqList->avoid_freq_range[destFreqList->ch_avoid_range_cnt];
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530839
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700840 destFreqList->ch_avoid_range_cnt += srcFreqList->ch_avoid_range_cnt;
Jeff Johnson31304cc2017-09-30 19:08:09 -0700841 if (destFreqList->ch_avoid_range_cnt > CH_AVOID_MAX_RANGE) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530842 hdd_err("avoid freq overflow");
843 return -EINVAL;
844 }
845
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700846 for (i = 0; i < srcFreqList->ch_avoid_range_cnt; i++) {
847 avoid_range->start_freq =
848 srcFreqList->avoid_freq_range[i].start_freq;
849 avoid_range->end_freq =
850 srcFreqList->avoid_freq_range[i].end_freq;
851 avoid_range++;
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530852 }
853 return 0;
854}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800855/*
856 * FUNCTION: wlan_hdd_send_avoid_freq_event
857 * This is called when wlan driver needs to send vendor specific
858 * avoid frequency range event to userspace
859 */
Jeff Johnsonb8944722017-09-03 09:03:19 -0700860int wlan_hdd_send_avoid_freq_event(struct hdd_context *hdd_ctx,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700861 struct ch_avoid_ind_type *avoid_freq_list)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800862{
863 struct sk_buff *vendor_event;
864
Dustin Brown491d54b2018-03-14 12:39:11 -0700865 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800866
Jeff Johnsonb8944722017-09-03 09:03:19 -0700867 if (!hdd_ctx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700868 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800869 return -EINVAL;
870 }
871
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700872 if (!avoid_freq_list) {
873 hdd_err("avoid_freq_list is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800874 return -EINVAL;
875 }
876
Jeff Johnsonb8944722017-09-03 09:03:19 -0700877 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700878 NULL, sizeof(struct ch_avoid_ind_type),
879 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
880 GFP_KERNEL);
881
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800882 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700883 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800884 return -EINVAL;
885 }
886
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700887 memcpy(skb_put(vendor_event, sizeof(struct ch_avoid_ind_type)),
888 (void *)avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800889
890 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
891
Dustin Browne74003f2018-03-14 12:51:58 -0700892 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800893 return 0;
894}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800895
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530896/*
897 * define short names for the global vendor params
898 * used by QCA_NL80211_VENDOR_SUBCMD_HANG
899 */
900#define HANG_REASON_INDEX QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX
901
902/**
903 * hdd_convert_hang_reason() - Convert cds recovery reason to vendor specific
904 * hang reason
905 * @reason: cds recovery reason
906 *
907 * Return: Vendor specific reason code
908 */
909static enum qca_wlan_vendor_hang_reason
910hdd_convert_hang_reason(enum qdf_hang_reason reason)
911{
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -0700912 u32 ret_val;
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530913
914 switch (reason) {
915 case QDF_RX_HASH_NO_ENTRY_FOUND:
916 ret_val = QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND;
917 break;
918 case QDF_PEER_DELETION_TIMEDOUT:
919 ret_val = QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT;
920 break;
921 case QDF_PEER_UNMAP_TIMEDOUT:
922 ret_val = QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT;
923 break;
924 case QDF_SCAN_REQ_EXPIRED:
925 ret_val = QCA_WLAN_HANG_SCAN_REQ_EXPIRED;
926 break;
927 case QDF_SCAN_ATTEMPT_FAILURES:
928 ret_val = QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES;
929 break;
930 case QDF_GET_MSG_BUFF_FAILURE:
931 ret_val = QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE;
932 break;
933 case QDF_ACTIVE_LIST_TIMEOUT:
934 ret_val = QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT;
935 break;
936 case QDF_SUSPEND_TIMEOUT:
937 ret_val = QCA_WLAN_HANG_SUSPEND_TIMEOUT;
938 break;
939 case QDF_RESUME_TIMEOUT:
940 ret_val = QCA_WLAN_HANG_RESUME_TIMEOUT;
941 break;
942 case QDF_REASON_UNSPECIFIED:
943 default:
944 ret_val = QCA_WLAN_HANG_REASON_UNSPECIFIED;
945 }
946 return ret_val;
947}
948
949/**
950 * wlan_hdd_send_hang_reason_event() - Send hang reason to the userspace
951 * @hdd_ctx: Pointer to hdd context
952 * @reason: cds recovery reason
953 *
954 * Return: 0 on success or failure reason
955 */
956int wlan_hdd_send_hang_reason_event(struct hdd_context *hdd_ctx,
957 enum qdf_hang_reason reason)
958{
959 struct sk_buff *vendor_event;
960 enum qca_wlan_vendor_hang_reason hang_reason;
961
Dustin Brown491d54b2018-03-14 12:39:11 -0700962 hdd_enter();
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530963
964 if (!hdd_ctx) {
965 hdd_err("HDD context is null");
966 return -EINVAL;
967 }
968
969 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
970 NULL,
971 sizeof(uint32_t),
972 HANG_REASON_INDEX,
973 GFP_KERNEL);
974 if (!vendor_event) {
975 hdd_err("cfg80211_vendor_event_alloc failed");
976 return -ENOMEM;
977 }
978
979 hang_reason = hdd_convert_hang_reason(reason);
980
981 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON,
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -0700982 (uint32_t)hang_reason)) {
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530983 hdd_err("QCA_WLAN_VENDOR_ATTR_HANG_REASON put fail");
984 kfree_skb(vendor_event);
985 return -EINVAL;
986 }
987
988 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
989
Dustin Browne74003f2018-03-14 12:51:58 -0700990 hdd_exit();
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530991 return 0;
992}
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -0700993
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530994#undef HANG_REASON_INDEX
995
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530996/**
997 * wlan_hdd_get_adjacent_chan(): Gets next/previous channel
998 * with respect to the channel passed.
999 * @chan: Channel
1000 * @upper: If "true" then next channel is returned or else
1001 * previous channel is returned.
1002 *
1003 * This function returns the next/previous adjacent-channel to
1004 * the channel passed. If "upper = true" then next channel is
1005 * returned else previous is returned.
1006 */
1007int wlan_hdd_get_adjacent_chan(uint8_t chan, bool upper)
1008{
1009 enum channel_enum ch_idx = reg_get_chan_enum(chan);
1010
1011 if (ch_idx == INVALID_CHANNEL)
1012 return -EINVAL;
1013
1014 if (upper && (ch_idx < (NUM_CHANNELS - 1)))
1015 ch_idx++;
1016 else if (!upper && (ch_idx > CHAN_ENUM_1))
1017 ch_idx--;
1018 else
1019 return -EINVAL;
1020
1021 return WLAN_REG_CH_NUM(ch_idx);
1022}
1023
1024/**
1025 * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
1026 * avoided when Do_Not_Break_Stream is active.
Jeff Johnsonb8944722017-09-03 09:03:19 -07001027 * @hdd_ctx: HDD Context
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301028 * @op_chan: AP/P2P-GO operating channel
1029 *
1030 * This function sends list of frequencies to be avoided when
1031 * Do_Not_Break_Stream is active.
1032 * To clear the avoid_frequency_list in the application,
1033 * op_chan = 0 can be passed.
1034 *
1035 * Return: 0 on success and errno on failure
1036 */
Jeff Johnsonb8944722017-09-03 09:03:19 -07001037int wlan_hdd_send_avoid_freq_for_dnbs(struct hdd_context *hdd_ctx, uint8_t op_chan)
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301038{
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001039 struct ch_avoid_ind_type p2p_avoid_freq_list;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301040 uint8_t min_chan, max_chan;
1041 int ret;
1042 int chan;
1043
Dustin Brown491d54b2018-03-14 12:39:11 -07001044 hdd_enter();
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301045
Jeff Johnsonb8944722017-09-03 09:03:19 -07001046 if (!hdd_ctx) {
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301047 hdd_err("invalid param");
1048 return -EINVAL;
1049 }
1050
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001051 qdf_mem_zero(&p2p_avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301052 /*
1053 * If channel passed is zero, clear the avoid_freq list in application.
1054 */
1055 if (!op_chan) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301056#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001057 mutex_lock(&hdd_ctx->avoid_freq_lock);
1058 qdf_mem_zero(&hdd_ctx->dnbs_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001059 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001060 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301061 memcpy(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001062 &hdd_ctx->coex_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001063 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001064 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301065#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001066 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx,
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301067 &p2p_avoid_freq_list);
1068 if (ret)
1069 hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
1070 ret);
1071
1072 return ret;
1073 }
1074
1075 if (WLAN_REG_IS_24GHZ_CH(op_chan)) {
1076 min_chan = REG_MIN_24GHZ_CH_NUM;
1077 max_chan = REG_MAX_24GHZ_CH_NUM;
1078 } else if WLAN_REG_IS_5GHZ_CH(op_chan) {
1079 min_chan = REG_MIN_5GHZ_CH_NUM;
1080 max_chan = REG_MAX_5GHZ_CH_NUM;
1081 } else {
1082 hdd_err("invalid channel:%d", op_chan);
1083 return -EINVAL;
1084 }
1085
1086 if ((op_chan > min_chan) && (op_chan < max_chan)) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001087 p2p_avoid_freq_list.ch_avoid_range_cnt = 2;
1088 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301089 wlan_chan_to_freq(min_chan);
1090
1091 /* Get channel before the op_chan */
1092 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1093 if (chan < 0)
1094 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001095 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301096 wlan_chan_to_freq(chan);
1097
1098 /* Get channel next to the op_chan */
1099 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1100 if (chan < 0)
1101 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001102 p2p_avoid_freq_list.avoid_freq_range[1].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301103 wlan_chan_to_freq(chan);
1104
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001105 p2p_avoid_freq_list.avoid_freq_range[1].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301106 wlan_chan_to_freq(max_chan);
1107 } else if (op_chan == min_chan) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001108 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301109
1110 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1111 if (chan < 0)
1112 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001113 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301114 wlan_chan_to_freq(chan);
1115
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001116 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301117 wlan_chan_to_freq(max_chan);
1118 } else {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001119 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
1120 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301121 wlan_chan_to_freq(min_chan);
1122
1123 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1124 if (chan < 0)
1125 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001126 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301127 wlan_chan_to_freq(chan);
1128 }
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301129#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001130 mutex_lock(&hdd_ctx->avoid_freq_lock);
1131 hdd_ctx->dnbs_avoid_freq_list = p2p_avoid_freq_list;
1132 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301133 ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001134 &hdd_ctx->coex_avoid_freq_list);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301135 if (ret) {
Jeff Johnsonb8944722017-09-03 09:03:19 -07001136 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301137 hdd_err("avoid freq merge failed");
1138 return ret;
1139 }
1140 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07001141 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301142#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001143 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx, &p2p_avoid_freq_list);
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301144 if (ret)
1145 hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
1146
1147 return ret;
1148}
1149
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001150/* vendor specific events */
1151static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001152 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
1153 .vendor_id =
1154 QCA_NL80211_VENDOR_ID,
1155 .subcmd =
1156 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
1157 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001158
1159#ifdef WLAN_FEATURE_NAN
1160 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
1161 .vendor_id =
1162 QCA_NL80211_VENDOR_ID,
1163 .subcmd =
1164 QCA_NL80211_VENDOR_SUBCMD_NAN
1165 },
1166#endif
1167
1168#ifdef WLAN_FEATURE_STATS_EXT
1169 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
1170 .vendor_id =
1171 QCA_NL80211_VENDOR_ID,
1172 .subcmd =
1173 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
1174 },
1175#endif /* WLAN_FEATURE_STATS_EXT */
1176#ifdef FEATURE_WLAN_EXTSCAN
1177 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
1178 .vendor_id =
1179 QCA_NL80211_VENDOR_ID,
1180 .subcmd =
1181 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
1182 },
1183 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
1184 .vendor_id =
1185 QCA_NL80211_VENDOR_ID,
1186 .subcmd =
1187 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
1188 },
1189 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
1190 .
1191 vendor_id
1192 =
1193 QCA_NL80211_VENDOR_ID,
1194 .subcmd =
1195 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
1196 },
1197 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
1198 .
1199 vendor_id
1200 =
1201 QCA_NL80211_VENDOR_ID,
1202 .
1203 subcmd =
1204 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
1205 },
1206 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
1207 .
1208 vendor_id
1209 =
1210 QCA_NL80211_VENDOR_ID,
1211 .
1212 subcmd
1213 =
1214 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1215 },
1216 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1217 .
1218 vendor_id
1219 =
1220 QCA_NL80211_VENDOR_ID,
1221 .subcmd =
1222 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1223 },
1224 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1225 .vendor_id =
1226 QCA_NL80211_VENDOR_ID,
1227 .subcmd =
1228 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1229 },
1230 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1231 .
1232 vendor_id
1233 =
1234 QCA_NL80211_VENDOR_ID,
1235 .subcmd =
1236 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1237 },
1238 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1239 .
1240 vendor_id
1241 =
1242 QCA_NL80211_VENDOR_ID,
1243 .subcmd =
1244 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1245 },
1246 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1247 .
1248 vendor_id
1249 =
1250 QCA_NL80211_VENDOR_ID,
1251 .
1252 subcmd
1253 =
1254 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1255 },
1256 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1257 .
1258 vendor_id
1259 =
1260 QCA_NL80211_VENDOR_ID,
1261 .
1262 subcmd =
1263 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1264 },
1265 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1266 .
1267 vendor_id
1268 =
1269 QCA_NL80211_VENDOR_ID,
1270 .
1271 subcmd
1272 =
1273 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
1274 },
1275 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
1276 .
1277 vendor_id
1278 =
1279 QCA_NL80211_VENDOR_ID,
1280 .
1281 subcmd
1282 =
1283 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
1284 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001285#endif /* FEATURE_WLAN_EXTSCAN */
1286
1287#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1288 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
1289 .vendor_id =
1290 QCA_NL80211_VENDOR_ID,
1291 .subcmd =
1292 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
1293 },
1294 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
1295 .vendor_id =
1296 QCA_NL80211_VENDOR_ID,
1297 .subcmd =
1298 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
1299 },
1300 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
1301 .vendor_id =
1302 QCA_NL80211_VENDOR_ID,
1303 .subcmd =
1304 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
1305 },
1306 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
1307 .vendor_id =
1308 QCA_NL80211_VENDOR_ID,
1309 .subcmd =
1310 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
1311 },
1312 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
1313 .vendor_id =
1314 QCA_NL80211_VENDOR_ID,
1315 .subcmd =
1316 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
1317 },
1318 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
1319 .vendor_id =
1320 QCA_NL80211_VENDOR_ID,
1321 .subcmd =
1322 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
1323 },
Zhang Qianca38fb12016-12-23 11:10:48 +08001324 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
1325 .vendor_id =
1326 QCA_NL80211_VENDOR_ID,
1327 .subcmd =
1328 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
1329 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001330#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1331 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1332 .vendor_id =
1333 QCA_NL80211_VENDOR_ID,
1334 .subcmd =
1335 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1336 },
1337 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1338 .vendor_id = QCA_NL80211_VENDOR_ID,
1339 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1340 },
1341#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1342 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1343 .vendor_id =
1344 QCA_NL80211_VENDOR_ID,
1345 .subcmd =
1346 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1347 },
1348#endif
1349 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1350 .vendor_id =
1351 QCA_NL80211_VENDOR_ID,
1352 .subcmd =
1353 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1354 },
1355 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1356 .vendor_id =
1357 QCA_NL80211_VENDOR_ID,
1358 .subcmd =
1359 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1360 },
1361 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1362 .vendor_id =
1363 QCA_NL80211_VENDOR_ID,
1364 .subcmd =
1365 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1366 },
1367 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1368 .vendor_id =
1369 QCA_NL80211_VENDOR_ID,
1370 .subcmd =
1371 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1372 },
1373 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1374 .vendor_id =
1375 QCA_NL80211_VENDOR_ID,
1376 .subcmd =
1377 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1378 },
1379#ifdef FEATURE_WLAN_EXTSCAN
1380 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1381 .vendor_id = QCA_NL80211_VENDOR_ID,
1382 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1383 },
1384 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1385 .vendor_id = QCA_NL80211_VENDOR_ID,
1386 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1387 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1389 .vendor_id = QCA_NL80211_VENDOR_ID,
1390 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1391 },
1392#endif /* FEATURE_WLAN_EXTSCAN */
Qiwei Caie689a262018-07-26 15:50:22 +08001393
1394 FEATURE_RSSI_MONITOR_VENDOR_EVENTS
1395
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001396#ifdef WLAN_FEATURE_TSF
1397 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1398 .vendor_id = QCA_NL80211_VENDOR_ID,
1399 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1400 },
1401#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001402 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1403 .vendor_id = QCA_NL80211_VENDOR_ID,
1404 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1405 },
1406 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1407 .vendor_id = QCA_NL80211_VENDOR_ID,
1408 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1409 },
1410 /* OCB events */
1411 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1412 .vendor_id = QCA_NL80211_VENDOR_ID,
1413 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1414 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001415#ifdef FEATURE_LFR_SUBNET_DETECTION
1416 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1417 .vendor_id = QCA_NL80211_VENDOR_ID,
1418 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1419 },
1420#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001421
1422#ifdef WLAN_FEATURE_NAN_DATAPATH
1423 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1424 .vendor_id = QCA_NL80211_VENDOR_ID,
1425 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1426 },
1427#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001428
1429 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1430 .vendor_id = QCA_NL80211_VENDOR_ID,
1431 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1432 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301433 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1434 .vendor_id = QCA_NL80211_VENDOR_ID,
1435 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1436 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301437 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1438 .vendor_id = QCA_NL80211_VENDOR_ID,
1439 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1440 },
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05301441 [QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX] = {
1442 .vendor_id = QCA_NL80211_VENDOR_ID,
1443 .subcmd = QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE
Anurag Chouhan3920c0f2017-09-11 17:10:56 +05301444 },
1445 [QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX] = {
1446 .vendor_id = QCA_NL80211_VENDOR_ID,
1447 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
1448 },
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301449 [QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX] = {
1450 .vendor_id = QCA_NL80211_VENDOR_ID,
1451 .subcmd = QCA_NL80211_VENDOR_SUBCMD_HANG,
1452 },
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +05301453 [QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX] = {
1454 .vendor_id = QCA_NL80211_VENDOR_ID,
1455 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO,
1456 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001457#ifdef WLAN_UMAC_CONVERGENCE
1458 COMMON_VENDOR_EVENTS
1459#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001460};
1461
1462/**
1463 * __is_driver_dfs_capable() - get driver DFS capability
1464 * @wiphy: pointer to wireless wiphy structure.
1465 * @wdev: pointer to wireless_dev structure.
1466 * @data: Pointer to the data to be passed via vendor interface
1467 * @data_len:Length of the data to be passed
1468 *
1469 * This function is called by userspace to indicate whether or not
1470 * the driver supports DFS offload.
1471 *
1472 * Return: 0 on success, negative errno on failure
1473 */
1474static int __is_driver_dfs_capable(struct wiphy *wiphy,
1475 struct wireless_dev *wdev,
1476 const void *data,
1477 int data_len)
1478{
1479 u32 dfs_capability = 0;
1480 struct sk_buff *temp_skbuff;
1481 int ret_val;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001482 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001483
Dustin Brownfdf17c12018-03-14 12:55:34 -07001484 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001485
1486 ret_val = wlan_hdd_validate_context(hdd_ctx);
1487 if (ret_val)
1488 return ret_val;
1489
Anurag Chouhan6d760662016-02-20 16:05:43 +05301490 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001491 hdd_err("Command not allowed in FTM mode");
1492 return -EPERM;
1493 }
1494
Peng Xu8e8b0392018-04-30 11:32:34 -07001495#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
1496 defined(CFG80211_DFS_OFFLOAD_BACKPORT)
1497 dfs_capability =
1498 wiphy_ext_feature_isset(wiphy,
1499 NL80211_EXT_FEATURE_DFS_OFFLOAD);
1500#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001501 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Peng Xu8e8b0392018-04-30 11:32:34 -07001502#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001503
1504 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1505 NLMSG_HDRLEN);
1506
1507 if (temp_skbuff != NULL) {
1508 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1509 dfs_capability);
1510 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001511 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001512 kfree_skb(temp_skbuff);
1513
1514 return ret_val;
1515 }
1516
1517 return cfg80211_vendor_cmd_reply(temp_skbuff);
1518 }
1519
Jeff Johnson020db452016-06-29 14:37:26 -07001520 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001521 return -ENOMEM;
1522}
1523
1524/**
1525 * is_driver_dfs_capable() - get driver DFS capability
1526 * @wiphy: pointer to wireless wiphy structure.
1527 * @wdev: pointer to wireless_dev structure.
1528 * @data: Pointer to the data to be passed via vendor interface
1529 * @data_len:Length of the data to be passed
1530 *
1531 * This function is called by userspace to indicate whether or not
1532 * the driver supports DFS offload. This is an SSR-protected
1533 * wrapper function.
1534 *
1535 * Return: 0 on success, negative errno on failure
1536 */
1537static int is_driver_dfs_capable(struct wiphy *wiphy,
1538 struct wireless_dev *wdev,
1539 const void *data,
1540 int data_len)
1541{
1542 int ret;
1543
1544 cds_ssr_protect(__func__);
1545 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1546 cds_ssr_unprotect(__func__);
1547
1548 return ret;
1549}
1550
1551/**
1552 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1553 *
1554 * @adapter: SAP adapter pointer
1555 *
1556 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1557 * radio. So in case of DFS MCC scenario override current SAP given config
1558 * to follow concurrent SAP DFS config
1559 *
1560 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1561 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001562int wlan_hdd_sap_cfg_dfs_override(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563{
Jeff Johnsone5006672017-08-29 14:39:02 -07001564 struct hdd_adapter *con_sap_adapter;
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001565 tsap_config_t *sap_config, *con_sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001566 int con_ch;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001567 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001568
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001569 if (!hdd_ctx) {
1570 hdd_err("hdd context is NULL");
1571 return 0;
1572 }
1573
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001574 /*
1575 * Check if AP+AP case, once primary AP chooses a DFS
1576 * channel secondary AP should always follow primary APs channel
1577 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001578 if (!policy_mgr_concurrent_beaconing_sessions_running(
1579 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001580 return 0;
1581
1582 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1583 if (!con_sap_adapter)
1584 return 0;
1585
Jeff Johnsonb9424862017-10-30 08:49:35 -07001586 sap_config = &adapter->session.ap.sap_config;
1587 con_sap_config = &con_sap_adapter->session.ap.sap_config;
1588 con_ch = con_sap_adapter->session.ap.operating_channel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001589
Dustin Brown07901ec2018-09-07 11:02:41 -07001590 if (!wlan_reg_is_dfs_ch(hdd_ctx->pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001591 return 0;
1592
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001593 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001594 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001595 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001596 sap_config->channel = con_ch;
1597
1598 if (con_sap_config->acs_cfg.acs_mode == true) {
1599 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1600 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001601 hdd_err("Primary AP channel config error");
1602 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001603 con_ch, con_sap_config->acs_cfg.pri_ch,
1604 con_sap_config->acs_cfg.ht_sec_ch);
1605 return -EINVAL;
1606 }
1607 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1608 * MCC restriction. So free ch list allocated in do_acs
1609 * func for Sec AP and realloc for Pri AP ch list size
1610 */
1611 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301612 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001613
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301614 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001615 &con_sap_config->acs_cfg,
1616 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301617 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001618 sizeof(uint8_t) *
1619 con_sap_config->acs_cfg.ch_list_count);
1620 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001621 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001622 return -ENOMEM;
1623 }
1624
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301625 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001626 con_sap_config->acs_cfg.ch_list,
1627 con_sap_config->acs_cfg.ch_list_count);
1628
1629 } else {
1630 sap_config->acs_cfg.pri_ch = con_ch;
1631 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1632 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1633 }
1634
1635 return con_ch;
1636}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001637
1638/**
wadesong1795e142018-01-05 11:13:07 +08001639 * wlan_hdd_set_acs_ch_range : Populate ACS hw mode and channel range values
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001640 * @sap_cfg: pointer to SAP config struct
wadesong1795e142018-01-05 11:13:07 +08001641 * @hw_mode: hw mode retrieved from vendor command buffer
1642 * @ht_enabled: whether HT phy mode is enabled
1643 * @vht_enabled: whether VHT phy mode is enabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001644 *
wadesong1795e142018-01-05 11:13:07 +08001645 * This function populates the ACS hw mode based on the configuration retrieved
1646 * from the vendor command buffer; and sets ACS start and end channel for the
1647 * given band.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001648 *
wadesong1795e142018-01-05 11:13:07 +08001649 * Return: 0 if success; -EINVAL if ACS channel list is NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001650 */
wadesong1795e142018-01-05 11:13:07 +08001651static int wlan_hdd_set_acs_ch_range(
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001652 tsap_config_t *sap_cfg, enum qca_wlan_vendor_acs_hw_mode hw_mode,
wadesong1795e142018-01-05 11:13:07 +08001653 bool ht_enabled, bool vht_enabled)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001654{
1655 int i;
Srinivas Girigowda576b2352017-08-25 14:44:26 -07001656
wadesong1795e142018-01-05 11:13:07 +08001657 if (hw_mode == QCA_ACS_MODE_IEEE80211B) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001658 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001659 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1660 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
wadesong1795e142018-01-05 11:13:07 +08001661 } else if (hw_mode == QCA_ACS_MODE_IEEE80211G) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001662 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001663 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1664 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
wadesong1795e142018-01-05 11:13:07 +08001665 } else if (hw_mode == QCA_ACS_MODE_IEEE80211A) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001666 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001667 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07001668 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_173);
wadesong1795e142018-01-05 11:13:07 +08001669 } else if (hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001670 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001671 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07001672 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_173);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001673 }
1674
1675 if (ht_enabled)
1676 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1677
1678 if (vht_enabled)
1679 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1680
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001681 /* Parse ACS Chan list from hostapd */
1682 if (!sap_cfg->acs_cfg.ch_list)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301683 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001684
1685 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1686 sap_cfg->acs_cfg.end_ch =
1687 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1688 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301689 /* avoid channel as start channel */
1690 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1691 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001692 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1693 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1694 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1695 }
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301696
1697 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001698}
1699
1700
1701static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1702
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301703
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001704static void hdd_update_acs_channel_list(tsap_config_t *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001705 enum band_info band)
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301706{
1707 int i, temp_count = 0;
1708 int acs_list_count = sap_config->acs_cfg.ch_list_count;
1709
1710 for (i = 0; i < acs_list_count; i++) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001711 if (BAND_2G == band) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301712 if (WLAN_REG_IS_24GHZ_CH(
1713 sap_config->acs_cfg.ch_list[i])) {
1714 sap_config->acs_cfg.ch_list[temp_count] =
1715 sap_config->acs_cfg.ch_list[i];
1716 temp_count++;
1717 }
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001718 } else if (BAND_5G == band) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301719 if (WLAN_REG_IS_5GHZ_CH(
1720 sap_config->acs_cfg.ch_list[i])) {
1721 sap_config->acs_cfg.ch_list[temp_count] =
1722 sap_config->acs_cfg.ch_list[i];
1723 temp_count++;
1724 }
1725 }
1726 }
1727 sap_config->acs_cfg.ch_list_count = temp_count;
1728}
1729
1730
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001731/**
1732 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1733 * @adapter: pointer to SAP adapter struct
1734 *
1735 * This function starts the ACS procedure if there are no
1736 * constraints like MBSSID DFS restrictions.
1737 *
1738 * Return: Status of ACS Start procedure
1739 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001740int wlan_hdd_cfg80211_start_acs(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001741{
1742
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001743 struct hdd_context *hdd_ctx;
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001744 tsap_config_t *sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001745 tpWLAN_SAPEventCB acs_event_callback;
1746 int status;
1747
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001748 if (!adapter) {
Jeff Johnsondd2f1fc2018-05-06 11:22:52 -07001749 hdd_err("adapter is NULL");
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001750 return -EINVAL;
1751 }
1752 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb9424862017-10-30 08:49:35 -07001753 sap_config = &adapter->session.ap.sap_config;
Agrawal Ashish65634612016-08-18 13:24:32 +05301754 if (hdd_ctx->acs_policy.acs_channel)
1755 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1756 else
1757 sap_config->channel = AUTO_CHANNEL_SELECT;
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301758 /*
1759 * No DFS SCC is allowed in Auto use case. Hence not
1760 * calling DFS override
1761 */
1762 if (QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION !=
1763 hdd_ctx->config->WlanMccToSccSwitchMode) {
1764 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1765 if (status < 0)
1766 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001767
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301768 if (status > 0) {
1769 /*notify hostapd about channel override */
1770 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1771 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1772 return 0;
1773 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001774 }
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301775 /* When first 2 connections are on the same frequency band,
1776 * then PCL would include only channels from the other
1777 * frequency band on which no connections are active
1778 */
1779 if ((policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) == 2) &&
1780 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
1781 struct policy_mgr_conc_connection_info *conc_connection_info;
1782 uint32_t i;
Jeff Johnson68755312017-02-10 11:46:55 -08001783
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301784 conc_connection_info = policy_mgr_get_conn_info(&i);
1785 if (conc_connection_info[0].mac ==
1786 conc_connection_info[1].mac) {
1787 if (WLAN_REG_IS_5GHZ_CH(sap_config->acs_cfg.
1788 pcl_channels[0])) {
1789 sap_config->acs_cfg.band =
1790 QCA_ACS_MODE_IEEE80211A;
1791 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001792 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301793 } else {
1794 sap_config->acs_cfg.band =
1795 QCA_ACS_MODE_IEEE80211G;
1796 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001797 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301798 }
1799 }
1800 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001801 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1802 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001803 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001804 return -EINVAL;
1805 }
1806
1807 acs_event_callback = hdd_hostapd_sap_event_cb;
1808
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301809 qdf_mem_copy(sap_config->self_macaddr.bytes,
Jeff Johnson1e851a12017-10-28 14:36:12 -07001810 adapter->mac_addr.bytes, sizeof(struct qdf_mac_addr));
Dustin Brown5e89ef82018-03-14 11:50:23 -07001811 hdd_info("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001812 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001813 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001814 acs_event_callback, sap_config, adapter->dev);
1815
1816
1817 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001818 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001819 return -EINVAL;
1820 }
bings394afdd2017-01-09 11:22:38 +08001821 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1822 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001823 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1824
1825 return 0;
1826}
1827
1828/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301829 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1830 * @hdd_ctx: hdd context
1831 * @acs_chan_params: external acs channel params
1832 * @sap_config: SAP config
1833 *
1834 * This API provides unsorted pcl list.
1835 * this list is a subset of the valid channel list given by hostapd.
1836 * if channel is not present in pcl, weightage will be given as zero
1837 *
1838 * Return: Zero on success, non-zero on failure
1839 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001840static void hdd_update_vendor_pcl_list(struct hdd_context *hdd_ctx,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301841 struct hdd_vendor_acs_chan_params *acs_chan_params,
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001842 tsap_config_t *sap_config)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301843{
1844 int i, j;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301845 /*
1846 * PCL shall contain only the preferred channels from the
1847 * application. If those channels are not present in the
1848 * driver PCL, then set the weight to zero
1849 */
1850 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1851 acs_chan_params->vendor_pcl_list[i] =
1852 sap_config->acs_cfg.ch_list[i];
1853 acs_chan_params->vendor_weight_list[i] = 0;
1854 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1855 if (sap_config->acs_cfg.ch_list[i] ==
1856 sap_config->acs_cfg.pcl_channels[j]) {
1857 acs_chan_params->vendor_weight_list[i] =
1858 sap_config->
1859 acs_cfg.pcl_channels_weight_list[j];
1860 break;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301861 }
1862 }
1863 }
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301864 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301865}
1866
1867/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301868 * hdd_update_reg_chan_info : This API contructs channel info
1869 * for all the given channel
1870 * @adapter: pointer to SAP adapter struct
1871 * @channel_count: channel count
1872 * @channel_list: channel list
1873 *
1874 * Return: Status of of channel information updation
1875 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001876static int hdd_update_reg_chan_info(struct hdd_adapter *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301877 uint32_t channel_count,
1878 uint8_t *channel_list)
1879{
1880 int i;
1881 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001882 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301883 uint8_t bw_offset = 0, chan = 0;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001884 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001885 tsap_config_t *sap_config = &adapter->session.ap.sap_config;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07001886 mac_handle_t mac_handle;
Kapil Gupta086c6202016-12-11 18:17:06 +05301887
Jeff Johnson34fc63a2018-06-14 10:10:02 -07001888 mac_handle = hdd_ctx->mac_handle;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301889 sap_config->channel_info_count = channel_count;
Kapil Gupta086c6202016-12-11 18:17:06 +05301890 for (i = 0; i < channel_count; i++) {
1891 icv = &sap_config->channel_info[i];
1892 chan = channel_list[i];
1893
1894 if (chan == 0)
1895 continue;
1896
1897 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1898 bw_offset = 1 << BW_40_OFFSET_BIT;
1899 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1900 bw_offset = 1 << BW_20_OFFSET_BIT;
Dustin Brown07901ec2018-09-07 11:02:41 -07001901 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301902 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001903 icv->max_reg_power = wlan_reg_get_channel_reg_power(
Dustin Brown07901ec2018-09-07 11:02:41 -07001904 hdd_ctx->pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301905
1906 /* filling demo values */
1907 icv->max_radio_power = HDD_MAX_TX_POWER;
1908 icv->min_radio_power = HDD_MIN_TX_POWER;
1909 /* not supported in current driver */
1910 icv->max_antenna_gain = 0;
1911
Jeff Johnson34fc63a2018-06-14 10:10:02 -07001912 icv->reg_class_id =
1913 wlan_hdd_find_opclass(mac_handle, chan, bw_offset);
Kapil Gupta086c6202016-12-11 18:17:06 +05301914
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001915 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301916 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Dustin Brown07901ec2018-09-07 11:02:41 -07001917 wlan_reg_set_channel_params(hdd_ctx->pdev, chan,
1918 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301919 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1920 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1921 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001922
Kapil Gupta086c6202016-12-11 18:17:06 +05301923 icv->flags = 0;
Dustin Brown07901ec2018-09-07 11:02:41 -07001924 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301925 sap_config->acs_cfg.ch_width,
1926 sap_config->acs_cfg.is_ht_enabled,
1927 sap_config->acs_cfg.is_vht_enabled,
1928 hdd_ctx->config->enable_sub_20_channel_width);
Kapil Guptac1224bf2017-06-22 21:22:40 +05301929 if (icv->flags & IEEE80211_CHAN_PASSIVE)
1930 icv->flagext |= IEEE80211_CHAN_DFS;
Kapil Gupta086c6202016-12-11 18:17:06 +05301931
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +05301932 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 +05301933 icv->freq, icv->flags,
1934 icv->flagext, icv->ieee_chan_number,
1935 icv->max_reg_power, icv->max_radio_power,
1936 icv->min_radio_power, icv->reg_class_id,
1937 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1938 icv->vht_center_freq_seg1);
1939 }
1940 return 0;
1941}
1942
1943/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1944#define CHAN_INFO_ATTR_FLAGS \
1945 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1946#define CHAN_INFO_ATTR_FLAG_EXT \
1947 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1948#define CHAN_INFO_ATTR_FREQ \
1949 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1950#define CHAN_INFO_ATTR_MAX_REG_POWER \
1951 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1952#define CHAN_INFO_ATTR_MAX_POWER \
1953 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1954#define CHAN_INFO_ATTR_MIN_POWER \
1955 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1956#define CHAN_INFO_ATTR_REG_CLASS_ID \
1957 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1958#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1959 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1960#define CHAN_INFO_ATTR_VHT_SEG_0 \
1961 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1962#define CHAN_INFO_ATTR_VHT_SEG_1 \
1963 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1964
1965/**
1966 * hdd_cfg80211_update_channel_info() - add channel info attributes
1967 * @skb: pointer to sk buff
1968 * @hdd_ctx: pointer to hdd station context
1969 * @idx: attribute index
1970 *
1971 * Return: Success(0) or reason code for failure
1972 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301973static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301974hdd_cfg80211_update_channel_info(struct sk_buff *skb,
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001975 tsap_config_t *sap_config, int idx)
Kapil Gupta086c6202016-12-11 18:17:06 +05301976{
1977 struct nlattr *nla_attr, *channel;
1978 struct hdd_channel_info *icv;
1979 int i;
1980
1981 nla_attr = nla_nest_start(skb, idx);
1982 if (!nla_attr)
1983 goto fail;
1984
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301985 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301986 channel = nla_nest_start(skb, i);
1987 if (!channel)
1988 goto fail;
1989
1990 icv = &sap_config->channel_info[i];
1991 if (!icv) {
1992 hdd_err("channel info not found");
1993 goto fail;
1994 }
1995 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1996 icv->freq) ||
1997 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1998 icv->flags) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05301999 nla_put_u32(skb, CHAN_INFO_ATTR_FLAG_EXT,
Kapil Gupta086c6202016-12-11 18:17:06 +05302000 icv->flagext) ||
2001 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
2002 icv->max_reg_power) ||
2003 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
2004 icv->max_radio_power) ||
2005 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
2006 icv->min_radio_power) ||
2007 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
2008 icv->reg_class_id) ||
2009 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
2010 icv->max_antenna_gain) ||
2011 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
2012 icv->vht_center_freq_seg0) ||
2013 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
2014 icv->vht_center_freq_seg1)) {
2015 hdd_err("put fail");
2016 goto fail;
2017 }
2018 nla_nest_end(skb, channel);
2019 }
2020 nla_nest_end(skb, nla_attr);
2021 return 0;
2022fail:
2023 hdd_err("nl channel update failed");
2024 return -EINVAL;
2025}
2026#undef CHAN_INFO_ATTR_FLAGS
2027#undef CHAN_INFO_ATTR_FLAG_EXT
2028#undef CHAN_INFO_ATTR_FREQ
2029#undef CHAN_INFO_ATTR_MAX_REG_POWER
2030#undef CHAN_INFO_ATTR_MAX_POWER
2031#undef CHAN_INFO_ATTR_MIN_POWER
2032#undef CHAN_INFO_ATTR_REG_CLASS_ID
2033#undef CHAN_INFO_ATTR_ANTENNA_GAIN
2034#undef CHAN_INFO_ATTR_VHT_SEG_0
2035#undef CHAN_INFO_ATTR_VHT_SEG_1
2036
2037/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05302038 * hdd_cfg80211_update_pcl() - add pcl info attributes
2039 * @skb: pointer to sk buff
2040 * @hdd_ctx: pointer to hdd station context
2041 * @idx: attribute index
2042 * @vendor_pcl_list: PCL list
2043 * @vendor_weight_list: PCL weights
2044 *
2045 * Return: Success(0) or reason code for failure
2046 */
2047static int32_t
2048hdd_cfg80211_update_pcl(struct sk_buff *skb,
2049 uint8_t ch_list_count, int idx,
2050 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
2051{
2052 struct nlattr *nla_attr, *channel;
2053 int i;
2054
2055 nla_attr = nla_nest_start(skb, idx);
2056
2057 if (!nla_attr)
2058 goto fail;
2059
2060 for (i = 0; i < ch_list_count; i++) {
2061 channel = nla_nest_start(skb, i);
2062 if (!channel)
2063 goto fail;
Kapil Gupta63e75282017-05-18 20:55:10 +05302064 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302065 vendor_pcl_list[i]) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302066 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302067 vendor_weight_list[i])) {
2068 hdd_err("put fail");
2069 goto fail;
2070 }
2071 nla_nest_end(skb, channel);
2072 }
2073 nla_nest_end(skb, nla_attr);
2074
2075 return 0;
2076fail:
2077 hdd_err("updating pcl list failed");
2078 return -EINVAL;
2079}
2080
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002081static void hdd_get_scan_band(struct hdd_context *hdd_ctx,
Jeff Johnsone4c11db2018-05-05 23:22:32 -07002082 tsap_config_t *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002083 enum band_info *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302084{
2085 /* Get scan band */
Kapil Guptac1224bf2017-06-22 21:22:40 +05302086 if ((sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211B) ||
2087 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211G)) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002088 *band = BAND_2G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302089 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002090 *band = BAND_5G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302091 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002092 *band = BAND_ALL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302093 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302094}
2095
Kapil Gupta63e75282017-05-18 20:55:10 +05302096
2097/**
2098 * hdd_get_freq_list: API to get Frequency list based on channel list
2099 * @channel_list: channel list
2100 * @freq_list: frequency list
2101 * @channel_count: channel count
2102 *
2103 * Return: None
2104 */
2105static void hdd_get_freq_list(uint8_t *channel_list, uint32_t *freq_list,
2106 uint32_t channel_count)
2107{
2108 int count;
2109
2110 for (count = 0; count < channel_count ; count++)
2111 freq_list[count] = cds_chan_to_freq(channel_list[count]);
2112}
2113
Qiwei Caie689a262018-07-26 15:50:22 +08002114/**
2115 * wlan_hdd_sap_get_valid_channellist() - Get SAPs valid channel list
2116 * @ap_adapter: adapter
2117 * @channel_count: valid channel count
2118 * @channel_list: valid channel list
2119 * @band: frequency band
2120 *
2121 * This API returns valid channel list for SAP after removing nol and
2122 * channel which lies outside of configuration.
2123 *
2124 * Return: Zero on success, non-zero on failure
2125 */
2126static int wlan_hdd_sap_get_valid_channellist(struct hdd_adapter *adapter,
2127 uint32_t *channel_count,
2128 uint8_t *channel_list,
2129 enum band_info band)
2130{
2131 tsap_config_t *sap_config;
2132 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2133 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
2134 uint32_t chan_count;
2135 uint8_t i;
2136 QDF_STATUS status;
Dustin Brown07901ec2018-09-07 11:02:41 -07002137 struct wlan_objmgr_pdev *pdev = hdd_ctx->pdev;
Qiwei Caie689a262018-07-26 15:50:22 +08002138 uint8_t tmp_chan;
2139
2140 sap_config = &adapter->session.ap.sap_config;
2141
2142 status =
2143 policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
2144 tmp_chan_list,
2145 &chan_count);
2146 if (QDF_IS_STATUS_ERROR(status)) {
2147 hdd_err("Failed to get channel list");
2148 return -EINVAL;
2149 }
2150
2151 for (i = 0; i < chan_count; i++) {
2152 tmp_chan = tmp_chan_list[i];
2153 if (*channel_count < QDF_MAX_NUM_CHAN) {
2154 if ((band == BAND_2G) &&
2155 (WLAN_REG_IS_24GHZ_CH(tmp_chan)) &&
2156 (!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
2157 channel_list[*channel_count] = tmp_chan;
2158 *channel_count += 1;
2159 } else if ((band == BAND_5G) &&
2160 (WLAN_REG_IS_5GHZ_CH(tmp_chan)) &&
2161 (!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
2162 channel_list[*channel_count] = tmp_chan;
2163 *channel_count += 1;
2164 }
2165 } else {
2166 break;
2167 }
2168 }
2169
2170 if (*channel_count == 0) {
2171 hdd_err("no valid channel found");
2172 return -EINVAL;
2173 }
2174
2175 return 0;
2176}
2177
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302178int hdd_cfg80211_update_acs_config(struct hdd_adapter *adapter,
2179 uint8_t reason)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302180{
2181 struct sk_buff *skb;
Jeff Johnsone4c11db2018-05-05 23:22:32 -07002182 tsap_config_t *sap_config;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302183 uint32_t channel_count = 0, status = -EINVAL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302184 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
Kapil Gupta63e75282017-05-18 20:55:10 +05302185 uint32_t freq_list[QDF_MAX_NUM_CHAN] = {0};
Kapil Gupta8878ad92017-02-13 11:56:04 +05302186 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
2187 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
2188 struct hdd_vendor_acs_chan_params acs_chan_params;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002189 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002190 enum band_info band = BAND_2G;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302191 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302192 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
2193 uint32_t i;
2194
Kapil Gupta8878ad92017-02-13 11:56:04 +05302195 if (!hdd_ctx) {
2196 hdd_err("HDD context is NULL");
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302197 return -EINVAL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302198 }
2199
Dustin Brown491d54b2018-03-14 12:39:11 -07002200 hdd_enter();
Jeff Johnsonb9424862017-10-30 08:49:35 -07002201 sap_config = &adapter->session.ap.sap_config;
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302202 /* When first 2 connections are on the same frequency band,
2203 * then PCL would include only channels from the other
2204 * frequency band on which no connections are active
2205 */
2206 if ((policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) == 2) &&
2207 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
2208 struct policy_mgr_conc_connection_info *conc_connection_info;
2209
2210 conc_connection_info = policy_mgr_get_conn_info(&i);
2211 if (conc_connection_info[0].mac ==
2212 conc_connection_info[1].mac) {
2213
2214 if (WLAN_REG_IS_5GHZ_CH(sap_config->acs_cfg.
2215 pcl_channels[0])) {
2216 sap_config->acs_cfg.band =
2217 QCA_ACS_MODE_IEEE80211A;
2218 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002219 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302220 } else {
2221 sap_config->acs_cfg.band =
2222 QCA_ACS_MODE_IEEE80211G;
2223 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002224 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302225 }
2226 }
2227 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302228
Jeff Johnsonb9424862017-10-30 08:49:35 -07002229 hdd_get_scan_band(hdd_ctx, &adapter->session.ap.sap_config, &band);
Nachiket Kukade3208c162017-08-29 17:40:59 +05302230
2231 if (sap_config->acs_cfg.ch_list) {
2232 /* Copy INI or hostapd provided ACS channel range*/
2233 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
2234 sap_config->acs_cfg.ch_list_count);
2235 channel_count = sap_config->acs_cfg.ch_list_count;
2236 } else {
2237 /* No channel list provided, copy all valid channels */
2238 wlan_hdd_sap_get_valid_channellist(adapter,
2239 &channel_count,
2240 channel_list,
2241 band);
2242 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302243
Lin Baifac77972018-07-05 19:51:49 +08002244 sap_config->channel_info = qdf_mem_malloc(
2245 sizeof(struct hdd_channel_info) *
2246 channel_count);
2247 if (!sap_config->channel_info) {
2248 hdd_err("memory allocation failed");
2249 return -ENOMEM;
2250 }
2251
Kapil Gupta8878ad92017-02-13 11:56:04 +05302252 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta63e75282017-05-18 20:55:10 +05302253 hdd_get_freq_list(channel_list, freq_list, channel_count);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302254 /* Get phymode */
Jeff Johnsonb9424862017-10-30 08:49:35 -07002255 phy_mode = adapter->session.ap.sap_config.acs_cfg.hw_mode;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302256
2257 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
2258 &(adapter->wdev),
2259 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2260 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
2261 GFP_KERNEL);
2262
2263 if (!skb) {
2264 hdd_err("cfg80211_vendor_event_alloc failed");
Lin Baifac77972018-07-05 19:51:49 +08002265 qdf_mem_free(sap_config->channel_info);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302266 return -ENOMEM;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302267 }
2268 /*
2269 * Application expects pcl to be a subset of channel list
2270 * Remove all channels which are not in channel list from pcl
2271 * and add weight as zero
2272 */
2273 acs_chan_params.channel_count = channel_count;
2274 acs_chan_params.channel_list = channel_list;
2275 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
2276 acs_chan_params.vendor_weight_list = vendor_weight_list;
2277
2278 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
2279 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302280
2281 if (acs_chan_params.channel_count) {
2282 hdd_debug("ACS channel list: len: %d",
2283 acs_chan_params.channel_count);
2284 for (i = 0; i < acs_chan_params.channel_count; i++)
2285 hdd_debug("%d ", acs_chan_params.channel_list[i]);
2286 }
2287
2288 if (acs_chan_params.pcl_count) {
2289 hdd_debug("ACS PCL list: len: %d",
2290 acs_chan_params.pcl_count);
2291 for (i = 0; i < acs_chan_params.pcl_count; i++)
2292 hdd_debug("channel:%d, weight:%d ",
2293 acs_chan_params.
2294 vendor_pcl_list[i],
2295 acs_chan_params.
2296 vendor_weight_list[i]);
2297 }
2298
2299 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
2300 hdd_ctx->config->external_acs_policy) {
2301 acs_policy =
2302 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
2303 } else {
2304 acs_policy =
2305 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
2306 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302307 /* Update values in NL buffer */
2308 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
2309 reason) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302310 nla_put_flag(skb,
2311 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED) ||
2312 nla_put_flag(skb,
2313 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT)
2314 ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302315 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
2316 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302317 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
2318 band) ||
2319 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
2320 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05302321 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta63e75282017-05-18 20:55:10 +05302322 channel_count * sizeof(uint32_t), freq_list)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302323 hdd_err("nla put fail");
2324 goto fail;
2325 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302326 status =
2327 hdd_cfg80211_update_pcl(skb,
2328 acs_chan_params.
2329 pcl_count,
2330 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
2331 vendor_pcl_list,
2332 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302333
2334 if (status != 0)
2335 goto fail;
2336
2337 status = hdd_cfg80211_update_channel_info(skb, sap_config,
2338 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
2339
2340 if (status != 0)
2341 goto fail;
2342
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302343 status = nla_put_u32(skb,
2344 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
2345 acs_policy);
2346
2347 if (status != 0)
2348 goto fail;
2349
Kapil Gupta8878ad92017-02-13 11:56:04 +05302350 cfg80211_vendor_event(skb, GFP_KERNEL);
Lin Baifac77972018-07-05 19:51:49 +08002351 qdf_mem_free(sap_config->channel_info);
2352
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302353 return 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302354fail:
Lin Baifac77972018-07-05 19:51:49 +08002355 qdf_mem_free(sap_config->channel_info);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302356 if (skb)
2357 kfree_skb(skb);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302358 return status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302359}
2360
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302361/**
2362 * hdd_create_acs_timer(): Initialize vendor ACS timer
2363 * @adapter: pointer to SAP adapter struct
2364 *
2365 * This function initializes the vendor ACS timer.
2366 *
2367 * Return: Status of create vendor ACS timer
2368 */
Jeff Johnsone5006672017-08-29 14:39:02 -07002369static int hdd_create_acs_timer(struct hdd_adapter *adapter)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302370{
2371 struct hdd_external_acs_timer_context *timer_context;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302372 QDF_STATUS status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302373
Jeff Johnsonb9424862017-10-30 08:49:35 -07002374 if (adapter->session.ap.vendor_acs_timer_initialized)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302375 return 0;
2376
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302377 hdd_debug("Starting vendor app based ACS");
Kapil Gupta8878ad92017-02-13 11:56:04 +05302378 timer_context = qdf_mem_malloc(sizeof(*timer_context));
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302379 if (!timer_context) {
2380 hdd_err("Could not allocate for timer_context");
2381 return -ENOMEM;
2382 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302383 timer_context->adapter = adapter;
2384
2385 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
Jeff Johnsonb9424862017-10-30 08:49:35 -07002386 status = qdf_mc_timer_init(&adapter->session.ap.vendor_acs_timer,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302387 QDF_TIMER_TYPE_SW,
2388 hdd_acs_response_timeout_handler, timer_context);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302389 if (status != QDF_STATUS_SUCCESS) {
2390 hdd_err("Failed to initialize acs response timeout timer");
2391 return -EFAULT;
2392 }
Jeff Johnsonb9424862017-10-30 08:49:35 -07002393 adapter->session.ap.vendor_acs_timer_initialized = true;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302394 return 0;
2395}
2396
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302397static const struct nla_policy
2398wlan_hdd_cfg80211_do_acs_policy[QCA_WLAN_VENDOR_ATTR_ACS_MAX+1] = {
2399 [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
2400 [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
2401 [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
2402 [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
2403 [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
2404 [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_UNSPEC },
2405 [QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_UNSPEC },
2406};
2407
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302408int hdd_start_vendor_acs(struct hdd_adapter *adapter)
2409{
2410 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2411 int status;
2412
2413 status = hdd_create_acs_timer(adapter);
2414 if (status != 0) {
2415 hdd_err("failed to create acs timer");
2416 return status;
2417 }
2418 status = hdd_update_acs_timer_reason(adapter,
2419 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2420 if (status != 0) {
2421 hdd_err("failed to update acs timer reason");
2422 return status;
2423 }
2424
2425 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2426 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2427 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2428 true));
2429 else
2430 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2431 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2432 false));
2433
2434 return status;
2435}
2436
Kapil Gupta8878ad92017-02-13 11:56:04 +05302437/**
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302438 * __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002439 * @wiphy: Linux wiphy struct pointer
2440 * @wdev: Linux wireless device struct pointer
2441 * @data: ACS information from hostapd
2442 * @data_len: ACS information length
2443 *
2444 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2445 * and starts ACS procedure.
2446 *
2447 * Return: ACS procedure start status
2448 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2450 struct wireless_dev *wdev,
2451 const void *data, int data_len)
2452{
2453 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07002454 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002455 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsone4c11db2018-05-05 23:22:32 -07002456 tsap_config_t *sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002457 struct sk_buff *temp_skbuff;
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002458 int ret, i, ch_cnt = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002459 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
2460 bool ht_enabled, ht40_enabled, vht_enabled;
wadesong1795e142018-01-05 11:13:07 +08002461 uint8_t ch_width;
2462 enum qca_wlan_vendor_acs_hw_mode hw_mode;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302463 QDF_STATUS qdf_status;
Himanshu Agarwal33163982018-05-17 18:11:10 +05302464 uint8_t conc_channel;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07002465 mac_handle_t mac_handle;
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002466 bool skip_etsi13_srd_chan = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002467
2468 /* ***Note*** Donot set SME config related to ACS operation here because
2469 * ACS operation is not synchronouse and ACS for Second AP may come when
2470 * ACS operation for first AP is going on. So only do_acs is split to
Jeff Johnsonfa7d9602018-05-06 11:25:31 -07002471 * separate start_acs routine. Also SME-PMAC struct that is used to
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
2473 * config shall be set only from start_acs.
2474 */
2475
Dustin Brownfdf17c12018-03-14 12:55:34 -07002476 hdd_enter_dev(ndev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08002477
Anurag Chouhan6d760662016-02-20 16:05:43 +05302478 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 hdd_err("Command not allowed in FTM mode");
2480 return -EPERM;
2481 }
2482
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302483 ret = wlan_hdd_validate_context(hdd_ctx);
2484 if (ret)
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302485 return ret;
2486
Amar Singhalf9898792018-08-20 12:13:34 -07002487 hdd_debug("current country is %s", hdd_ctx->reg.alpha2);
2488
Hanumanth Reddy Pothula89b0dce2018-05-18 12:49:43 +05302489 if (!((adapter->device_mode == QDF_SAP_MODE) ||
2490 (adapter->device_mode == QDF_P2P_GO_MODE))) {
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302491 hdd_err("Invalid device mode %d", adapter->device_mode);
2492 return -EINVAL;
2493 }
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302494
Naveen Rawat64e477e2016-05-20 10:34:56 -07002495 if (cds_is_sub_20_mhz_enabled()) {
2496 hdd_err("ACS not supported in sub 20 MHz ch wd.");
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302497 return -EINVAL;
Naveen Rawat64e477e2016-05-20 10:34:56 -07002498 }
2499
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302500 if (qdf_atomic_read(&adapter->session.ap.acs_in_progress) > 0) {
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302501 hdd_err("ACS rejected as previous req already in progress");
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302502 return -EINVAL;
2503 } else {
2504 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 1);
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302505 }
2506
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302507 ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
Dustin Brown4ea21db2018-01-05 14:13:17 -08002508 data_len,
2509 wlan_hdd_cfg80211_do_acs_policy);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302510 if (ret) {
Jeff Johnson020db452016-06-29 14:37:26 -07002511 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002512 goto out;
2513 }
2514
2515 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002516 hdd_err("Attr hw_mode failed");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302517 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002518 goto out;
2519 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302520 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002521
2522 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
2523 ht_enabled =
2524 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2525 else
2526 ht_enabled = 0;
2527
2528 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2529 ht40_enabled =
2530 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2531 else
2532 ht40_enabled = 0;
2533
Kapil Guptac1224bf2017-06-22 21:22:40 +05302534 hdd_debug("ht40_enabled %d", ht40_enabled);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002535 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2536 vht_enabled =
2537 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2538 else
2539 vht_enabled = 0;
2540
Bala Venkateshb9cf3362017-11-09 15:48:46 +05302541 if (((adapter->device_mode == QDF_SAP_MODE) &&
2542 (hdd_ctx->config->sap_force_11n_for_11ac)) ||
2543 ((adapter->device_mode == QDF_P2P_GO_MODE) &&
2544 (hdd_ctx->config->go_force_11n_for_11ac))) {
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302545 vht_enabled = 0;
Dustin Brownbacc48f2018-03-14 14:48:44 -07002546 hdd_info("VHT is Disabled in ACS");
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302547 }
2548
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2550 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2551 } else {
2552 if (ht_enabled && ht40_enabled)
2553 ch_width = 40;
2554 else
2555 ch_width = 20;
2556 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302557
Bala Venkateshb9cf3362017-11-09 15:48:46 +05302558 /* this may be possible, when sap_force_11n_for_11ac or
2559 * go_force_11n_for_11ac is set
2560 */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302561 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2562 if (ht_enabled && ht40_enabled)
2563 ch_width = 40;
2564 else
2565 ch_width = 20;
2566 }
2567
Hanumanth Reddy Pothula560d5712018-03-15 18:11:27 +05302568 sap_config = &adapter->session.ap.sap_config;
2569
2570 /* Check and free if memory is already allocated for acs channel list */
2571 wlan_hdd_undo_acs(adapter);
2572
2573 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
2574
Kapil Guptac1224bf2017-06-22 21:22:40 +05302575 hdd_debug("channel width =%d", ch_width);
Himanshu Agarwal75e74412018-02-01 20:51:47 +05302576 if (ch_width == 160)
2577 sap_config->acs_cfg.ch_width = CH_WIDTH_160MHZ;
2578 else if (ch_width == 80)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2580 else if (ch_width == 40)
2581 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2582 else
2583 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2584
2585 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2586 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2587 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2588 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2589 * since it contains the frequency values of the channels in
2590 * the channel list.
2591 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2592 * is present
2593 */
Himanshu Agarwal1b3be702018-02-20 12:16:57 +05302594
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2596 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
Srinivas Girigowda576b2352017-08-25 14:44:26 -07002597
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002598 sap_config->acs_cfg.ch_list_count = nla_len(
2599 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2600 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302601 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002602 sizeof(uint8_t) *
2603 sap_config->acs_cfg.ch_list_count);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302604 if (!sap_config->acs_cfg.ch_list) {
2605 hdd_err("ACS config alloc fail");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302606 ret = -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002607 goto out;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302608 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302610 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002611 sap_config->acs_cfg.ch_list_count);
2612 }
2613 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2614 uint32_t *freq =
2615 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2616 sap_config->acs_cfg.ch_list_count = nla_len(
2617 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2618 sizeof(uint32_t);
2619 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302620 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002621 sap_config->acs_cfg.ch_list_count);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302622 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07002623 hdd_err("ACS config alloc fail");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302624 ret = -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625 goto out;
2626 }
2627
2628 /* convert frequency to channel */
2629 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2630 sap_config->acs_cfg.ch_list[i] =
2631 ieee80211_frequency_to_channel(freq[i]);
2632 }
2633 }
2634
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302635 if (!sap_config->acs_cfg.ch_list_count) {
Amar Singhal5f783132018-03-29 13:58:50 -07002636 hdd_err("acs config chan count 0");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302637 ret = -EINVAL;
2638 goto out;
2639 }
2640
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002641 skip_etsi13_srd_chan =
2642 !hdd_ctx->config->etsi13_srd_chan_in_master_mode &&
Dustin Brown07901ec2018-09-07 11:02:41 -07002643 wlan_reg_is_etsi13_regdmn(hdd_ctx->pdev);
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002644
2645 if (skip_etsi13_srd_chan) {
2646 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
Dustin Brown07901ec2018-09-07 11:02:41 -07002647 if (wlan_reg_is_etsi13_srd_chan(hdd_ctx->pdev,
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -07002648 sap_config->acs_cfg.
2649 ch_list[i]))
2650 sap_config->acs_cfg.ch_list[i] = 0;
2651 else
2652 sap_config->acs_cfg.ch_list[ch_cnt++] =
2653 sap_config->acs_cfg.ch_list[i];
2654 }
2655 sap_config->acs_cfg.ch_list_count = ch_cnt;
2656 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002657 hdd_debug("get pcl for DO_ACS vendor command");
2658
2659 /* consult policy manager to get PCL */
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302660 qdf_status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302661 sap_config->acs_cfg.pcl_channels,
2662 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302663 sap_config->acs_cfg.pcl_channels_weight_list,
2664 QDF_MAX_NUM_CHAN);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302665 if (qdf_status != QDF_STATUS_SUCCESS)
Jeff Johnson020db452016-06-29 14:37:26 -07002666 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002667
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302668 if (sap_config->acs_cfg.pcl_ch_count) {
2669 hdd_debug("ACS config PCL: len: %d",
2670 sap_config->acs_cfg.pcl_ch_count);
2671 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2672 hdd_debug("channel:%d, weight:%d ",
2673 sap_config->acs_cfg.
2674 pcl_channels[i],
2675 sap_config->acs_cfg.
2676 pcl_channels_weight_list[i]);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302677 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302678
Tushnim Bhattacharyya087bff32018-02-21 13:25:15 -08002679 if (hw_mode == QCA_ACS_MODE_IEEE80211ANY)
2680 policy_mgr_trim_acs_channel_list(hdd_ctx->hdd_psoc,
2681 sap_config->acs_cfg.ch_list,
2682 &sap_config->acs_cfg.ch_list_count);
2683
Kapil Guptac1224bf2017-06-22 21:22:40 +05302684 sap_config->acs_cfg.band = hw_mode;
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302685 ret = wlan_hdd_set_acs_ch_range(sap_config, hw_mode,
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302686 ht_enabled, vht_enabled);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302687 if (ret) {
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302688 hdd_err("set acs channel range failed");
2689 goto out;
2690 }
2691
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302692 /* ACS override for android */
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05302693 if (ht_enabled &&
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302694 sap_config->acs_cfg.end_ch >= WLAN_REG_CH_NUM(CHAN_ENUM_36) &&
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05302695 ((adapter->device_mode == QDF_SAP_MODE &&
2696 !hdd_ctx->config->sap_force_11n_for_11ac &&
2697 hdd_ctx->config->sap_11ac_override) ||
2698 (adapter->device_mode == QDF_P2P_GO_MODE &&
2699 !hdd_ctx->config->go_force_11n_for_11ac &&
2700 hdd_ctx->config->go_11ac_override))) {
2701 hdd_debug("ACS Config override for 11AC, vhtChannelWidth %d",
2702 hdd_ctx->config->vhtChannelWidth);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703 vht_enabled = 1;
2704 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2705 sap_config->acs_cfg.ch_width =
2706 hdd_ctx->config->vhtChannelWidth;
Himanshu Agarwal29a9a3e2018-02-21 17:44:37 +05302707 }
2708
2709 /* No VHT80 in 2.4G so perform ACS accordingly */
2710 if (sap_config->acs_cfg.end_ch <= 14 &&
2711 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
2712 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
2713 hdd_debug("resetting to 40Mhz in 2.4Ghz");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714 }
2715
Kapil Guptac1224bf2017-06-22 21:22:40 +05302716 hdd_debug("ACS Config for %s: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d band %d",
2717 adapter->dev->name, sap_config->acs_cfg.hw_mode,
Himanshu Agarwal1ed8bff2018-02-07 12:50:41 +05302718 sap_config->acs_cfg.ch_width, ht_enabled, vht_enabled,
Kapil Guptac1224bf2017-06-22 21:22:40 +05302719 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch,
2720 sap_config->acs_cfg.band);
wadesongcb0ded22018-02-02 17:57:20 +08002721 host_log_acs_req_event(adapter->dev->name,
2722 csr_phy_mode_str(sap_config->acs_cfg.hw_mode),
2723 ch_width, ht_enabled, vht_enabled,
2724 sap_config->acs_cfg.start_ch,
2725 sap_config->acs_cfg.end_ch);
gaoleze5108942017-03-31 16:56:42 +08002726 if (hdd_ctx->config->auto_channel_select_weight)
2727 sap_config->auto_channel_select_weight =
2728 hdd_ctx->config->auto_channel_select_weight;
2729
Kapil Gupta8878ad92017-02-13 11:56:04 +05302730 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2731 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2732
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002733 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002734 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002735 sap_config->acs_cfg.ch_list_count);
2736 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002737 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002738 }
Himanshu Agarwal33163982018-05-17 18:11:10 +05302739
2740 conc_channel = policy_mgr_mode_specific_get_channel(hdd_ctx->hdd_psoc,
2741 PM_STA_MODE);
2742 if (hdd_ctx->config->external_acs_policy ==
2743 HDD_EXTERNAL_ACS_PCL_MANDATORY) {
2744 if ((conc_channel >= WLAN_REG_CH_NUM(CHAN_ENUM_36) &&
2745 sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A) ||
2746 (conc_channel <= WLAN_REG_CH_NUM(CHAN_ENUM_14) &&
2747 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211B ||
2748 sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A))) {
2749 sap_config->acs_cfg.pri_ch = conc_channel;
2750 wlan_sap_set_sap_ctx_acs_cfg(
2751 WLAN_HDD_GET_SAP_CTX_PTR(adapter), sap_config);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07002752 mac_handle = hdd_ctx->mac_handle;
2753 sap_config_acs_result(mac_handle,
Himanshu Agarwal33163982018-05-17 18:11:10 +05302754 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2755 sap_config->acs_cfg.ht_sec_ch);
2756 sap_config->ch_params.ch_width =
2757 sap_config->acs_cfg.ch_width;
2758 sap_config->ch_params.sec_ch_offset =
2759 sap_config->acs_cfg.ht_sec_ch;
2760 sap_config->ch_params.center_freq_seg0 =
2761 sap_config->acs_cfg.vht_seg0_center_ch;
2762 sap_config->ch_params.center_freq_seg1 =
2763 sap_config->acs_cfg.vht_seg1_center_ch;
2764 /*notify hostapd about channel override */
2765 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
2766 ret = 0;
2767 goto out;
2768 }
2769 }
2770
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002771 sap_config->acs_cfg.acs_mode = true;
2772 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002773 /* ***Note*** Completion variable usage is not allowed
2774 * here since ACS scan operation may take max 2.2 sec
2775 * for 5G band:
2776 * 9 Active channel X 40 ms active scan time +
2777 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002778 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2779 * for this long. So we split up the scanning part.
2780 */
2781 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002782 hdd_debug("ACS Pending for %s", adapter->dev->name);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302783 ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302785 /* Check if vendor specific acs is enabled */
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302786 if (hdd_ctx->config->vendor_acs_support)
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302787 ret = hdd_start_vendor_acs(adapter);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302788 else
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302789 ret = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002790 }
2791
2792out:
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302793 if (ret == 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002794 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2795 NLMSG_HDRLEN);
2796 if (temp_skbuff != NULL)
2797 return cfg80211_vendor_cmd_reply(temp_skbuff);
2798 }
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302799 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 0);
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002800 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002801 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2802
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302803 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002804}
2805
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002806/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002807 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2808 * @wiphy: Linux wiphy struct pointer
2809 * @wdev: Linux wireless device struct pointer
2810 * @data: ACS information from hostapd
2811 * @data_len: ACS information len
2812 *
2813 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2814 * and starts ACS procedure.
2815 *
2816 * Return: ACS procedure start status
2817 */
2818
2819static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2820 struct wireless_dev *wdev,
2821 const void *data, int data_len)
2822{
2823 int ret;
2824
2825 cds_ssr_protect(__func__);
2826 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2827 cds_ssr_unprotect(__func__);
2828
2829 return ret;
2830}
2831
2832/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002833 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2834 * @adapter: Pointer to adapter struct
2835 *
2836 * This function handle cleanup of what was done in DO_ACS, including free
2837 * memory.
2838 *
2839 * Return: void
2840 */
2841
Jeff Johnsone5006672017-08-29 14:39:02 -07002842void wlan_hdd_undo_acs(struct hdd_adapter *adapter)
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002843{
2844 if (adapter == NULL)
2845 return;
Jeff Johnsonb9424862017-10-30 08:49:35 -07002846 if (adapter->session.ap.sap_config.acs_cfg.ch_list) {
2847 qdf_mem_free(adapter->session.ap.sap_config.acs_cfg.ch_list);
2848 adapter->session.ap.sap_config.acs_cfg.ch_list = NULL;
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002849 }
2850}
2851
2852/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002853 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2854 * @work: Linux workqueue struct pointer for ACS work
2855 *
2856 * This function starts the ACS procedure which was marked pending when an ACS
2857 * procedure was in progress for a concurrent SAP interface.
2858 *
2859 * Return: None
2860 */
2861
2862static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2863{
Jeff Johnsone5006672017-08-29 14:39:02 -07002864 struct hdd_adapter *adapter = container_of(work, struct hdd_adapter,
Jeff Johnson3aa54d42018-06-26 11:36:50 -07002865 acs_pending_work.work);
2866
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002867 wlan_hdd_cfg80211_start_acs(adapter);
Will Huang7049bae2018-08-13 17:25:02 +08002868 clear_bit(ACS_PENDING, &adapter->event_flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002869}
2870
2871/**
2872 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2873 * @adapter: Pointer to SAP adapter struct
2874 * @pri_channel: SAP ACS procedure selected Primary channel
2875 * @sec_channel: SAP ACS procedure selected secondary channel
2876 *
2877 * This is a callback function from SAP module on ACS procedure is completed.
2878 * This function send the ACS selected channel information to hostapd
2879 *
2880 * Return: None
2881 */
2882
Jeff Johnsone5006672017-08-29 14:39:02 -07002883void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002884{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002885 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsone4c11db2018-05-05 23:22:32 -07002886 tsap_config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002887 struct sk_buff *vendor_event;
2888 int ret_val;
Jeff Johnsone5006672017-08-29 14:39:02 -07002889 struct hdd_adapter *con_sap_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002890 uint16_t ch_width;
2891
2892 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002893 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002894 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2895 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2896 GFP_KERNEL);
2897
2898 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002899 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002900 return;
2901 }
2902
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002903 ret_val = nla_put_u8(vendor_event,
2904 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2905 sap_cfg->acs_cfg.pri_ch);
2906 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002907 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002908 kfree_skb(vendor_event);
2909 return;
2910 }
2911
2912 ret_val = nla_put_u8(vendor_event,
2913 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2914 sap_cfg->acs_cfg.ht_sec_ch);
2915 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002916 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917 kfree_skb(vendor_event);
2918 return;
2919 }
2920
2921 ret_val = nla_put_u8(vendor_event,
2922 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2923 sap_cfg->acs_cfg.vht_seg0_center_ch);
2924 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002925 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002926 kfree_skb(vendor_event);
2927 return;
2928 }
2929
2930 ret_val = nla_put_u8(vendor_event,
2931 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2932 sap_cfg->acs_cfg.vht_seg1_center_ch);
2933 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002934 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002935 kfree_skb(vendor_event);
2936 return;
2937 }
2938
Himanshu Agarwal75e74412018-02-01 20:51:47 +05302939 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_160MHZ)
2940 ch_width = 160;
2941 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002942 ch_width = 80;
2943 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2944 ch_width = 40;
2945 else
2946 ch_width = 20;
2947
2948 ret_val = nla_put_u16(vendor_event,
2949 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2950 ch_width);
2951 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002952 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002953 kfree_skb(vendor_event);
2954 return;
2955 }
2956 if (sap_cfg->acs_cfg.pri_ch > 14)
2957 ret_val = nla_put_u8(vendor_event,
2958 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2959 QCA_ACS_MODE_IEEE80211A);
2960 else
2961 ret_val = nla_put_u8(vendor_event,
2962 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2963 QCA_ACS_MODE_IEEE80211G);
2964
2965 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002966 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967 kfree_skb(vendor_event);
2968 return;
2969 }
2970
Mahesh Kumar Kalikot Veetilec1da142017-09-20 10:01:13 -07002971 hdd_debug("ACS result for %s: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
2972 adapter->dev->name, sap_cfg->acs_cfg.pri_ch,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002973 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2974 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2975
2976 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2977 /* ***Note*** As already mentioned Completion variable usage is not
2978 * allowed here since ACS scan operation may take max 2.2 sec.
2979 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2980 * operation.
2981 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2982 * when Primary AP ACS is complete and secondary AP ACS is started here
2983 * immediately, Primary AP start_bss may come inbetween ACS operation
Jeff Johnson60ed45a2018-05-06 15:28:49 -07002984 * and overwrite Sec AP ACS parameters. Thus Sec AP ACS is executed with
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985 * delay. This path and below constraint will be removed on sessionizing
2986 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2987 * As per design constraint user space control application must take
2988 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2989 * this code path. Sec AP hostapd should be started after Primary AP
2990 * start beaconing which can be confirmed by getchannel iwpriv command
2991 */
2992
2993 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2994 if (con_sap_adapter &&
2995 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002996 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2997 wlan_hdd_cfg80211_start_pending_acs);
hqu71a1a3b2018-01-23 15:38:13 +08002998 /* Lets give 1500ms for OBSS + START_BSS to complete */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002999 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
hqu71a1a3b2018-01-23 15:38:13 +08003000 msecs_to_jiffies(1500));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003001 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002}
3003
3004static int
3005__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
3006 struct wireless_dev *wdev,
3007 const void *data,
3008 int data_len)
3009{
Jeff Johnsonb8944722017-09-03 09:03:19 -07003010 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003011 struct sk_buff *skb = NULL;
3012 uint32_t fset = 0;
3013 int ret;
Wu Gaobdb7f272018-07-05 19:33:26 +08003014#ifdef FEATURE_WLAN_TDLS
3015 bool bvalue;
3016#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07003018 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303019
Anurag Chouhan6d760662016-02-20 16:05:43 +05303020 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003021 hdd_err("Command not allowed in FTM mode");
3022 return -EPERM;
3023 }
3024
Jeff Johnsonb8944722017-09-03 09:03:19 -07003025 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303026 if (ret)
3027 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003028
3029 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003030 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031 fset |= WIFI_FEATURE_INFRA;
3032 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07003033 if (true == hdd_is_5g_supported(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003034 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003035 fset |= WIFI_FEATURE_INFRA_5G;
3036 }
3037#ifdef WLAN_FEATURE_P2P
3038 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
3039 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003040 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003041 fset |= WIFI_FEATURE_P2P;
3042 }
3043#endif
3044 fset |= WIFI_FEATURE_SOFT_AP;
3045
3046 /* HOTSPOT is a supplicant feature, enable it by default */
3047 fset |= WIFI_FEATURE_HOTSPOT;
3048
Harprit Chhabadae8155d32018-08-22 16:19:34 -07003049 if (ucfg_extscan_get_enable(hdd_ctx->hdd_psoc) &&
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303050 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003051 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003052 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
3053 }
Nachiket Kukade989bb352018-07-31 18:01:17 +05303054 if (wlan_hdd_nan_is_supported(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003055 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 fset |= WIFI_FEATURE_NAN;
3057 }
3058 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003059 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003060 fset |= WIFI_FEATURE_D2D_RTT;
3061 fset |= WIFI_FEATURE_D2AP_RTT;
3062 }
3063#ifdef FEATURE_WLAN_SCAN_PNO
Jeff Johnsonb8944722017-09-03 09:03:19 -07003064 if (hdd_ctx->config->configPNOScanSupport &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003065 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003066 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003067 fset |= WIFI_FEATURE_PNO;
3068 }
3069#endif
3070 fset |= WIFI_FEATURE_ADDITIONAL_STA;
3071#ifdef FEATURE_WLAN_TDLS
Wu Gaobdb7f272018-07-05 19:33:26 +08003072 cfg_tdls_get_support_enable(hdd_ctx->hdd_psoc, &bvalue);
3073 if ((bvalue) && sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003074 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003075 fset |= WIFI_FEATURE_TDLS;
3076 }
Wu Gaobdb7f272018-07-05 19:33:26 +08003077
3078 cfg_tdls_get_off_channel_enable(hdd_ctx->hdd_psoc, &bvalue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003079 if (sme_is_feature_supported_by_fw(TDLS) &&
Wu Gaobdb7f272018-07-05 19:33:26 +08003080 bvalue && sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003081 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003082 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
3083 }
3084#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003085 fset |= WIFI_FEATURE_AP_STA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003086 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07003087 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Srinivas Girigowda5a1da622017-07-12 17:07:44 -07003088 fset |= WIFI_FEATURE_SET_TX_POWER_LIMIT;
Sourav Mohapatra804359e2017-12-07 13:52:05 +05303089 fset |= WIFI_FEATURE_CONFIG_NDO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003090
3091 if (hdd_link_layer_stats_supported())
3092 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
3093
Jeff Johnsonb8944722017-09-03 09:03:19 -07003094 if (hdd_roaming_supported(hdd_ctx))
Srinivas Girigowda8df27ea2017-01-06 12:42:16 -08003095 fset |= WIFI_FEATURE_CONTROL_ROAMING;
3096
3097 if (hdd_scan_random_mac_addr_supported())
3098 fset |= WIFI_FEATURE_SCAN_RAND;
3099
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003100 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
3101 NLMSG_HDRLEN);
3102 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003103 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003104 return -EINVAL;
3105 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003106 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003107 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003108 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003109 goto nla_put_failure;
3110 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303111 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303112 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003113nla_put_failure:
3114 kfree_skb(skb);
3115 return -EINVAL;
3116}
3117
3118/**
3119 * wlan_hdd_cfg80211_get_supported_features() - get supported features
3120 * @wiphy: pointer to wireless wiphy structure.
3121 * @wdev: pointer to wireless_dev structure.
3122 * @data: Pointer to the data to be passed via vendor interface
3123 * @data_len:Length of the data to be passed
3124 *
3125 * Return: Return the Success or Failure code.
3126 */
3127static int
3128wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
3129 struct wireless_dev *wdev,
3130 const void *data, int data_len)
3131{
3132 int ret = 0;
3133
3134 cds_ssr_protect(__func__);
3135 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
3136 data, data_len);
3137 cds_ssr_unprotect(__func__);
3138
3139 return ret;
3140}
3141
3142/**
3143 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3144 * @wiphy: pointer to wireless wiphy structure.
3145 * @wdev: pointer to wireless_dev structure.
3146 * @data: Pointer to the data to be passed via vendor interface
3147 * @data_len:Length of the data to be passed
3148 *
3149 * Set the MAC address that is to be used for scanning.
3150 *
3151 * Return: Return the Success or Failure code.
3152 */
3153static int
3154__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3155 struct wireless_dev *wdev,
3156 const void *data,
3157 int data_len)
3158{
3159 tpSirScanMacOui pReqMsg = NULL;
Jeff Johnsonb8944722017-09-03 09:03:19 -07003160 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003161 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303162 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163 int ret;
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003164 int len;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303165 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07003166 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003167 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168
Dustin Brownfdf17c12018-03-14 12:55:34 -07003169 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003170
Anurag Chouhan6d760662016-02-20 16:05:43 +05303171 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172 hdd_err("Command not allowed in FTM mode");
3173 return -EPERM;
3174 }
3175
Jeff Johnsonb8944722017-09-03 09:03:19 -07003176 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303177 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003179
Dustin Browna7bb6ae2018-08-16 16:51:50 -07003180 if (!hdd_ctx->config->enable_mac_spoofing) {
3181 hdd_debug("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003182 return -ENOTSUPP;
3183 }
3184
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003185 /*
3186 * audit note: it is ok to pass a NULL policy here since only
3187 * one attribute is parsed and it is explicitly validated
3188 */
Dustin Brown4ea21db2018-01-05 14:13:17 -08003189 if (wlan_cfg80211_nla_parse(tb,
3190 QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
3191 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003192 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003193 return -EINVAL;
3194 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303195 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003196 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07003197 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198 return -ENOMEM;
3199 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003200
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003201 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003202 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 goto fail;
3204 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003205
3206 len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]);
3207 if (len != sizeof(pReqMsg->oui)) {
3208 hdd_err("attr mac oui invalid size %d expected %zu",
3209 len, sizeof(pReqMsg->oui));
3210 goto fail;
3211 }
3212
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003213 nla_memcpy(&pReqMsg->oui[0],
3214 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
3215 sizeof(pReqMsg->oui));
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303216
3217 /* populate pReqMsg for mac addr randomization */
Jeff Johnson1b780e42017-10-31 14:11:45 -07003218 pReqMsg->vdev_id = adapter->session_id;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303219 pReqMsg->enb_probe_req_sno_randomization = true;
3220
3221 hdd_debug("Oui (%02x:%02x:%02x), vdev_id = %d", pReqMsg->oui[0],
3222 pReqMsg->oui[1], pReqMsg->oui[2], pReqMsg->vdev_id);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303223
Jeff Johnsonb8944722017-09-03 09:03:19 -07003224 hdd_update_ie_whitelist_attr(&pReqMsg->ie_whitelist, hdd_ctx->config);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303225
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003226 mac_handle = hdd_ctx->mac_handle;
3227 status = sme_set_scanning_mac_oui(mac_handle, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303228 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003229 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003230 goto fail;
3231 }
3232 return 0;
3233fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303234 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 return -EINVAL;
3236}
3237
3238/**
3239 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3240 * @wiphy: pointer to wireless wiphy structure.
3241 * @wdev: pointer to wireless_dev structure.
3242 * @data: Pointer to the data to be passed via vendor interface
3243 * @data_len:Length of the data to be passed
3244 *
3245 * Set the MAC address that is to be used for scanning. This is an
3246 * SSR-protecting wrapper function.
3247 *
3248 * Return: Return the Success or Failure code.
3249 */
3250static int
3251wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3252 struct wireless_dev *wdev,
3253 const void *data,
3254 int data_len)
3255{
3256 int ret;
3257
3258 cds_ssr_protect(__func__);
3259 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
3260 data, data_len);
3261 cds_ssr_unprotect(__func__);
3262
3263 return ret;
3264}
3265
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303266/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
3268 * @feature_flags: pointer to the byte array of features.
3269 * @feature: Feature to be turned ON in the byte array.
3270 *
3271 * Return: None
3272 *
3273 * This is called to turn ON or SET the feature flag for the requested feature.
3274 **/
3275#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07003276static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
3277 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278{
3279 uint32_t index;
3280 uint8_t bit_mask;
3281
3282 index = feature / NUM_BITS_IN_BYTE;
3283 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
3284 feature_flags[index] |= bit_mask;
3285}
3286
3287/**
3288 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
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 * This is called when wlan driver needs to send supported feature set to
3295 * supplicant upon a request/query from the supplicant.
3296 *
3297 * Return: Return the Success or Failure code.
3298 **/
3299#define MAX_CONCURRENT_CHAN_ON_24G 2
3300#define MAX_CONCURRENT_CHAN_ON_5G 2
3301static int
3302__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3303 struct wireless_dev *wdev,
3304 const void *data, int data_len)
3305{
3306 struct sk_buff *skb = NULL;
3307 uint32_t dbs_capability = 0;
3308 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303309 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003310 int ret_val;
3311
3312 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003313 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003314
Dustin Brownfdf17c12018-03-14 12:55:34 -07003315 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08003316
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003317 ret_val = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003318 if (ret_val)
3319 return ret_val;
3320
Anurag Chouhan6d760662016-02-20 16:05:43 +05303321 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003322 hdd_err("Command not allowed in FTM mode");
3323 return -EPERM;
3324 }
3325
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003326 if (roaming_offload_enabled(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003327 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003328 wlan_hdd_cfg80211_set_feature(feature_flags,
3329 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
3330 }
3331
3332 wlan_hdd_cfg80211_set_feature(feature_flags,
3333 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003334 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003335 wlan_hdd_cfg80211_set_feature(feature_flags,
3336 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07003337
3338 if (wma_is_p2p_lo_capable())
3339 wlan_hdd_cfg80211_set_feature(feature_flags,
3340 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
3341
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003342 if (hdd_ctx->config->oce_sta_enabled)
yeshwanth sriram guntuka1413dfb2017-06-23 14:09:48 +05303343 wlan_hdd_cfg80211_set_feature(feature_flags,
3344 QCA_WLAN_VENDOR_FEATURE_OCE_STA);
3345
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003346 if (hdd_ctx->config->oce_sap_enabled)
yeshwanth sriram guntuka1413dfb2017-06-23 14:09:48 +05303347 wlan_hdd_cfg80211_set_feature(feature_flags,
3348 QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON);
3349
Kiran Kumar Lokere0508af92018-04-23 18:38:32 -07003350 /* Check the kernel version for upstream commit aced43ce780dc5 that
3351 * has support for processing user cell_base hints when wiphy is
3352 * self managed or check the backport flag for the same.
3353 */
3354#if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
3355 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
3356 wlan_hdd_cfg80211_set_feature(feature_flags,
3357 QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY);
3358#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003359 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
3360 NLMSG_HDRLEN);
3361
3362 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003363 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003364 return -ENOMEM;
3365 }
3366
3367 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
3368 sizeof(feature_flags), feature_flags))
3369 goto nla_put_failure;
3370
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003371 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx->hdd_psoc,
3372 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303373 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003374 if (one_by_one_dbs)
3375 dbs_capability = DRV_DBS_CAPABILITY_1X1;
3376
3377 if (two_by_two_dbs)
3378 dbs_capability = DRV_DBS_CAPABILITY_2X2;
3379
3380 if (!one_by_one_dbs && !two_by_two_dbs)
3381 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
3382 } else {
3383 hdd_err("wma_get_dbs_hw_mode failed");
3384 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
3385 }
3386
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003387 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003388
3389 if (nla_put_u32(skb,
Ganesh Kondabattinid921ed92017-06-20 16:40:48 +05303390 QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA,
3391 dbs_capability))
3392 goto nla_put_failure;
3393
3394
3395 if (nla_put_u32(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003396 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
3397 MAX_CONCURRENT_CHAN_ON_24G))
3398 goto nla_put_failure;
3399
3400 if (nla_put_u32(skb,
3401 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
3402 MAX_CONCURRENT_CHAN_ON_5G))
3403 goto nla_put_failure;
3404
3405 return cfg80211_vendor_cmd_reply(skb);
3406
3407nla_put_failure:
3408 kfree_skb(skb);
3409 return -EINVAL;
3410}
3411
3412/**
3413 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
3414 * @wiphy: pointer to wireless wiphy structure.
3415 * @wdev: pointer to wireless_dev structure.
3416 * @data: Pointer to the data to be passed via vendor interface
3417 * @data_len:Length of the data to be passed
3418 *
3419 * This is called when wlan driver needs to send supported feature set to
3420 * supplicant upon a request/query from the supplicant.
3421 *
3422 * Return: Return the Success or Failure code.
3423 */
3424static int
3425wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3426 struct wireless_dev *wdev,
3427 const void *data, int data_len)
3428{
3429 int ret;
3430
3431 cds_ssr_protect(__func__);
3432 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
3433 data, data_len);
3434 cds_ssr_unprotect(__func__);
3435
3436 return ret;
3437}
3438
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303439#define PARAM_NUM_NW \
3440 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
3441#define PARAM_SET_BSSID \
3442 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003443#define PARAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303444#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303445#define MAX_ROAMING_PARAM \
3446 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003447#define PARAM_NUM_BSSID \
3448 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID
3449#define PARAM_BSSID_PREFS \
3450 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS
3451#define PARAM_ROAM_BSSID \
3452 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID
3453#define PARAM_RSSI_MODIFIER \
3454 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER
3455#define PARAMS_NUM_BSSID \
3456 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID
3457#define PARAM_BSSID_PARAMS \
3458 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS
3459#define PARAM_A_BAND_BOOST_THLD \
3460 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD
3461#define PARAM_A_BAND_PELT_THLD \
3462 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD
3463#define PARAM_A_BAND_BOOST_FACTOR \
3464 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR
3465#define PARAM_A_BAND_PELT_FACTOR \
3466 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR
3467#define PARAM_A_BAND_MAX_BOOST \
3468 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST
3469#define PARAM_ROAM_HISTERESYS \
3470 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS
3471#define PARAM_RSSI_TRIGGER \
3472 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER
3473#define PARAM_ROAM_ENABLE \
3474 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE
3475
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303476
3477static const struct nla_policy
3478wlan_hdd_set_roam_param_policy[MAX_ROAMING_PARAM + 1] = {
3479 [QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD] = {.type = NLA_U32},
3480 [QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID] = {.type = NLA_U32},
3481 [PARAM_NUM_NW] = {.type = NLA_U32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003482 [PARAM_A_BAND_BOOST_FACTOR] = {.type = NLA_U32},
3483 [PARAM_A_BAND_PELT_FACTOR] = {.type = NLA_U32},
3484 [PARAM_A_BAND_MAX_BOOST] = {.type = NLA_U32},
3485 [PARAM_ROAM_HISTERESYS] = {.type = NLA_S32},
3486 [PARAM_A_BAND_BOOST_THLD] = {.type = NLA_S32},
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07003487 [PARAM_A_BAND_PELT_THLD] = {.type = NLA_S32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003488 [PARAM_RSSI_TRIGGER] = {.type = NLA_U32},
3489 [PARAM_ROAM_ENABLE] = { .type = NLA_S32},
3490 [PARAM_NUM_BSSID] = {.type = NLA_U32},
3491 [PARAM_RSSI_MODIFIER] = {.type = NLA_U32},
3492 [PARAMS_NUM_BSSID] = {.type = NLA_U32},
3493 [PARAM_ROAM_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
3494 [PARAM_SET_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303495};
3496
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003497/**
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003498 * hdd_set_white_list() - parse white list
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003499 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003500 * @roam_params: roam params
3501 * @tb: list of attributes
3502 * @session_id: session id
3503 *
3504 * Return: 0 on success; error number on failure
3505 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003506static int hdd_set_white_list(struct hdd_context *hdd_ctx,
3507 struct roam_ext_params *roam_params,
3508 struct nlattr **tb, uint8_t session_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003509{
3510 int rem, i;
3511 uint32_t buf_len = 0, count;
3512 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3513 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003514 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003515
3516 i = 0;
3517 if (tb[PARAM_NUM_NW]) {
3518 count = nla_get_u32(tb[PARAM_NUM_NW]);
3519 } else {
3520 hdd_err("Number of networks is not provided");
3521 goto fail;
3522 }
3523
3524 if (count && tb[PARAM_SSID_LIST]) {
3525 nla_for_each_nested(curr_attr,
3526 tb[PARAM_SSID_LIST], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08003527 if (wlan_cfg80211_nla_parse(tb2,
3528 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
3529 nla_data(curr_attr),
3530 nla_len(curr_attr),
3531 wlan_hdd_set_roam_param_policy)) {
3532 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003533 goto fail;
3534 }
3535 /* Parse and Fetch allowed SSID list*/
3536 if (!tb2[PARAM_LIST_SSID]) {
3537 hdd_err("attr allowed ssid failed");
3538 goto fail;
3539 }
3540 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
3541 /*
3542 * Upper Layers include a null termination
3543 * character. Check for the actual permissible
3544 * length of SSID and also ensure not to copy
3545 * the NULL termination character to the driver
3546 * buffer.
3547 */
3548 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
3549 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
3550 nla_memcpy(roam_params->ssid_allowed_list[i].ssId,
3551 tb2[PARAM_LIST_SSID], buf_len - 1);
3552 roam_params->ssid_allowed_list[i].length = buf_len - 1;
3553 hdd_debug("SSID[%d]: %.*s,length = %d",
3554 i,
3555 roam_params->ssid_allowed_list[i].length,
3556 roam_params->ssid_allowed_list[i].ssId,
3557 roam_params->ssid_allowed_list[i].length);
3558 i++;
3559 } else {
3560 hdd_err("Invalid buffer length");
3561 }
3562 }
3563 }
3564
3565 if (i != count) {
3566 hdd_err("Invalid number of SSIDs i = %d, count = %d", i, count);
3567 goto fail;
3568 }
3569
3570 roam_params->num_ssid_allowed_list = i;
3571 hdd_debug("Num of Allowed SSID %d", roam_params->num_ssid_allowed_list);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003572 mac_handle = hdd_ctx->mac_handle;
3573 sme_update_roam_params(mac_handle, session_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003574 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3575 return 0;
3576
3577fail:
3578 return -EINVAL;
3579}
3580
3581/**
3582 * hdd_set_bssid_prefs() - parse set bssid prefs
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003583 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003584 * @roam_params: roam params
3585 * @tb: list of attributes
3586 * @session_id: session id
3587 *
3588 * Return: 0 on success; error number on failure
3589 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003590static int hdd_set_bssid_prefs(struct hdd_context *hdd_ctx,
3591 struct roam_ext_params *roam_params,
3592 struct nlattr **tb, uint8_t session_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003593{
3594 int rem, i;
3595 uint32_t count;
3596 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3597 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003598 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003599
3600 /* Parse and fetch number of preferred BSSID */
3601 if (!tb[PARAM_NUM_BSSID]) {
3602 hdd_err("attr num of preferred bssid failed");
3603 goto fail;
3604 }
3605 count = nla_get_u32(tb[PARAM_NUM_BSSID]);
3606 if (count > MAX_BSSID_FAVORED) {
3607 hdd_err("Preferred BSSID count %u exceeds max %u",
3608 count, MAX_BSSID_FAVORED);
3609 goto fail;
3610 }
3611 hdd_debug("Num of Preferred BSSID (%d)", count);
3612 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS]) {
3613 hdd_err("attr Preferred BSSID failed");
3614 goto fail;
3615 }
3616
3617 i = 0;
3618 nla_for_each_nested(curr_attr,
3619 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3620 rem) {
3621 if (i == count) {
3622 hdd_warn("Ignoring excess Preferred BSSID");
3623 break;
3624 }
3625
Dustin Brown4ea21db2018-01-05 14:13:17 -08003626 if (wlan_cfg80211_nla_parse(tb2,
3627 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3628 nla_data(curr_attr),
3629 nla_len(curr_attr),
3630 wlan_hdd_set_roam_param_policy)) {
3631 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003632 goto fail;
3633 }
3634 /* Parse and fetch MAC address */
3635 if (!tb2[PARAM_ROAM_BSSID]) {
3636 hdd_err("attr mac address failed");
3637 goto fail;
3638 }
3639 nla_memcpy(roam_params->bssid_favored[i].bytes,
3640 tb2[PARAM_ROAM_BSSID],
3641 QDF_MAC_ADDR_SIZE);
3642 hdd_debug(MAC_ADDRESS_STR,
3643 MAC_ADDR_ARRAY(roam_params->bssid_favored[i].bytes));
3644 /* Parse and fetch preference factor*/
3645 if (!tb2[PARAM_RSSI_MODIFIER]) {
3646 hdd_err("BSSID Preference score failed");
3647 goto fail;
3648 }
3649 roam_params->bssid_favored_factor[i] = nla_get_u32(
3650 tb2[PARAM_RSSI_MODIFIER]);
3651 hdd_debug("BSSID Preference score (%d)",
3652 roam_params->bssid_favored_factor[i]);
3653 i++;
3654 }
3655 if (i < count)
3656 hdd_warn("Num Preferred BSSID %u less than expected %u",
3657 i, count);
3658
3659 roam_params->num_bssid_favored = i;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003660 mac_handle = hdd_ctx->mac_handle;
3661 sme_update_roam_params(mac_handle, session_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003662 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3663
3664 return 0;
3665
3666fail:
3667 return -EINVAL;
3668}
3669
3670/**
3671 * hdd_set_blacklist_bssid() - parse set blacklist bssid
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003672 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003673 * @roam_params: roam params
3674 * @tb: list of attributes
3675 * @session_id: session id
3676 *
3677 * Return: 0 on success; error number on failure
3678 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003679static int hdd_set_blacklist_bssid(struct hdd_context *hdd_ctx,
3680 struct roam_ext_params *roam_params,
3681 struct nlattr **tb,
3682 uint8_t session_id)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003683{
3684 int rem, i;
3685 uint32_t count;
3686 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3687 struct nlattr *curr_attr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003688 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003689
3690 /* Parse and fetch number of blacklist BSSID */
3691 if (!tb[PARAMS_NUM_BSSID]) {
3692 hdd_err("attr num of blacklist bssid failed");
3693 goto fail;
3694 }
3695 count = nla_get_u32(tb[PARAMS_NUM_BSSID]);
3696 if (count > MAX_BSSID_AVOID_LIST) {
3697 hdd_err("Blacklist BSSID count %u exceeds max %u",
3698 count, MAX_BSSID_AVOID_LIST);
3699 goto fail;
3700 }
3701 hdd_debug("Num of blacklist BSSID (%d)", count);
3702
3703 i = 0;
3704 if (count && tb[PARAM_BSSID_PARAMS]) {
3705 nla_for_each_nested(curr_attr,
3706 tb[PARAM_BSSID_PARAMS],
3707 rem) {
3708 if (i == count) {
3709 hdd_warn("Ignoring excess Blacklist BSSID");
3710 break;
3711 }
3712
Dustin Brown4ea21db2018-01-05 14:13:17 -08003713 if (wlan_cfg80211_nla_parse(tb2,
Dustin Brown3fb15042017-08-15 15:54:49 -07003714 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3715 nla_data(curr_attr),
3716 nla_len(curr_attr),
3717 wlan_hdd_set_roam_param_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08003718 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003719 goto fail;
3720 }
3721 /* Parse and fetch MAC address */
3722 if (!tb2[PARAM_SET_BSSID]) {
3723 hdd_err("attr blacklist addr failed");
3724 goto fail;
3725 }
3726 nla_memcpy(roam_params->bssid_avoid_list[i].bytes,
3727 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3728 hdd_debug(MAC_ADDRESS_STR,
3729 MAC_ADDR_ARRAY(roam_params->bssid_avoid_list[i].bytes));
3730 i++;
3731 }
3732 }
3733
3734 if (i < count)
3735 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3736 i, count);
3737
3738 roam_params->num_bssid_avoid_list = i;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003739 mac_handle = hdd_ctx->mac_handle;
3740 sme_update_roam_params(mac_handle, session_id,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003741 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3742
3743 return 0;
3744fail:
3745 return -EINVAL;
3746}
3747
3748/**
3749 * hdd_set_ext_roam_params() - parse ext roam params
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003750 * @hdd_ctx: HDD context
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003751 * @roam_params: roam params
3752 * @tb: list of attributes
3753 * @session_id: session id
3754 *
3755 * Return: 0 on success; error number on failure
3756 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003757static int hdd_set_ext_roam_params(struct hdd_context *hdd_ctx,
3758 const void *data, int data_len,
3759 uint8_t session_id,
3760 struct roam_ext_params *roam_params)
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003761{
3762 uint32_t cmd_type, req_id;
3763 struct nlattr *tb[MAX_ROAMING_PARAM + 1];
3764 int ret;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003765 mac_handle_t mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003766
Dustin Brown4ea21db2018-01-05 14:13:17 -08003767 if (wlan_cfg80211_nla_parse(tb, MAX_ROAMING_PARAM, data, data_len,
3768 wlan_hdd_set_roam_param_policy)) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003769 hdd_err("Invalid ATTR");
3770 return -EINVAL;
3771 }
3772 /* Parse and fetch Command Type */
3773 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
3774 hdd_err("roam cmd type failed");
3775 goto fail;
3776 }
3777
3778 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
3779 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
3780 hdd_err("attr request id failed");
3781 goto fail;
3782 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003783 mac_handle = hdd_ctx->mac_handle;
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003784 req_id = nla_get_u32(
3785 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
3786 hdd_debug("Req Id: %u Cmd Type: %u", req_id, cmd_type);
3787 switch (cmd_type) {
3788 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003789 ret = hdd_set_white_list(hdd_ctx, roam_params, tb, session_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003790 if (ret)
3791 goto fail;
3792 break;
3793
3794 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
3795 /* Parse and fetch 5G Boost Threshold */
3796 if (!tb[PARAM_A_BAND_BOOST_THLD]) {
3797 hdd_err("5G boost threshold failed");
3798 goto fail;
3799 }
3800 roam_params->raise_rssi_thresh_5g = nla_get_s32(
3801 tb[PARAM_A_BAND_BOOST_THLD]);
3802 hdd_debug("5G Boost Threshold (%d)",
3803 roam_params->raise_rssi_thresh_5g);
3804 /* Parse and fetch 5G Penalty Threshold */
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07003805 if (!tb[PARAM_A_BAND_PELT_THLD]) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003806 hdd_err("5G penalty threshold failed");
3807 goto fail;
3808 }
3809 roam_params->drop_rssi_thresh_5g = nla_get_s32(
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07003810 tb[PARAM_A_BAND_PELT_THLD]);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003811 hdd_debug("5G Penalty Threshold (%d)",
3812 roam_params->drop_rssi_thresh_5g);
3813 /* Parse and fetch 5G Boost Factor */
3814 if (!tb[PARAM_A_BAND_BOOST_FACTOR]) {
3815 hdd_err("5G boost Factor failed");
3816 goto fail;
3817 }
3818 roam_params->raise_factor_5g = nla_get_u32(
3819 tb[PARAM_A_BAND_BOOST_FACTOR]);
3820 hdd_debug("5G Boost Factor (%d)",
3821 roam_params->raise_factor_5g);
3822 /* Parse and fetch 5G Penalty factor */
3823 if (!tb[PARAM_A_BAND_PELT_FACTOR]) {
3824 hdd_err("5G Penalty Factor failed");
3825 goto fail;
3826 }
3827 roam_params->drop_factor_5g = nla_get_u32(
3828 tb[PARAM_A_BAND_PELT_FACTOR]);
3829 hdd_debug("5G Penalty factor (%d)",
3830 roam_params->drop_factor_5g);
3831 /* Parse and fetch 5G Max Boost */
3832 if (!tb[PARAM_A_BAND_MAX_BOOST]) {
3833 hdd_err("5G Max Boost failed");
3834 goto fail;
3835 }
3836 roam_params->max_raise_rssi_5g = nla_get_u32(
3837 tb[PARAM_A_BAND_MAX_BOOST]);
3838 hdd_debug("5G Max Boost (%d)",
3839 roam_params->max_raise_rssi_5g);
3840 /* Parse and fetch Rssi Diff */
3841 if (!tb[PARAM_ROAM_HISTERESYS]) {
3842 hdd_err("Rssi Diff failed");
3843 goto fail;
3844 }
3845 roam_params->rssi_diff = nla_get_s32(
3846 tb[PARAM_ROAM_HISTERESYS]);
3847 hdd_debug("RSSI Diff (%d)",
3848 roam_params->rssi_diff);
3849 /* Parse and fetch Alert Rssi Threshold */
3850 if (!tb[PARAM_RSSI_TRIGGER]) {
3851 hdd_err("Alert Rssi Threshold failed");
3852 goto fail;
3853 }
3854 roam_params->alert_rssi_threshold = nla_get_u32(
3855 tb[PARAM_RSSI_TRIGGER]);
3856 hdd_debug("Alert RSSI Threshold (%d)",
3857 roam_params->alert_rssi_threshold);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003858 sme_update_roam_params(mac_handle, session_id,
3859 roam_params,
3860 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003861 break;
3862 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
3863 /* Parse and fetch Activate Good Rssi Roam */
3864 if (!tb[PARAM_ROAM_ENABLE]) {
3865 hdd_err("Activate Good Rssi Roam failed");
3866 goto fail;
3867 }
3868 roam_params->good_rssi_roam = nla_get_s32(
3869 tb[PARAM_ROAM_ENABLE]);
3870 hdd_debug("Activate Good Rssi Roam (%d)",
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003871 roam_params->good_rssi_roam);
3872 sme_update_roam_params(mac_handle, session_id,
3873 roam_params,
3874 REASON_ROAM_GOOD_RSSI_CHANGED);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003875 break;
3876 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003877 ret = hdd_set_bssid_prefs(hdd_ctx, roam_params, tb, session_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003878 if (ret)
3879 goto fail;
3880 break;
3881 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
Jeff Johnson34fc63a2018-06-14 10:10:02 -07003882 ret = hdd_set_blacklist_bssid(hdd_ctx, roam_params,
3883 tb, session_id);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003884 if (ret)
3885 goto fail;
3886 break;
3887 }
3888
3889 return 0;
3890
3891fail:
3892 return -EINVAL;
3893}
3894
3895/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003896 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
3897 * @wiphy: The wiphy structure
3898 * @wdev: The wireless device
3899 * @data: Data passed by framework
3900 * @data_len: Parameters to be configured passed as data
3901 *
3902 * The roaming related parameters are configured by the framework
3903 * using this interface.
3904 *
3905 * Return: Return either success or failure code.
3906 */
3907static int
3908__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3909 struct wireless_dev *wdev, const void *data, int data_len)
3910{
3911 struct net_device *dev = wdev->netdev;
Jeff Johnsonce2ba702017-10-02 13:30:24 -07003912 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -07003913 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003914 struct roam_ext_params *roam_params = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915 int ret;
3916
Dustin Brownfdf17c12018-03-14 12:55:34 -07003917 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08003918
Anurag Chouhan6d760662016-02-20 16:05:43 +05303919 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003920 hdd_err("Command not allowed in FTM mode");
3921 return -EPERM;
3922 }
3923
Jeff Johnsonb8944722017-09-03 09:03:19 -07003924 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303925 if (ret)
3926 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003927
Jeff Johnsonb8944722017-09-03 09:03:19 -07003928 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05303929 hdd_err("Driver Modules are closed");
3930 return -EINVAL;
3931 }
3932
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003933 roam_params = qdf_mem_malloc(sizeof(*roam_params));
3934 if (!roam_params) {
3935 hdd_err("failed to allocate memory");
3936 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003937 }
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003938
Jeff Johnsonb8944722017-09-03 09:03:19 -07003939 ret = hdd_set_ext_roam_params(hdd_ctx, data, data_len,
Jeff Johnson1b780e42017-10-31 14:11:45 -07003940 adapter->session_id, roam_params);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003941 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003942 goto fail;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303943
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003944 if (roam_params)
3945 qdf_mem_free(roam_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003946 return 0;
3947fail:
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003948 if (roam_params)
3949 qdf_mem_free(roam_params);
3950
3951 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003952}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303953#undef PARAM_NUM_NW
3954#undef PARAM_SET_BSSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003955#undef PARAM_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303956#undef PARAM_LIST_SSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003957#undef MAX_ROAMING_PARAM
3958#undef PARAM_NUM_BSSID
3959#undef PARAM_BSSID_PREFS
3960#undef PARAM_ROAM_BSSID
3961#undef PARAM_RSSI_MODIFIER
3962#undef PARAMS_NUM_BSSID
3963#undef PARAM_BSSID_PARAMS
3964#undef PARAM_A_BAND_BOOST_THLD
3965#undef PARAM_A_BAND_PELT_THLD
3966#undef PARAM_A_BAND_BOOST_FACTOR
3967#undef PARAM_A_BAND_PELT_FACTOR
3968#undef PARAM_A_BAND_MAX_BOOST
3969#undef PARAM_ROAM_HISTERESYS
3970#undef PARAM_RSSI_TRIGGER
3971#undef PARAM_ROAM_ENABLE
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303972
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003973
3974/**
3975 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3976 * @wiphy: pointer to wireless wiphy structure.
3977 * @wdev: pointer to wireless_dev structure.
3978 * @data: Pointer to the data to be passed via vendor interface
3979 * @data_len:Length of the data to be passed
3980 *
3981 * Return: Return the Success or Failure code.
3982 */
3983static int
3984wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3985 struct wireless_dev *wdev,
3986 const void *data,
3987 int data_len)
3988{
3989 int ret;
3990
3991 cds_ssr_protect(__func__);
3992 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3993 data, data_len);
3994 cds_ssr_unprotect(__func__);
3995
3996 return ret;
3997}
3998
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05303999#define PWR_SAVE_FAIL_CMD_INDEX \
4000 QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX
Jeff Johnsonb7fa2562018-07-02 08:36:17 -07004001
4002void hdd_chip_pwr_save_fail_detected_cb(hdd_handle_t hdd_handle,
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304003 struct chip_pwr_save_fail_detected_params
4004 *data)
4005{
Jeff Johnsonb7fa2562018-07-02 08:36:17 -07004006 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304007 struct sk_buff *skb;
4008 int flags = cds_get_gfp_flags();
4009
Dustin Brown491d54b2018-03-14 12:39:11 -07004010 hdd_enter();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304011
4012 if (wlan_hdd_validate_context(hdd_ctx))
4013 return;
4014
4015 if (!data) {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07004016 hdd_debug("data is null");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304017 return;
4018 }
4019
4020 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4021 NULL, NLMSG_HDRLEN +
4022 sizeof(data->failure_reason_code) +
4023 NLMSG_HDRLEN, PWR_SAVE_FAIL_CMD_INDEX,
4024 flags);
4025
4026 if (!skb) {
Dustin Brown5e89ef82018-03-14 11:50:23 -07004027 hdd_info("cfg80211_vendor_event_alloc failed");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304028 return;
4029 }
4030
Dustin Brownbacc48f2018-03-14 14:48:44 -07004031 hdd_debug("failure reason code: %u", data->failure_reason_code);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304032
4033 if (nla_put_u32(skb,
4034 QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON,
4035 data->failure_reason_code))
4036 goto fail;
4037
4038 cfg80211_vendor_event(skb, flags);
Dustin Browne74003f2018-03-14 12:51:58 -07004039 hdd_exit();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304040 return;
4041
4042fail:
4043 kfree_skb(skb);
4044}
4045#undef PWR_SAVE_FAIL_CMD_INDEX
4046
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004047static const struct nla_policy
4048wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
4049 +1] = {
4050 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
4051};
4052
4053/**
4054 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
4055 * @hdd_ctx: HDD context
4056 * @device_mode: device mode
4057 * Return: bool
4058 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004059static bool wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context *hdd_ctx,
Jeff Johnsonc1e62782017-11-09 09:50:17 -08004060 enum QDF_OPMODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004061{
Jeff Johnsone5006672017-08-29 14:39:02 -07004062 struct hdd_adapter *adapter;
Jeff Johnson87251032017-08-29 13:31:11 -07004063 struct hdd_ap_ctx *ap_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004064 struct hdd_station_ctx *sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004065
Dustin Brown920397d2017-12-13 16:27:50 -08004066 hdd_for_each_adapter(hdd_ctx, adapter) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004067 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08004068 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004069 ap_ctx =
4070 WLAN_HDD_GET_AP_CTX_PTR(adapter);
4071
4072 /*
4073 * if there is SAP already running on DFS channel,
4074 * do not disable scan on dfs channels. Note that
4075 * with SAP on DFS, there cannot be conurrency on
4076 * single radio. But then we can have multiple
4077 * radios !!
4078 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07004079 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
Dustin Brown07901ec2018-09-07 11:02:41 -07004080 hdd_ctx->pdev,
Jeff Johnson01206862017-10-27 20:55:59 -07004081 ap_ctx->operating_channel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004082 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004083 return true;
4084 }
4085 }
4086
4087 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08004088 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004089 sta_ctx =
4090 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4091
4092 /*
4093 * if STA is already connected on DFS channel,
4094 * do not disable scan on dfs channels
4095 */
4096 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07004097 (CHANNEL_STATE_DFS ==
Dustin Brown07901ec2018-09-07 11:02:41 -07004098 wlan_reg_get_channel_state(hdd_ctx->pdev,
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07004099 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07004100 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004101 return true;
4102 }
4103 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004104 }
4105
4106 return false;
4107}
4108
4109/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004110 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004111 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004112 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004113 *
4114 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004115 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004116 * Fails the disable request if any device is active on a DFS channel.
4117 *
4118 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004119 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004120
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004121int wlan_hdd_enable_dfs_chan_scan(struct hdd_context *hdd_ctx,
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004122 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004123{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304124 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004125 bool err;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004126 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004127
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004128 if (enable_dfs_channels == hdd_ctx->config->enableDFSChnlScan) {
Dustin Brown6a8d39b2018-08-14 15:27:26 -07004129 hdd_debug("DFS channels are already %s",
4130 enable_dfs_channels ? "enabled" : "disabled");
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004131 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004132 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004133
4134 if (!enable_dfs_channels) {
4135 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
4136 QDF_STA_MODE);
4137 if (err)
4138 return -EOPNOTSUPP;
4139
4140 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
4141 QDF_SAP_MODE);
4142 if (err)
4143 return -EOPNOTSUPP;
4144 }
4145
4146 hdd_ctx->config->enableDFSChnlScan = enable_dfs_channels;
4147
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004148 mac_handle = hdd_ctx->mac_handle;
4149 status = sme_enable_dfs_chan_scan(mac_handle, enable_dfs_channels);
Min Liu5eaf7242018-03-13 17:32:15 +08004150 if (QDF_IS_STATUS_ERROR(status)) {
4151 hdd_err("Failed to set DFS channel scan flag to %d",
4152 enable_dfs_channels);
4153 return qdf_status_to_os_return(status);
4154 }
4155
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004156 hdd_abort_mac_scan_all_adapters(hdd_ctx);
4157
4158 /* pass dfs channel status to regulatory component */
Dustin Brown07901ec2018-09-07 11:02:41 -07004159 status = ucfg_reg_enable_dfs_channels(hdd_ctx->pdev,
4160 enable_dfs_channels);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004161
4162 if (QDF_IS_STATUS_ERROR(status))
4163 hdd_err("Failed to %s DFS channels",
4164 enable_dfs_channels ? "enable" : "disable");
4165
4166 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004167}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004168
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004169/**
4170 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
4171 * @wiphy: corestack handler
4172 * @wdev: wireless device
4173 * @data: data
4174 * @data_len: data length
4175 * Return: success(0) or reason code for failure
4176 */
4177static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
4178 struct wireless_dev *wdev,
4179 const void *data,
4180 int data_len)
4181{
4182 struct net_device *dev = wdev->netdev;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004183 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004184 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
4185 int ret_val;
4186 uint32_t no_dfs_flag = 0;
4187
Dustin Brownfdf17c12018-03-14 12:55:34 -07004188 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08004189
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004190 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304191 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004192 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004193
Dustin Brown4ea21db2018-01-05 14:13:17 -08004194 if (wlan_cfg80211_nla_parse(tb,
4195 QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
4196 data, data_len,
4197 wlan_hdd_set_no_dfs_flag_config_policy)) {
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004198 hdd_err("invalid attr");
4199 return -EINVAL;
4200 }
4201
4202 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
4203 hdd_err("attr dfs flag failed");
4204 return -EINVAL;
4205 }
4206
4207 no_dfs_flag = nla_get_u32(
4208 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
4209
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004210 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004211
4212 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07004213 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004214 return -EINVAL;
4215 }
4216
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004217 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004218 return ret_val;
4219}
4220
4221/**
4222 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
4223 *
4224 * @wiphy: wiphy device pointer
4225 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07004226 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004227 * @data_len: Buffer length
4228 *
4229 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
4230 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
4231 *
4232 * Return: EOK or other error codes.
4233 */
4234
4235static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
4236 struct wireless_dev *wdev,
4237 const void *data,
4238 int data_len)
4239{
4240 int ret;
4241
4242 cds_ssr_protect(__func__);
4243 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
4244 data, data_len);
4245 cds_ssr_unprotect(__func__);
4246
4247 return ret;
4248}
4249
Manikandan Mohan80dea792016-04-28 16:36:48 -07004250static const struct nla_policy
4251wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
4252 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
4253};
4254
4255/**
4256 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
4257 * @wiphy: wiphy device pointer
4258 * @wdev: wireless device pointer
4259 * @data: Vendor command data buffer
4260 * @data_len: Buffer length
4261 *
4262 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
4263 * setup WISA Mode features.
4264 *
4265 * Return: Success(0) or reason code for failure
4266 */
4267static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
4268 struct wireless_dev *wdev, const void *data, int data_len)
4269{
4270 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07004271 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004272 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004273 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
4274 struct sir_wisa_params wisa;
4275 int ret_val;
4276 QDF_STATUS status;
4277 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07004278 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
4279 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004280 mac_handle_t mac_handle;
Manikandan Mohan80dea792016-04-28 16:36:48 -07004281
Dustin Brownfdf17c12018-03-14 12:55:34 -07004282 hdd_enter_dev(dev);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004283 ret_val = wlan_hdd_validate_context(hdd_ctx);
4284 if (ret_val)
4285 goto err;
4286
4287 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4288 hdd_err("Command not allowed in FTM mode");
4289 return -EPERM;
4290 }
4291
Dustin Brown4ea21db2018-01-05 14:13:17 -08004292 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data,
4293 data_len, wlan_hdd_wisa_cmd_policy)) {
Manikandan Mohan80dea792016-04-28 16:36:48 -07004294 hdd_err("Invalid WISA cmd attributes");
4295 ret_val = -EINVAL;
4296 goto err;
4297 }
4298 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
4299 hdd_err("Invalid WISA mode");
4300 ret_val = -EINVAL;
4301 goto err;
4302 }
4303
4304 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004305 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004306 wisa.mode = wisa_mode;
Jeff Johnson1b780e42017-10-31 14:11:45 -07004307 wisa.vdev_id = adapter->session_id;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004308 mac_handle = hdd_ctx->mac_handle;
4309 status = sme_set_wisa_params(mac_handle, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07004310 if (!QDF_IS_STATUS_SUCCESS(status)) {
4311 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004312 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07004313 }
4314 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07004315 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08004316 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
4317 (struct cdp_pdev *)pdev,
Jeff Johnson1b780e42017-10-31 14:11:45 -07004318 adapter->session_id),
Leo Changfdb45c32016-10-28 11:09:23 -07004319 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004320err:
Dustin Browne74003f2018-03-14 12:51:58 -07004321 hdd_exit();
Manikandan Mohan80dea792016-04-28 16:36:48 -07004322 return ret_val;
4323}
4324
4325/**
4326 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
4327 * @wiphy: corestack handler
4328 * @wdev: wireless device
4329 * @data: data
4330 * @data_len: data length
4331 *
4332 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
4333 * setup WISA mode features.
4334 *
4335 * Return: Success(0) or reason code for failure
4336 */
4337static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
4338 struct wireless_dev *wdev,
4339 const void *data,
4340 int data_len)
4341{
4342 int ret;
4343
4344 cds_ssr_protect(__func__);
4345 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
4346 cds_ssr_unprotect(__func__);
4347
4348 return ret;
4349}
4350
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05304351struct hdd_station_info *hdd_get_stainfo(struct hdd_station_info *astainfo,
4352 struct qdf_mac_addr mac_addr)
Will Huang496b36c2017-07-11 16:38:50 +08004353{
Jeff Johnson82155922017-09-30 16:54:14 -07004354 struct hdd_station_info *stainfo = NULL;
Will Huang496b36c2017-07-11 16:38:50 +08004355 int i;
4356
4357 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05304358 if (!qdf_mem_cmp(&astainfo[i].sta_mac,
Will Huang496b36c2017-07-11 16:38:50 +08004359 &mac_addr,
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05304360 QDF_MAC_ADDR_SIZE)) {
4361 stainfo = &astainfo[i];
4362 break;
4363 }
Will Huang496b36c2017-07-11 16:38:50 +08004364 }
4365
4366 return stainfo;
4367}
4368
Anurag Chouhan96919482016-07-13 16:36:57 +05304369/*
4370 * undef short names defined for get station command
4371 * used by __wlan_hdd_cfg80211_get_station_cmd()
4372 */
4373#undef STATION_INVALID
4374#undef STATION_INFO
4375#undef STATION_ASSOC_FAIL_REASON
Will Huang496b36c2017-07-11 16:38:50 +08004376#undef STATION_REMOTE
Anurag Chouhan96919482016-07-13 16:36:57 +05304377#undef STATION_MAX
Will Huang496b36c2017-07-11 16:38:50 +08004378#undef LINK_INFO_STANDARD_NL80211_ATTR
4379#undef AP_INFO_STANDARD_NL80211_ATTR
4380#undef INFO_ROAM_COUNT
4381#undef INFO_AKM
4382#undef WLAN802_11_MODE
4383#undef AP_INFO_HS20_INDICATION
4384#undef HT_OPERATION
4385#undef VHT_OPERATION
4386#undef INFO_ASSOC_FAIL_REASON
4387#undef REMOTE_MAX_PHY_RATE
4388#undef REMOTE_TX_PACKETS
4389#undef REMOTE_TX_BYTES
4390#undef REMOTE_RX_PACKETS
4391#undef REMOTE_RX_BYTES
4392#undef REMOTE_LAST_TX_RATE
4393#undef REMOTE_LAST_RX_RATE
4394#undef REMOTE_WMM
4395#undef REMOTE_SUPPORTED_MODE
4396#undef REMOTE_AMPDU
4397#undef REMOTE_TX_STBC
4398#undef REMOTE_RX_STBC
4399#undef REMOTE_CH_WIDTH
4400#undef REMOTE_SGI_ENABLE
4401#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
4402#undef REMOTE_PAD
4403#endif
Anurag Chouhan96919482016-07-13 16:36:57 +05304404
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004405#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4406/**
4407 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4408 * @wiphy: pointer to wireless wiphy structure.
4409 * @wdev: pointer to wireless_dev structure.
4410 * @data: Pointer to the Key data
4411 * @data_len:Length of the data passed
4412 *
4413 * This is called when wlan driver needs to save the keys received via
4414 * vendor specific command.
4415 *
4416 * Return: Return the Success or Failure code.
4417 */
4418static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4419 struct wireless_dev *wdev,
4420 const void *data, int data_len)
4421{
4422 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4423 struct net_device *dev = wdev->netdev;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004424 struct hdd_adapter *hdd_adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4425 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004426 int status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08004427 struct pmkid_mode_bits pmkid_modes;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004428 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004429
Dustin Brownfdf17c12018-03-14 12:55:34 -07004430 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08004431
Anurag Chouhan6d760662016-02-20 16:05:43 +05304432 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004433 hdd_err("Command not allowed in FTM mode");
4434 return -EPERM;
4435 }
4436
Hanumanth Reddy Pothula53874852018-03-08 19:57:49 +05304437 if ((data == NULL) || (data_len <= 0) ||
4438 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004439 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004440 return -EINVAL;
4441 }
4442
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004443 hdd_ctx = WLAN_HDD_GET_CTX(hdd_adapter);
4444 if (!hdd_ctx) {
Jeff Johnson020db452016-06-29 14:37:26 -07004445 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004446 return -EINVAL;
4447 }
4448
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004449 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304450 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004451 return status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08004452
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004453 hdd_get_pmkid_modes(hdd_ctx, &pmkid_modes);
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08004454
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004455 mac_handle = hdd_ctx->mac_handle;
4456 sme_update_roam_key_mgmt_offload_enabled(mac_handle,
4457 hdd_adapter->session_id,
4458 true, &pmkid_modes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304459 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4460 qdf_mem_copy(local_pmk, data, data_len);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004461 sme_roam_set_psk_pmk(mac_handle, hdd_adapter->session_id,
4462 local_pmk, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463 return 0;
4464}
4465
4466/**
4467 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4468 * @wiphy: pointer to wireless wiphy structure.
4469 * @wdev: pointer to wireless_dev structure.
4470 * @data: Pointer to the Key data
4471 * @data_len:Length of the data passed
4472 *
4473 * This is called when wlan driver needs to save the keys received via
4474 * vendor specific command.
4475 *
4476 * Return: Return the Success or Failure code.
4477 */
4478static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4479 struct wireless_dev *wdev,
4480 const void *data, int data_len)
4481{
4482 int ret;
4483
4484 cds_ssr_protect(__func__);
4485 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4486 cds_ssr_unprotect(__func__);
4487
4488 return ret;
4489}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004490#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491
4492static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4493 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4494 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4495 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004496 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004497};
4498
4499/**
4500 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4501 * @wiphy: pointer to wireless wiphy structure.
4502 * @wdev: pointer to wireless_dev structure.
4503 * @data: Pointer to the data to be passed via vendor interface
4504 * @data_len:Length of the data to be passed
4505 *
4506 * This is called when wlan driver needs to send wifi driver related info
4507 * (driver/fw version) to the user space application upon request.
4508 *
4509 * Return: Return the Success or Failure code.
4510 */
4511static int
4512__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4513 struct wireless_dev *wdev,
4514 const void *data, int data_len)
4515{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004516 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004517 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004518 tSirVersionString driver_version;
4519 tSirVersionString firmware_version;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004520 const char *hw_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004522 uint32_t sub_id = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004523 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004524 struct sk_buff *reply_skb;
4525 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004526
Dustin Brownfdf17c12018-03-14 12:55:34 -07004527 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08004528
Anurag Chouhan6d760662016-02-20 16:05:43 +05304529 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004530 hdd_err("Command not allowed in FTM mode");
4531 return -EPERM;
4532 }
4533
4534 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304535 if (status)
4536 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004537
Dustin Brown4ea21db2018-01-05 14:13:17 -08004538 if (wlan_cfg80211_nla_parse(tb_vendor,
4539 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
4540 data, data_len,
4541 qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004542 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004543 return -EINVAL;
4544 }
4545
4546 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004547 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004548 strlcpy(driver_version, QWLAN_VERSIONSTR,
4549 sizeof(driver_version));
4550 skb_len += strlen(driver_version) + 1;
4551 count++;
4552 }
4553
4554 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004555 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004556 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4557 &crmid);
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004558 sub_id = (hdd_ctx->target_fw_vers_ext & 0xf0000000) >> 28;
4559 hw_version = hdd_ctx->target_hw_name;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004560 snprintf(firmware_version, sizeof(firmware_version),
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004561 "FW:%d.%d.%d.%d.%d HW:%s", major_spid, minor_spid,
4562 siid, crmid, sub_id, hw_version);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004563 skb_len += strlen(firmware_version) + 1;
4564 count++;
4565 }
4566
Rajeev Kumar Sirasanagandla551613d2018-05-16 17:21:01 +05304567 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4568 hdd_debug("Rcvd req for Radio index");
4569 skb_len += sizeof(uint32_t);
4570 count++;
4571 }
4572
Ryan Hsu7ac88852016-04-28 10:20:34 -07004573 if (count == 0) {
4574 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004575 return -EINVAL;
4576 }
4577
Ryan Hsu7ac88852016-04-28 10:20:34 -07004578 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4579 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004582 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004583 return -ENOMEM;
4584 }
4585
Ryan Hsu7ac88852016-04-28 10:20:34 -07004586 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4587 if (nla_put_string(reply_skb,
4588 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4589 driver_version))
4590 goto error_nla_fail;
4591 }
4592
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304593 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004594 if (nla_put_string(reply_skb,
4595 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4596 firmware_version))
4597 goto error_nla_fail;
4598 }
4599
4600 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4601 if (nla_put_u32(reply_skb,
4602 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4603 hdd_ctx->radio_index))
4604 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004605 }
4606
4607 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004608
4609error_nla_fail:
4610 hdd_err("nla put fail");
4611 kfree_skb(reply_skb);
4612 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004613}
4614
4615/**
4616 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4617 * @wiphy: pointer to wireless wiphy structure.
4618 * @wdev: pointer to wireless_dev structure.
4619 * @data: Pointer to the data to be passed via vendor interface
4620 * @data_len:Length of the data to be passed
4621 *
4622 * This is called when wlan driver needs to send wifi driver related info
4623 * (driver/fw version) to the user space application upon request.
4624 *
4625 * Return: Return the Success or Failure code.
4626 */
4627static int
4628wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4629 struct wireless_dev *wdev,
4630 const void *data, int data_len)
4631{
4632 int ret;
4633
4634 cds_ssr_protect(__func__);
4635 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4636 cds_ssr_unprotect(__func__);
4637
4638 return ret;
4639}
4640
4641/**
4642 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4643 * @wiphy: pointer to wireless wiphy structure.
4644 * @wdev: pointer to wireless_dev structure.
4645 * @data: Pointer to the data to be passed via vendor interface
4646 * @data_len:Length of the data to be passed
4647 *
4648 * This is called by userspace to know the supported logger features
4649 *
4650 * Return: Return the Success or Failure code.
4651 */
4652static int
4653__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4654 struct wireless_dev *wdev,
4655 const void *data, int data_len)
4656{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004657 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004658 int status;
4659 uint32_t features;
4660 struct sk_buff *reply_skb = NULL;
4661
Dustin Brownfdf17c12018-03-14 12:55:34 -07004662 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08004663
Anurag Chouhan6d760662016-02-20 16:05:43 +05304664 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665 hdd_err("Command not allowed in FTM mode");
4666 return -EPERM;
4667 }
4668
4669 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304670 if (status)
4671 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004672
4673 features = 0;
4674
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004675 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4676 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4677 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
Srinivas Girigowdaa26eac02018-01-23 12:49:20 -08004678 features |= WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
Dundi Ravitejab189b742018-05-08 15:59:57 +05304679 features |= WIFI_LOGGER_PACKET_FATE_SUPPORTED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680
4681 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4682 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4683 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004684 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004685 return -ENOMEM;
4686 }
4687
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004688 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4690 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004691 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004692 kfree_skb(reply_skb);
4693 return -EINVAL;
4694 }
4695
4696 return cfg80211_vendor_cmd_reply(reply_skb);
4697}
4698
4699/**
4700 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4701 * @wiphy: pointer to wireless wiphy structure.
4702 * @wdev: pointer to wireless_dev structure.
4703 * @data: Pointer to the data to be passed via vendor interface
4704 * @data_len:Length of the data to be passed
4705 *
4706 * This is called by userspace to know the supported logger features
4707 *
4708 * Return: Return the Success or Failure code.
4709 */
4710static int
4711wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4712 struct wireless_dev *wdev,
4713 const void *data, int data_len)
4714{
4715 int ret;
4716
4717 cds_ssr_protect(__func__);
4718 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4719 data, data_len);
4720 cds_ssr_unprotect(__func__);
4721
4722 return ret;
4723}
4724
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304725#ifdef WLAN_FEATURE_GTK_OFFLOAD
4726void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
4727 uint8_t *kck_ptr, uint8_t *kek_ptr,
4728 uint32_t kek_len, uint8_t *replay_ctr,
4729 bool big_endian)
4730{
4731 struct hdd_station_ctx *hdd_sta_ctx;
4732 uint8_t *buf;
4733 int i;
4734 struct pmo_gtk_req *gtk_req = NULL;
4735 QDF_STATUS status = QDF_STATUS_E_FAILURE;
4736
4737 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
4738 if (!gtk_req) {
4739 hdd_err("cannot allocate gtk_req");
4740 return;
4741 }
4742
4743 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4744 if (kck_ptr)
4745 qdf_mem_copy(gtk_req->kck, kck_ptr, NL80211_KCK_LEN);
4746
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08004747 if (kek_ptr) {
4748 /* paranoia */
4749 if (kek_len > sizeof(gtk_req->kek)) {
4750 kek_len = sizeof(gtk_req->kek);
4751 QDF_ASSERT(0);
4752 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304753 qdf_mem_copy(gtk_req->kek, kek_ptr, kek_len);
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08004754 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304755
4756 qdf_copy_macaddr(&gtk_req->bssid, &hdd_sta_ctx->conn_info.bssId);
4757
4758 gtk_req->kek_len = kek_len;
gaurank kathpalia82a1b2b2018-07-10 16:49:10 +05304759 gtk_req->is_fils_connection = hdd_is_fils_connection(adapter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304760
4761 /* convert big to little endian since driver work on little endian */
4762 buf = (uint8_t *)&gtk_req->replay_counter;
4763 for (i = 0; i < 8; i++)
4764 buf[7 - i] = replay_ctr[i];
4765
Dustin Brown89fa06e2018-09-07 10:47:27 -07004766 status = pmo_ucfg_cache_gtk_offload_req(adapter->vdev, gtk_req);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304767 if (status != QDF_STATUS_SUCCESS)
4768 hdd_err("Failed to cache GTK Offload");
4769
4770 qdf_mem_free(gtk_req);
4771}
4772#else
4773void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
4774 uint8_t *kck_ptr,
4775 uint8_t *kek_ptr,
4776 uint32_t kek_len,
4777 uint8_t *replay_ctr,
4778 bool big_endian)
4779{
4780}
4781#endif
4782
Sridhar Selvaraje5260442017-08-19 10:12:03 +05304783#if defined(WLAN_FEATURE_FILS_SK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304784/**
4785 * wlan_hdd_add_fils_params_roam_auth_event() - Adds FILS params in roam auth
4786 * @skb: SK buffer
4787 * @roam_info: Roam info
4788 *
4789 * API adds fils params[pmk, pmkid, next sequence number] to roam auth event
4790 *
4791 * Return: zero on success, error code on failure
4792 */
Jeff Johnson172237b2017-11-07 15:32:59 -08004793static int
4794wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
4795 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304796{
4797 if (roam_info->pmk_len &&
4798 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK,
4799 roam_info->pmk_len, roam_info->pmk)) {
4800 hdd_err("pmk send fail");
4801 return -EINVAL;
4802 }
4803
4804 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID,
4805 SIR_PMKID_LEN, roam_info->pmkid)) {
4806 hdd_err("pmkid send fail");
4807 return -EINVAL;
4808 }
4809
Vignesh Viswanathan8da68cf2017-09-07 14:00:04 +05304810 hdd_debug("Update ERP Seq Num %d, Next ERP Seq Num %d",
4811 roam_info->update_erp_next_seq_num,
4812 roam_info->next_erp_seq_num);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304813 if (roam_info->update_erp_next_seq_num &&
4814 nla_put_u16(skb,
4815 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM,
4816 roam_info->next_erp_seq_num)) {
4817 hdd_err("ERP seq num send fail");
4818 return -EINVAL;
4819 }
4820
4821 return 0;
4822}
4823#else
Jeff Johnson172237b2017-11-07 15:32:59 -08004824static inline int
4825wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
4826 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304827{
4828 return 0;
4829}
4830#endif
4831
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004832#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004833/**
4834 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304835 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004836 * @bssid: pointer to bssid of roamed AP.
4837 * @req_rsn_ie: Pointer to request RSN IE
4838 * @req_rsn_len: Length of the request RSN IE
4839 * @rsp_rsn_ie: Pointer to response RSN IE
4840 * @rsp_rsn_len: Length of the response RSN IE
4841 * @roam_info_ptr: Pointer to the roaming related information
4842 *
4843 * This is called when wlan driver needs to send the roaming and
4844 * authorization information after roaming.
4845 *
4846 * The information that would be sent is the request RSN IE, response
4847 * RSN IE and BSSID of the newly roamed AP.
4848 *
4849 * If the Authorized status is authenticated, then additional parameters
4850 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4851 * supplicant.
4852 *
4853 * The supplicant upon receiving this event would ignore the legacy
4854 * cfg80211_roamed call and use the entire information from this event.
4855 * The cfg80211_roamed should still co-exist since the kernel will
4856 * make use of the parameters even if the supplicant ignores it.
4857 *
4858 * Return: Return the Success or Failure code.
4859 */
Jeff Johnsone5006672017-08-29 14:39:02 -07004860int wlan_hdd_send_roam_auth_event(struct hdd_adapter *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004861 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
Jeff Johnson172237b2017-11-07 15:32:59 -08004862 uint32_t rsp_rsn_len, struct csr_roam_info *roam_info_ptr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004863{
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004864 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004865 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004866 eCsrAuthType auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304867 uint32_t fils_params_len;
4868 int status;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -07004869
Dustin Brown491d54b2018-03-14 12:39:11 -07004870 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004871
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004872 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004874
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004875 if (!roaming_offload_enabled(hdd_ctx) ||
4876 !roam_info_ptr->roamSynchInProgress)
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004877 return 0;
4878
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304879 /*
4880 * PMK is sent from FW in Roam Synch Event for FILS Roaming.
4881 * In that case, add three more NL attributes.ie. PMK, PMKID
4882 * and ERP next sequence number. Add corresponding lengths
4883 * with 3 extra NL message headers for each of the
4884 * aforementioned params.
4885 */
4886 fils_params_len = roam_info_ptr->pmk_len + SIR_PMKID_LEN +
4887 sizeof(uint16_t) + (3 * NLMSG_HDRLEN);
4888
Jeff Johnson34fc63a2018-06-14 10:10:02 -07004889 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304890 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004891 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4892 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304893 SIR_KCK_KEY_LEN + roam_info_ptr->kek_len +
4894 sizeof(uint8_t) + (8 * NLMSG_HDRLEN) +
4895 fils_params_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004896 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4897 GFP_KERNEL);
4898
4899 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004900 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004901 return -EINVAL;
4902 }
4903
4904 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4905 ETH_ALEN, bssid) ||
4906 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4907 req_rsn_len, req_rsn_ie) ||
4908 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4909 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004910 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004911 goto nla_put_failure;
4912 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004913 if (roam_info_ptr->synchAuthStatus ==
4914 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004915 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004916 if (nla_put_u8(skb,
4917 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4918 hdd_err("nla put fail");
4919 goto nla_put_failure;
4920 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004921 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4922 /* if FT or CCKM connection: dont send replay counter */
4923 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4924 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4925 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4926 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4927 nla_put(skb,
4928 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4929 SIR_REPLAY_CTR_LEN,
4930 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004931 hdd_err("non FT/non CCKM connection");
4932 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004933 goto nla_put_failure;
4934 }
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05304935 if (roam_info_ptr->kek_len > SIR_KEK_KEY_LEN_FILS ||
4936 nla_put(skb,
Naveen Rawat14298b92015-11-25 16:27:41 -08004937 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4938 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4939 nla_put(skb,
4940 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304941 roam_info_ptr->kek_len, roam_info_ptr->kek)) {
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05304942 hdd_err("nla put fail, kek_len %d",
4943 roam_info_ptr->kek_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004944 goto nla_put_failure;
4945 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05304946
4947 status = wlan_hdd_add_fils_params_roam_auth_event(skb,
4948 roam_info_ptr);
4949 if (status)
4950 goto nla_put_failure;
4951
4952 /*
4953 * Save the gtk rekey parameters in HDD STA context. They will
4954 * be used next time when host enables GTK offload and goes
4955 * into power save state.
4956 */
4957 wlan_hdd_save_gtk_offload_params(adapter, roam_info_ptr->kck,
4958 roam_info_ptr->kek,
4959 roam_info_ptr->kek_len,
4960 roam_info_ptr->replay_ctr,
4961 true);
4962 hdd_debug("roam_info_ptr->replay_ctr 0x%llx",
4963 *((uint64_t *)roam_info_ptr->replay_ctr));
4964
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004965 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004966 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004967 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4968 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004969 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004970 goto nla_put_failure;
4971 }
4972 }
4973
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304974 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4975 roam_info_ptr->synchAuthStatus,
4976 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004977
4978 /*
4979 * Add subnet change status if subnet has changed
4980 * 0 = unchanged
4981 * 1 = changed
4982 * 2 = unknown
4983 */
4984 if (roam_info_ptr->subnet_change_status) {
4985 if (nla_put_u8(skb,
4986 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4987 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004988 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004989 goto nla_put_failure;
4990 }
4991 }
4992
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004993 cfg80211_vendor_event(skb, GFP_KERNEL);
4994 return 0;
4995
4996nla_put_failure:
4997 kfree_skb(skb);
4998 return -EINVAL;
4999}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08005000#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005001
lifeng907edd62017-05-12 10:10:36 +08005002#define ANT_DIV_PROBE_PERIOD \
5003 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD
5004#define ANT_DIV_STAY_PERIOD \
5005 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD
5006#define ANT_DIV_SNR_DIFF \
5007 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF
5008#define ANT_DIV_PROBE_DWELL_TIME \
5009 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME
5010#define ANT_DIV_MGMT_SNR_WEIGHT \
5011 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT
5012#define ANT_DIV_DATA_SNR_WEIGHT \
5013 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT
5014#define ANT_DIV_ACK_SNR_WEIGHT \
5015 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT
lifeng66831662017-05-19 16:01:35 +08005016#define RX_REORDER_TIMEOUT_VOICE \
5017 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE
5018#define RX_REORDER_TIMEOUT_VIDEO \
5019 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO
5020#define RX_REORDER_TIMEOUT_BESTEFFORT \
5021 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT
5022#define RX_REORDER_TIMEOUT_BACKGROUND \
5023 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND
5024#define RX_BLOCKSIZE_PEER_MAC \
5025 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC
5026#define RX_BLOCKSIZE_WINLIMIT \
5027 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005028static const struct nla_policy
5029wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
5030
5031 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
5032 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
5033 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Jeff Johnson79f6a602017-06-15 09:48:25 -07005034 [QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT] = {.type = NLA_U32},
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05305035 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05305036 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
5037 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005038 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
5039 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
5040 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
5041 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
5042 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05305043 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
lifeng907edd62017-05-12 10:10:36 +08005044 [ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
5045 [ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
5046 [ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
5047 [ANT_DIV_PROBE_DWELL_TIME] = {.type = NLA_U32},
5048 [ANT_DIV_MGMT_SNR_WEIGHT] = {.type = NLA_U32},
5049 [ANT_DIV_DATA_SNR_WEIGHT] = {.type = NLA_U32},
5050 [ANT_DIV_ACK_SNR_WEIGHT] = {.type = NLA_U32},
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305051 [QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL] = {.type = NLA_U8},
lifeng66831662017-05-19 16:01:35 +08005052 [RX_REORDER_TIMEOUT_VOICE] = {.type = NLA_U32},
5053 [RX_REORDER_TIMEOUT_VIDEO] = {.type = NLA_U32},
5054 [RX_REORDER_TIMEOUT_BESTEFFORT] = {.type = NLA_U32},
5055 [RX_REORDER_TIMEOUT_BACKGROUND] = {.type = NLA_U32},
Jeff Johnson19a5a7e2017-06-15 14:51:26 -07005056 [RX_BLOCKSIZE_PEER_MAC] = {
5057 .type = NLA_UNSPEC,
5058 .len = QDF_MAC_ADDR_SIZE},
lifeng66831662017-05-19 16:01:35 +08005059 [RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32},
Mukul Sharma6398b252017-05-01 17:58:12 +05305060 [QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL] = {.type = NLA_U32 },
Poddar, Siddarth4b3f7312017-11-02 17:00:20 +05305061 [QCA_WLAN_VENDOR_ATTR_CONFIG_LRO] = {.type = NLA_U8 },
lifengd217d192017-05-09 19:44:16 +08005062 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA] = {.type = NLA_U32 },
5063 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN] = {.type = NLA_U32 },
5064 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST] = {.type = NLA_U32 },
5065 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL] = {.type = NLA_U32 },
Paul Zhang99fe8842017-12-08 14:43:46 +08005066 [QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL] = {.type = NLA_U16 },
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05305067 [QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT] = {.type = NLA_U8},
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07005068 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE] = {.type = NLA_U8 },
Abhishek Singh6454ad32017-12-20 10:42:21 +05305069 [QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] = {.type = NLA_U8},
Ashish Kumar Dhanotiya1e20bcc2018-06-15 11:28:51 +05305070 [QCA_WLAN_VENDOR_ATTR_CONFIG_GTX] = {.type = NLA_U8},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005071};
5072
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08005073static const struct nla_policy
5074wlan_hdd_wifi_test_config_policy[
5075 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1] = {
5076 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE] = {
5077 .type = NLA_U8},
5078 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ] = {
5079 .type = NLA_U8},
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08005080 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS] = {
5081 .type = NLA_U8},
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08005082 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ] = {
5083 .type = NLA_U8},
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08005084 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION] = {
5085 .type = NLA_U8},
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08005086 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE] = {
5087 .type = NLA_U8},
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08005088 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION] = {
5089 .type = NLA_U8},
5090 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID] = {
5091 .type = NLA_U8},
5092 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE] = {
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07005093 .type = NLA_U16},
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08005094 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK] = {
5095 .type = NLA_U8},
5096 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC] = {
5097 .type = NLA_U8},
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08005098 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF] = {
5099 .type = NLA_U8},
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07005100 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE] = {
5101 .type = NLA_U8},
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07005102 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS] = {
5103 .type = NLA_U8},
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07005104 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR] = {
5105 .type = NLA_U8},
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07005106 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AC] = {
5107 .type = NLA_U8},
5108 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA] = {
5109 .type = NLA_U8},
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07005110 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP] = {
5111 .type = NLA_U8},
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08005112};
5113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005114/**
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305115 * wlan_hdd_add_qcn_ie() - Add QCN IE to a given IE buffer
5116 * @ie_data: IE buffer
5117 * @ie_len: length of the @ie_data
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305118 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305119 * Return: QDF_STATUS
5120 */
5121static QDF_STATUS wlan_hdd_add_qcn_ie(uint8_t *ie_data, uint16_t *ie_len)
5122{
5123 tDot11fIEQCN_IE qcn_ie;
5124 uint8_t qcn_ie_hdr[QCN_IE_HDR_LEN]
5125 = {IE_EID_VENDOR, DOT11F_IE_QCN_IE_MAX_LEN,
5126 0x8C, 0xFD, 0xF0, 0x1};
5127
5128 if (((*ie_len) + QCN_IE_HDR_LEN +
5129 QCN_IE_VERSION_SUBATTR_DATA_LEN) > MAX_DEFAULT_SCAN_IE_LEN) {
5130 hdd_err("IE buffer not enough for QCN IE");
5131 return QDF_STATUS_E_FAILURE;
5132 }
5133
5134 /* Add QCN IE header */
5135 qdf_mem_copy(ie_data + (*ie_len), qcn_ie_hdr, QCN_IE_HDR_LEN);
5136 (*ie_len) += QCN_IE_HDR_LEN;
5137
5138 /* Retrieve Version sub-attribute data */
5139 populate_dot11f_qcn_ie(&qcn_ie);
5140
5141 /* Add QCN IE data[version sub attribute] */
5142 qdf_mem_copy(ie_data + (*ie_len), qcn_ie.version,
5143 (QCN_IE_VERSION_SUBATTR_LEN));
5144 (*ie_len) += (QCN_IE_VERSION_SUBATTR_LEN);
5145
5146 return QDF_STATUS_SUCCESS;
5147}
5148
5149/**
5150 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
5151 * @hdd_ctx: HDD context
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305152 * @adapter: Pointer to HDD adapter
5153 * @ie_data: Pointer to Scan IEs buffer
5154 * @ie_len: Length of Scan IEs
5155 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305156 * This API is used to store the default scan ies received from
5157 * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
5158 *
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305159 * Return: 0 on success; error number otherwise
5160 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005161static int wlan_hdd_save_default_scan_ies(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07005162 struct hdd_adapter *adapter,
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305163 uint8_t *ie_data, uint16_t ie_len)
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305164{
Jeff Johnson37588942017-08-15 16:11:41 -07005165 struct hdd_scan_info *scan_info = &adapter->scan_info;
Wu Gao93816212018-08-31 16:49:54 +08005166 bool add_qcn_ie;
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305167
5168 if (!scan_info)
5169 return -EINVAL;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305170
5171 if (scan_info->default_scan_ies) {
5172 qdf_mem_free(scan_info->default_scan_ies);
5173 scan_info->default_scan_ies = NULL;
5174 }
5175
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05305176 scan_info->default_scan_ies_len = ie_len;
Wu Gao93816212018-08-31 16:49:54 +08005177 ucfg_mlme_get_qcn_ie_support(hdd_ctx->hdd_psoc, &add_qcn_ie);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305178 if (add_qcn_ie)
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05305179 ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305180
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305181 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05305182 if (!scan_info->default_scan_ies) {
5183 scan_info->default_scan_ies_len = 0;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305184 return -ENOMEM;
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05305185 }
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305186
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05305187 qdf_mem_copy(scan_info->default_scan_ies, ie_data,
5188 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305189
5190 /* Add QCN IE if g_qcn_ie_support INI is enabled */
5191 if (add_qcn_ie)
5192 wlan_hdd_add_qcn_ie(scan_info->default_scan_ies,
5193 &(scan_info->default_scan_ies_len));
5194
5195 hdd_debug("Saved default scan IE:");
5196 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
5197 (uint8_t *) scan_info->default_scan_ies,
5198 scan_info->default_scan_ies_len);
5199
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305200 return 0;
5201}
5202
5203/**
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305204 * wlan_hdd_handle_restrict_offchan_config() -
5205 * Handle wifi configuration attribute :
5206 * QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL
5207 * @adapter: Pointer to HDD adapter
5208 * @restrict_offchan: Restrict offchannel setting done by
5209 * application
5210 *
5211 * Return: 0 on success; error number otherwise
5212 */
Jeff Johnsone5006672017-08-29 14:39:02 -07005213static int wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter *adapter,
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305214 u8 restrict_offchan)
5215{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005216 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonc1e62782017-11-09 09:50:17 -08005217 enum QDF_OPMODE dev_mode = adapter->device_mode;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305218 int ret_val = 0;
Liangwei Dongcf5a5062017-12-28 00:51:32 -05005219 QDF_STATUS status;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305220
5221 if (!(dev_mode == QDF_SAP_MODE || dev_mode == QDF_P2P_GO_MODE)) {
5222 hdd_err("Invalid interface type:%d", dev_mode);
5223 return -EINVAL;
5224 }
Dustin Brown89fa06e2018-09-07 10:47:27 -07005225 status = wlan_objmgr_vdev_try_get_ref(adapter->vdev, WLAN_OSIF_ID);
Liangwei Dongcf5a5062017-12-28 00:51:32 -05005226 if (status != QDF_STATUS_SUCCESS) {
5227 hdd_err("Access hdd_vdev failed: %d", status);
5228 return -EINVAL;
5229 }
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305230 if (restrict_offchan == 1) {
5231 enum policy_mgr_con_mode pmode =
5232 policy_mgr_convert_device_mode_to_qdf_type(dev_mode);
5233 int chan;
5234
Dustin Brown89fa06e2018-09-07 10:47:27 -07005235 u32 vdev_id = wlan_vdev_get_id(adapter->vdev);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305236
Dustin Brown89fa06e2018-09-07 10:47:27 -07005237 wlan_vdev_obj_lock(adapter->vdev);
5238 wlan_vdev_mlme_cap_set(adapter->vdev,
Liangwei Dongcf5a5062017-12-28 00:51:32 -05005239 WLAN_VDEV_C_RESTRICT_OFFCHAN);
Dustin Brown89fa06e2018-09-07 10:47:27 -07005240 wlan_vdev_obj_unlock(adapter->vdev);
Liangwei Dongcf5a5062017-12-28 00:51:32 -05005241 chan = policy_mgr_get_channel(hdd_ctx->hdd_psoc, pmode,
5242 &vdev_id);
5243 if (!chan ||
5244 wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, chan)) {
5245 hdd_err("unable to send avoid_freq");
5246 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305247 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05005248 hdd_info("vdev %d mode %d dnbs enabled", vdev_id, dev_mode);
5249 } else if (restrict_offchan == 0) {
Dustin Brown89fa06e2018-09-07 10:47:27 -07005250 wlan_vdev_obj_lock(adapter->vdev);
5251 wlan_vdev_mlme_cap_clear(adapter->vdev,
Liangwei Dongcf5a5062017-12-28 00:51:32 -05005252 WLAN_VDEV_C_RESTRICT_OFFCHAN);
Dustin Brown89fa06e2018-09-07 10:47:27 -07005253 wlan_vdev_obj_unlock(adapter->vdev);
Liangwei Dongcf5a5062017-12-28 00:51:32 -05005254 if (wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0)) {
5255 hdd_err("unable to clear avoid_freq");
5256 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305257 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05005258 hdd_info("vdev mode %d dnbs disabled", dev_mode);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305259 } else {
5260 ret_val = -EINVAL;
5261 hdd_err("Invalid RESTRICT_OFFCHAN setting");
5262 }
Dustin Brown89fa06e2018-09-07 10:47:27 -07005263 wlan_objmgr_vdev_release_ref(adapter->vdev, WLAN_OSIF_ID);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305264 return ret_val;
5265}
5266
5267/**
lifeng66831662017-05-19 16:01:35 +08005268 * wlan_hdd_cfg80211_wifi_set_reorder_timeout - set reorder timeout
lifeng66831662017-05-19 16:01:35 +08005269 * @hdd_ctx: hdd context
5270 * @tb: array of pointer to struct nlattr
5271 *
5272 * Return: 0 on success; error number otherwise
5273 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005274static
5275int wlan_hdd_cfg80211_wifi_set_reorder_timeout(struct hdd_context *hdd_ctx,
5276 struct nlattr *tb[])
lifeng66831662017-05-19 16:01:35 +08005277{
Min Liuab6ed4f2018-01-09 13:13:57 +08005278 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08005279 QDF_STATUS qdf_status;
5280 struct sir_set_rx_reorder_timeout_val reorder_timeout;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005281 mac_handle_t mac_handle;
lifeng66831662017-05-19 16:01:35 +08005282
5283#define RX_TIMEOUT_VAL_MIN 10
5284#define RX_TIMEOUT_VAL_MAX 1000
5285
5286 if (tb[RX_REORDER_TIMEOUT_VOICE] ||
5287 tb[RX_REORDER_TIMEOUT_VIDEO] ||
5288 tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
5289 tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
5290
5291 /* if one is specified, all must be specified */
5292 if (!tb[RX_REORDER_TIMEOUT_VOICE] ||
5293 !tb[RX_REORDER_TIMEOUT_VIDEO] ||
5294 !tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
5295 !tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
5296 hdd_err("four AC timeout val are required MAC");
5297 return -EINVAL;
5298 }
5299
5300 reorder_timeout.rx_timeout_pri[0] = nla_get_u32(
5301 tb[RX_REORDER_TIMEOUT_VOICE]);
5302 reorder_timeout.rx_timeout_pri[1] = nla_get_u32(
5303 tb[RX_REORDER_TIMEOUT_VIDEO]);
5304 reorder_timeout.rx_timeout_pri[2] = nla_get_u32(
5305 tb[RX_REORDER_TIMEOUT_BESTEFFORT]);
5306 reorder_timeout.rx_timeout_pri[3] = nla_get_u32(
5307 tb[RX_REORDER_TIMEOUT_BACKGROUND]);
5308 /* timeout value is required to be in the rang 10 to 1000ms */
5309 if (reorder_timeout.rx_timeout_pri[0] >= RX_TIMEOUT_VAL_MIN &&
5310 reorder_timeout.rx_timeout_pri[0] <= RX_TIMEOUT_VAL_MAX &&
5311 reorder_timeout.rx_timeout_pri[1] >= RX_TIMEOUT_VAL_MIN &&
5312 reorder_timeout.rx_timeout_pri[1] <= RX_TIMEOUT_VAL_MAX &&
5313 reorder_timeout.rx_timeout_pri[2] >= RX_TIMEOUT_VAL_MIN &&
5314 reorder_timeout.rx_timeout_pri[2] <= RX_TIMEOUT_VAL_MAX &&
5315 reorder_timeout.rx_timeout_pri[3] >= RX_TIMEOUT_VAL_MIN &&
5316 reorder_timeout.rx_timeout_pri[3] <= RX_TIMEOUT_VAL_MAX) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005317 mac_handle = hdd_ctx->mac_handle;
5318 qdf_status = sme_set_reorder_timeout(mac_handle,
lifeng66831662017-05-19 16:01:35 +08005319 &reorder_timeout);
5320 if (qdf_status != QDF_STATUS_SUCCESS) {
5321 hdd_err("failed to set reorder timeout err %d",
5322 qdf_status);
5323 ret_val = -EPERM;
5324 }
5325 } else {
5326 hdd_err("one of the timeout value is not in range");
5327 ret_val = -EINVAL;
5328 }
5329 }
5330
5331 return ret_val;
5332}
5333
5334/**
5335 * wlan_hdd_cfg80211_wifi_set_rx_blocksize - set rx blocksize
5336 *
5337 * @hdd_ctx: hdd context
5338 * @adapter: hdd adapter
5339 * @tb: array of pointer to struct nlattr
5340 *
5341 * Return: 0 on success; error number otherwise
5342 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005343static int wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07005344 struct hdd_adapter *adapter,
lifeng66831662017-05-19 16:01:35 +08005345 struct nlattr *tb[])
5346{
Min Liuab6ed4f2018-01-09 13:13:57 +08005347 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08005348 uint32_t set_value;
5349 QDF_STATUS qdf_status;
5350 struct sir_peer_set_rx_blocksize rx_blocksize;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005351 mac_handle_t mac_handle;
lifeng66831662017-05-19 16:01:35 +08005352
5353#define WINDOW_SIZE_VAL_MIN 1
5354#define WINDOW_SIZE_VAL_MAX 64
5355
5356 if (tb[RX_BLOCKSIZE_PEER_MAC] ||
5357 tb[RX_BLOCKSIZE_WINLIMIT]) {
5358
5359 /* if one is specified, both must be specified */
5360 if (!tb[RX_BLOCKSIZE_PEER_MAC] ||
5361 !tb[RX_BLOCKSIZE_WINLIMIT]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07005362 hdd_err("Both Peer MAC and windows limit required");
lifeng66831662017-05-19 16:01:35 +08005363 return -EINVAL;
5364 }
5365
5366 memcpy(&rx_blocksize.peer_macaddr,
5367 nla_data(tb[RX_BLOCKSIZE_PEER_MAC]),
5368 sizeof(rx_blocksize.peer_macaddr)),
5369
Jeff Johnson1b780e42017-10-31 14:11:45 -07005370 rx_blocksize.vdev_id = adapter->session_id;
lifeng66831662017-05-19 16:01:35 +08005371 set_value = nla_get_u32(tb[RX_BLOCKSIZE_WINLIMIT]);
5372 /* maximum window size is 64 */
5373 if (set_value >= WINDOW_SIZE_VAL_MIN &&
5374 set_value <= WINDOW_SIZE_VAL_MAX) {
5375 rx_blocksize.rx_block_ack_win_limit = set_value;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005376 mac_handle = hdd_ctx->mac_handle;
5377 qdf_status = sme_set_rx_set_blocksize(mac_handle,
lifeng66831662017-05-19 16:01:35 +08005378 &rx_blocksize);
5379 if (qdf_status != QDF_STATUS_SUCCESS) {
5380 hdd_err("failed to set aggr sizes err %d",
5381 qdf_status);
5382 ret_val = -EPERM;
5383 }
5384 } else {
5385 hdd_err("window size val is not in range");
5386 ret_val = -EINVAL;
5387 }
5388 }
5389
5390 return ret_val;
5391}
5392
Jeff Johnson3b2abe92017-12-15 09:03:47 -08005393static int hdd_config_scan_default_ies(struct hdd_adapter *adapter,
5394 const struct nlattr *attr)
5395{
5396 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5397 uint8_t *scan_ie;
5398 uint16_t scan_ie_len;
5399 QDF_STATUS status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005400 mac_handle_t mac_handle;
Jeff Johnson3b2abe92017-12-15 09:03:47 -08005401
5402 if (!attr)
5403 return 0;
5404
5405 scan_ie_len = nla_len(attr);
5406 hdd_debug("IE len %d session %d device mode %d",
5407 scan_ie_len, adapter->session_id, adapter->device_mode);
5408
5409 if (!scan_ie_len) {
5410 hdd_err("zero-length IE prohibited");
5411 return -EINVAL;
5412 }
5413
5414 if (scan_ie_len > MAX_DEFAULT_SCAN_IE_LEN) {
5415 hdd_err("IE length %d exceeds max of %d",
5416 scan_ie_len, MAX_DEFAULT_SCAN_IE_LEN);
5417 return -EINVAL;
5418 }
5419
5420 scan_ie = nla_data(attr);
Jeff Johnson4933c3a2018-01-10 19:33:33 -08005421 if (!wlan_is_ie_valid(scan_ie, scan_ie_len)) {
Jeff Johnson3b2abe92017-12-15 09:03:47 -08005422 hdd_err("Invalid default scan IEs");
5423 return -EINVAL;
5424 }
5425
5426 if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
5427 scan_ie, scan_ie_len))
5428 hdd_err("Failed to save default scan IEs");
5429
5430 if (adapter->device_mode == QDF_STA_MODE) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005431 mac_handle = hdd_ctx->mac_handle;
5432 status = sme_set_default_scan_ie(mac_handle,
Jeff Johnson3b2abe92017-12-15 09:03:47 -08005433 adapter->session_id, scan_ie,
5434 scan_ie_len);
5435 if (QDF_STATUS_SUCCESS != status) {
5436 hdd_err("failed to set default scan IEs in sme: %d",
5437 status);
5438 return -EPERM;
5439 }
5440 }
5441
5442 return 0;
5443}
5444
lifeng66831662017-05-19 16:01:35 +08005445/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
5447 * vendor command
5448 *
5449 * @wiphy: wiphy device pointer
5450 * @wdev: wireless device pointer
5451 * @data: Vendor command data buffer
5452 * @data_len: Buffer length
5453 *
5454 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
5455 *
5456 * Return: Error code.
5457 */
5458static int
5459__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
5460 struct wireless_dev *wdev,
5461 const void *data,
5462 int data_len)
5463{
5464 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07005465 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005466 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005467 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
Jeff Johnson3b2abe92017-12-15 09:03:47 -08005468 const struct nlattr *attr;
5469 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005470 int ret_val = 0;
Mukul Sharma6398b252017-05-01 17:58:12 +05305471 u32 modulated_dtim, override_li;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005472 u16 stats_avg_factor;
5473 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05305474 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07005475 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07005476 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305477 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305478 int attr_len;
5479 int access_policy = 0;
5480 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
5481 bool vendor_ie_present = false, access_policy_present = false;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05305482 struct sir_set_tx_rx_aggregation_size request;
5483 QDF_STATUS qdf_status;
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07005484 uint8_t retry, delay, enable_flag;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08005485 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005486 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05305487 uint32_t tx_fail_count;
lifeng907edd62017-05-12 10:10:36 +08005488 uint32_t ant_div_usrcfg;
lifengd217d192017-05-09 19:44:16 +08005489 uint32_t antdiv_enable, antdiv_chain;
5490 uint32_t antdiv_selftest, antdiv_selftest_intvl;
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05305491 uint8_t bmiss_bcnt;
Paul Zhang99fe8842017-12-08 14:43:46 +08005492 uint16_t latency_level;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005493 mac_handle_t mac_handle;
Wu Gao93816212018-08-31 16:49:54 +08005494 bool b_value;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05305495
Dustin Brownfdf17c12018-03-14 12:55:34 -07005496 hdd_enter_dev(dev);
Arif Hussain0e246802018-05-01 18:13:44 -07005497 qdf_mem_zero(&request, sizeof(request));
Jeff Johnson1f61b612016-02-12 16:28:33 -08005498
Anurag Chouhan6d760662016-02-20 16:05:43 +05305499 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005500 hdd_err("Command not allowed in FTM mode");
5501 return -EPERM;
5502 }
5503
5504 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305505 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005506 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005507
Dustin Brown4ea21db2018-01-05 14:13:17 -08005508 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
5509 data_len, wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005510 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005511 return -EINVAL;
5512 }
5513
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005514 mac_handle = hdd_ctx->mac_handle;
5515
Krunal Sonie3531942016-04-12 17:43:53 -07005516 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
5517 ftm_capab = nla_get_u32(tb[
5518 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
5519 hdd_ctx->config->fine_time_meas_cap =
5520 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005521 sme_update_fine_time_measurement_capab(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -07005522 adapter->session_id,
Krunal Sonie3531942016-04-12 17:43:53 -07005523 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawatd2657be2017-10-10 14:31:23 -07005524 ucfg_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
Naveen Rawat5f040ba2017-03-06 12:20:25 -08005525 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005526 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07005527 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
5528 hdd_ctx->config->fine_time_meas_cap);
5529 }
5530
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005531 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
5532 modulated_dtim = nla_get_u32(
5533 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
5534
Dustin Brown89fa06e2018-09-07 10:47:27 -07005535 status = pmo_ucfg_config_modulated_dtim(adapter->vdev,
Nachiket Kukade4b7c8e02018-06-01 22:53:06 +05305536 modulated_dtim);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305537 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005538 ret_val = -EPERM;
5539 }
5540
Mukul Sharma6398b252017-05-01 17:58:12 +05305541 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL]) {
5542 override_li = nla_get_u32(
5543 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL]);
5544
Nachiket Kukade54e7be72018-06-27 17:10:17 +05305545 if (override_li > CFG_ENABLE_DYNAMIC_DTIM_MAX) {
5546 hdd_err_rl("Invalid value for listen interval - %d",
5547 override_li);
5548 return -EINVAL;
5549 }
5550
Dustin Brown89fa06e2018-09-07 10:47:27 -07005551 status = pmo_ucfg_config_listen_interval(adapter->vdev,
Nachiket Kukade4b7c8e02018-06-01 22:53:06 +05305552 override_li);
Mukul Sharma6398b252017-05-01 17:58:12 +05305553 if (status != QDF_STATUS_SUCCESS)
5554 ret_val = -EPERM;
5555 }
Poddar, Siddarth4b3f7312017-11-02 17:00:20 +05305556
5557 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LRO]) {
5558 enable_flag = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LRO]);
5559 ret_val = hdd_lro_set_reset(hdd_ctx, adapter,
5560 enable_flag);
5561 }
5562
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07005563 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE]) {
5564 enable_flag =
5565 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE]);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005566 sme_set_scan_disable(mac_handle, !enable_flag);
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07005567 }
Mukul Sharma6398b252017-05-01 17:58:12 +05305568
Kapil Gupta6213c012016-09-02 19:39:09 +05305569 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
5570 qpower = nla_get_u8(
5571 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
5572 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
5573 ret_val = -EINVAL;
5574 }
5575
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005576 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
5577 stats_avg_factor = nla_get_u16(
5578 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005579 status = sme_configure_stats_avg_factor(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -07005580 adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005581 stats_avg_factor);
5582
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305583 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005584 ret_val = -EPERM;
5585 }
5586
5587
5588 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
5589 guard_time = nla_get_u32(
5590 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005591 status = sme_configure_guard_time(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -07005592 adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005593 guard_time);
5594
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305595 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005596 ret_val = -EPERM;
5597 }
5598
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305599 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
5600 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
5601 attr_len = nla_len(
5602 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
5603 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005604 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305605 attr_len);
5606 return -EINVAL;
5607 }
5608
5609 nla_memcpy(&vendor_ie,
5610 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
5611 attr_len);
5612 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005613 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305614 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305615 }
5616
5617 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
5618 access_policy = (int) nla_get_u32(
5619 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
5620 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
5621 (access_policy >
5622 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005623 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305624 access_policy);
5625 return -EINVAL;
5626 }
5627 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005628 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305629 access_policy);
5630 }
5631
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005632 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
5633 retry = nla_get_u8(tb[
5634 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
5635 retry = retry > CFG_NON_AGG_RETRY_MAX ?
5636 CFG_NON_AGG_RETRY_MAX : retry;
5637 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
Jeff Johnson1b780e42017-10-31 14:11:45 -07005638 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005639 retry, PDEV_CMD);
5640 }
5641
5642 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
5643 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
5644 retry = retry > CFG_AGG_RETRY_MAX ?
5645 CFG_AGG_RETRY_MAX : retry;
5646
5647 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
5648 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
5649 CFG_AGG_RETRY_MIN : retry;
5650 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
Jeff Johnson1b780e42017-10-31 14:11:45 -07005651 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005652 retry, PDEV_CMD);
5653 }
5654
5655 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
5656 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
5657 retry = retry > CFG_MGMT_RETRY_MAX ?
5658 CFG_MGMT_RETRY_MAX : retry;
5659 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
Jeff Johnson1b780e42017-10-31 14:11:45 -07005660 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005661 retry, PDEV_CMD);
5662 }
5663
5664 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
5665 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
5666 retry = retry > CFG_CTRL_RETRY_MAX ?
5667 CFG_CTRL_RETRY_MAX : retry;
5668 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
Jeff Johnson1b780e42017-10-31 14:11:45 -07005669 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005670 retry, PDEV_CMD);
5671 }
5672
5673 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
5674 delay = nla_get_u8(tb[
5675 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
5676 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
5677 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08005678 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005679 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
Jeff Johnson1b780e42017-10-31 14:11:45 -07005680 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08005681 abs_delay, PDEV_CMD);
5682 }
5683
5684 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
5685 abs_delay = nla_get_u8(tb[
5686 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
5687 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
Jeff Johnson1b780e42017-10-31 14:11:45 -07005688 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08005689 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005690 }
5691
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05305692 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
5693 tx_fail_count = nla_get_u32(
5694 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
5695 if (tx_fail_count) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005696 status = sme_update_tx_fail_cnt_threshold(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -07005697 adapter->session_id, tx_fail_count);
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05305698 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005699 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05305700 status);
5701 return -EINVAL;
5702 }
5703 }
5704 }
5705
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305706 if (vendor_ie_present && access_policy_present) {
5707 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
5708 access_policy =
5709 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305710 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305711 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305712 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305713
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005714 hdd_debug("calling sme_update_access_policy_vendor_ie");
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005715 status = sme_update_access_policy_vendor_ie(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -07005716 adapter->session_id, &vendor_ie[0],
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305717 access_policy);
5718 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005719 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305720 return -EINVAL;
5721 }
5722 }
5723
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05305724 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
5725 set_value = nla_get_u8(
5726 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005727 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05305728 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
5729 }
5730
Jeff Johnson3b2abe92017-12-15 09:03:47 -08005731 attr = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES];
5732 ret = hdd_config_scan_default_ies(adapter, attr);
5733 if (ret)
5734 ret_val = ret;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05305735
5736 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
5737 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
5738 /* if one is specified, both must be specified */
5739 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
5740 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
5741 hdd_err("Both TX and RX MPDU Aggregation required");
5742 return -EINVAL;
5743 }
5744
5745 request.tx_aggregation_size = nla_get_u8(
5746 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
5747 request.rx_aggregation_size = nla_get_u8(
5748 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
Jeff Johnson1b780e42017-10-31 14:11:45 -07005749 request.vdev_id = adapter->session_id;
Arif Hussain0e246802018-05-01 18:13:44 -07005750 request.aggr_type = WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05305751
5752 if (request.tx_aggregation_size >=
5753 CFG_TX_AGGREGATION_SIZE_MIN &&
5754 request.tx_aggregation_size <=
5755 CFG_TX_AGGREGATION_SIZE_MAX &&
5756 request.rx_aggregation_size >=
5757 CFG_RX_AGGREGATION_SIZE_MIN &&
5758 request.rx_aggregation_size <=
5759 CFG_RX_AGGREGATION_SIZE_MAX) {
5760 qdf_status = wma_set_tx_rx_aggregation_size(&request);
5761 if (qdf_status != QDF_STATUS_SUCCESS) {
5762 hdd_err("failed to set aggr sizes err %d",
5763 qdf_status);
5764 ret_val = -EPERM;
5765 }
5766 } else {
5767 hdd_err("TX %d RX %d MPDU aggr size not in range",
5768 request.tx_aggregation_size,
5769 request.rx_aggregation_size);
5770 ret_val = -EINVAL;
5771 }
5772 }
5773
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305774 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
5775 uint8_t ignore_assoc_disallowed;
5776
5777 ignore_assoc_disallowed
5778 = nla_get_u8(tb[
5779 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005780 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305781 ignore_assoc_disallowed);
5782 if ((ignore_assoc_disallowed <
5783 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
5784 (ignore_assoc_disallowed >
5785 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
5786 return -EPERM;
5787
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005788 sme_update_session_param(mac_handle,
5789 adapter->session_id,
5790 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
5791 ignore_assoc_disallowed);
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305792 }
5793
lifeng907edd62017-05-12 10:10:36 +08005794#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
5795 ((1<<26)|((probe_period&0x1fff)<<13)|(stay_period&0x1fff))
5796
5797#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
5798 ((1<<27)|(snr_diff&0x1fff))
5799
5800#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
5801 ((1<<28)|(probe_dwell_time&0x1fff))
5802
5803#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
5804 ((1<<29)|((mgmt_snr_weight&0xff)<<16)|((data_snr_weight&0xff)<<8)| \
5805 (ack_snr_weight&0xff))
5806
5807 if (tb[ANT_DIV_PROBE_PERIOD] ||
5808 tb[ANT_DIV_STAY_PERIOD]) {
5809
5810 if (!tb[ANT_DIV_PROBE_PERIOD] ||
5811 !tb[ANT_DIV_STAY_PERIOD]) {
5812 hdd_err("Both probe and stay period required");
5813 return -EINVAL;
5814 }
5815
5816 ant_div_usrcfg = ANT_DIV_SET_PERIOD(
5817 nla_get_u32(tb[ANT_DIV_PROBE_PERIOD]),
5818 nla_get_u32(tb[ANT_DIV_STAY_PERIOD]));
5819 hdd_debug("ant div set period: %x", ant_div_usrcfg);
Jeff Johnson1b780e42017-10-31 14:11:45 -07005820 ret_val = wma_cli_set_command((int)adapter->session_id,
lifeng907edd62017-05-12 10:10:36 +08005821 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5822 ant_div_usrcfg, PDEV_CMD);
5823 if (ret_val) {
5824 hdd_err("Failed to set ant div period");
5825 return ret_val;
5826 }
5827 }
5828
5829 if (tb[ANT_DIV_SNR_DIFF]) {
5830 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(
5831 nla_get_u32(tb[ANT_DIV_SNR_DIFF]));
5832 hdd_debug("ant div set snr diff: %x", ant_div_usrcfg);
Jeff Johnson1b780e42017-10-31 14:11:45 -07005833 ret_val = wma_cli_set_command((int)adapter->session_id,
lifeng907edd62017-05-12 10:10:36 +08005834 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5835 ant_div_usrcfg, PDEV_CMD);
5836 if (ret_val) {
5837 hdd_err("Failed to set ant snr diff");
5838 return ret_val;
5839 }
5840 }
5841
5842 if (tb[ANT_DIV_PROBE_DWELL_TIME]) {
5843 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(
5844 nla_get_u32(tb[ANT_DIV_PROBE_DWELL_TIME]));
5845 hdd_debug("ant div set probe dewll time: %x",
5846 ant_div_usrcfg);
Jeff Johnson1b780e42017-10-31 14:11:45 -07005847 ret_val = wma_cli_set_command((int)adapter->session_id,
lifeng907edd62017-05-12 10:10:36 +08005848 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5849 ant_div_usrcfg, PDEV_CMD);
5850 if (ret_val) {
5851 hdd_err("Failed to set ant div probe dewll time");
5852 return ret_val;
5853 }
5854 }
5855
5856 if (tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5857 tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5858 tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5859
5860 if (!tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5861 !tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5862 !tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5863 hdd_err("Mgmt snr, data snr and ack snr weight are required");
5864 return -EINVAL;
5865 }
5866
5867 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(
5868 nla_get_u32(tb[ANT_DIV_MGMT_SNR_WEIGHT]),
5869 nla_get_u32(tb[ANT_DIV_DATA_SNR_WEIGHT]),
5870 nla_get_u32(tb[ANT_DIV_ACK_SNR_WEIGHT]));
5871 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
Jeff Johnson1b780e42017-10-31 14:11:45 -07005872 ret_val = wma_cli_set_command((int)adapter->session_id,
lifeng907edd62017-05-12 10:10:36 +08005873 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5874 ant_div_usrcfg, PDEV_CMD);
5875 if (ret_val) {
5876 hdd_err("Failed to set ant div weight");
5877 return ret_val;
5878 }
5879 }
5880
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305881 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL]) {
5882 u8 restrict_offchan = nla_get_u8(
5883 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL]);
5884
5885 hdd_debug("Restrict offchannel:%d", restrict_offchan);
5886 if (restrict_offchan <= 1)
5887 ret_val =
5888 wlan_hdd_handle_restrict_offchan_config(adapter,
5889 restrict_offchan);
5890 else {
5891 ret_val = -EINVAL;
5892 hdd_err("Invalid RESTRICT_OFFCHAN setting");
5893 }
5894 }
lifeng66831662017-05-19 16:01:35 +08005895
5896 ret_val =
5897 wlan_hdd_cfg80211_wifi_set_reorder_timeout(hdd_ctx, tb);
5898 if (ret_val != 0)
5899 return ret_val;
5900
5901 ret_val =
5902 wlan_hdd_cfg80211_wifi_set_rx_blocksize(hdd_ctx, adapter, tb);
5903 if (ret_val != 0)
5904 return ret_val;
5905
lifengd217d192017-05-09 19:44:16 +08005906 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA]) {
5907 antdiv_enable = nla_get_u32(
5908 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA]);
5909 hdd_debug("antdiv_enable: %d", antdiv_enable);
Jeff Johnson1b780e42017-10-31 14:11:45 -07005910 ret_val = wma_cli_set_command((int)adapter->session_id,
lifengd217d192017-05-09 19:44:16 +08005911 (int)WMI_PDEV_PARAM_ENA_ANT_DIV,
5912 antdiv_enable, PDEV_CMD);
5913 if (ret_val) {
5914 hdd_err("Failed to set antdiv_enable");
5915 return ret_val;
5916 }
5917 }
5918
5919 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN]) {
5920 antdiv_chain = nla_get_u32(
5921 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN]);
5922 hdd_debug("antdiv_chain: %d", antdiv_chain);
Jeff Johnson1b780e42017-10-31 14:11:45 -07005923 ret_val = wma_cli_set_command((int)adapter->session_id,
lifengd217d192017-05-09 19:44:16 +08005924 (int)WMI_PDEV_PARAM_FORCE_CHAIN_ANT,
5925 antdiv_chain, PDEV_CMD);
5926 if (ret_val) {
5927 hdd_err("Failed to set antdiv_chain");
5928 return ret_val;
5929 }
5930 }
5931
5932 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST]) {
5933 antdiv_selftest = nla_get_u32(
5934 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST]);
5935 hdd_debug("antdiv_selftest: %d", antdiv_selftest);
Jeff Johnson1b780e42017-10-31 14:11:45 -07005936 ret_val = wma_cli_set_command((int)adapter->session_id,
lifengd217d192017-05-09 19:44:16 +08005937 (int)WMI_PDEV_PARAM_ANT_DIV_SELFTEST,
5938 antdiv_selftest, PDEV_CMD);
5939 if (ret_val) {
5940 hdd_err("Failed to set antdiv_selftest");
5941 return ret_val;
5942 }
5943 }
5944
5945 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL]) {
5946 antdiv_selftest_intvl = nla_get_u32(
5947 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL]);
5948 hdd_debug("antdiv_selftest_intvl: %d",
5949 antdiv_selftest_intvl);
Jeff Johnson1b780e42017-10-31 14:11:45 -07005950 ret_val = wma_cli_set_command((int)adapter->session_id,
lifengd217d192017-05-09 19:44:16 +08005951 (int)WMI_PDEV_PARAM_ANT_DIV_SELFTEST_INTVL,
5952 antdiv_selftest_intvl, PDEV_CMD);
5953 if (ret_val) {
5954 hdd_err("Failed to set antdiv_selftest_intvl");
5955 return ret_val;
5956 }
5957 }
5958
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05305959 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT]) {
5960 bmiss_bcnt = nla_get_u8(
5961 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT]);
5962 if (hdd_ctx->config->nRoamBmissFirstBcnt < bmiss_bcnt) {
5963 hdd_ctx->config->nRoamBmissFinalBcnt = bmiss_bcnt
5964 - hdd_ctx->config->nRoamBmissFirstBcnt;
5965 hdd_debug("Bmiss first cnt(%d), Bmiss final cnt(%d)",
5966 hdd_ctx->config->nRoamBmissFirstBcnt,
5967 hdd_ctx->config->nRoamBmissFinalBcnt);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07005968 ret_val = sme_set_roam_bmiss_final_bcnt(mac_handle,
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05305969 0, hdd_ctx->config->nRoamBmissFinalBcnt);
5970
5971 if (ret_val) {
5972 hdd_err("Failed to set bmiss final Bcnt");
5973 return ret_val;
5974 }
5975
Jeff Johnson1b780e42017-10-31 14:11:45 -07005976 ret_val = sme_set_bmiss_bcnt(adapter->session_id,
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05305977 hdd_ctx->config->nRoamBmissFirstBcnt,
5978 hdd_ctx->config->nRoamBmissFinalBcnt);
5979 if (ret_val) {
5980 hdd_err("Failed to set bmiss Bcnt");
5981 return ret_val;
5982 }
5983 } else {
5984 hdd_err("Bcnt(%d) needs to exceed BmissFirstBcnt(%d)",
5985 bmiss_bcnt,
5986 hdd_ctx->config->nRoamBmissFirstBcnt);
5987 return -EINVAL;
5988 }
5989 }
Paul Zhang99fe8842017-12-08 14:43:46 +08005990
5991 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL]) {
5992 latency_level = nla_get_u16(
5993 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL]);
5994
5995 if ((latency_level >
5996 QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MAX) ||
5997 (latency_level ==
5998 QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_INVALID)) {
5999 hdd_err("Invalid Wlan latency level value");
6000 return -EINVAL;
6001 }
6002
6003 /* Mapping the latency value to the level which fw expected
6004 * 0 - normal, 1 - moderate, 2 - low, 3 - ultralow
6005 */
6006 latency_level = latency_level - 1;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006007 qdf_status = sme_set_wlm_latency_level(mac_handle,
Paul Zhang99fe8842017-12-08 14:43:46 +08006008 adapter->session_id,
6009 latency_level);
6010 if (qdf_status != QDF_STATUS_SUCCESS) {
6011 hdd_err("set Wlan latency level failed");
6012 ret_val = -EINVAL;
6013 }
6014 }
6015
Vignesh Viswanathan32761e42017-09-25 17:10:54 +05306016 if (adapter->device_mode == QDF_STA_MODE &&
6017 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS]) {
6018 uint8_t disable_fils;
6019
6020 disable_fils = nla_get_u8(tb[
6021 QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS]);
6022 hdd_debug("Set disable_fils - %d", disable_fils);
6023
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006024 qdf_status = sme_update_fils_setting(mac_handle,
Vignesh Viswanathan32761e42017-09-25 17:10:54 +05306025 adapter->session_id,
6026 disable_fils);
6027 if (qdf_status != QDF_STATUS_SUCCESS) {
6028 hdd_err("set disable_fils failed");
6029 ret_val = -EINVAL;
6030 }
6031 }
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05306032
Wu Gao93816212018-08-31 16:49:54 +08006033 ucfg_mlme_get_force_rsne_override(hdd_ctx->hdd_psoc, &b_value);
6034 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] && b_value) {
Abhishek Singh6454ad32017-12-20 10:42:21 +05306035 uint8_t force_rsne_override;
6036
6037 force_rsne_override =
6038 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE]);
6039 if (force_rsne_override > 1) {
6040 hdd_err("Invalid test_mode %d", force_rsne_override);
6041 ret_val = -EINVAL;
6042 }
6043
6044 hdd_ctx->force_rsne_override = force_rsne_override;
6045 hdd_debug("force_rsne_override - %d",
6046 hdd_ctx->force_rsne_override);
6047 }
6048
Ashish Kumar Dhanotiya1e20bcc2018-06-15 11:28:51 +05306049 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GTX]) {
6050 uint8_t config_gtx;
6051
6052 config_gtx = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GTX]);
6053 if (config_gtx > 1) {
6054 hdd_err_rl("Invalid config_gtx value %d", config_gtx);
6055 return -EINVAL;
6056 }
6057 ret_val = sme_cli_set_command(adapter->session_id,
6058 WMI_VDEV_PARAM_GTX_ENABLE,
6059 config_gtx, VDEV_CMD);
6060 if (ret_val)
6061 hdd_err("Failed to set GTX");
6062 }
6063
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006064 return ret_val;
6065}
6066
6067/**
6068 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
6069 * vendor command
6070 *
6071 * @wiphy: wiphy device pointer
6072 * @wdev: wireless device pointer
6073 * @data: Vendor command data buffer
6074 * @data_len: Buffer length
6075 *
6076 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
6077 *
6078 * Return: EOK or other error codes.
6079 */
6080static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
6081 struct wireless_dev *wdev,
6082 const void *data,
6083 int data_len)
6084{
6085 int ret;
6086
6087 cds_ssr_protect(__func__);
6088 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
6089 data, data_len);
6090 cds_ssr_unprotect(__func__);
6091
6092 return ret;
6093}
6094
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006095/**
6096 * __wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
6097 * vendor command
6098 *
6099 * @wiphy: wiphy device pointer
6100 * @wdev: wireless device pointer
6101 * @data: Vendor command data buffer
6102 * @data_len: Buffer length
6103 *
6104 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
6105 *
6106 * Return: Error code.
6107 */
6108static int
6109__wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
Srinivas Girigowdaa19eafd2018-09-07 15:28:21 -07006110 struct wireless_dev *wdev, const void *data, int data_len)
6111{
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006112 struct net_device *dev = wdev->netdev;
6113 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6114 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
6115 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1];
6116 int ret_val = 0;
6117 uint8_t cfg_val = 0;
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08006118 uint8_t set_val = 0;
Krunal Soni707eb782018-01-18 12:04:19 -08006119 tSmeConfigParams *sme_config;
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006120 bool update_sme_cfg = false;
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08006121 uint8_t tid = 0, ac;
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006122 uint16_t buff_size = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006123 mac_handle_t mac_handle;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006124
Dustin Brownfdf17c12018-03-14 12:55:34 -07006125 hdd_enter_dev(dev);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006126
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006127 sme_config = qdf_mem_malloc(sizeof(*sme_config));
6128 if (!sme_config) {
6129 hdd_err("mem alloc failed for sme_config");
6130 return -ENOMEM;
6131 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006132 mac_handle = hdd_ctx->mac_handle;
6133 sme_get_config_param(mac_handle, sme_config);
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006134
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006135 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6136 hdd_err("Command not allowed in FTM mode");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006137 ret_val = -EPERM;
6138 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006139 }
6140
6141 ret_val = wlan_hdd_validate_context(hdd_ctx);
6142 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006143 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006144
6145 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
6146 hdd_err("Driver Modules are closed, can not start logger");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006147 ret_val = -EINVAL;
6148 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006149 }
6150
6151 if (wlan_cfg80211_nla_parse(tb,
6152 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX,
6153 data, data_len, wlan_hdd_wifi_test_config_policy)) {
6154 hdd_err("invalid attr");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006155 ret_val = -EINVAL;
6156 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006157 }
6158
6159 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]) {
6160 cfg_val = nla_get_u8(tb[
6161 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]
6162 );
6163 hdd_debug("set addba accept req from peer value %d", cfg_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006164 ret_val = sme_set_addba_accept(mac_handle, adapter->session_id,
6165 cfg_val);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006166 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006167 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006168 }
6169
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08006170 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]) {
6171 cfg_val = nla_get_u8(tb[
6172 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]);
6173 hdd_debug("set HE MCS value 0x%0X", cfg_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006174 ret_val = sme_update_he_mcs(mac_handle, adapter->session_id,
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08006175 cfg_val);
6176 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006177 goto send_err;
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08006178 }
6179
Krunal Soni707eb782018-01-18 12:04:19 -08006180 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]) {
6181 cfg_val = nla_get_u8(tb[
6182 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]);
Krunal Soni707eb782018-01-18 12:04:19 -08006183 if (!cfg_val) {
6184 sme_config->csrConfig.WMMSupportMode =
6185 hdd_to_csr_wmm_mode(HDD_WMM_USER_MODE_NO_QOS);
6186 hdd_debug("wmm is disabled");
6187 } else {
6188 sme_config->csrConfig.WMMSupportMode =
6189 hdd_to_csr_wmm_mode(hdd_ctx->config->WmmMode);
6190 hdd_debug("using wmm default value");
6191 }
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006192 update_sme_cfg = true;
Krunal Soni707eb782018-01-18 12:04:19 -08006193 }
6194
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08006195 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]) {
6196 cfg_val = nla_get_u8(tb[
6197 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]);
6198 if (cfg_val) {
6199 /*Auto BA mode*/
6200 set_val = 0;
6201 hdd_debug("BA operating mode is set to auto");
6202 } else {
6203 /*Manual BA mode*/
6204 set_val = 1;
6205 hdd_debug("BA operating mode is set to Manual");
6206 }
6207
6208 ret_val = wma_cli_set_command(adapter->session_id,
6209 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
Kiran Kumar Lokere015f77f2018-04-24 18:25:28 -07006210 if (ret_val) {
6211 hdd_err("Set BA operating mode failed");
6212 goto send_err;
6213 }
6214 if (!cfg_val) {
6215 ret_val = wma_cli_set_command(adapter->session_id,
6216 WMI_VDEV_PARAM_AMSDU_AGGREGATION_SIZE_OPTIMIZATION,
6217 0, VDEV_CMD);
6218 }
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08006219 }
6220
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08006221 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]) {
6222 cfg_val = nla_get_u8(tb[
6223 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]
6224 );
6225 if (cfg_val > HE_FRAG_LEVEL1)
6226 set_val = HE_FRAG_LEVEL1;
6227 else
6228 set_val = cfg_val;
6229
6230 hdd_debug("set HE fragmention to %d", set_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006231 ret_val = sme_update_he_frag_supp(mac_handle,
6232 adapter->session_id, set_val);
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08006233 }
6234
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006235 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]) {
6236 cfg_val = nla_get_u8(tb[
6237 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]);
6238 sme_config->csrConfig.wep_tkip_in_he = cfg_val;
6239 hdd_debug("Set WEP/TKIP allow in HE %d", cfg_val);
6240
6241 update_sme_cfg = true;
6242 }
6243
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006244 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]) {
6245 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]) {
6246 tid = nla_get_u8(tb[
6247 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]);
6248 } else {
6249 hdd_err("TID is not set for ADD/DEL BA cfg");
6250 ret_val = -EINVAL;
6251 goto send_err;
6252 }
6253 cfg_val = nla_get_u8(tb[
6254 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]);
6255 if (cfg_val == QCA_WLAN_ADD_BA) {
6256 if (tb[
6257 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE])
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07006258 buff_size = nla_get_u16(tb[
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006259 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006260 ret_val = sme_send_addba_req(mac_handle,
6261 adapter->session_id,
6262 tid, buff_size);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006263 } else if (cfg_val == QCA_WLAN_DELETE_BA) {
6264 } else {
6265 hdd_err("Invalid BA session cfg");
6266 ret_val = -EINVAL;
6267 goto send_err;
6268 }
6269 } else if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]) {
Kiran Kumar Lokereeac7fe92018-07-24 16:56:01 -07006270 buff_size = nla_get_u16(tb[
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006271 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
6272 hdd_debug("set buff size to %d for all tids", buff_size);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006273 ret_val = sme_set_ba_buff_size(mac_handle,
6274 adapter->session_id, buff_size);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006275 if (ret_val)
6276 goto send_err;
6277 if (buff_size > 64)
6278 /* Configure ADDBA req buffer size to 256 */
6279 set_val = 3;
6280 else
6281 /* Configure ADDBA req buffer size to 64 */
6282 set_val = 2;
6283 ret_val = wma_cli_set_command(adapter->session_id,
6284 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07006285 if (ret_val)
6286 hdd_err("Failed to set BA operating mode %d", set_val);
6287 ret_val = wma_cli_set_command(adapter->session_id,
6288 GEN_VDEV_PARAM_AMPDU,
6289 buff_size, GEN_CMD);
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006290 }
6291
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08006292 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]) {
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07006293 int he_mcs_val;
Srinivas Girigowda50335342018-09-07 15:21:01 -07006294
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08006295 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]) {
6296 ac = nla_get_u8(tb[
6297 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]);
6298 } else {
6299 hdd_err("AC is not set for NO ACK policy config");
6300 ret_val = -EINVAL;
6301 goto send_err;
6302 }
6303 cfg_val = nla_get_u8(tb[
6304 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]);
6305 hdd_debug("Set NO_ACK to %d for ac %d", cfg_val, ac);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006306 ret_val = sme_set_no_ack_policy(mac_handle,
6307 adapter->session_id,
6308 cfg_val, ac);
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07006309 if (cfg_val) {
6310 if (sme_config->csrConfig.enable2x2)
6311 /*2x2 MCS 5 value*/
6312 he_mcs_val = 0x45;
6313 else
6314 /*1x1 MCS 5 value*/
6315 he_mcs_val = 0x25;
6316
6317 if (hdd_set_11ax_rate(adapter, he_mcs_val, NULL))
6318 hdd_err("HE MCS set failed, MCS val %0x",
6319 he_mcs_val);
6320 } else {
6321 if (hdd_set_11ax_rate(adapter, 0xFF, NULL))
6322 hdd_err("disable fixed rate failed");
6323 }
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08006324 }
6325
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08006326 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]) {
6327 cfg_val = nla_get_u8(tb[
6328 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]);
6329 hdd_debug("Set HE LTF to %d", cfg_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006330 ret_val = sme_set_auto_rate_he_ltf(mac_handle,
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08006331 adapter->session_id,
6332 cfg_val);
6333 if (ret_val)
6334 sme_err("Failed to set auto rate HE LTF");
6335
6336 ret_val = wma_cli_set_command(adapter->session_id,
6337 WMI_VDEV_PARAM_HE_LTF,
6338 cfg_val, VDEV_CMD);
6339 if (ret_val)
6340 goto send_err;
6341 }
6342
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07006343 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]) {
6344 cfg_val = nla_get_u8(tb[
6345 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]);
6346 hdd_debug("Set Tx beamformee to %d", cfg_val);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006347 ret_val = sme_update_tx_bfee_supp(mac_handle,
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07006348 adapter->session_id,
6349 cfg_val);
6350 if (ret_val)
6351 sme_err("Failed to set Tx beamformee cap");
6352
6353 }
6354
Kiran Kumar Lokeref3044852018-06-27 14:14:24 -07006355 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]) {
6356 cfg_val = nla_get_u8(tb[
6357 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]);
6358 if (cfg_val > hdd_ctx->config->txBFCsnValue) {
6359 hdd_err("NSTS %d not supported, supp_val %d", cfg_val,
6360 hdd_ctx->config->txBFCsnValue);
6361 ret_val = -ENOTSUPP;
6362 goto send_err;
6363 }
6364 hdd_debug("Set Tx beamformee NSTS to %d", cfg_val);
6365 ret_val = sme_update_tx_bfee_nsts(hdd_ctx->mac_handle,
6366 adapter->session_id,
6367 cfg_val,
6368 hdd_ctx->config->txBFCsnValue
6369 );
6370 if (ret_val)
6371 sme_err("Failed to set Tx beamformee cap");
6372
6373 }
6374
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07006375 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]) {
6376 cfg_val = nla_get_u8(tb[
6377 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]);
6378 if (cfg_val) {
Kiran Kumar Lokere427a20f2018-08-23 18:47:27 -07006379 hdd_debug("Set HE mac padding dur to %d", cfg_val);
Kiran Kumar Lokeref54b8552018-07-10 00:53:38 -07006380 ret_val = sme_cli_set_command(adapter->session_id,
6381 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
6382 0, VDEV_CMD);
6383 if (ret_val)
6384 hdd_err("MU_EDCA update disable failed");
6385 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
6386 sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
6387 if (sme_update_mu_edca_params(hdd_ctx->mac_handle,
6388 adapter->session_id))
6389 hdd_err("Failed to send mu edca params");
6390 } else {
6391 ret_val = sme_cli_set_command(adapter->session_id,
6392 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
6393 1, VDEV_CMD);
6394 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
6395 }
6396 ret_val = sme_update_he_trigger_frm_mac_pad(hdd_ctx->mac_handle,
6397 adapter->session_id,
6398 cfg_val);
6399 if (ret_val)
6400 hdd_err("Failed to set Trig frame mac padding cap");
6401 }
6402
Kiran Kumar Lokere8d685d12018-07-23 17:17:26 -07006403 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]) {
6404 cfg_val = nla_get_u8(tb[
6405 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]);
6406 if (cfg_val) {
6407 ret_val = sme_cli_set_command(adapter->session_id,
6408 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
6409 0, VDEV_CMD);
6410 if (ret_val)
6411 hdd_err("MU_EDCA update disable failed");
6412 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
6413 sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
6414 if (sme_update_mu_edca_params(hdd_ctx->mac_handle,
6415 adapter->session_id))
6416 hdd_err("Failed to send mu edca params");
6417 } else {
6418 ret_val = sme_cli_set_command(adapter->session_id,
6419 WMI_VDEV_PARAM_MU_EDCA_FW_UPDATE_EN,
6420 1, VDEV_CMD);
6421 sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
6422 }
6423 }
Kiran Kumar Lokeref1a96f42018-08-29 18:53:47 -07006424
6425 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]) {
6426 cfg_val = nla_get_u8(tb[
6427 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]);
6428 ret_val = sme_update_he_om_ctrl_supp(hdd_ctx->mac_handle,
6429 adapter->session_id,
6430 cfg_val);
6431 }
6432
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006433 if (update_sme_cfg)
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006434 sme_update_config(mac_handle, sme_config);
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006435
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006436send_err:
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006437 qdf_mem_free(sme_config);
6438
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006439 return ret_val;
6440}
6441
6442/**
6443 * wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
6444 * vendor command
6445 *
6446 * @wiphy: wiphy device pointer
6447 * @wdev: wireless device pointer
6448 * @data: Vendor command data buffer
6449 * @data_len: Buffer length
6450 *
6451 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
6452 *
6453 * Return: EOK or other error codes.
6454 */
6455static int wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
6456 struct wireless_dev *wdev, const void *data, int data_len)
6457{
6458 int ret;
6459
6460 cds_ssr_protect(__func__);
6461 ret = __wlan_hdd_cfg80211_set_wifi_test_config(wiphy, wdev,
6462 data, data_len);
6463 cds_ssr_unprotect(__func__);
6464
6465 return ret;
6466}
6467
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006468static const struct
6469nla_policy
6470qca_wlan_vendor_wifi_logger_start_policy
6471[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
6472 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
6473 = {.type = NLA_U32 },
6474 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
6475 = {.type = NLA_U32 },
6476 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
6477 = {.type = NLA_U32 },
6478};
6479
6480/**
6481 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
6482 * or disable the collection of packet statistics from the firmware
6483 * @wiphy: WIPHY structure pointer
6484 * @wdev: Wireless device structure pointer
6485 * @data: Pointer to the data received
6486 * @data_len: Length of the data received
6487 *
6488 * This function enables or disables the collection of packet statistics from
6489 * the firmware
6490 *
6491 * Return: 0 on success and errno on failure
6492 */
6493static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
6494 struct wireless_dev *wdev,
6495 const void *data,
6496 int data_len)
6497{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306498 QDF_STATUS status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006499 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006500 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
Hanumanth Reddy Pothulae9af1162018-06-13 13:41:44 +05306501 struct sir_wifi_start_log start_log = { 0 };
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006502 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006503
Dustin Brownfdf17c12018-03-14 12:55:34 -07006504 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08006505
Anurag Chouhan6d760662016-02-20 16:05:43 +05306506 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006507 hdd_err("Command not allowed in FTM mode");
6508 return -EPERM;
6509 }
6510
6511 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05306512 if (status)
6513 return status;
6514
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05306515 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
6516 hdd_err("Driver Modules are closed, can not start logger");
6517 return -EINVAL;
6518 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006519
Dustin Brown4ea21db2018-01-05 14:13:17 -08006520 if (wlan_cfg80211_nla_parse(tb,
6521 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
6522 data, data_len,
6523 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006524 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006525 return -EINVAL;
6526 }
6527
6528 /* Parse and fetch ring id */
6529 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006530 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006531 return -EINVAL;
6532 }
6533 start_log.ring_id = nla_get_u32(
6534 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006535 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006536
6537 /* Parse and fetch verbose level */
6538 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006539 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006540 return -EINVAL;
6541 }
6542 start_log.verbose_level = nla_get_u32(
6543 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006544 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006545
6546 /* Parse and fetch flag */
6547 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006548 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006549 return -EINVAL;
6550 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05306551 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006552 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006553
Hanumanth Reddy Pothulae9af1162018-06-13 13:41:44 +05306554 start_log.user_triggered = 1;
6555
Poddar, Siddarth176c4362016-10-03 12:25:00 +05306556 /* size is buff size which can be set using iwpriv command*/
6557 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05306558 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05306559
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006560 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
6561
6562 if (start_log.ring_id == RING_ID_WAKELOCK) {
6563 /* Start/stop wakelock events */
6564 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
6565 cds_set_wakelock_logging(true);
6566 else
6567 cds_set_wakelock_logging(false);
6568 return 0;
6569 }
6570
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006571 mac_handle = hdd_ctx->mac_handle;
6572 status = sme_wifi_start_logger(mac_handle, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306573 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006574 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006575 status);
6576 return -EINVAL;
6577 }
6578 return 0;
6579}
6580
6581/**
6582 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
6583 * or disable the collection of packet statistics from the firmware
6584 * @wiphy: WIPHY structure pointer
6585 * @wdev: Wireless device structure pointer
6586 * @data: Pointer to the data received
6587 * @data_len: Length of the data received
6588 *
6589 * This function is used to enable or disable the collection of packet
6590 * statistics from the firmware
6591 *
6592 * Return: 0 on success and errno on failure
6593 */
6594static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
6595 struct wireless_dev *wdev,
6596 const void *data,
6597 int data_len)
6598{
6599 int ret = 0;
6600
6601 cds_ssr_protect(__func__);
6602 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
6603 wdev, data, data_len);
6604 cds_ssr_unprotect(__func__);
6605
6606 return ret;
6607}
6608
6609static const struct
6610nla_policy
6611qca_wlan_vendor_wifi_logger_get_ring_data_policy
6612[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
6613 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
6614 = {.type = NLA_U32 },
6615};
6616
6617/**
6618 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
6619 * @wiphy: WIPHY structure pointer
6620 * @wdev: Wireless device structure pointer
6621 * @data: Pointer to the data received
6622 * @data_len: Length of the data received
6623 *
6624 * This function is used to flush or retrieve the per packet statistics from
6625 * the driver
6626 *
6627 * Return: 0 on success and errno on failure
6628 */
6629static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
6630 struct wireless_dev *wdev,
6631 const void *data,
6632 int data_len)
6633{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306634 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006635 uint32_t ring_id;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006636 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006637 struct nlattr *tb
6638 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
6639
Dustin Brownfdf17c12018-03-14 12:55:34 -07006640 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08006641
Anurag Chouhan6d760662016-02-20 16:05:43 +05306642 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006643 hdd_err("Command not allowed in FTM mode");
6644 return -EPERM;
6645 }
6646
6647 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05306648 if (status)
6649 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006650
Dustin Brown4ea21db2018-01-05 14:13:17 -08006651 if (wlan_cfg80211_nla_parse(tb,
6652 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
6653 data, data_len,
6654 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006655 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006656 return -EINVAL;
6657 }
6658
6659 /* Parse and fetch ring id */
6660 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006661 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006662 return -EINVAL;
6663 }
6664
6665 ring_id = nla_get_u32(
6666 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
6667
6668 if (ring_id == RING_ID_PER_PACKET_STATS) {
6669 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006670 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05306671 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
6672 /*
6673 * As part of DRIVER ring ID, flush both driver and fw logs.
6674 * For other Ring ID's driver doesn't have any rings to flush
6675 */
Dustin Brown5e89ef82018-03-14 11:50:23 -07006676 hdd_info("Bug report triggered by framework");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05306677
6678 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
6679 WLAN_LOG_INDICATOR_FRAMEWORK,
6680 WLAN_LOG_REASON_CODE_UNUSED,
6681 true, false);
6682 if (QDF_STATUS_SUCCESS != status) {
6683 hdd_err("Failed to trigger bug report");
6684 return -EINVAL;
6685 }
6686 } else {
6687 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
6688 WLAN_LOG_INDICATOR_FRAMEWORK,
Agrawal Ashishaff28982017-05-30 15:25:47 +05306689 WLAN_LOG_REASON_CODE_UNUSED,
6690 ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006691 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006692 return 0;
6693}
6694
6695/**
6696 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
6697 * @wiphy: WIPHY structure pointer
6698 * @wdev: Wireless device structure pointer
6699 * @data: Pointer to the data received
6700 * @data_len: Length of the data received
6701 *
6702 * This function is used to flush or retrieve the per packet statistics from
6703 * the driver
6704 *
6705 * Return: 0 on success and errno on failure
6706 */
6707static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
6708 struct wireless_dev *wdev,
6709 const void *data,
6710 int data_len)
6711{
6712 int ret = 0;
6713
6714 cds_ssr_protect(__func__);
6715 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
6716 wdev, data, data_len);
6717 cds_ssr_unprotect(__func__);
6718
6719 return ret;
6720}
6721
6722#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
6723/**
6724 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
6725 * @hdd_ctx: HDD context
6726 * @request_id: [input] request id
6727 * @pattern_id: [output] pattern id
6728 *
6729 * This function loops through request id to pattern id array
6730 * if the slot is available, store the request id and return pattern id
6731 * if entry exists, return the pattern id
6732 *
6733 * Return: 0 on success and errno on failure
6734 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006735static int hdd_map_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006736 uint32_t request_id,
6737 uint8_t *pattern_id)
6738{
6739 uint32_t i;
6740
6741 mutex_lock(&hdd_ctx->op_ctx.op_lock);
6742 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
6743 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
6744 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
6745 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
6746 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
6747 return 0;
6748 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
6749 request_id) {
6750 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
6751 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
6752 return 0;
6753 }
6754 }
6755 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
6756 return -EINVAL;
6757}
6758
6759/**
6760 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
6761 * @hdd_ctx: HDD context
6762 * @request_id: [input] request id
6763 * @pattern_id: [output] pattern id
6764 *
6765 * This function loops through request id to pattern id array
6766 * reset request id to 0 (slot available again) and
6767 * return pattern id
6768 *
6769 * Return: 0 on success and errno on failure
6770 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006771static int hdd_unmap_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006772 uint32_t request_id,
6773 uint8_t *pattern_id)
6774{
6775 uint32_t i;
6776
6777 mutex_lock(&hdd_ctx->op_ctx.op_lock);
6778 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
6779 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
6780 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
6781 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
6782 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
6783 return 0;
6784 }
6785 }
6786 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
6787 return -EINVAL;
6788}
6789
6790
6791/*
6792 * define short names for the global vendor params
6793 * used by __wlan_hdd_cfg80211_offloaded_packets()
6794 */
6795#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
6796#define PARAM_REQUEST_ID \
6797 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
6798#define PARAM_CONTROL \
6799 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
6800#define PARAM_IP_PACKET \
6801 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
6802#define PARAM_SRC_MAC_ADDR \
6803 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
6804#define PARAM_DST_MAC_ADDR \
6805 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
6806#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
6807
6808/**
6809 * wlan_hdd_add_tx_ptrn() - add tx pattern
6810 * @adapter: adapter pointer
6811 * @hdd_ctx: hdd context
6812 * @tb: nl attributes
6813 *
6814 * This function reads the NL attributes and forms a AddTxPtrn message
6815 * posts it to SME.
6816 *
6817 */
6818static int
Jeff Johnsone5006672017-08-29 14:39:02 -07006819wlan_hdd_add_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006820 struct nlattr **tb)
6821{
6822 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306823 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006824 uint32_t request_id, ret, len;
6825 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306826 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006827 uint16_t eth_type = htons(ETH_P_IP);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006828 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006829
6830 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07006831 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006832 return -ENOTSUPP;
6833 }
6834
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306835 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006836 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07006837 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006838 return -ENOMEM;
6839 }
6840
6841 /* Parse and fetch request Id */
6842 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006843 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006844 goto fail;
6845 }
6846
6847 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
6848 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07006849 hdd_err("request_id cannot be MAX");
SaidiReddy Yenuga466b3ce2017-05-02 18:50:25 +05306850 goto fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006851 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006852 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006853
6854 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006855 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006856 goto fail;
6857 }
6858 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006859 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006860 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07006861 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006862 goto fail;
6863 }
6864
6865 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006866 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006867 goto fail;
6868 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08006869 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05306870 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006871 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08006872 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006873
Anurag Chouhanc5548422016-02-24 18:33:27 +05306874 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Jeff Johnson1e851a12017-10-28 14:36:12 -07006875 &adapter->mac_addr)) {
Srinivas Girigowda31896552015-11-18 22:59:52 -08006876 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006877 goto fail;
6878 }
6879
6880 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006881 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006882 goto fail;
6883 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05306884 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006885 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006886 MAC_ADDR_ARRAY(dst_addr.bytes));
6887
6888 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006889 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006890 goto fail;
6891 }
6892 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006893 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006894
6895 if (add_req->ucPtrnSize < 0 ||
6896 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
6897 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006898 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006899 add_req->ucPtrnSize);
6900 goto fail;
6901 }
6902
6903 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306904 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05306905 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306906 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306907 QDF_MAC_ADDR_SIZE);
6908 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306909 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006910 len += 2;
6911
6912 /*
6913 * This is the IP packet, add 14 bytes Ethernet (802.3) header
6914 * ------------------------------------------------------------
6915 * | 14 bytes Ethernet (802.3) header | IP header and payload |
6916 * ------------------------------------------------------------
6917 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306918 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006919 nla_data(tb[PARAM_IP_PACKET]),
6920 add_req->ucPtrnSize);
6921 add_req->ucPtrnSize += len;
6922
6923 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
6924 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006925 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006926 goto fail;
6927 }
6928 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006929 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006930
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006931 mac_handle = hdd_ctx->mac_handle;
6932 status = sme_add_periodic_tx_ptrn(mac_handle, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306933 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006934 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006935 goto fail;
6936 }
6937
Dustin Browne74003f2018-03-14 12:51:58 -07006938 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306939 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006940 return 0;
6941
6942fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306943 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006944 return -EINVAL;
6945}
6946
6947/**
6948 * wlan_hdd_del_tx_ptrn() - delete tx pattern
6949 * @adapter: adapter pointer
6950 * @hdd_ctx: hdd context
6951 * @tb: nl attributes
6952 *
6953 * This function reads the NL attributes and forms a DelTxPtrn message
6954 * posts it to SME.
6955 *
6956 */
6957static int
Jeff Johnsone5006672017-08-29 14:39:02 -07006958wlan_hdd_del_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006959 struct nlattr **tb)
6960{
6961 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306962 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006963 uint32_t request_id, ret;
6964 uint8_t pattern_id = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006965 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006966
6967 /* Parse and fetch request Id */
6968 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006969 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006970 return -EINVAL;
6971 }
6972 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
6973 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07006974 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006975 return -EINVAL;
6976 }
6977
6978 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
6979 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006980 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006981 return -EINVAL;
6982 }
6983
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306984 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006985 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07006986 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006987 return -ENOMEM;
6988 }
6989
Jeff Johnson1e851a12017-10-28 14:36:12 -07006990 qdf_copy_macaddr(&del_req->mac_address, &adapter->mac_addr);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006991 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006992 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006993 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006994 request_id, del_req->ucPtrnId);
6995
Jeff Johnson34fc63a2018-06-14 10:10:02 -07006996 mac_handle = hdd_ctx->mac_handle;
6997 status = sme_del_periodic_tx_ptrn(mac_handle, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306998 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006999 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007000 goto fail;
7001 }
7002
Dustin Browne74003f2018-03-14 12:51:58 -07007003 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307004 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007005 return 0;
7006
7007fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307008 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007009 return -EINVAL;
7010}
7011
7012
7013/**
7014 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
7015 * @wiphy: Pointer to wireless phy
7016 * @wdev: Pointer to wireless device
7017 * @data: Pointer to data
7018 * @data_len: Data length
7019 *
7020 * Return: 0 on success, negative errno on failure
7021 */
7022static int
7023__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
7024 struct wireless_dev *wdev,
7025 const void *data,
7026 int data_len)
7027{
7028 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07007029 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007030 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007031 struct nlattr *tb[PARAM_MAX + 1];
7032 uint8_t control;
7033 int ret;
7034 static const struct nla_policy policy[PARAM_MAX + 1] = {
7035 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
7036 [PARAM_CONTROL] = { .type = NLA_U32 },
7037 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307038 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007039 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307040 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007041 [PARAM_PERIOD] = { .type = NLA_U32 },
7042 };
7043
Dustin Brownfdf17c12018-03-14 12:55:34 -07007044 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007045
Anurag Chouhan6d760662016-02-20 16:05:43 +05307046 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007047 hdd_err("Command not allowed in FTM mode");
7048 return -EPERM;
7049 }
7050
7051 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05307052 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007053 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007054
7055 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007056 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007057 return -ENOTSUPP;
7058 }
7059
Dustin Brown4ea21db2018-01-05 14:13:17 -08007060 if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007061 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007062 return -EINVAL;
7063 }
7064
7065 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007066 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007067 return -EINVAL;
7068 }
7069 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007070 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007071
7072 if (control == WLAN_START_OFFLOADED_PACKETS)
7073 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08007074 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007075 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08007076
7077 hdd_err("Invalid control: %d", control);
Jeff Johnson68755312017-02-10 11:46:55 -08007078 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007079}
7080
7081/*
7082 * done with short names for the global vendor params
7083 * used by __wlan_hdd_cfg80211_offloaded_packets()
7084 */
7085#undef PARAM_MAX
7086#undef PARAM_REQUEST_ID
7087#undef PARAM_CONTROL
7088#undef PARAM_IP_PACKET
7089#undef PARAM_SRC_MAC_ADDR
7090#undef PARAM_DST_MAC_ADDR
7091#undef PARAM_PERIOD
7092
7093/**
7094 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
7095 * @wiphy: wiphy structure pointer
7096 * @wdev: Wireless device structure pointer
7097 * @data: Pointer to the data received
7098 * @data_len: Length of @data
7099 *
7100 * Return: 0 on success; errno on failure
7101 */
7102static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
7103 struct wireless_dev *wdev,
7104 const void *data,
7105 int data_len)
7106{
7107 int ret = 0;
7108
7109 cds_ssr_protect(__func__);
7110 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
7111 wdev, data, data_len);
7112 cds_ssr_unprotect(__func__);
7113
7114 return ret;
7115}
7116#endif
7117
Qiwei Cai1083f5b2018-07-02 19:10:11 +08007118#ifdef WLAN_NS_OFFLOAD
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307119static const struct nla_policy
7120ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
7121 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
7122};
7123
7124/**
7125 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
7126 * @wiphy: Pointer to wireless phy
7127 * @wdev: Pointer to wireless device
7128 * @data: Pointer to data
7129 * @data_len: Length of @data
7130 *
7131 * Return: 0 on success, negative errno on failure
7132 */
7133static int
7134__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
7135 struct wireless_dev *wdev,
7136 const void *data, int data_len)
7137{
7138 int status;
7139 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
Jeff Johnsonb8944722017-09-03 09:03:19 -07007140 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07007141 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07007142 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307143
Dustin Brownfdf17c12018-03-14 12:55:34 -07007144 hdd_enter_dev(wdev->netdev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307145
Jeff Johnsonb8944722017-09-03 09:03:19 -07007146 status = wlan_hdd_validate_context(hdd_ctx);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307147 if (0 != status)
7148 return status;
Jeff Johnsonb8944722017-09-03 09:03:19 -07007149 if (!hdd_ctx->config->fhostNSOffload) {
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307150 hdd_err("ND Offload not supported");
7151 return -EINVAL;
7152 }
7153
Mukul Sharma495df602017-09-25 14:52:18 +05307154 if (!hdd_ctx->config->active_mode_offload) {
7155 hdd_warn("Active mode offload is disabled");
7156 return -EINVAL;
7157 }
7158
Dustin Brown4ea21db2018-01-05 14:13:17 -08007159 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
7160 (struct nlattr *)data, data_len,
7161 ns_offload_set_policy)) {
7162 hdd_err("nla_parse failed");
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307163 return -EINVAL;
7164 }
7165
7166 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
7167 hdd_err("ND Offload flag attribute not present");
7168 return -EINVAL;
7169 }
7170
Jeff Johnsonb8944722017-09-03 09:03:19 -07007171 hdd_ctx->ns_offload_enable =
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307172 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
7173
Nachiket Kukadedbffab82017-04-25 19:26:02 +05307174 if (QDF_IBSS_MODE == adapter->device_mode) {
7175 hdd_debug("NS Offload is not supported in IBSS mode");
7176 return -EINVAL;
7177 }
7178
Dustin Brownd8279d22016-09-07 14:52:57 -07007179 /* update ns offload in case it is already enabled/disabled */
Jeff Johnsonb8944722017-09-03 09:03:19 -07007180 if (hdd_ctx->ns_offload_enable)
Mukul Sharma3ba26b82017-01-12 21:59:41 +05307181 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
7182 else
7183 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07007184
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307185 return 0;
7186}
7187
7188/**
7189 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
7190 * @wiphy: pointer to wireless wiphy structure.
7191 * @wdev: pointer to wireless_dev structure.
7192 * @data: Pointer to the data to be passed via vendor interface
7193 * @data_len:Length of the data to be passed
7194 *
7195 * Return: Return the Success or Failure code.
7196 */
7197static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
7198 struct wireless_dev *wdev,
7199 const void *data, int data_len)
7200{
7201 int ret;
7202
7203 cds_ssr_protect(__func__);
7204 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
7205 cds_ssr_unprotect(__func__);
7206
7207 return ret;
7208}
Qiwei Cai1083f5b2018-07-02 19:10:11 +08007209#endif /* WLAN_NS_OFFLOAD */
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307210
Jeff Johnsondd7bd3e2017-06-05 13:25:24 -07007211static const struct nla_policy get_preferred_freq_list_policy
7212 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1] = {
7213 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE] = {
7214 .type = NLA_U32},
7215};
7216
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007217/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
7218 * @wiphy: Pointer to wireless phy
7219 * @wdev: Pointer to wireless device
7220 * @data: Pointer to data
7221 * @data_len: Data length
7222 *
7223 * This function return the preferred frequency list generated by the policy
7224 * manager.
7225 *
7226 * Return: success or failure code
7227 */
7228static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
7229 struct wireless_dev
7230 *wdev, const void *data,
7231 int data_len)
7232{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007233 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007234 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307235 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307236 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007237 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307238 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007239 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007240 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
7241 struct sk_buff *reply_skb;
7242
Dustin Brownfdf17c12018-03-14 12:55:34 -07007243 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08007244
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007245 ret = wlan_hdd_validate_context(hdd_ctx);
7246 if (ret)
7247 return -EINVAL;
7248
Dustin Brown4ea21db2018-01-05 14:13:17 -08007249 if (wlan_cfg80211_nla_parse(tb,
7250 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
7251 data, data_len,
7252 get_preferred_freq_list_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007253 hdd_err("Invalid ATTR");
7254 return -EINVAL;
7255 }
7256
7257 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
7258 hdd_err("attr interface type failed");
7259 return -EINVAL;
7260 }
7261
7262 intf_mode = nla_get_u32(tb
7263 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
7264
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007265 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007266 hdd_err("Invalid interface type");
7267 return -EINVAL;
7268 }
7269
7270 hdd_debug("Userspace requested pref freq list");
7271
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007272 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
7273 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05307274 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307275 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007276 hdd_err("Get pcl failed");
7277 return -EINVAL;
7278 }
7279
7280 /* convert channel number to frequency */
7281 for (i = 0; i < pcl_len; i++) {
7282 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
7283 freq_list[i] =
7284 ieee80211_channel_to_frequency(pcl[i],
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -07007285 HDD_NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007286 else
7287 freq_list[i] =
7288 ieee80211_channel_to_frequency(pcl[i],
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -07007289 HDD_NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007290 }
7291
7292 /* send the freq_list back to supplicant */
7293 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
7294 sizeof(u32) *
7295 pcl_len +
7296 NLMSG_HDRLEN);
7297
7298 if (!reply_skb) {
7299 hdd_err("Allocate reply_skb failed");
7300 return -EINVAL;
7301 }
7302
7303 if (nla_put_u32(reply_skb,
7304 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
7305 intf_mode) ||
7306 nla_put(reply_skb,
7307 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
7308 sizeof(uint32_t) * pcl_len,
7309 freq_list)) {
7310 hdd_err("nla put fail");
7311 kfree_skb(reply_skb);
7312 return -EINVAL;
7313 }
7314
7315 return cfg80211_vendor_cmd_reply(reply_skb);
7316}
7317
7318/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
7319 * @wiphy: Pointer to wireless phy
7320 * @wdev: Pointer to wireless device
7321 * @data: Pointer to data
7322 * @data_len: Data length
7323 *
7324 * This function return the preferred frequency list generated by the policy
7325 * manager.
7326 *
7327 * Return: success or failure code
7328 */
7329static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
7330 struct wireless_dev
7331 *wdev, const void *data,
7332 int data_len)
7333{
7334 int ret = 0;
7335
7336 cds_ssr_protect(__func__);
7337 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
7338 data, data_len);
7339 cds_ssr_unprotect(__func__);
7340
7341 return ret;
7342}
7343
Jeff Johnsone5f33ba2017-06-05 14:48:48 -07007344static const struct nla_policy set_probable_oper_channel_policy
7345 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1] = {
7346 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE] = {
7347 .type = NLA_U32},
7348 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ] = {
7349 .type = NLA_U32},
7350};
7351
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007352/**
7353 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
7354 * @wiphy: Pointer to wireless phy
7355 * @wdev: Pointer to wireless device
7356 * @data: Pointer to data
7357 * @data_len: Data length
7358 *
7359 * Return: 0 on success, negative errno on failure
7360 */
7361static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
7362 struct wireless_dev *wdev,
7363 const void *data,
7364 int data_len)
7365{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05307366 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07007367 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007368 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007369 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007370 enum policy_mgr_con_mode intf_mode;
Jeff Johnsone5f33ba2017-06-05 14:48:48 -07007371 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007372 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007373
Dustin Brownfdf17c12018-03-14 12:55:34 -07007374 hdd_enter_dev(ndev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08007375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007376 ret = wlan_hdd_validate_context(hdd_ctx);
7377 if (ret)
7378 return ret;
7379
Dustin Brown4ea21db2018-01-05 14:13:17 -08007380 if (wlan_cfg80211_nla_parse(tb,
7381 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
7382 data, data_len,
7383 set_probable_oper_channel_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007384 hdd_err("Invalid ATTR");
7385 return -EINVAL;
7386 }
7387
7388 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
7389 hdd_err("attr interface type failed");
7390 return -EINVAL;
7391 }
7392
7393 intf_mode = nla_get_u32(tb
7394 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
7395
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007396 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007397 hdd_err("Invalid interface type");
7398 return -EINVAL;
7399 }
7400
7401 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
7402 hdd_err("attr probable freq failed");
7403 return -EINVAL;
7404 }
7405
7406 channel_hint = cds_freq_to_chan(nla_get_u32(tb
7407 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
7408
7409 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007410 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007411 channel_hint, HW_MODE_20_MHZ)) {
7412 hdd_err("Set channel hint failed due to concurrency check");
7413 return -EINVAL;
7414 }
7415
Krunal Soni09e55032016-06-07 10:06:55 -07007416 if (0 != wlan_hdd_check_remain_on_channel(adapter))
7417 hdd_warn("Remain On Channel Pending");
7418
Krunal Sonied3bc8e2018-01-26 12:13:34 -08007419 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, channel_hint,
7420 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
7421 hdd_err("Failed to change hw mode");
Krunal Soni3091bcc2016-06-23 12:28:21 -07007422 return -EINVAL;
7423 }
7424
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007425 return 0;
7426}
7427
7428/**
7429 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
7430 * @wiphy: Pointer to wireless phy
7431 * @wdev: Pointer to wireless device
7432 * @data: Pointer to data
7433 * @data_len: Data length
7434 *
7435 * Return: 0 on success, negative errno on failure
7436 */
7437static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
7438 struct wireless_dev *wdev,
7439 const void *data,
7440 int data_len)
7441{
7442 int ret = 0;
7443
7444 cds_ssr_protect(__func__);
7445 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
7446 data, data_len);
7447 cds_ssr_unprotect(__func__);
7448
7449 return ret;
7450}
7451
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307452static const struct
7453nla_policy
7454qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +05307455 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {
7456 .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307457};
7458
7459/**
7460 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
7461 * @wiphy: WIPHY structure pointer
7462 * @wdev: Wireless device structure pointer
7463 * @data: Pointer to the data received
7464 * @data_len: Length of the data received
7465 *
7466 * This function is used to get link properties like nss, rate flags and
7467 * operating frequency for the active connection with the given peer.
7468 *
7469 * Return: 0 on success and errno on failure
7470 */
7471static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
7472 struct wireless_dev *wdev,
7473 const void *data,
7474 int data_len)
7475{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007476 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307477 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07007478 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson40dae4e2017-08-29 14:00:25 -07007479 struct hdd_station_ctx *hdd_sta_ctx;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307480 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05307481 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307482 uint32_t sta_id;
7483 struct sk_buff *reply_skb;
7484 uint32_t rate_flags = 0;
7485 uint8_t nss;
7486 uint8_t final_rate_flags = 0;
7487 uint32_t freq;
7488
Dustin Brownfdf17c12018-03-14 12:55:34 -07007489 hdd_enter_dev(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307490
Anurag Chouhan6d760662016-02-20 16:05:43 +05307491 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307492 hdd_err("Command not allowed in FTM mode");
7493 return -EPERM;
7494 }
7495
7496 if (0 != wlan_hdd_validate_context(hdd_ctx))
7497 return -EINVAL;
7498
Dustin Brown4ea21db2018-01-05 14:13:17 -08007499 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
7500 data_len, qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007501 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307502 return -EINVAL;
7503 }
7504
7505 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007506 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307507 adapter->device_mode);
7508 return -EINVAL;
7509 }
7510
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +05307511 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) < QDF_MAC_ADDR_SIZE) {
7512 hdd_err("Attribute peerMac is invalid for mode=%d",
7513 adapter->device_mode);
7514 return -EINVAL;
7515 }
7516
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307517 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307518 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007519 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307520 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
7521
Krunal Sonib4326f22016-03-10 13:05:51 -08007522 if (adapter->device_mode == QDF_STA_MODE ||
7523 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307524 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
7525 if ((hdd_sta_ctx->conn_info.connState !=
7526 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307527 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307528 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007529 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307530 MAC_ADDR_ARRAY(peer_mac));
7531 return -EINVAL;
7532 }
7533
7534 nss = hdd_sta_ctx->conn_info.nss;
7535 freq = cds_chan_to_freq(
7536 hdd_sta_ctx->conn_info.operationChannel);
7537 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08007538 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
7539 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307540
7541 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07007542 if (adapter->sta_info[sta_id].in_use &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05307543 !qdf_is_macaddr_broadcast(
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07007544 &adapter->sta_info[sta_id].sta_mac) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307545 !qdf_mem_cmp(
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07007546 &adapter->sta_info[sta_id].sta_mac.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307547 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307548 break;
7549 }
7550
7551 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07007552 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307553 MAC_ADDR_ARRAY(peer_mac));
7554 return -EINVAL;
7555 }
7556
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07007557 nss = adapter->sta_info[sta_id].nss;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307558 freq = cds_chan_to_freq(
Jeff Johnson01206862017-10-27 20:55:59 -07007559 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operating_channel);
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07007560 rate_flags = adapter->sta_info[sta_id].rate_flags;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307561 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07007562 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307563 MAC_ADDR_ARRAY(peer_mac));
7564 return -EINVAL;
7565 }
7566
Naveen Rawatea1564b2018-05-17 15:56:11 -07007567 if (!(rate_flags & TX_RATE_LEGACY)) {
7568 if (rate_flags & TX_RATE_VHT80) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307569 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08007570#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307571 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08007572#endif
Naveen Rawatea1564b2018-05-17 15:56:11 -07007573 } else if (rate_flags & TX_RATE_VHT40) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307574 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08007575#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307576 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08007577#endif
Naveen Rawatea1564b2018-05-17 15:56:11 -07007578 } else if (rate_flags & TX_RATE_VHT20) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307579 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
7580 } else if (rate_flags &
Naveen Rawatea1564b2018-05-17 15:56:11 -07007581 (TX_RATE_HT20 | TX_RATE_HT40)) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307582 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08007583#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Naveen Rawatea1564b2018-05-17 15:56:11 -07007584 if (rate_flags & TX_RATE_HT40)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307585 final_rate_flags |=
7586 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08007587#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307588 }
7589
Naveen Rawatea1564b2018-05-17 15:56:11 -07007590 if (rate_flags & TX_RATE_SGI) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307591 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
7592 final_rate_flags |= RATE_INFO_FLAGS_MCS;
7593 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
7594 }
7595 }
7596
7597 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
7598 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
7599
7600 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07007601 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307602 return -EINVAL;
7603 }
7604
7605 if (nla_put_u8(reply_skb,
7606 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
7607 nss) ||
7608 nla_put_u8(reply_skb,
7609 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
7610 final_rate_flags) ||
7611 nla_put_u32(reply_skb,
7612 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
7613 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007614 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307615 kfree_skb(reply_skb);
7616 return -EINVAL;
7617 }
7618
7619 return cfg80211_vendor_cmd_reply(reply_skb);
7620}
7621
7622/**
7623 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
7624 * properties.
7625 * @wiphy: WIPHY structure pointer
7626 * @wdev: Wireless device structure pointer
7627 * @data: Pointer to the data received
7628 * @data_len: Length of the data received
7629 *
7630 * This function is used to get link properties like nss, rate flags and
7631 * operating frequency for the active connection with the given peer.
7632 *
7633 * Return: 0 on success and errno on failure
7634 */
7635static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
7636 struct wireless_dev *wdev,
7637 const void *data,
7638 int data_len)
7639{
7640 int ret = 0;
7641
7642 cds_ssr_protect(__func__);
7643 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
7644 wdev, data, data_len);
7645 cds_ssr_unprotect(__func__);
7646
7647 return ret;
7648}
7649
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307650static const struct nla_policy
7651wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7652 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
Ganesh Kondabattini099e6e82017-06-28 12:24:20 +05307653 [QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST] = {
7654 .type = NLA_NESTED },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307655};
7656
Agrawal Ashish65634612016-08-18 13:24:32 +05307657static const struct nla_policy
7658wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7659 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7660 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7661};
7662
7663/**
7664 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7665 * @wiphy: Pointer to wireless phy
7666 * @wdev: Pointer to wireless device
7667 * @data: Pointer to data
7668 * @data_len: Length of @data
7669 *
7670 * This function parses the incoming NL vendor command data attributes and
7671 * updates the SAP context about channel_hint and DFS mode.
7672 * If channel_hint is set, SAP will choose that channel
7673 * as operating channel.
7674 *
7675 * If DFS mode is enabled, driver will include DFS channels
7676 * in ACS else driver will skip DFS channels.
7677 *
7678 * Return: 0 on success, negative errno on failure
7679 */
7680static int
7681__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7682 struct wireless_dev *wdev,
7683 const void *data, int data_len)
7684{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007685 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish65634612016-08-18 13:24:32 +05307686 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7687 int ret;
7688 struct acs_dfs_policy *acs_policy;
7689 int mode = DFS_MODE_NONE;
7690 int channel_hint = 0;
7691
Dustin Brownfdf17c12018-03-14 12:55:34 -07007692 hdd_enter_dev(wdev->netdev);
Agrawal Ashish65634612016-08-18 13:24:32 +05307693
7694 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7695 hdd_err("Command not allowed in FTM mode");
7696 return -EINVAL;
7697 }
7698
7699 ret = wlan_hdd_validate_context(hdd_ctx);
7700 if (0 != ret)
7701 return ret;
7702
Dustin Brown4ea21db2018-01-05 14:13:17 -08007703 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7704 data, data_len,
7705 wlan_hdd_set_acs_dfs_config_policy)) {
Agrawal Ashish65634612016-08-18 13:24:32 +05307706 hdd_err("invalid attr");
7707 return -EINVAL;
7708 }
7709
7710 acs_policy = &hdd_ctx->acs_policy;
7711 /*
7712 * SCM sends this attribute to restrict SAP from choosing
7713 * DFS channels from ACS.
7714 */
7715 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7716 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7717
7718 if (!IS_DFS_MODE_VALID(mode)) {
7719 hdd_err("attr acs dfs mode is not valid");
7720 return -EINVAL;
7721 }
7722 acs_policy->acs_dfs_mode = mode;
7723
7724 /*
7725 * SCM sends this attribute to provide an active channel,
7726 * to skip redundant ACS between drivers, and save driver start up time
7727 */
7728 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7729 channel_hint = nla_get_u8(
7730 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7731
7732 if (!IS_CHANNEL_VALID(channel_hint)) {
7733 hdd_err("acs channel is not valid");
7734 return -EINVAL;
7735 }
7736 acs_policy->acs_channel = channel_hint;
7737
7738 return 0;
7739}
7740
7741/**
7742 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7743 * @wiphy: wiphy structure pointer
7744 * @wdev: Wireless device structure pointer
7745 * @data: Pointer to the data received
7746 * @data_len: Length of @data
7747 *
7748 * This function parses the incoming NL vendor command data attributes and
7749 * updates the SAP context about channel_hint and DFS mode.
7750 *
7751 * Return: 0 on success; errno on failure
7752 */
7753static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7754 struct wireless_dev *wdev,
7755 const void *data, int data_len)
7756{
7757 int ret;
7758
7759 cds_ssr_protect(__func__);
7760 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7761 cds_ssr_unprotect(__func__);
7762
7763 return ret;
7764}
7765
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307766/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307767 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7768 * @mode : cfg80211 dfs mode
7769 *
7770 * Return: return csr sta roam dfs mode else return NONE
7771 */
7772static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7773 enum dfs_mode mode)
7774{
7775 switch (mode) {
7776 case DFS_MODE_ENABLE:
7777 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307778 case DFS_MODE_DISABLE:
7779 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307780 case DFS_MODE_DEPRIORITIZE:
7781 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307782 default:
7783 hdd_err("STA Roam policy dfs mode is NONE");
7784 return CSR_STA_ROAM_POLICY_NONE;
7785 }
7786}
7787
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307788/*
7789 * hdd_get_sap_operating_band: Get current operating channel
7790 * for sap.
7791 * @hdd_ctx: hdd context
7792 *
7793 * Return : Corresponding band for SAP operating channel
7794 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007795uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307796{
Jeff Johnsone5006672017-08-29 14:39:02 -07007797 struct hdd_adapter *adapter;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307798 uint8_t operating_channel = 0;
7799 uint8_t sap_operating_band = 0;
Srinivas Girigowda576b2352017-08-25 14:44:26 -07007800
Dustin Brown920397d2017-12-13 16:27:50 -08007801 hdd_for_each_adapter(hdd_ctx, adapter) {
7802 if (adapter->device_mode != QDF_SAP_MODE)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307803 continue;
Dustin Brown920397d2017-12-13 16:27:50 -08007804
Jeff Johnsonb9424862017-10-30 08:49:35 -07007805 operating_channel = adapter->session.ap.operating_channel;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307806 if (IS_24G_CH(operating_channel))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08007807 sap_operating_band = BAND_2G;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307808 else if (IS_5G_CH(operating_channel))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08007809 sap_operating_band = BAND_5G;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307810 else
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08007811 sap_operating_band = BAND_ALL;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307812 }
Dustin Brown920397d2017-12-13 16:27:50 -08007813
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307814 return sap_operating_band;
7815}
7816
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307817static const struct nla_policy
7818wlan_hdd_set_sta_roam_config_policy[
7819QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7820 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7821 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7822};
7823
7824/**
7825 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7826 * for station connection or roaming.
7827 * @wiphy: Pointer to wireless phy
7828 * @wdev: Pointer to wireless device
7829 * @data: Pointer to data
7830 * @data_len: Length of @data
7831 *
7832 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7833 * channels needs to be skipped in scanning or not.
7834 * If dfs_mode is disabled, driver will not scan DFS channels.
7835 * If skip_unsafe_channels is set, driver will skip unsafe channels
7836 * in Scanning.
7837 *
7838 * Return: 0 on success, negative errno on failure
7839 */
7840static int
7841__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7842 struct wireless_dev *wdev,
7843 const void *data, int data_len)
7844{
7845 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07007846 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007847 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307848 struct nlattr *tb[
7849 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7850 int ret;
7851 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7852 enum dfs_mode mode = DFS_MODE_NONE;
7853 bool skip_unsafe_channels = false;
7854 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307855 uint8_t sap_operating_band;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007856 mac_handle_t mac_handle;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307857
Dustin Brownfdf17c12018-03-14 12:55:34 -07007858 hdd_enter_dev(dev);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307859
7860 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7861 hdd_err("Command not allowed in FTM mode");
7862 return -EINVAL;
7863 }
7864
7865 ret = wlan_hdd_validate_context(hdd_ctx);
7866 if (0 != ret)
7867 return ret;
Dustin Brown4ea21db2018-01-05 14:13:17 -08007868 if (wlan_cfg80211_nla_parse(tb,
7869 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7870 data, data_len,
7871 wlan_hdd_set_sta_roam_config_policy)) {
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307872 hdd_err("invalid attr");
7873 return -EINVAL;
7874 }
7875 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7876 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7877 if (!IS_DFS_MODE_VALID(mode)) {
7878 hdd_err("attr sta roam dfs mode policy is not valid");
7879 return -EINVAL;
7880 }
7881
7882 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7883
7884 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7885 skip_unsafe_channels = nla_get_u8(
7886 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307887 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Jeff Johnson34fc63a2018-06-14 10:10:02 -07007888 mac_handle = hdd_ctx->mac_handle;
7889 status = sme_update_sta_roam_policy(mac_handle, sta_roam_dfs_mode,
7890 skip_unsafe_channels,
7891 adapter->session_id,
7892 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307893
7894 if (!QDF_IS_STATUS_SUCCESS(status)) {
7895 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7896 return -EINVAL;
7897 }
7898 return 0;
7899}
7900
7901/**
7902 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7903 * connection and roaming for station.
7904 * @wiphy: wiphy structure pointer
7905 * @wdev: Wireless device structure pointer
7906 * @data: Pointer to the data received
7907 * @data_len: Length of @data
7908 *
7909 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7910 * channels needs to be skipped in scanning or not.
7911 * If dfs_mode is disabled, driver will not scan DFS channels.
7912 * If skip_unsafe_channels is set, driver will skip unsafe channels
7913 * in Scanning.
7914 * Return: 0 on success; errno on failure
7915 */
7916static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7917 struct wireless_dev *wdev,
7918 const void *data, int data_len)
7919{
7920 int ret;
7921
7922 cds_ssr_protect(__func__);
7923 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7924 cds_ssr_unprotect(__func__);
7925
7926 return ret;
7927}
7928
Agrawal Ashish467dde42016-09-08 18:44:22 +05307929#ifdef FEATURE_WLAN_CH_AVOID
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05307930
7931static int hdd_validate_avoid_freq_chanlist(
7932 struct hdd_context *hdd_ctx,
7933 struct ch_avoid_ind_type *channel_list)
7934{
7935 unsigned int range_idx, ch_idx;
7936 unsigned int unsafe_channel_index, unsafe_channel_count = 0;
7937 bool ch_found = false;
7938
7939 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7940 (uint16_t)NUM_CHANNELS);
7941
7942 for (range_idx = 0; range_idx < channel_list->ch_avoid_range_cnt;
7943 range_idx++) {
7944 if ((channel_list->avoid_freq_range[range_idx].start_freq <
7945 CDS_24_GHZ_CHANNEL_1) ||
7946 (channel_list->avoid_freq_range[range_idx].end_freq >
7947 CDS_5_GHZ_CHANNEL_165) ||
7948 (channel_list->avoid_freq_range[range_idx].start_freq >
7949 channel_list->avoid_freq_range[range_idx].end_freq))
7950 continue;
7951
7952 for (ch_idx = channel_list->
7953 avoid_freq_range[range_idx].start_freq;
7954 ch_idx <= channel_list->
7955 avoid_freq_range[range_idx].end_freq;
7956 ch_idx++) {
7957 for (unsafe_channel_index = 0;
7958 unsafe_channel_index < unsafe_channel_count;
7959 unsafe_channel_index++) {
7960 if (ch_idx ==
7961 hdd_ctx->unsafe_channel_list[
7962 unsafe_channel_index]) {
Dustin Brown632af712018-03-14 15:03:55 -07007963 hdd_info("Duplicate channel %d",
7964 ch_idx);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05307965 ch_found = true;
7966 break;
7967 }
7968 }
7969 if (!ch_found) {
7970 hdd_ctx->unsafe_channel_list[
7971 unsafe_channel_count++] = ch_idx;
7972 }
7973 ch_found = false;
7974 }
7975 }
7976 return unsafe_channel_count;
7977}
7978
Agrawal Ashish467dde42016-09-08 18:44:22 +05307979/**
7980 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7981 * is on unsafe channel.
7982 * @wiphy: wiphy structure pointer
7983 * @wdev: Wireless device structure pointer
7984 * @data: Pointer to the data received
7985 * @data_len: Length of @data
7986 *
7987 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7988 * on any of unsafe channels.
7989 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7990 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7991 *
7992 * Return: 0 on success; errno on failure
7993 */
7994static int
7995__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7996 struct wireless_dev *wdev,
7997 const void *data, int data_len)
7998{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007999 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish467dde42016-09-08 18:44:22 +05308000 int ret;
Agrawal Ashish467dde42016-09-08 18:44:22 +05308001 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
Liangwei Dong6e1a2092017-08-30 16:29:06 +08008002 uint16_t *local_unsafe_list;
hqubf1b6182018-08-14 17:22:41 +08008003 uint16_t unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308004 uint16_t unsafe_channel_index, local_unsafe_list_count;
8005 struct ch_avoid_ind_type *channel_list;
Jeff Johnson2e60a142018-05-20 12:08:12 -07008006 enum QDF_GLOBAL_MODE curr_mode;
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +05308007 uint8_t num_args = 0;
hqubf1b6182018-08-14 17:22:41 +08008008 bool user_set_avoid_channel = true;
Agrawal Ashish467dde42016-09-08 18:44:22 +05308009
Dustin Brownfdf17c12018-03-14 12:55:34 -07008010 hdd_enter_dev(wdev->netdev);
Agrawal Ashish467dde42016-09-08 18:44:22 +05308011
8012 if (!qdf_ctx) {
Jeff Johnson6867ec32017-09-29 20:30:20 -07008013 hdd_err("qdf_ctx is NULL");
Agrawal Ashish467dde42016-09-08 18:44:22 +05308014 return -EINVAL;
8015 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308016 curr_mode = hdd_get_conparam();
8017 if (QDF_GLOBAL_FTM_MODE == curr_mode ||
8018 QDF_GLOBAL_MONITOR_MODE == curr_mode) {
8019 hdd_err("Command not allowed in FTM/MONITOR mode");
Agrawal Ashish467dde42016-09-08 18:44:22 +05308020 return -EINVAL;
8021 }
8022
8023 ret = wlan_hdd_validate_context(hdd_ctx);
8024 if (0 != ret)
8025 return ret;
hqubf1b6182018-08-14 17:22:41 +08008026 if (!data && data_len == 0) {
8027 hdd_debug("Userspace doesn't set avoid frequency channel list");
8028 user_set_avoid_channel = false;
8029 goto process_unsafe_channel;
8030 }
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +05308031 if (!data || data_len < (sizeof(channel_list->ch_avoid_range_cnt) +
8032 sizeof(struct ch_avoid_freq_type))) {
8033 hdd_err("Avoid frequency channel list empty");
8034 return -EINVAL;
8035 }
8036 num_args = (data_len - sizeof(channel_list->ch_avoid_range_cnt)) /
8037 sizeof(channel_list->avoid_freq_range[0].start_freq);
8038
8039 if (num_args < 2 || num_args > CH_AVOID_MAX_RANGE * 2 ||
8040 num_args % 2 != 0) {
8041 hdd_err("Invalid avoid frequency channel list");
8042 return -EINVAL;
8043 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308044
8045 channel_list = (struct ch_avoid_ind_type *)data;
Ashish Kumar Dhanotiya7e345d02018-06-28 12:43:41 +05308046 if (channel_list->ch_avoid_range_cnt == 0 ||
8047 channel_list->ch_avoid_range_cnt > CH_AVOID_MAX_RANGE ||
8048 2 * channel_list->ch_avoid_range_cnt != num_args) {
8049 hdd_err("Invalid frequency range count %d",
8050 channel_list->ch_avoid_range_cnt);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308051 return -EINVAL;
8052 }
8053
hqubf1b6182018-08-14 17:22:41 +08008054process_unsafe_channel:
Liangwei Dong6e1a2092017-08-30 16:29:06 +08008055 ret = hdd_clone_local_unsafe_chan(hdd_ctx,
8056 &local_unsafe_list,
8057 &local_unsafe_list_count);
8058 if (0 != ret) {
8059 hdd_err("failed to clone the cur unsafe chan list");
8060 return ret;
8061 }
8062
Agrawal Ashish467dde42016-09-08 18:44:22 +05308063 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8064 &(hdd_ctx->unsafe_channel_count),
8065 sizeof(hdd_ctx->unsafe_channel_list));
hqubf1b6182018-08-14 17:22:41 +08008066 if (user_set_avoid_channel) {
8067 hdd_ctx->unsafe_channel_count =
8068 hdd_validate_avoid_freq_chanlist(
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308069 hdd_ctx,
8070 channel_list);
hqubf1b6182018-08-14 17:22:41 +08008071 unsafe_channel_count = hdd_ctx->unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308072
hqubf1b6182018-08-14 17:22:41 +08008073 pld_set_wlan_unsafe_channel(qdf_ctx->dev,
8074 hdd_ctx->unsafe_channel_list,
8075 hdd_ctx->unsafe_channel_count);
8076 } else {
8077 unsafe_channel_count = QDF_MIN(
8078 (uint16_t)hdd_ctx->unsafe_channel_count,
8079 (uint16_t)NUM_CHANNELS);
8080 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308081
Agrawal Ashish467dde42016-09-08 18:44:22 +05308082 for (unsafe_channel_index = 0;
hqubf1b6182018-08-14 17:22:41 +08008083 unsafe_channel_index < unsafe_channel_count;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308084 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008085 hdd_debug("Channel %d is not safe",
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +05308086 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
Agrawal Ashish467dde42016-09-08 18:44:22 +05308087 }
Liangwei Dong6e1a2092017-08-30 16:29:06 +08008088 if (hdd_local_unsafe_channel_updated(hdd_ctx, local_unsafe_list,
8089 local_unsafe_list_count))
8090 hdd_unsafe_channel_restart_sap(hdd_ctx);
8091 qdf_mem_free(local_unsafe_list);
8092
Agrawal Ashish467dde42016-09-08 18:44:22 +05308093 return 0;
8094}
8095
8096/**
8097 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8098 * is on unsafe channel.
8099 * @wiphy: wiphy structure pointer
8100 * @wdev: Wireless device structure pointer
8101 * @data: Pointer to the data received
8102 * @data_len: Length of @data
8103 *
8104 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8105 * on any of unsafe channels.
8106 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8107 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8108 *
8109 * Return: 0 on success; errno on failure
8110 */
8111static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8112 struct wireless_dev *wdev,
8113 const void *data, int data_len)
8114{
8115 int ret;
8116
8117 cds_ssr_protect(__func__);
8118 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8119 cds_ssr_unprotect(__func__);
8120
8121 return ret;
8122}
8123
8124#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308125/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308126 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8127 * SAP is on unsafe channel.
8128 * @wiphy: wiphy structure pointer
8129 * @wdev: Wireless device structure pointer
8130 * @data: Pointer to the data received
8131 * @data_len: Length of @data
8132 *
8133 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8134 * driver.
8135 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8136 * will initiate restart of sap.
8137 *
8138 * Return: 0 on success; errno on failure
8139 */
8140static int
8141__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8142 struct wireless_dev *wdev,
8143 const void *data, int data_len)
8144{
8145 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008146 struct hdd_adapter *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008147 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308148 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8149 uint8_t config_channel = 0;
Jeff Johnson87251032017-08-29 13:31:11 -07008150 struct hdd_ap_ctx *ap_ctx;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308151 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308152 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308153
Dustin Brown491d54b2018-03-14 12:39:11 -07008154 hdd_enter();
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308155
8156 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008157 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308158 return -EINVAL;
8159 }
8160
8161 ret = wlan_hdd_validate_context(hdd_ctx);
8162 if (0 != ret)
8163 return -EINVAL;
8164
Dustin Brown4ea21db2018-01-05 14:13:17 -08008165 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8166 data, data_len,
8167 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008168 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308169 return -EINVAL;
8170 }
8171
8172 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8173 if (!test_bit(SOFTAP_BSS_STARTED,
8174 &hostapd_adapter->event_flags)) {
8175 hdd_err("SAP is not started yet. Restart sap will be invalid");
8176 return -EINVAL;
8177 }
8178
8179 config_channel =
8180 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8181
8182 if (!((IS_24G_CH(config_channel)) ||
8183 (IS_5G_CH(config_channel)))) {
8184 hdd_err("Channel %d is not valid to restart SAP",
8185 config_channel);
8186 return -ENOTSUPP;
8187 }
8188
8189 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
Jeff Johnson91df29d2017-10-27 19:29:50 -07008190 ap_ctx->sap_config.channel = config_channel;
8191 ap_ctx->sap_config.ch_params.ch_width =
8192 ap_ctx->sap_config.ch_width_orig;
hqu73bccf22017-10-28 15:34:17 +08008193 ap_ctx->bss_stop_reason = BSS_STOP_DUE_TO_VENDOR_CONFIG_CHAN;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308194
Dustin Brown07901ec2018-09-07 11:02:41 -07008195 wlan_reg_set_channel_params(hdd_ctx->pdev,
8196 ap_ctx->sap_config.channel,
8197 ap_ctx->sap_config.sec_ch,
8198 &ap_ctx->sap_config.ch_params);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308199
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008200 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308201 }
8202
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308203 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8204 uint32_t freq_len, i;
8205 uint32_t *freq;
8206 uint8_t chans[QDF_MAX_NUM_CHAN];
8207
8208 hdd_debug("setting mandatory freq/chan list");
8209
8210 freq_len = nla_len(
8211 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8212 sizeof(uint32_t);
8213
8214 if (freq_len > QDF_MAX_NUM_CHAN) {
8215 hdd_err("insufficient space to hold channels");
8216 return -ENOMEM;
8217 }
8218
8219 freq = nla_data(
8220 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8221
8222 hdd_debug("freq_len=%d", freq_len);
8223
8224 for (i = 0; i < freq_len; i++) {
8225 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8226 hdd_debug("freq[%d]=%d", i, freq[i]);
8227 }
8228
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008229 status = policy_mgr_set_sap_mandatory_channels(
8230 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308231 if (QDF_IS_STATUS_ERROR(status))
8232 return -EINVAL;
8233 }
8234
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308235 return 0;
8236}
8237
8238/**
8239 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8240 * @wiphy: wiphy structure pointer
8241 * @wdev: Wireless device structure pointer
8242 * @data: Pointer to the data received
8243 * @data_len: Length of @data
8244 *
8245 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8246 * driver.
8247 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8248 * will initiate restart of sap.
8249 *
8250 * Return: 0 on success; errno on failure
8251 */
8252static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8253 struct wireless_dev *wdev,
8254 const void *data, int data_len)
8255{
8256 int ret;
8257
8258 cds_ssr_protect(__func__);
8259 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8260 wdev, data, data_len);
8261 cds_ssr_unprotect(__func__);
8262
8263 return ret;
8264}
8265
Nachiket Kukadee547a482018-05-22 16:43:30 +05308266#undef APF_INVALID
8267#undef APF_SET_RESET
8268#undef APF_VERSION
8269#undef APF_ID
8270#undef APF_PACKET_SIZE
8271#undef APF_CURRENT_OFFSET
8272#undef APF_PROGRAM
8273#undef APF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308274
Naveen Rawat3ff5cff2018-01-29 14:31:16 -08008275#ifndef QCA_SUPPORT_CP_STATS
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308276/**
8277 * define short names for the global vendor params
8278 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8279 */
8280#define PARAM_TOTAL_CMD_EVENT_WAKE \
8281 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8282#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8283 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8284#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8285 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8286#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8287 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8288#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8289 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8290#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8291 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8292#define PARAM_TOTAL_RX_DATA_WAKE \
8293 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8294#define PARAM_RX_UNICAST_CNT \
8295 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8296#define PARAM_RX_MULTICAST_CNT \
8297 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8298#define PARAM_RX_BROADCAST_CNT \
8299 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8300#define PARAM_ICMP_PKT \
8301 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8302#define PARAM_ICMP6_PKT \
8303 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8304#define PARAM_ICMP6_RA \
8305 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8306#define PARAM_ICMP6_NA \
8307 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8308#define PARAM_ICMP6_NS \
8309 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8310#define PARAM_ICMP4_RX_MULTICAST_CNT \
8311 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8312#define PARAM_ICMP6_RX_MULTICAST_CNT \
8313 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8314#define PARAM_OTHER_RX_MULTICAST_CNT \
8315 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308316#define PARAM_RSSI_BREACH_CNT \
8317 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8318#define PARAM_LOW_RSSI_CNT \
8319 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8320#define PARAM_GSCAN_CNT \
8321 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8322#define PARAM_PNO_COMPLETE_CNT \
8323 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8324#define PARAM_PNO_MATCH_CNT \
8325 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8326
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308327/**
8328 * hdd_send_wakelock_stats() - API to send wakelock stats
8329 * @ctx: context to be passed to callback
8330 * @data: data passed to callback
8331 *
8332 * This function is used to send wake lock stats to HAL layer
8333 *
8334 * Return: 0 on success, error number otherwise.
8335 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008336static uint32_t hdd_send_wakelock_stats(struct hdd_context *hdd_ctx,
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308337 const struct sir_wake_lock_stats *data)
8338{
8339 struct sk_buff *skb;
8340 uint32_t nl_buf_len;
8341 uint32_t total_rx_data_wake, rx_multicast_cnt;
8342 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308343 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308344
Dustin Brown491d54b2018-03-14 12:39:11 -07008345 hdd_enter();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308346
8347 nl_buf_len = NLMSG_HDRLEN;
8348 nl_buf_len +=
8349 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8350 (NLMSG_HDRLEN + sizeof(uint32_t));
8351
8352 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8353
8354 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008355 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308356 return -ENOMEM;
8357 }
8358
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008359 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308360 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008361 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308362 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008363 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308364 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008365 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308366 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008367 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308368 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008369 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308370 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008371 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308372 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008373 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8374 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308375 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008376 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308377 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008378 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308379 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008380 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308381 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008382 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308383 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008384 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308385 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308386
8387 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308388 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308389
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308390 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308391 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308392
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308393 rx_multicast_cnt =
8394 data->wow_ipv4_mcast_wake_up_count +
8395 ipv6_rx_multicast_addr_cnt;
8396
8397 total_rx_data_wake =
8398 data->wow_ucast_wake_up_count +
8399 data->wow_bcast_wake_up_count +
8400 rx_multicast_cnt;
8401
8402 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8403 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8404 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8405 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8406 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8407 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8408 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8409 total_rx_data_wake) ||
8410 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8411 data->wow_ucast_wake_up_count) ||
8412 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8413 rx_multicast_cnt) ||
8414 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8415 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308416 nla_put_u32(skb, PARAM_ICMP_PKT,
8417 data->wow_icmpv4_count) ||
8418 nla_put_u32(skb, PARAM_ICMP6_PKT,
8419 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308420 nla_put_u32(skb, PARAM_ICMP6_RA,
8421 data->wow_ipv6_mcast_ra_stats) ||
8422 nla_put_u32(skb, PARAM_ICMP6_NA,
8423 data->wow_ipv6_mcast_na_stats) ||
8424 nla_put_u32(skb, PARAM_ICMP6_NS,
8425 data->wow_ipv6_mcast_ns_stats) ||
8426 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8427 data->wow_ipv4_mcast_wake_up_count) ||
8428 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8429 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308430 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8431 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8432 data->wow_rssi_breach_wake_up_count) ||
8433 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8434 data->wow_low_rssi_wake_up_count) ||
8435 nla_put_u32(skb, PARAM_GSCAN_CNT,
8436 data->wow_gscan_wake_up_count) ||
8437 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8438 data->wow_pno_complete_wake_up_count) ||
8439 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8440 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008441 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308442 goto nla_put_failure;
8443 }
8444
8445 cfg80211_vendor_cmd_reply(skb);
8446
Dustin Browne74003f2018-03-14 12:51:58 -07008447 hdd_exit();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308448 return 0;
8449
8450nla_put_failure:
8451 kfree_skb(skb);
8452 return -EINVAL;
8453}
Naveen Rawat3ff5cff2018-01-29 14:31:16 -08008454#endif
8455
8456#ifdef QCA_SUPPORT_CP_STATS
8457static int wlan_hdd_process_wake_lock_stats(struct hdd_context *hdd_ctx)
8458{
8459 return wlan_cfg80211_mc_cp_stats_get_wakelock_stats(hdd_ctx->hdd_psoc,
8460 hdd_ctx->wiphy);
8461}
8462#else
8463/**
8464 * wlan_hdd_process_wake_lock_stats() - wrapper function to absract cp_stats
8465 * or legacy get_wake_lock_stats API.
8466 * @hdd_ctx: pointer to hdd_ctx
8467 *
8468 * Return: 0 on success; error number otherwise.
8469 */
8470static int wlan_hdd_process_wake_lock_stats(struct hdd_context *hdd_ctx)
8471{
8472 int ret;
8473 QDF_STATUS qdf_status;
8474 struct sir_wake_lock_stats wake_lock_stats = {0};
8475
8476 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8477 if (qdf_status != QDF_STATUS_SUCCESS) {
8478 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
8479 return -EINVAL;
8480 }
8481
8482 ret = hdd_send_wakelock_stats(hdd_ctx, &wake_lock_stats);
8483 if (ret)
8484 hdd_err("Failed to post wake lock stats");
8485
8486 return ret;
8487}
8488#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308489
8490/**
8491 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8492 * @wiphy: wiphy pointer
8493 * @wdev: pointer to struct wireless_dev
8494 * @data: pointer to incoming NL vendor data
8495 * @data_len: length of @data
8496 *
8497 * This function parses the incoming NL vendor command data attributes and
8498 * invokes the SME Api and blocks on a completion variable.
8499 * WMA copies required data and invokes callback
8500 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8501 *
8502 * Return: 0 on success; error number otherwise.
8503 */
8504static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8505 struct wireless_dev *wdev,
8506 const void *data,
8507 int data_len)
8508{
Naveen Rawat3ff5cff2018-01-29 14:31:16 -08008509 int ret;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008510 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308511
Dustin Brown491d54b2018-03-14 12:39:11 -07008512 hdd_enter();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308513
8514 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008515 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308516 return -EINVAL;
8517 }
8518
Naveen Rawat3ff5cff2018-01-29 14:31:16 -08008519 ret = wlan_hdd_validate_context(hdd_ctx);
8520 if (0 != ret)
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308521 return -EINVAL;
8522
Naveen Rawat3ff5cff2018-01-29 14:31:16 -08008523 ret = wlan_hdd_process_wake_lock_stats(hdd_ctx);
Dustin Browne74003f2018-03-14 12:51:58 -07008524 hdd_exit();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308525 return ret;
8526}
8527
8528/**
8529 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8530 * @wiphy: wiphy pointer
8531 * @wdev: pointer to struct wireless_dev
8532 * @data: pointer to incoming NL vendor data
8533 * @data_len: length of @data
8534 *
8535 * This function parses the incoming NL vendor command data attributes and
8536 * invokes the SME Api and blocks on a completion variable.
8537 * WMA copies required data and invokes callback
8538 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8539 *
8540 * Return: 0 on success; error number otherwise.
8541 */
8542static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8543 struct wireless_dev *wdev,
8544 const void *data, int data_len)
8545{
8546 int ret;
8547
8548 cds_ssr_protect(__func__);
8549 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8550 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008551 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308552
8553 return ret;
8554}
8555
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308556/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308557 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8558 * @wiphy: wiphy structure pointer
8559 * @wdev: Wireless device structure pointer
8560 * @data: Pointer to the data received
8561 * @data_len: Length of @data
8562 *
8563 * This function reads wmi max bus size and fill in the skb with
8564 * NL attributes and send up the NL event.
8565 * Return: 0 on success; errno on failure
8566 */
8567static int
8568__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8569 struct wireless_dev *wdev,
8570 const void *data, int data_len)
8571{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008572 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308573 int ret_val;
8574 struct sk_buff *skb;
8575 uint32_t nl_buf_len;
8576
Dustin Brown491d54b2018-03-14 12:39:11 -07008577 hdd_enter();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308578
8579 ret_val = wlan_hdd_validate_context(hdd_ctx);
8580 if (ret_val)
8581 return ret_val;
8582
8583 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8584 hdd_err("Command not allowed in FTM mode");
8585 return -EINVAL;
8586 }
8587
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008588 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308589
8590 nl_buf_len = NLMSG_HDRLEN;
8591 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8592
8593 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8594 if (!skb) {
8595 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8596 return -ENOMEM;
8597 }
8598
8599 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8600 hdd_ctx->wmi_max_len)) {
8601 hdd_err("nla put failure");
8602 goto nla_put_failure;
8603 }
8604
8605 cfg80211_vendor_cmd_reply(skb);
8606
Dustin Browne74003f2018-03-14 12:51:58 -07008607 hdd_exit();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308608
8609 return 0;
8610
8611nla_put_failure:
8612 kfree_skb(skb);
8613 return -EINVAL;
8614}
8615
8616/**
8617 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8618 * @wiphy: wiphy structure pointer
8619 * @wdev: Wireless device structure pointer
8620 * @data: Pointer to the data received
8621 * @data_len: Length of @data
8622 *
8623 * Return: 0 on success; errno on failure
8624 */
8625static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8626 struct wireless_dev *wdev,
8627 const void *data, int data_len)
8628{
8629 int ret;
8630
8631 cds_ssr_protect(__func__);
8632 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8633 cds_ssr_unprotect(__func__);
8634
8635 return ret;
8636}
8637
8638/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308639 *__wlan_hdd_cfg80211_setband() - set band
8640 * @wiphy: Pointer to wireless phy
8641 * @wdev: Pointer to wireless device
8642 * @data: Pointer to data
8643 * @data_len: Length of @data
8644 *
8645 * Return: 0 on success, negative errno on failure
8646 */
8647static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8648 struct wireless_dev *wdev,
8649 const void *data, int data_len)
8650{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008651 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008652 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308653 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8654 int ret;
8655 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8656 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8657
Dustin Brown491d54b2018-03-14 12:39:11 -07008658 hdd_enter();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308659
8660 ret = wlan_hdd_validate_context(hdd_ctx);
8661 if (ret)
8662 return ret;
8663
Dustin Brown4ea21db2018-01-05 14:13:17 -08008664 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
8665 data, data_len, policy)) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07008666 hdd_err("Invalid ATTR");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308667 return -EINVAL;
8668 }
8669
8670 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07008671 hdd_err("attr SETBAND_VALUE failed");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308672 return -EINVAL;
8673 }
8674
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008675 ret = hdd_reg_set_band(dev,
8676 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308677
Dustin Browne74003f2018-03-14 12:51:58 -07008678 hdd_exit();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308679 return ret;
8680}
8681
8682/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308683 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8684 * @adapter: hdd adapter
8685 * @channel: channel number
8686 *
8687 * return: QDF status based on success or failure
8688 */
Jeff Johnsone5006672017-08-29 14:39:02 -07008689static QDF_STATUS wlan_hdd_validate_acs_channel(struct hdd_adapter *adapter,
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308690 int channel, int chan_bw)
8691{
8692 if (QDF_STATUS_SUCCESS !=
8693 wlan_hdd_validate_operation_channel(adapter, channel))
8694 return QDF_STATUS_E_FAILURE;
8695 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8696 channel,
8697 PHY_SINGLE_CHANNEL_CENTERED))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -07008698 hdd_info("channel %d is in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308699 return -EINVAL;
8700 }
8701
8702 if ((wlansap_is_channel_leaking_in_nol(
8703 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8704 channel, chan_bw))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -07008705 hdd_info("channel %d is leaking in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308706 return -EINVAL;
8707 }
8708
8709 return 0;
8710
8711}
8712
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008713static void hdd_update_acs_sap_config(struct hdd_context *hdd_ctx,
Jeff Johnsone4c11db2018-05-05 23:22:32 -07008714 tsap_config_t *sap_config,
Kapil Gupta8878ad92017-02-13 11:56:04 +05308715 struct hdd_vendor_chan_info *channel_list)
8716{
8717 sap_config->channel = channel_list->pri_ch;
8718
8719 sap_config->ch_params.center_freq_seg0 =
8720 channel_list->vht_seg0_center_ch;
8721 sap_config->ch_params.center_freq_seg1 =
8722 channel_list->vht_seg1_center_ch;
8723
8724 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8725 sap_config->ch_params.ch_width = channel_list->chan_width;
8726 if (sap_config->channel >= 36)
8727 sap_config->ch_width_orig =
8728 hdd_ctx->config->vhtChannelWidth;
8729 else
8730 sap_config->ch_width_orig =
8731 hdd_ctx->config->nChannelBondingMode24GHz ?
8732 eHT_CHANNEL_WIDTH_40MHZ :
8733 eHT_CHANNEL_WIDTH_20MHZ;
8734
8735 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8736 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8737 sap_config->acs_cfg.vht_seg0_center_ch =
8738 channel_list->vht_seg0_center_ch;
8739 sap_config->acs_cfg.vht_seg1_center_ch =
8740 channel_list->vht_seg1_center_ch;
8741 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8742}
8743
Jeff Johnsone5006672017-08-29 14:39:02 -07008744static int hdd_update_acs_channel(struct hdd_adapter *adapter, uint8_t reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +05308745 uint8_t channel_cnt,
8746 struct hdd_vendor_chan_info *channel_list)
8747{
Jeff Johnsone4c11db2018-05-05 23:22:32 -07008748 tsap_config_t *sap_config;
Jeff Johnson87251032017-08-29 13:31:11 -07008749 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008750 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308751 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008752 mac_handle_t mac_handle;
Kapil Gupta8878ad92017-02-13 11:56:04 +05308753
Min Liuab6ed4f2018-01-09 13:13:57 +08008754 if (!channel_list) {
8755 hdd_err("channel_list is NULL");
8756 return -EINVAL;
8757 }
8758
Kapil Gupta8878ad92017-02-13 11:56:04 +05308759 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnsonb9424862017-10-30 08:49:35 -07008760 sap_config = &adapter->session.ap.sap_config;
Kapil Gupta8878ad92017-02-13 11:56:04 +05308761
8762 if (QDF_TIMER_STATE_RUNNING ==
Jeff Johnsonb9424862017-10-30 08:49:35 -07008763 qdf_mc_timer_get_current_state(&adapter->session.
Kapil Gupta8878ad92017-02-13 11:56:04 +05308764 ap.vendor_acs_timer)) {
Jeff Johnsonb9424862017-10-30 08:49:35 -07008765 qdf_mc_timer_stop(&adapter->session.ap.vendor_acs_timer);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308766 }
8767
Min Liuab6ed4f2018-01-09 13:13:57 +08008768 if (channel_list->pri_ch == 0) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05308769 /* Check mode, set default channel */
8770 channel_list->pri_ch = 6;
8771 /*
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008772 * sap_select_default_oper_chan(mac_handle,
Kapil Gupta8878ad92017-02-13 11:56:04 +05308773 * sap_config->acs_cfg.hw_mode);
8774 */
8775 }
8776
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008777 mac_handle = hdd_ctx->mac_handle;
Kapil Gupta8878ad92017-02-13 11:56:04 +05308778 switch (reason) {
8779 /* SAP init case */
8780 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8781 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8782 /* Update Hostapd */
8783 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8784 break;
8785
8786 /* DFS detected on current channel */
8787 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8788 wlan_sap_update_next_channel(
8789 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8790 channel_list->pri_ch,
8791 channel_list->chan_width);
8792 status = sme_update_new_channel_event(
Jeff Johnson34fc63a2018-06-14 10:10:02 -07008793 mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -07008794 adapter->session_id);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308795 break;
8796
8797 /* LTE coex event on current channel */
8798 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8799 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8800 sap_config->acs_cfg.ch_width = channel_list->chan_width;
Jeff Johnson91df29d2017-10-27 19:29:50 -07008801 hdd_ap_ctx->sap_config.ch_width_orig =
Kapil Gupta8878ad92017-02-13 11:56:04 +05308802 channel_list->chan_width;
Min Liu2fef5792018-01-19 17:59:42 +08008803 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch,
8804 true);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308805 break;
8806
8807 default:
8808 hdd_info("invalid reason for timer invoke");
8809 }
Dustin Browne74003f2018-03-14 12:51:58 -07008810 hdd_exit();
Min Liuab6ed4f2018-01-09 13:13:57 +08008811 return qdf_status_to_os_return(status);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308812}
8813
8814/**
8815 * Define short name for vendor channel set config
8816 */
8817#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
Kapil Gupta8878ad92017-02-13 11:56:04 +05308818#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8819#define SET_CHAN_PRIMARY_CHANNEL \
8820 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8821#define SET_CHAN_SECONDARY_CHANNEL \
8822 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8823#define SET_CHAN_SEG0_CENTER_CHANNEL \
8824 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8825#define SET_CHAN_SEG1_CENTER_CHANNEL \
8826 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8827#define SET_CHAN_CHANNEL_WIDTH \
8828 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8829#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
Kapil Gupta63e75282017-05-18 20:55:10 +05308830#define SET_EXT_ACS_BAND QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND
Kapil Gupta8878ad92017-02-13 11:56:04 +05308831
8832/**
8833 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8834 * @channel_list: pointer to hdd_vendor_chan_info
8835 * @reason: channel change reason
8836 * @channel_cnt: channel count
8837 * @data: data
8838 * @data_len: data len
8839 *
8840 * Return: 0 on success, negative errno on failure
8841 */
8842static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8843 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8844 const void *data, int data_len)
8845{
8846 int rem, i = 0;
8847 struct nlattr *tb[SET_CHAN_MAX + 1];
8848 struct nlattr *tb2[SET_CHAN_MAX + 1];
8849 struct nlattr *curr_attr;
8850 struct hdd_vendor_chan_info *channel_list;
8851
Dustin Brown4ea21db2018-01-05 14:13:17 -08008852 if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05308853 hdd_err("Invalid ATTR");
8854 return -EINVAL;
8855 }
8856
8857 if (tb[SET_CHAN_REASON])
8858 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8859
Kapil Gupta63e75282017-05-18 20:55:10 +05308860 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem)
8861 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +05308862
Kapil Gupta63e75282017-05-18 20:55:10 +05308863 *channel_cnt = i;
8864
8865 if (i == 0)
8866 hdd_err("incorrect channel count");
Kapil Gupta8878ad92017-02-13 11:56:04 +05308867
8868 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8869 (*channel_cnt));
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05308870 if (NULL == channel_list) {
8871 hdd_err("Could not allocate for channel_list");
8872 return -ENOMEM;
8873 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05308874
Kapil Gupta63e75282017-05-18 20:55:10 +05308875 i = 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +05308876 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08008877 if (wlan_cfg80211_nla_parse(tb2, SET_CHAN_MAX,
8878 nla_data(curr_attr),
8879 nla_len(curr_attr), NULL)) {
8880 hdd_err("nla_parse failed");
Kapil Gupta8878ad92017-02-13 11:56:04 +05308881 return -EINVAL;
8882 }
Kapil Gupta63e75282017-05-18 20:55:10 +05308883 if (tb2[SET_EXT_ACS_BAND]) {
8884 channel_list[i].band =
8885 nla_get_u8(tb2[SET_EXT_ACS_BAND]);
8886 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05308887 /* Parse and Fetch allowed SSID list*/
8888 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8889 channel_list[i].pri_ch =
8890 nla_get_u8(
8891 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8892 }
8893 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8894 channel_list[i].ht_sec_ch =
8895 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8896 }
8897 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8898 channel_list[i].vht_seg0_center_ch =
8899 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8900 }
8901 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8902 channel_list[i].vht_seg1_center_ch =
8903 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8904 }
8905 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8906 channel_list[i].chan_width =
8907 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8908 }
Kapil Gupta63e75282017-05-18 20:55:10 +05308909 hdd_debug("index %d pri %d sec %d seg0 %d seg1 %d width %d",
Kapil Gupta8878ad92017-02-13 11:56:04 +05308910 i, channel_list[i].pri_ch,
8911 channel_list[i].ht_sec_ch,
8912 channel_list[i].vht_seg0_center_ch,
8913 channel_list[i].vht_seg1_center_ch,
8914 channel_list[i].chan_width);
8915 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +05308916 }
8917 *chan_list_ptr = channel_list;
8918
8919 return 0;
8920}
8921
8922/**
8923 * Undef short names for vendor set channel configuration
8924 */
8925#undef SET_CHAN_REASON
8926#undef SET_CHAN_CHANNEL_COUNT
8927#undef SET_CHAN_CHAN_LIST
8928#undef SET_CHAN_PRIMARY_CHANNEL
8929#undef SET_CHAN_SECONDARY_CHANNEL
8930#undef SET_CHAN_SEG0_CENTER_CHANNEL
8931#undef SET_CHAN_SEG1_CENTER_CHANNEL
8932#undef SET_CHAN_CHANNEL_WIDTH
8933#undef SET_CHAN_MAX
8934
8935/**
8936 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8937 * @wiphy: Pointer to wireless phy
8938 * @wdev: Pointer to wireless device
8939 * @data: Pointer to data
8940 * @data_len: Length of @data
8941 *
8942 * Return: 0 on success, negative errno on failure
8943 */
8944static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8945 struct wireless_dev *wdev,
8946 const void *data, int data_len)
8947{
8948 int ret_val;
8949 QDF_STATUS qdf_status;
8950 uint8_t channel_cnt = 0, reason = -1;
8951 struct hdd_vendor_chan_info *channel_list = NULL;
Jeff Johnsone5006672017-08-29 14:39:02 -07008952 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008953 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05308954 struct hdd_vendor_chan_info *channel_list_ptr;
Kapil Gupta8878ad92017-02-13 11:56:04 +05308955
Dustin Brown491d54b2018-03-14 12:39:11 -07008956 hdd_enter();
Kapil Gupta8878ad92017-02-13 11:56:04 +05308957
8958 ret_val = wlan_hdd_validate_context(hdd_ctx);
8959 if (ret_val)
8960 return ret_val;
8961
8962 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8963 hdd_err("Command not allowed in FTM mode");
8964 return -EINVAL;
8965 }
8966
8967 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8968 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8969 else {
8970 hdd_err("already timeout happened for acs");
8971 return -EINVAL;
8972 }
8973
8974 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8975 &channel_cnt, data, data_len);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05308976 channel_list_ptr = channel_list;
Kapil Gupta8878ad92017-02-13 11:56:04 +05308977 if (ret_val)
8978 return ret_val;
8979
8980 /* Validate channel to be set */
8981 while (channel_cnt && channel_list) {
8982 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8983 channel_list->pri_ch,
8984 channel_list->chan_width);
8985 if (qdf_status == QDF_STATUS_SUCCESS)
8986 break;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05308987 else if (channel_cnt == 1) {
8988 hdd_err("invalid channel %d received from app",
8989 channel_list->pri_ch);
8990 channel_list->pri_ch = 0;
8991 break;
8992 }
8993
Kapil Gupta8878ad92017-02-13 11:56:04 +05308994 channel_cnt--;
8995 channel_list++;
8996 }
Min Liuab6ed4f2018-01-09 13:13:57 +08008997
Kapil Gupta8878ad92017-02-13 11:56:04 +05308998 if ((channel_cnt <= 0) || !channel_list) {
Jeff Johnson36e74c42017-09-18 08:15:42 -07008999 hdd_err("no available channel/chanlist %d/%pK", channel_cnt,
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05309000 channel_list);
9001 qdf_mem_free(channel_list_ptr);
Kapil Gupta8878ad92017-02-13 11:56:04 +05309002 return -EINVAL;
9003 }
9004
Min Liuab6ed4f2018-01-09 13:13:57 +08009005 hdd_debug("received primary channel as %d", channel_list->pri_ch);
9006
9007 ret_val = hdd_update_acs_channel(adapter, reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +05309008 channel_cnt, channel_list);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05309009 qdf_mem_free(channel_list_ptr);
Min Liuab6ed4f2018-01-09 13:13:57 +08009010 return ret_val;
Kapil Gupta8878ad92017-02-13 11:56:04 +05309011}
9012
9013/**
9014 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9015 * @wiphy: Pointer to wireless phy
9016 * @wdev: Pointer to wireless device
9017 * @data: Pointer to data
9018 * @data_len: Length of @data
9019 *
9020 * Return: 0 on success, negative errno on failure
9021 */
9022static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9023 struct wireless_dev *wdev,
9024 const void *data, int data_len)
9025{
9026 int ret;
9027
9028 cds_ssr_protect(__func__);
9029 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
9030 data_len);
9031 cds_ssr_protect(__func__);
9032
9033 return ret;
9034}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309035
9036/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309037 * wlan_hdd_cfg80211_setband() - Wrapper to setband
9038 * @wiphy: wiphy structure pointer
9039 * @wdev: Wireless device structure pointer
9040 * @data: Pointer to the data received
9041 * @data_len: Length of @data
9042 *
9043 * Return: 0 on success; errno on failure
9044 */
9045static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9046 struct wireless_dev *wdev,
9047 const void *data, int data_len)
9048{
9049 int ret;
9050
9051 cds_ssr_protect(__func__);
9052 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
9053 cds_ssr_unprotect(__func__);
9054
9055 return ret;
9056}
9057
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009058/**
9059 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
9060 * @nl80211_value: Vendor command attribute value
9061 * @wmi_value: Pointer to return converted WMI return value
9062 *
9063 * Convert NL80211 vendor command value for SAR limit set to WMI value
9064 * Return: 0 on success, -1 on invalid value
9065 */
9066static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
9067 u32 *wmi_value)
9068{
9069 int ret = 0;
9070
9071 switch (nl80211_value) {
9072 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
9073 *wmi_value = WMI_SAR_FEATURE_OFF;
9074 break;
9075 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
9076 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
9077 break;
9078 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
9079 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
9080 break;
9081 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
9082 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
9083 break;
9084 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
9085 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
9086 break;
9087 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
9088 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
9089 break;
9090 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
9091 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
9092 break;
Kabilan Kannancaa85502018-04-13 18:04:58 -07009093 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0:
9094 *wmi_value = WMI_SAR_FEATURE_ON_SAR_V2_0;
9095 break;
9096
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009097 default:
9098 ret = -1;
9099 }
9100 return ret;
9101}
9102
Jeff Johnson354c20b2018-07-17 20:15:56 -07009103#ifdef WLAN_FEATURE_SARV1_TO_SARV2
9104/**
9105 * hdd_convert_sarv1_to_sarv2() - convert SAR V1 BDF reference to SAR V2
9106 * @hdd_ctx: The HDD global context
9107 * @tb: The parsed array of netlink attributes
9108 * @sar_limit_cmd: The WMI command to be filled
9109 *
9110 * This feature/function is designed to solve the following problem:
9111 * 1) Userspace application was written to use SARv1 BDF entries
9112 * 2) Product is configured with SAR V2 BDF entries
9113 *
9114 * So if this feature is enabled, and if the firmware is configured
9115 * with SAR V2 support, and if the incoming request is to enable a SAR
9116 * V1 BDF entry, then the WMI command is generated to actually
9117 * configure a SAR V2 BDF entry.
9118 *
9119 * Return: true if conversion was performed and @sar_limit_cmd is
9120 * ready to be sent to firmware. Otherwise false in which case the
9121 * normal parsing logic should be applied.
9122 */
9123
9124static bool
9125hdd_convert_sarv1_to_sarv2(struct hdd_context *hdd_ctx,
9126 struct nlattr *tb[],
9127 struct sar_limit_cmd_params *sar_limit_cmd)
9128{
9129 struct nlattr *attr;
9130 uint32_t bdf_index, set;
9131 struct sar_limit_cmd_row *row;
9132
9133 if (hdd_ctx->sar_version != SAR_VERSION_2) {
9134 hdd_debug("SAR version: %d", hdd_ctx->sar_version);
9135 return false;
9136 }
9137
9138 attr = tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE];
9139 if (!attr)
9140 return false;
9141
9142 bdf_index = nla_get_u32(attr);
9143
9144 if ((bdf_index >= QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0) &&
9145 (bdf_index <= QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4)) {
9146 set = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0;
9147 } else if (bdf_index == QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE) {
9148 set = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE;
9149 bdf_index = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0;
9150 } else {
9151 return false;
9152 }
9153
9154 /* Need two rows to hold the per-chain V2 power index
9155 * To disable SARv2 limit, send chain, num_limits_row and
9156 * power limit set to 0 (except power index 0xff)
9157 */
9158 row = qdf_mem_malloc(2 * sizeof(*row));
9159 if (!row)
9160 return false;
9161
9162 if (wlan_hdd_cfg80211_sar_convert_limit_set(
9163 set, &sar_limit_cmd->sar_enable)) {
9164 hdd_err("Failed to convert SAR limit to WMI value");
9165 return false;
9166 }
9167
9168 sar_limit_cmd->commit_limits = 1;
9169 sar_limit_cmd->num_limit_rows = 2;
9170 sar_limit_cmd->sar_limit_row_list = row;
9171 row[0].limit_value = bdf_index;
9172 row[1].limit_value = row[0].limit_value;
9173 row[0].chain_id = 0;
9174 row[1].chain_id = 1;
9175 row[0].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
9176 row[1].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
9177
9178 return true;
9179}
9180
9181#else /* WLAN_FEATURE_SARV1_TO_SARV2 */
9182
9183static bool
9184hdd_convert_sarv1_to_sarv2(struct hdd_context *hdd_ctx,
9185 struct nlattr *tb[],
9186 struct sar_limit_cmd_params *sar_limit_cmd)
9187{
9188 return false;
9189}
9190
9191#endif /* WLAN_FEATURE_SARV1_TO_SARV2 */
9192
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009193/**
9194 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
9195 * @nl80211_value: Vendor command attribute value
9196 * @wmi_value: Pointer to return converted WMI return value
9197 *
9198 * Convert NL80211 vendor command value for SAR BAND to WMI value
9199 * Return: 0 on success, -1 on invalid value
9200 */
9201static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
9202{
9203 int ret = 0;
9204
9205 switch (nl80211_value) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -07009206 case HDD_NL80211_BAND_2GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009207 *wmi_value = WMI_SAR_2G_ID;
9208 break;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -07009209 case HDD_NL80211_BAND_5GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009210 *wmi_value = WMI_SAR_5G_ID;
9211 break;
9212 default:
9213 ret = -1;
9214 }
9215 return ret;
9216}
9217
9218/**
9219 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9220 * @nl80211_value: Vendor command attribute value
9221 * @wmi_value: Pointer to return converted WMI return value
9222 *
9223 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9224 * Return: 0 on success, -1 on invalid value
9225 */
9226static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9227 u32 *wmi_value)
9228{
9229 int ret = 0;
9230
9231 switch (nl80211_value) {
9232 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9233 *wmi_value = WMI_SAR_MOD_CCK;
9234 break;
9235 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9236 *wmi_value = WMI_SAR_MOD_OFDM;
9237 break;
9238 default:
9239 ret = -1;
9240 }
9241 return ret;
9242}
9243
Jeff Johnsonb17a93c2017-06-02 12:26:55 -07009244static const struct nla_policy
9245sar_limits_policy[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1] = {
9246 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE] = {.type = NLA_U32},
9247 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS] = {.type = NLA_U32},
9248 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND] = {.type = NLA_U32},
9249 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN] = {.type = NLA_U32},
9250 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION] = {.type = NLA_U32},
9251 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT] = {.type = NLA_U32},
Kabilan Kannancaa85502018-04-13 18:04:58 -07009252 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX] = {.type = NLA_U32},
Jeff Johnsonb17a93c2017-06-02 12:26:55 -07009253};
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009254
9255/**
9256 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9257 * @wiphy: Pointer to wireless phy
9258 * @wdev: Pointer to wireless device
9259 * @data: Pointer to data
9260 * @data_len: Length of @data
9261 *
9262 * This function is used to setup Specific Absorption Rate limit specs.
9263 *
9264 * Return: 0 on success, negative errno on failure
9265 */
9266static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9267 struct wireless_dev *wdev,
9268 const void *data, int data_len)
9269{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009270 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009271 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9272 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9273 *sar_spec_list;
9274 struct sar_limit_cmd_params sar_limit_cmd = {0};
9275 int ret = -EINVAL, i = 0, rem = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009276 mac_handle_t mac_handle;
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009277
Dustin Brown491d54b2018-03-14 12:39:11 -07009278 hdd_enter();
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009279
9280 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9281 hdd_err("Command not allowed in FTM mode");
9282 return -EPERM;
9283 }
9284
9285 if (wlan_hdd_validate_context(hdd_ctx))
9286 return -EINVAL;
9287
Dustin Brown4ea21db2018-01-05 14:13:17 -08009288 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9289 data, data_len, sar_limits_policy)) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009290 hdd_err("Invalid SAR attributes");
9291 return -EINVAL;
9292 }
9293
Jeff Johnson354c20b2018-07-17 20:15:56 -07009294 /* is special SAR V1 => SAR V2 logic enabled and applicable? */
9295 if (hdd_convert_sarv1_to_sarv2(hdd_ctx, tb, &sar_limit_cmd))
9296 goto send_sar_limits;
9297
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009298 /* Vendor command manadates all SAR Specs in single call */
9299 sar_limit_cmd.commit_limits = 1;
9300 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9301 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9302 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9303 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9304 &sar_limit_cmd.sar_enable) < 0) {
9305 hdd_err("Invalid SAR Enable attr");
9306 goto fail;
9307 }
9308 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009309 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009310
9311 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9312 sar_limit_cmd.num_limit_rows = nla_get_u32(
9313 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009314 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009315 sar_limit_cmd.num_limit_rows);
9316 }
9317 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9318 hdd_err("SAR Spec list exceed supported size");
9319 goto fail;
9320 }
9321 if (sar_limit_cmd.num_limit_rows == 0)
9322 goto send_sar_limits;
9323 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9324 struct sar_limit_cmd_row) *
9325 sar_limit_cmd.num_limit_rows);
9326 if (!sar_limit_cmd.sar_limit_row_list) {
9327 ret = -ENOMEM;
9328 goto fail;
9329 }
9330 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9331 hdd_err("Invalid SAR SPECs list");
9332 goto fail;
9333 }
9334
9335 nla_for_each_nested(sar_spec_list,
9336 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9337 if (i == sar_limit_cmd.num_limit_rows) {
9338 hdd_warn("SAR Cmd has excess SPECs in list");
9339 break;
9340 }
9341
Dustin Brown4ea21db2018-01-05 14:13:17 -08009342 if (wlan_cfg80211_nla_parse(sar_spec,
9343 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9344 nla_data(sar_spec_list),
9345 nla_len(sar_spec_list),
9346 sar_limits_policy)) {
9347 hdd_err("nla_parse failed for SAR Spec list");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009348 goto fail;
9349 }
9350 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9351 if (sar_spec[
9352 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9353 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9354 nla_get_u32(sar_spec[
9355 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
Kabilan Kannancaa85502018-04-13 18:04:58 -07009356 } else if (sar_spec[
9357 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX]) {
9358 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9359 nla_get_u32(sar_spec[
9360 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX]);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009361 } else {
Kabilan Kannancaa85502018-04-13 18:04:58 -07009362 hdd_err("SAR Spec does not have power limit or index value");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009363 goto fail;
9364 }
9365
9366 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9367 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9368 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9369 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9370 < 0) {
9371 hdd_err("Invalid SAR Band attr");
9372 goto fail;
9373 }
9374 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9375 WMI_SAR_BAND_ID_VALID_MASK;
9376 }
9377 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9378 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9379 nla_get_u32(sar_spec[
9380 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9381 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9382 WMI_SAR_CHAIN_ID_VALID_MASK;
9383 }
9384 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9385 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9386 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9387 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9388 < 0) {
9389 hdd_err("Invalid SAR Modulation attr");
9390 goto fail;
9391 }
9392 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9393 WMI_SAR_MOD_ID_VALID_MASK;
9394 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009395 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009396 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9397 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9398 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9399 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9400 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9401 i++;
9402 }
9403
9404 if (i < sar_limit_cmd.num_limit_rows) {
9405 hdd_warn("SAR Cmd has less SPECs in list");
9406 sar_limit_cmd.num_limit_rows = i;
9407 }
9408
9409send_sar_limits:
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009410 mac_handle = hdd_ctx->mac_handle;
9411 if (sme_set_sar_power_limits(mac_handle, &sar_limit_cmd) ==
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009412 QDF_STATUS_SUCCESS)
9413 ret = 0;
9414fail:
9415 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9416 return ret;
9417}
9418
9419/**
9420 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9421 * @wiphy: Pointer to wireless phy
9422 * @wdev: Pointer to wireless device
9423 * @data: Pointer to data
9424 * @data_len: Length of @data
9425 *
9426 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9427 *
9428 * Return: 0 on success, negative errno on failure
9429 */
9430static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9431 struct wireless_dev *wdev,
9432 const void *data,
9433 int data_len)
9434{
9435 int ret;
9436
9437 cds_ssr_protect(__func__);
9438 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9439 data_len);
9440 cds_ssr_unprotect(__func__);
9441
9442 return ret;
9443}
9444
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309445static const struct
9446nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9447 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9448 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9449 .len = QDF_MAC_ADDR_SIZE},
9450};
9451
Jeff Johnson43975142018-07-04 15:33:47 -07009452void wlan_hdd_rso_cmd_status_cb(hdd_handle_t hdd_handle,
9453 struct rso_cmd_status *rso_status)
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309454{
Jeff Johnson43975142018-07-04 15:33:47 -07009455 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Jeff Johnsone5006672017-08-29 14:39:02 -07009456 struct hdd_adapter *adapter;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309457
9458 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9459 if (!adapter) {
9460 hdd_err("adapter NULL");
9461 return;
9462 }
9463
9464 adapter->lfr_fw_status.is_disabled = rso_status->status;
9465 complete(&adapter->lfr_fw_status.disable_lfr_event);
9466}
9467
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309468/**
9469 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9470 * @wiphy: Pointer to wireless phy
9471 * @wdev: Pointer to wireless device
9472 * @data: Pointer to data
9473 * @data_len: Length of @data
9474 *
9475 * This function is used to enable/disable roaming using vendor commands
9476 *
9477 * Return: 0 on success, negative errno on failure
9478 */
9479static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9480 struct wireless_dev *wdev,
9481 const void *data, int data_len)
9482{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009483 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309484 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009485 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309486 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Abhishek Singh1f217ec2017-12-22 11:48:27 +05309487 uint32_t is_fast_roam_enabled;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309488 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309489 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309490 unsigned long rc;
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009491 struct hdd_station_ctx *hdd_sta_ctx =
9492 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9493 mac_handle_t mac_handle;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309494
Dustin Brownfdf17c12018-03-14 12:55:34 -07009495 hdd_enter_dev(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309496
9497 ret = wlan_hdd_validate_context(hdd_ctx);
9498 if (0 != ret)
9499 return ret;
9500
9501 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9502 hdd_err("Command not allowed in FTM mode");
9503 return -EINVAL;
9504 }
9505
Dustin Brown4ea21db2018-01-05 14:13:17 -08009506 ret = wlan_cfg80211_nla_parse(tb,
9507 QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9508 qca_wlan_vendor_attr);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309509 if (ret) {
9510 hdd_err("Invalid ATTR");
9511 return -EINVAL;
9512 }
9513
9514 /* Parse and fetch Enable flag */
9515 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9516 hdd_err("attr enable failed");
9517 return -EINVAL;
9518 }
9519
9520 is_fast_roam_enabled = nla_get_u32(
9521 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Abhishek Singh1f217ec2017-12-22 11:48:27 +05309522 hdd_debug("isFastRoamEnabled %d", is_fast_roam_enabled);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309523
9524 /* Update roaming */
Jeff Johnson34fc63a2018-06-14 10:10:02 -07009525 mac_handle = hdd_ctx->mac_handle;
9526 qdf_status = sme_config_fast_roaming(mac_handle, adapter->session_id,
Abhishek Singh1f217ec2017-12-22 11:48:27 +05309527 is_fast_roam_enabled);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309528 if (qdf_status != QDF_STATUS_SUCCESS)
9529 hdd_err("sme_config_fast_roaming failed with status=%d",
9530 qdf_status);
9531 ret = qdf_status_to_os_return(qdf_status);
9532
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309533 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.connState &&
Abhishek Singh1f217ec2017-12-22 11:48:27 +05309534 QDF_IS_STATUS_SUCCESS(qdf_status) && !is_fast_roam_enabled) {
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309535
9536 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309537 /*
9538 * wait only for LFR disable in fw as LFR enable
9539 * is always success
9540 */
9541 rc = wait_for_completion_timeout(
9542 &adapter->lfr_fw_status.disable_lfr_event,
9543 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9544 if (!rc) {
9545 hdd_err("Timed out waiting for RSO CMD status");
9546 return -ETIMEDOUT;
9547 }
9548
9549 if (!adapter->lfr_fw_status.is_disabled) {
9550 hdd_err("Roam disable attempt in FW fails");
9551 return -EBUSY;
9552 }
9553 }
9554
Dustin Browne74003f2018-03-14 12:51:58 -07009555 hdd_exit();
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309556 return ret;
9557}
9558
9559/**
9560 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9561 * @wiphy: Pointer to wireless phy
9562 * @wdev: Pointer to wireless device
9563 * @data: Pointer to data
9564 * @data_len: Length of @data
9565 *
9566 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9567 *
9568 * Return: 0 on success, negative errno on failure
9569 */
9570static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9571 struct wireless_dev *wdev,
9572 const void *data, int data_len)
9573{
9574 int ret;
9575
9576 cds_ssr_protect(__func__);
9577 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9578 cds_ssr_unprotect(__func__);
9579
9580 return ret;
9581}
9582
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309583/*
9584 * define short names for the global vendor params
9585 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
9586 */
9587#define STATS_SET_INVALID \
9588 QCA_ATTR_NUD_STATS_SET_INVALID
9589#define STATS_SET_START \
9590 QCA_ATTR_NUD_STATS_SET_START
9591#define STATS_GW_IPV4 \
9592 QCA_ATTR_NUD_STATS_GW_IPV4
9593#define STATS_SET_DATA_PKT_INFO \
9594 QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
9595#define STATS_SET_MAX \
9596 QCA_ATTR_NUD_STATS_SET_MAX
9597
9598const struct nla_policy
9599qca_wlan_vendor_set_nud_stats[STATS_SET_MAX + 1] = {
9600 [STATS_SET_START] = {.type = NLA_FLAG },
9601 [STATS_GW_IPV4] = {.type = NLA_U32 },
9602 [STATS_SET_DATA_PKT_INFO] = {.type = NLA_U32 },
9603};
9604
9605/* define short names for the global vendor params */
9606#define CONNECTIVITY_STATS_SET_INVALID \
9607 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
9608#define STATS_PKT_INFO_TYPE \
9609 QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
9610#define STATS_DNS_DOMAIN_NAME \
9611 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
9612#define STATS_SRC_PORT \
9613 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
9614#define STATS_DEST_PORT \
9615 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
9616#define STATS_DEST_IPV4 \
9617 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
9618#define STATS_DEST_IPV6 \
9619 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
9620#define CONNECTIVITY_STATS_SET_MAX \
9621 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
9622
9623const struct nla_policy
9624qca_wlan_vendor_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
9625 [STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
9626 [STATS_DNS_DOMAIN_NAME] = {.type = NLA_BINARY,
9627 .len = DNS_DOMAIN_NAME_MAX_LEN },
9628 [STATS_SRC_PORT] = {.type = NLA_U32 },
9629 [STATS_DEST_PORT] = {.type = NLA_U32 },
9630 [STATS_DEST_IPV4] = {.type = NLA_U32 },
9631 [STATS_DEST_IPV6] = {.type = NLA_BINARY,
9632 .len = ICMPv6_ADDR_LEN },
9633};
9634
9635/**
9636 * hdd_dns_unmake_name_query() - Convert an uncompressed DNS name to a
9637 * NUL-terminated string
9638 * @name: DNS name
9639 *
9640 * Return: Produce a printable version of a DNS name.
9641 */
9642static inline uint8_t *hdd_dns_unmake_name_query(uint8_t *name)
9643{
9644 uint8_t *p;
9645 unsigned int len;
9646
9647 p = name;
9648 while ((len = *p)) {
9649 *(p++) = '.';
9650 p += len;
9651 }
9652
9653 return name + 1;
9654}
9655
9656/**
9657 * hdd_dns_make_name_query() - Convert a standard NUL-terminated string
9658 * to DNS name
9659 * @string: Name as a NUL-terminated string
9660 * @buf: Buffer in which to place DNS name
9661 *
9662 * DNS names consist of "<length>element" pairs.
9663 *
9664 * Return: Byte following constructed DNS name
9665 */
9666static uint8_t *hdd_dns_make_name_query(const uint8_t *string, uint8_t *buf)
9667{
9668 uint8_t *length_byte = buf++;
9669 uint8_t c;
9670
9671 while ((c = *(string++))) {
9672 if (c == '.') {
9673 *length_byte = buf - length_byte - 1;
9674 length_byte = buf;
9675 }
9676 *(buf++) = c;
9677 }
9678 *length_byte = buf - length_byte - 1;
9679 *(buf++) = '\0';
9680 return buf;
9681}
9682
9683/**
9684 * hdd_set_clear_connectivity_check_stats_info() - set/clear stats info
9685 * @adapter: Pointer to hdd adapter
9686 * @arp_stats_params: arp stats structure to be sent to FW
9687 * @tb: nl attribute
9688 * @is_set_stats: set/clear stats
9689 *
9690 *
9691 * Return: 0 on success, negative errno on failure
9692 */
9693static int hdd_set_clear_connectivity_check_stats_info(
9694 struct hdd_adapter *adapter,
9695 struct set_arp_stats_params *arp_stats_params,
9696 struct nlattr **tb, bool is_set_stats)
9697{
9698 struct nlattr *tb2[CONNECTIVITY_STATS_SET_MAX + 1];
9699 struct nlattr *curr_attr = NULL;
9700 int err = 0;
9701 uint32_t pkt_bitmap;
9702 int rem;
9703
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309704 /* Set NUD command for start tracking is received. */
9705 nla_for_each_nested(curr_attr,
9706 tb[STATS_SET_DATA_PKT_INFO],
9707 rem) {
9708
9709 if (wlan_cfg80211_nla_parse(tb2,
9710 CONNECTIVITY_STATS_SET_MAX,
9711 nla_data(curr_attr), nla_len(curr_attr),
9712 qca_wlan_vendor_set_connectivity_check_stats)) {
9713 hdd_err("nla_parse failed");
9714 err = -EINVAL;
9715 goto end;
9716 }
9717
9718 if (tb2[STATS_PKT_INFO_TYPE]) {
9719 pkt_bitmap = nla_get_u32(tb2[STATS_PKT_INFO_TYPE]);
9720 if (!pkt_bitmap) {
9721 hdd_err("pkt tracking bitmap is empty");
9722 err = -EINVAL;
9723 goto end;
9724 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +05309725
9726 if (is_set_stats) {
9727 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
9728 arp_stats_params->flag = true;
9729 adapter->pkt_type_bitmap |=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309730 arp_stats_params->pkt_type_bitmap;
9731
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +05309732 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
Srinivas Girigowda683726a2018-09-07 15:10:40 -07009733 if (!tb[STATS_GW_IPV4]) {
9734 hdd_err("GW ipv4 address is not present");
9735 err = -EINVAL;
9736 goto end;
9737 }
9738 arp_stats_params->ip_addr =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309739 nla_get_u32(tb[STATS_GW_IPV4]);
Srinivas Girigowda683726a2018-09-07 15:10:40 -07009740 arp_stats_params->pkt_type =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309741 WLAN_NUD_STATS_ARP_PKT_TYPE;
Srinivas Girigowda683726a2018-09-07 15:10:40 -07009742 adapter->track_arp_ip =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309743 arp_stats_params->ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309744 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +05309745
9746 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
9747 uint8_t *domain_name;
9748
9749 if (!tb2[STATS_DNS_DOMAIN_NAME]) {
9750 hdd_err("DNS domain id is not present");
9751 err = -EINVAL;
9752 goto end;
9753 }
9754 domain_name = nla_data(
9755 tb2[STATS_DNS_DOMAIN_NAME]);
9756 adapter->track_dns_domain_len =
9757 nla_len(tb2[
9758 STATS_DNS_DOMAIN_NAME]);
9759 hdd_dns_make_name_query(domain_name,
9760 adapter->dns_payload);
9761 /* DNStracking isn't supported in FW. */
9762 arp_stats_params->pkt_type_bitmap &=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309763 ~CONNECTIVITY_CHECK_SET_DNS;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309764 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +05309765
9766 if (pkt_bitmap &
9767 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
9768 if (!tb2[STATS_SRC_PORT] ||
9769 !tb2[STATS_DEST_PORT]) {
9770 hdd_err("Source/Dest port is not present");
9771 err = -EINVAL;
9772 goto end;
9773 }
9774 arp_stats_params->tcp_src_port =
9775 nla_get_u32(
9776 tb2[STATS_SRC_PORT]);
9777 arp_stats_params->tcp_dst_port =
9778 nla_get_u32(
9779 tb2[STATS_DEST_PORT]);
9780 adapter->track_src_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309781 arp_stats_params->tcp_src_port;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +05309782 adapter->track_dest_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309783 arp_stats_params->tcp_dst_port;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309784 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +05309785
9786 if (pkt_bitmap &
9787 CONNECTIVITY_CHECK_SET_ICMPV4) {
9788 if (!tb2[STATS_DEST_IPV4]) {
9789 hdd_err("destination ipv4 address to track ping packets is not present");
9790 err = -EINVAL;
9791 goto end;
9792 }
9793 arp_stats_params->icmp_ipv4 =
9794 nla_get_u32(
9795 tb2[STATS_DEST_IPV4]);
9796 adapter->track_dest_ipv4 =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309797 arp_stats_params->icmp_ipv4;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +05309798 }
9799 } else {
9800 /* clear stats command received */
9801 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
9802 arp_stats_params->flag = false;
9803 adapter->pkt_type_bitmap &=
9804 (~arp_stats_params->pkt_type_bitmap);
9805
9806 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
9807 arp_stats_params->pkt_type =
9808 WLAN_NUD_STATS_ARP_PKT_TYPE;
9809 qdf_mem_zero(&adapter->hdd_stats.
9810 hdd_arp_stats,
9811 sizeof(adapter->hdd_stats.
9812 hdd_arp_stats));
9813 adapter->track_arp_ip = 0;
9814 }
9815
9816 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
9817 /* DNStracking isn't supported in FW. */
9818 arp_stats_params->pkt_type_bitmap &=
9819 ~CONNECTIVITY_CHECK_SET_DNS;
9820 qdf_mem_zero(&adapter->hdd_stats.
9821 hdd_dns_stats,
9822 sizeof(adapter->hdd_stats.
9823 hdd_dns_stats));
9824 qdf_mem_zero(adapter->dns_payload,
9825 adapter->track_dns_domain_len);
9826 adapter->track_dns_domain_len = 0;
9827 }
9828
9829 if (pkt_bitmap &
9830 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
9831 qdf_mem_zero(&adapter->hdd_stats.
9832 hdd_tcp_stats,
9833 sizeof(adapter->hdd_stats.
9834 hdd_tcp_stats));
9835 adapter->track_src_port = 0;
9836 adapter->track_dest_port = 0;
9837 }
9838
9839 if (pkt_bitmap &
9840 CONNECTIVITY_CHECK_SET_ICMPV4) {
9841 qdf_mem_zero(&adapter->hdd_stats.
9842 hdd_icmpv4_stats,
9843 sizeof(adapter->hdd_stats.
9844 hdd_icmpv4_stats));
9845 adapter->track_dest_ipv4 = 0;
9846 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309847 }
9848 } else {
9849 hdd_err("stats list empty");
9850 err = -EINVAL;
9851 goto end;
9852 }
9853 }
9854
9855end:
9856 return err;
9857}
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309858
Jeff Johnsonf6182e42018-07-03 14:46:17 -07009859void hdd_update_cca_info_cb(hdd_handle_t hdd_handle, uint32_t congestion,
Poddar, Siddarth31797fa2018-01-22 17:24:15 +05309860 uint32_t vdev_id)
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309861{
Jeff Johnsonf6182e42018-07-03 14:46:17 -07009862 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309863 int status;
Jeff Johnsone5006672017-08-29 14:39:02 -07009864 struct hdd_adapter *adapter = NULL;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07009865 struct hdd_station_ctx *hdd_sta_ctx;
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309866
9867 status = wlan_hdd_validate_context(hdd_ctx);
9868 if (status != 0)
9869 return;
9870
9871 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9872 if (adapter == NULL) {
9873 hdd_err("vdev_id %d does not exist with host", vdev_id);
9874 return;
9875 }
9876
9877 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9878 hdd_sta_ctx->conn_info.cca = congestion;
9879 hdd_info("congestion:%d", congestion);
9880}
9881
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309882static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9883 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9884 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9885 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9886 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9887};
9888
9889/**
9890 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9891 * @wiphy: Pointer to wireless phy
9892 * @wdev: Pointer to wireless device
9893 * @data: Pointer to data
9894 * @data_len: Length of @data
9895 *
9896 * Return: 0 on success, negative errno on failure
9897 */
9898static int
9899__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9900 struct wireless_dev *wdev,
9901 const void *data,
9902 int data_len)
9903{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009904 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309905 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9906 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9907 struct nlattr *apth;
9908 int rem;
9909 int ret = 1;
9910 int print_idx = -1;
9911 int module_id = -1;
9912 int bit_mask = -1;
9913 int status;
9914
Dustin Brown491d54b2018-03-14 12:39:11 -07009915 hdd_enter();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309916
9917 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9918 hdd_err("Command not allowed in FTM mode");
9919 return -EINVAL;
9920 }
9921
9922 ret = wlan_hdd_validate_context(hdd_ctx);
9923 if (ret != 0)
9924 return -EINVAL;
9925
9926 print_idx = qdf_get_pidx();
9927 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9928 hdd_err("Invalid print controle object index");
9929 return -EINVAL;
9930 }
9931
Dustin Brown4ea21db2018-01-05 14:13:17 -08009932 if (wlan_cfg80211_nla_parse(tb1,
9933 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9934 data, data_len,
9935 qca_wlan_vendor_set_trace_level_policy)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309936 hdd_err("Invalid attr");
9937 return -EINVAL;
9938 }
9939
9940 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9941 hdd_err("attr trace level param failed");
9942 return -EINVAL;
9943 }
9944
9945 nla_for_each_nested(apth,
9946 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08009947 if (wlan_cfg80211_nla_parse(tb2,
9948 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9949 nla_data(apth), nla_len(apth), NULL)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309950 hdd_err("Invalid attr");
9951 return -EINVAL;
9952 }
9953
9954 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9955 hdd_err("attr Module ID failed");
9956 return -EINVAL;
9957 }
9958 module_id = nla_get_u32
9959 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9960
9961 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9962 hdd_err("attr Verbose mask failed");
9963 return -EINVAL;
9964 }
9965 bit_mask = nla_get_u32
9966 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9967
9968 status = hdd_qdf_trace_enable(module_id, bit_mask);
9969
9970 if (status != 0)
9971 hdd_err("can not set verbose mask %d for the category %d",
9972 bit_mask, module_id);
9973 }
9974
Dustin Browne74003f2018-03-14 12:51:58 -07009975 hdd_exit();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309976 return ret;
9977}
9978
9979/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309980 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9981 * @wiphy: Pointer to wireless phy
9982 * @wdev: Pointer to wireless device
9983 * @data: Pointer to data
9984 * @data_len: Length of @data
9985 *
9986 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9987 *
9988 * Return: 0 on success, negative errno on failure
9989 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309990
9991static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9992 struct wireless_dev *wdev,
9993 const void *data,
9994 int data_len)
9995{
9996 int ret;
9997
9998 cds_ssr_protect(__func__);
9999 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
10000 cds_ssr_unprotect(__func__);
10001
10002 return ret;
10003}
10004
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010005/**
10006 * __wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
10007 * @wiphy: pointer to wireless wiphy structure.
10008 * @wdev: pointer to wireless_dev structure.
10009 * @data: pointer to apfind configuration data.
10010 * @data_len: the length in byte of apfind data.
10011 *
10012 * This is called when wlan driver needs to send arp stats to
10013 * firmware.
10014 *
10015 * Return: An error code or 0 on success.
10016 */
10017static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
10018 struct wireless_dev *wdev,
10019 const void *data, int data_len)
10020{
10021 struct nlattr *tb[STATS_SET_MAX + 1];
10022 struct net_device *dev = wdev->netdev;
10023 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
10024 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010025 struct set_arp_stats_params arp_stats_params = {0};
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010026 int err = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010027 mac_handle_t mac_handle;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010028
Dustin Brown491d54b2018-03-14 12:39:11 -070010029 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010030
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053010031 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10032 hdd_err("Command not allowed in FTM mode");
10033 return -EINVAL;
10034 }
10035
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010036 err = wlan_hdd_validate_context(hdd_ctx);
10037 if (0 != err)
10038 return err;
10039
Dustin Brown4ea21db2018-01-05 14:13:17 -080010040 err = wlan_cfg80211_nla_parse(tb, STATS_SET_MAX, data, data_len,
10041 qca_wlan_vendor_set_nud_stats);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010042 if (err) {
Dustin Browna2868622018-03-20 11:38:14 -070010043 hdd_err("STATS_SET_START ATTR");
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010044 return err;
10045 }
10046
Yeshwanth Sriram Guntukad5aae7f2017-11-27 14:33:51 +053010047 if (adapter->session_id == HDD_SESSION_ID_INVALID) {
10048 hdd_err("Invalid session id");
10049 return -EINVAL;
10050 }
10051
Poddar, Siddarthdf076672018-02-26 14:21:45 +053010052 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070010053 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053010054 return -EINVAL;
10055 }
10056
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010057 if (tb[STATS_SET_START]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010058 /* tracking is enabled for stats other than arp. */
10059 if (tb[STATS_SET_DATA_PKT_INFO]) {
10060 err = hdd_set_clear_connectivity_check_stats_info(
10061 adapter,
10062 &arp_stats_params, tb, true);
10063 if (err)
10064 return -EINVAL;
10065
10066 /*
10067 * if only tracking dns, then don't send
10068 * wmi command to FW.
10069 */
10070 if (!arp_stats_params.pkt_type_bitmap)
10071 return err;
10072 } else {
10073 if (!tb[STATS_GW_IPV4]) {
Dustin Browna2868622018-03-20 11:38:14 -070010074 hdd_err("STATS_SET_START CMD");
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010075 return -EINVAL;
10076 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053010077
10078 arp_stats_params.pkt_type_bitmap =
10079 CONNECTIVITY_CHECK_SET_ARP;
10080 adapter->pkt_type_bitmap |=
10081 arp_stats_params.pkt_type_bitmap;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010082 arp_stats_params.flag = true;
10083 arp_stats_params.ip_addr =
10084 nla_get_u32(tb[STATS_GW_IPV4]);
10085 adapter->track_arp_ip = arp_stats_params.ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010086 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010087 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010088 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053010089 /* clear stats command received. */
10090 if (tb[STATS_SET_DATA_PKT_INFO]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010091 err = hdd_set_clear_connectivity_check_stats_info(
10092 adapter,
10093 &arp_stats_params, tb, false);
10094 if (err)
10095 return -EINVAL;
10096
10097 /*
10098 * if only tracking dns, then don't send
10099 * wmi command to FW.
10100 */
10101 if (!arp_stats_params.pkt_type_bitmap)
10102 return err;
10103 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053010104 arp_stats_params.pkt_type_bitmap =
10105 CONNECTIVITY_CHECK_SET_ARP;
10106 adapter->pkt_type_bitmap &=
10107 (~arp_stats_params.pkt_type_bitmap);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010108 arp_stats_params.flag = false;
10109 qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
10110 sizeof(adapter->hdd_stats.hdd_arp_stats));
10111 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
10112 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010113 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010114
Abhinav Kumar50d4dc72018-06-15 16:35:50 +053010115 hdd_debug("STATS_SET_START Received flag %d!", arp_stats_params.flag);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010116
Jeff Johnson1b780e42017-10-31 14:11:45 -070010117 arp_stats_params.vdev_id = adapter->session_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010118
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010119 mac_handle = hdd_ctx->mac_handle;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010120 if (QDF_STATUS_SUCCESS !=
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010121 sme_set_nud_debug_stats(mac_handle, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070010122 hdd_err("STATS_SET_START CMD Failed!");
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010123 return -EINVAL;
10124 }
10125
Dustin Browne74003f2018-03-14 12:51:58 -070010126 hdd_exit();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010127
10128 return err;
10129}
10130
10131/**
10132 * wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
10133 * @wiphy: pointer to wireless wiphy structure.
10134 * @wdev: pointer to wireless_dev structure.
10135 * @data: pointer to apfind configuration data.
10136 * @data_len: the length in byte of apfind data.
10137 *
10138 * This is called when wlan driver needs to send arp stats to
10139 * firmware.
10140 *
10141 * Return: An error code or 0 on success.
10142 */
10143static int wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
10144 struct wireless_dev *wdev,
10145 const void *data, int data_len)
10146{
10147 int ret;
10148
10149 cds_ssr_protect(__func__);
10150 ret = __wlan_hdd_cfg80211_set_nud_stats(wiphy, wdev, data, data_len);
10151 cds_ssr_unprotect(__func__);
10152
10153 return ret;
10154}
10155
10156#undef STATS_SET_INVALID
10157#undef STATS_SET_START
10158#undef STATS_GW_IPV4
10159#undef STATS_SET_MAX
10160
10161/*
10162 * define short names for the global vendor params
10163 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
10164 */
10165#define STATS_GET_INVALID \
10166 QCA_ATTR_NUD_STATS_SET_INVALID
10167#define COUNT_FROM_NETDEV \
10168 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
10169#define COUNT_TO_LOWER_MAC \
10170 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
10171#define RX_COUNT_BY_LOWER_MAC \
10172 QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
10173#define COUNT_TX_SUCCESS \
10174 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
10175#define RSP_RX_COUNT_BY_LOWER_MAC \
10176 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
10177#define RSP_RX_COUNT_BY_UPPER_MAC \
10178 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
10179#define RSP_COUNT_TO_NETDEV \
10180 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
10181#define RSP_COUNT_OUT_OF_ORDER_DROP \
10182 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
10183#define AP_LINK_ACTIVE \
10184 QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
10185#define AP_LINK_DAD \
10186 QCA_ATTR_NUD_STATS_IS_DAD
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010187#define DATA_PKT_STATS \
10188 QCA_ATTR_NUD_STATS_DATA_PKT_STATS
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010189#define STATS_GET_MAX \
10190 QCA_ATTR_NUD_STATS_GET_MAX
10191
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010192#define CHECK_STATS_INVALID \
10193 QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
10194#define CHECK_STATS_PKT_TYPE \
10195 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
10196#define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
10197 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
10198#define CHECK_STATS_PKT_SRC_PORT \
10199 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
10200#define CHECK_STATS_PKT_DEST_PORT \
10201 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
10202#define CHECK_STATS_PKT_DEST_IPV4 \
10203 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
10204#define CHECK_STATS_PKT_DEST_IPV6 \
10205 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
10206#define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
10207 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
10208#define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
10209 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
10210#define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
10211 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
10212#define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
10213 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
10214#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
10215 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
10216#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
10217 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
10218#define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
10219 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
10220#define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
10221 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
10222#define CHECK_DATA_STATS_MAX \
10223 QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
10224
10225
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010226const struct nla_policy
10227qca_wlan_vendor_get_nud_stats[STATS_GET_MAX + 1] = {
10228 [COUNT_FROM_NETDEV] = {.type = NLA_U16 },
10229 [COUNT_TO_LOWER_MAC] = {.type = NLA_U16 },
10230 [RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
10231 [COUNT_TX_SUCCESS] = {.type = NLA_U16 },
10232 [RSP_RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
10233 [RSP_RX_COUNT_BY_UPPER_MAC] = {.type = NLA_U16 },
10234 [RSP_COUNT_TO_NETDEV] = {.type = NLA_U16 },
10235 [RSP_COUNT_OUT_OF_ORDER_DROP] = {.type = NLA_U16 },
10236 [AP_LINK_ACTIVE] = {.type = NLA_FLAG },
10237 [AP_LINK_DAD] = {.type = NLA_FLAG },
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010238 [DATA_PKT_STATS] = {.type = NLA_U16 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010239};
10240
10241/**
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010242 * hdd_populate_dns_stats_info() - send dns stats info to network stack
10243 * @adapter: pointer to adapter context
10244 * @skb: pointer to skb
10245 *
10246 *
10247 * Return: An error code or 0 on success.
10248 */
10249static int hdd_populate_dns_stats_info(struct hdd_adapter *adapter,
10250 struct sk_buff *skb)
10251{
10252 uint8_t *dns_query;
10253
10254 dns_query = qdf_mem_malloc(adapter->track_dns_domain_len + 1);
10255 if (!dns_query) {
Dustin Browna2868622018-03-20 11:38:14 -070010256 hdd_err("mem alloc fail");
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010257 return -EINVAL;
10258 }
10259
10260 qdf_mem_copy(dns_query, adapter->dns_payload,
10261 adapter->track_dns_domain_len);
10262
10263 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
10264 CONNECTIVITY_CHECK_SET_DNS) ||
10265 nla_put(skb, CHECK_STATS_PKT_DNS_DOMAIN_NAME,
10266 adapter->track_dns_domain_len,
10267 hdd_dns_unmake_name_query(dns_query)) ||
10268 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
10269 adapter->hdd_stats.hdd_dns_stats.tx_dns_req_count) ||
10270 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
10271 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
10272 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
10273 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
10274 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
10275 adapter->hdd_stats.hdd_dns_stats.tx_ack_cnt) ||
10276 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
10277 adapter->hdd_stats.hdd_dns_stats.rx_dns_rsp_count) ||
10278 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
10279 adapter->hdd_stats.hdd_dns_stats.rx_delivered) ||
10280 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
10281 adapter->hdd_stats.hdd_dns_stats.rx_host_drop)) {
10282 hdd_err("nla put fail");
10283 qdf_mem_free(dns_query);
10284 kfree_skb(skb);
10285 return -EINVAL;
10286 }
10287 qdf_mem_free(dns_query);
10288 return 0;
10289}
10290
10291/**
10292 * hdd_populate_tcp_stats_info() - send tcp stats info to network stack
10293 * @adapter: pointer to adapter context
10294 * @skb: pointer to skb
10295 * @pkt_type: tcp pkt type
10296 *
10297 * Return: An error code or 0 on success.
10298 */
10299static int hdd_populate_tcp_stats_info(struct hdd_adapter *adapter,
10300 struct sk_buff *skb,
10301 uint8_t pkt_type)
10302{
10303 switch (pkt_type) {
10304 case CONNECTIVITY_CHECK_SET_TCP_SYN:
10305 /* Fill info for tcp syn packets (tx packet) */
10306 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
10307 CONNECTIVITY_CHECK_SET_TCP_SYN) ||
10308 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
10309 adapter->track_src_port) ||
10310 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
10311 adapter->track_dest_port) ||
10312 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
10313 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_count) ||
10314 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
10315 adapter->hdd_stats.hdd_tcp_stats.
10316 tx_tcp_syn_host_fw_sent) ||
10317 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
10318 adapter->hdd_stats.hdd_tcp_stats.
10319 tx_tcp_syn_host_fw_sent) ||
10320 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
10321 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_ack_cnt)) {
10322 hdd_err("nla put fail");
10323 kfree_skb(skb);
10324 return -EINVAL;
10325 }
10326 break;
10327 case CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
10328 /* Fill info for tcp syn-ack packets (rx packet) */
10329 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
10330 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK) ||
10331 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
10332 adapter->track_src_port) ||
10333 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
10334 adapter->track_dest_port) ||
10335 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
10336 adapter->hdd_stats.hdd_tcp_stats.rx_fw_cnt) ||
10337 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
10338 adapter->hdd_stats.hdd_tcp_stats.
10339 rx_tcp_syn_ack_count) ||
10340 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
10341 adapter->hdd_stats.hdd_tcp_stats.rx_delivered) ||
10342 nla_put_u16(skb,
10343 CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
10344 adapter->hdd_stats.hdd_tcp_stats.rx_host_drop)) {
10345 hdd_err("nla put fail");
10346 kfree_skb(skb);
10347 return -EINVAL;
10348 }
10349 break;
10350 case CONNECTIVITY_CHECK_SET_TCP_ACK:
10351 /* Fill info for tcp ack packets (tx packet) */
10352 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
10353 CONNECTIVITY_CHECK_SET_TCP_ACK) ||
10354 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
10355 adapter->track_src_port) ||
10356 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
10357 adapter->track_dest_port) ||
10358 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
10359 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_count) ||
10360 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
10361 adapter->hdd_stats.hdd_tcp_stats.
10362 tx_tcp_ack_host_fw_sent) ||
10363 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
10364 adapter->hdd_stats.hdd_tcp_stats.
10365 tx_tcp_ack_host_fw_sent) ||
10366 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
10367 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_ack_cnt)) {
10368 hdd_err("nla put fail");
10369 kfree_skb(skb);
10370 return -EINVAL;
10371 }
10372 break;
10373 default:
10374 break;
10375 }
10376 return 0;
10377}
10378
10379/**
10380 * hdd_populate_icmpv4_stats_info() - send icmpv4 stats info to network stack
10381 * @adapter: pointer to adapter context
10382 * @skb: pointer to skb
10383 *
10384 *
10385 * Return: An error code or 0 on success.
10386 */
10387static int hdd_populate_icmpv4_stats_info(struct hdd_adapter *adapter,
10388 struct sk_buff *skb)
10389{
10390 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
10391 CONNECTIVITY_CHECK_SET_ICMPV4) ||
10392 nla_put_u32(skb, CHECK_STATS_PKT_DEST_IPV4,
10393 adapter->track_dest_ipv4) ||
10394 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
10395 adapter->hdd_stats.hdd_icmpv4_stats.tx_icmpv4_req_count) ||
10396 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
10397 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
10398 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
10399 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
10400 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
10401 adapter->hdd_stats.hdd_icmpv4_stats.tx_ack_cnt) ||
10402 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
10403 adapter->hdd_stats.hdd_icmpv4_stats.rx_fw_cnt) ||
10404 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
10405 adapter->hdd_stats.hdd_icmpv4_stats.rx_icmpv4_rsp_count) ||
10406 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
10407 adapter->hdd_stats.hdd_icmpv4_stats.rx_delivered) ||
10408 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
10409 adapter->hdd_stats.hdd_icmpv4_stats.rx_host_drop)) {
10410 hdd_err("nla put fail");
10411 kfree_skb(skb);
10412 return -EINVAL;
10413 }
10414 return 0;
10415}
10416
10417/**
10418 * hdd_populate_connectivity_check_stats_info() - send connectivity stats info
10419 * to network stack
10420 * @adapter: pointer to adapter context
10421 * @skb: pointer to skb
10422 *
10423 *
10424 * Return: An error code or 0 on success.
10425 */
10426
10427static int hdd_populate_connectivity_check_stats_info(
10428 struct hdd_adapter *adapter, struct sk_buff *skb)
10429{
10430 struct nlattr *connect_stats, *connect_info;
10431 uint32_t count = 0;
10432
10433 connect_stats = nla_nest_start(skb, DATA_PKT_STATS);
10434 if (connect_stats == NULL) {
10435 hdd_err("nla_nest_start failed");
10436 return -EINVAL;
10437 }
10438
10439 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
10440 connect_info = nla_nest_start(skb, count);
10441 if (connect_info == NULL) {
10442 hdd_err("nla_nest_start failed count %u", count);
10443 return -EINVAL;
10444 }
10445
10446 if (hdd_populate_dns_stats_info(adapter, skb))
10447 goto put_attr_fail;
10448 nla_nest_end(skb, connect_info);
10449 count++;
10450 }
10451
10452 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
10453 connect_info = nla_nest_start(skb, count);
10454 if (connect_info == NULL) {
10455 hdd_err("nla_nest_start failed count %u", count);
10456 return -EINVAL;
10457 }
10458 if (hdd_populate_tcp_stats_info(adapter, skb,
10459 CONNECTIVITY_CHECK_SET_TCP_SYN))
10460 goto put_attr_fail;
10461 nla_nest_end(skb, connect_info);
10462 count++;
10463
10464 connect_info = nla_nest_start(skb, count);
10465 if (connect_info == NULL) {
10466 hdd_err("nla_nest_start failed count %u", count);
10467 return -EINVAL;
10468 }
10469 if (hdd_populate_tcp_stats_info(adapter, skb,
10470 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK))
10471 goto put_attr_fail;
10472 nla_nest_end(skb, connect_info);
10473 count++;
10474
10475 connect_info = nla_nest_start(skb, count);
10476 if (connect_info == NULL) {
10477 hdd_err("nla_nest_start failed count %u", count);
10478 return -EINVAL;
10479 }
10480 if (hdd_populate_tcp_stats_info(adapter, skb,
10481 CONNECTIVITY_CHECK_SET_TCP_ACK))
10482 goto put_attr_fail;
10483 nla_nest_end(skb, connect_info);
10484 count++;
10485 }
10486
10487 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ICMPV4) {
10488 connect_info = nla_nest_start(skb, count);
10489 if (connect_info == NULL) {
10490 hdd_err("nla_nest_start failed count %u", count);
10491 return -EINVAL;
10492 }
10493
10494 if (hdd_populate_icmpv4_stats_info(adapter, skb))
10495 goto put_attr_fail;
10496 nla_nest_end(skb, connect_info);
10497 count++;
10498 }
10499
10500 nla_nest_end(skb, connect_stats);
10501 return 0;
10502
10503put_attr_fail:
10504 hdd_err("QCA_WLAN_VENDOR_ATTR put fail. count %u", count);
10505 return -EINVAL;
10506}
10507
10508
10509/**
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010510 * __wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
10511 * @wiphy: pointer to wireless wiphy structure.
10512 * @wdev: pointer to wireless_dev structure.
10513 * @data: pointer to apfind configuration data.
10514 * @data_len: the length in byte of apfind data.
10515 *
10516 * This is called when wlan driver needs to get arp stats to
10517 * firmware.
10518 *
10519 * Return: An error code or 0 on success.
10520 */
10521static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
10522 struct wireless_dev *wdev,
10523 const void *data, int data_len)
10524{
10525 int err = 0;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010526 struct net_device *dev = wdev->netdev;
10527 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
10528 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
10529 struct get_arp_stats_params arp_stats_params;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010530 mac_handle_t mac_handle;
Poddar, Siddarthdb568162017-07-27 18:16:38 +053010531 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010532 uint32_t pkt_type_bitmap;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010533 struct sk_buff *skb;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010534 struct osif_request *request = NULL;
10535 static const struct osif_request_params params = {
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053010536 .priv_size = 0,
10537 .timeout_ms = WLAN_WAIT_TIME_NUD_STATS,
10538 };
10539 void *cookie = NULL;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010540
Dustin Brown491d54b2018-03-14 12:39:11 -070010541 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010542
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053010543 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10544 hdd_err("Command not allowed in FTM mode");
10545 return -EINVAL;
10546 }
10547
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010548 err = wlan_hdd_validate_context(hdd_ctx);
10549 if (0 != err)
10550 return err;
10551
Rajeev Kumar7f28e8a32017-08-23 15:41:30 -070010552 err = hdd_validate_adapter(adapter);
10553 if (err)
10554 return err;
10555
Poddar, Siddarthdf076672018-02-26 14:21:45 +053010556 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070010557 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053010558 return -EINVAL;
10559 }
10560
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010561 request = osif_request_alloc(&params);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053010562 if (!request) {
10563 hdd_err("Request allocation failure");
10564 return -ENOMEM;
10565 }
10566
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010567 cookie = osif_request_cookie(request);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053010568
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010569 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Jeff Johnson1b780e42017-10-31 14:11:45 -070010570 arp_stats_params.vdev_id = adapter->session_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010571
Poddar, Siddarth762c5472018-03-20 14:55:35 +053010572 pkt_type_bitmap = adapter->pkt_type_bitmap;
10573
10574 /* send NUD failure event only when ARP tracking is enabled. */
10575 if (hdd_ctx->config->enable_data_stall_det &&
10576 (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ARP))
Poddar, Siddarth37033032017-10-11 15:47:40 +053010577 cdp_post_data_stall_event(soc,
10578 DATA_STALL_LOG_INDICATOR_FRAMEWORK,
Poddar, Siddarthdb568162017-07-27 18:16:38 +053010579 DATA_STALL_LOG_NUD_FAILURE,
10580 0xFF, 0XFF,
10581 DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
10582
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010583 mac_handle = hdd_ctx->mac_handle;
10584 if (sme_set_nud_debug_stats_cb(mac_handle, hdd_get_nud_stats_cb,
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053010585 cookie) != QDF_STATUS_SUCCESS) {
10586 hdd_err("Setting NUD debug stats callback failure");
10587 err = -EINVAL;
10588 goto exit;
10589 }
10590
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010591 if (QDF_STATUS_SUCCESS !=
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010592 sme_get_nud_debug_stats(mac_handle, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070010593 hdd_err("STATS_SET_START CMD Failed!");
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053010594 err = -EINVAL;
10595 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010596 }
10597
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010598 err = osif_request_wait_for_response(request);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053010599 if (err) {
10600 hdd_err("SME timedout while retrieving NUD stats");
10601 err = -ETIMEDOUT;
10602 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010603 }
10604
10605 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
10606 WLAN_NUD_STATS_LEN);
10607 if (!skb) {
10608 hdd_err("%s: cfg80211_vendor_cmd_alloc_reply_skb failed",
10609 __func__);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053010610 err = -ENOMEM;
10611 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010612 }
10613
10614 if (nla_put_u16(skb, COUNT_FROM_NETDEV,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053010615 adapter->hdd_stats.hdd_arp_stats.tx_arp_req_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010616 nla_put_u16(skb, COUNT_TO_LOWER_MAC,
10617 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
10618 nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053010619 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010620 nla_put_u16(skb, COUNT_TX_SUCCESS,
10621 adapter->hdd_stats.hdd_arp_stats.tx_ack_cnt) ||
10622 nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC,
10623 adapter->hdd_stats.hdd_arp_stats.rx_fw_cnt) ||
10624 nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053010625 adapter->hdd_stats.hdd_arp_stats.rx_arp_rsp_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010626 nla_put_u16(skb, RSP_COUNT_TO_NETDEV,
10627 adapter->hdd_stats.hdd_arp_stats.rx_delivered) ||
10628 nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP,
10629 adapter->hdd_stats.hdd_arp_stats.
10630 rx_host_drop_reorder)) {
10631 hdd_err("nla put fail");
10632 kfree_skb(skb);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053010633 err = -EINVAL;
10634 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010635 }
10636 if (adapter->con_status)
10637 nla_put_flag(skb, AP_LINK_ACTIVE);
10638 if (adapter->dad)
10639 nla_put_flag(skb, AP_LINK_DAD);
10640
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010641 /* ARP tracking is done above. */
10642 pkt_type_bitmap &= ~CONNECTIVITY_CHECK_SET_ARP;
10643
10644 if (pkt_type_bitmap) {
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053010645 if (hdd_populate_connectivity_check_stats_info(adapter, skb)) {
10646 err = -EINVAL;
10647 goto exit;
10648 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053010649 }
10650
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010651 cfg80211_vendor_cmd_reply(skb);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053010652exit:
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010653 osif_request_put(request);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053010654 return err;
10655}
10656
10657/**
10658 * wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
10659 * @wiphy: pointer to wireless wiphy structure.
10660 * @wdev: pointer to wireless_dev structure.
10661 * @data: pointer to apfind configuration data.
10662 * @data_len: the length in byte of apfind data.
10663 *
10664 * This is called when wlan driver needs to get arp stats to
10665 * firmware.
10666 *
10667 * Return: An error code or 0 on success.
10668 */
10669static int wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
10670 struct wireless_dev *wdev,
10671 const void *data, int data_len)
10672{
10673 int ret;
10674
10675 cds_ssr_protect(__func__);
10676 ret = __wlan_hdd_cfg80211_get_nud_stats(wiphy, wdev, data, data_len);
10677 cds_ssr_unprotect(__func__);
10678
10679 return ret;
10680}
10681
10682#undef QCA_ATTR_NUD_STATS_SET_INVALID
10683#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
10684#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
10685#undef QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
10686#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
10687#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
10688#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
10689#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
10690#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
10691#undef QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
10692#undef QCA_ATTR_NUD_STATS_GET_MAX
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053010693
Jeff Johnsond0b6c7e2018-07-04 14:53:06 -070010694void hdd_bt_activity_cb(hdd_handle_t hdd_handle, uint32_t bt_activity)
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053010695{
Jeff Johnsond0b6c7e2018-07-04 14:53:06 -070010696 struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053010697 int status;
10698
10699 status = wlan_hdd_validate_context(hdd_ctx);
10700 if (0 != status)
10701 return;
10702
10703 if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_ADD)
10704 hdd_ctx->bt_a2dp_active = 1;
10705 else if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_REMOVE)
10706 hdd_ctx->bt_a2dp_active = 0;
10707 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_ADD)
10708 hdd_ctx->bt_vo_active = 1;
10709 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_REMOVE)
10710 hdd_ctx->bt_vo_active = 0;
10711 else
10712 return;
10713
Yeshwanth Sriram Guntuka9b9eb432017-12-14 18:48:41 +053010714 ucfg_scan_set_bt_activity(hdd_ctx->hdd_psoc, hdd_ctx->bt_a2dp_active);
Srinivas Girigowda6598eea2017-07-06 19:26:19 -070010715 hdd_debug("a2dp_active: %d vo_active: %d", hdd_ctx->bt_a2dp_active,
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053010716 hdd_ctx->bt_vo_active);
10717}
10718
lifengd217d192017-05-09 19:44:16 +080010719struct chain_rssi_priv {
10720 struct chain_rssi_result chain_rssi;
10721};
10722
10723/**
10724 * hdd_get_chain_rssi_cb() - Callback function to get chain rssi
10725 * @context: opaque context originally passed to SME. HDD always passes
10726 * a cookie for the request context
10727 * @data: struct for get chain rssi
10728 *
10729 * This function receives the response/data from the lower layer and
10730 * checks to see if the thread is still waiting then post the results to
10731 * upper layer, if the request has timed out then ignore.
10732 *
10733 * Return: None
10734 */
10735static void hdd_get_chain_rssi_cb(void *context,
10736 struct chain_rssi_result *data)
10737{
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010738 struct osif_request *request;
lifengd217d192017-05-09 19:44:16 +080010739 struct chain_rssi_priv *priv;
10740
Dustin Brown491d54b2018-03-14 12:39:11 -070010741 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080010742
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010743 request = osif_request_get(context);
lifengd217d192017-05-09 19:44:16 +080010744 if (!request) {
10745 hdd_err("Obsolete request");
10746 return;
10747 }
10748
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010749 priv = osif_request_priv(request);
lifengd217d192017-05-09 19:44:16 +080010750 priv->chain_rssi = *data;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010751 osif_request_complete(request);
10752 osif_request_put(request);
lifengd217d192017-05-09 19:44:16 +080010753}
10754
10755/**
10756 * hdd_post_get_chain_rssi_rsp - send rsp to user space
10757 * @hdd_ctx: pointer to hdd context
10758 * @result: chain rssi result
10759 *
10760 * Return: 0 for success, non-zero for failure
10761 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010762static int hdd_post_get_chain_rssi_rsp(struct hdd_context *hdd_ctx,
lifengd217d192017-05-09 19:44:16 +080010763 struct chain_rssi_result *result)
10764{
10765 struct sk_buff *skb;
lifengd217d192017-05-09 19:44:16 +080010766
10767 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
lifengfe6c3e22018-04-03 12:10:04 +080010768 (sizeof(result->chain_rssi) + NLA_HDRLEN) +
10769 (sizeof(result->ant_id) + NLA_HDRLEN) +
10770 NLMSG_HDRLEN);
lifengd217d192017-05-09 19:44:16 +080010771
10772 if (!skb) {
10773 hdd_err("cfg80211_vendor_event_alloc failed");
10774 return -ENOMEM;
10775 }
10776
lifengfe6c3e22018-04-03 12:10:04 +080010777 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI,
10778 sizeof(result->chain_rssi),
lifengd217d192017-05-09 19:44:16 +080010779 result->chain_rssi)) {
10780 hdd_err("put fail");
10781 goto nla_put_failure;
10782 }
10783
lifengfe6c3e22018-04-03 12:10:04 +080010784 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO,
10785 sizeof(result->ant_id),
10786 result->ant_id)) {
10787 hdd_err("put fail");
10788 goto nla_put_failure;
10789 }
10790
lifengd217d192017-05-09 19:44:16 +080010791 cfg80211_vendor_cmd_reply(skb);
10792 return 0;
10793
10794nla_put_failure:
10795 kfree_skb(skb);
10796 return -EINVAL;
10797}
10798
10799/**
10800 * __wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
10801 * @wiphy: wiphy pointer
10802 * @wdev: pointer to struct wireless_dev
10803 * @data: pointer to incoming NL vendor data
10804 * @data_len: length of @data
10805 *
10806 * Return: 0 on success; error number otherwise.
10807 */
10808static int __wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
10809 struct wireless_dev *wdev,
10810 const void *data,
10811 int data_len)
10812{
Jeff Johnsone5006672017-08-29 14:39:02 -070010813 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010814 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010815 mac_handle_t mac_handle;
lifengd217d192017-05-09 19:44:16 +080010816 struct get_chain_rssi_req_params req_msg;
10817 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
10818 QDF_STATUS status;
10819 int retval;
10820 void *cookie;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010821 struct osif_request *request;
lifengd217d192017-05-09 19:44:16 +080010822 struct chain_rssi_priv *priv;
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010823 static const struct osif_request_params params = {
lifengd217d192017-05-09 19:44:16 +080010824 .priv_size = sizeof(*priv),
10825 .timeout_ms = WLAN_WAIT_TIME_STATS,
10826 };
10827
Dustin Brown491d54b2018-03-14 12:39:11 -070010828 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080010829
10830 retval = wlan_hdd_validate_context(hdd_ctx);
10831 if (0 != retval)
10832 return retval;
10833
Dustin Brown4ea21db2018-01-05 14:13:17 -080010834 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
10835 data, data_len, NULL)) {
lifengd217d192017-05-09 19:44:16 +080010836 hdd_err("Invalid ATTR");
10837 return -EINVAL;
10838 }
10839
10840 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
10841 hdd_err("attr mac addr failed");
10842 return -EINVAL;
10843 }
10844 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) !=
10845 QDF_MAC_ADDR_SIZE) {
10846 hdd_err("incorrect mac size");
10847 return -EINVAL;
10848 }
10849 memcpy(&req_msg.peer_macaddr,
10850 nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
10851 QDF_MAC_ADDR_SIZE);
Jeff Johnson1b780e42017-10-31 14:11:45 -070010852 req_msg.session_id = adapter->session_id;
lifengd217d192017-05-09 19:44:16 +080010853
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010854 request = osif_request_alloc(&params);
lifengd217d192017-05-09 19:44:16 +080010855 if (!request) {
10856 hdd_err("Request allocation failure");
10857 return -ENOMEM;
10858 }
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010859 cookie = osif_request_cookie(request);
lifengd217d192017-05-09 19:44:16 +080010860
Jeff Johnson34fc63a2018-06-14 10:10:02 -070010861 mac_handle = hdd_ctx->mac_handle;
10862 status = sme_get_chain_rssi(mac_handle,
10863 &req_msg,
10864 hdd_get_chain_rssi_cb,
10865 cookie);
lifengd217d192017-05-09 19:44:16 +080010866 if (QDF_STATUS_SUCCESS != status) {
10867 hdd_err("Unable to get chain rssi");
10868 retval = qdf_status_to_os_return(status);
10869 } else {
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010870 retval = osif_request_wait_for_response(request);
lifengd217d192017-05-09 19:44:16 +080010871 if (retval) {
10872 hdd_err("Target response timed out");
10873 } else {
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010874 priv = osif_request_priv(request);
lifengd217d192017-05-09 19:44:16 +080010875 retval = hdd_post_get_chain_rssi_rsp(hdd_ctx,
10876 &priv->chain_rssi);
10877 if (retval)
10878 hdd_err("Failed to post chain rssi");
10879 }
10880 }
Jeff Johnsonf1a99ea2018-06-28 13:27:01 -070010881 osif_request_put(request);
lifengd217d192017-05-09 19:44:16 +080010882
Dustin Browne74003f2018-03-14 12:51:58 -070010883 hdd_exit();
lifengd217d192017-05-09 19:44:16 +080010884 return retval;
10885}
10886
10887/**
10888 * wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
10889 * @wiphy: wiphy pointer
10890 * @wdev: pointer to struct wireless_dev
10891 * @data: pointer to incoming NL vendor data
10892 * @data_len: length of @data
10893 *
10894 * Return: 0 on success; error number otherwise.
10895 */
10896static int wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
10897 struct wireless_dev *wdev,
10898 const void *data,
10899 int data_len)
10900{
10901 int ret;
10902
10903 cds_ssr_protect(__func__);
10904 ret = __wlan_hdd_cfg80211_get_chain_rssi(wiphy, wdev, data, data_len);
10905 cds_ssr_unprotect(__func__);
10906
10907 return ret;
10908}
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053010909
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053010910/**
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053010911 * wlan_hdd_fill_intf_info() - Fill skb buffer with interface info
10912 * @skb: Pointer to skb
10913 * @info: mac mode info
10914 * @index: attribute type index for nla_nest_start()
10915 *
10916 * Return : 0 on success and errno on failure
10917 */
10918static int wlan_hdd_fill_intf_info(struct sk_buff *skb,
10919 struct connection_info *info, int index)
10920{
10921 struct nlattr *attr;
10922 uint32_t freq;
10923 struct hdd_context *hdd_ctx;
10924 struct hdd_adapter *hdd_adapter;
10925
10926 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10927 if (!hdd_ctx)
10928 goto error;
10929
10930 hdd_adapter = hdd_get_adapter_by_vdev(hdd_ctx, info->vdev_id);
10931 if (!hdd_adapter)
10932 goto error;
10933
10934 attr = nla_nest_start(skb, index);
10935 if (!attr)
10936 goto error;
10937
10938 freq = sme_chn_to_freq(info->channel);
10939
10940 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX,
10941 hdd_adapter->dev->ifindex) ||
10942 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ, freq))
10943 goto error;
10944
10945 nla_nest_end(skb, attr);
10946
10947 return 0;
10948error:
10949 hdd_err("Fill buffer with interface info failed");
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053010950 return -EINVAL;
10951}
10952
10953/**
10954 * wlan_hdd_fill_mac_info() - Fill skb buffer with mac info
10955 * @skb: Pointer to skb
10956 * @info: mac mode info
10957 * @mac_id: MAC id
10958 * @conn_count: number of current connections
10959 *
10960 * Return : 0 on success and errno on failure
10961 */
10962static int wlan_hdd_fill_mac_info(struct sk_buff *skb,
10963 struct connection_info *info, uint32_t mac_id,
10964 uint32_t conn_count)
10965{
10966 struct nlattr *attr, *intf_attr;
10967 uint32_t band = 0, i = 0, j = 0;
10968 bool present = false;
10969
10970 while (i < conn_count) {
10971 if (info[i].mac_id == mac_id) {
10972 present = true;
10973 if (info[i].channel <= SIR_11B_CHANNEL_END)
10974 band |= 1 << NL80211_BAND_2GHZ;
10975 else if (info[i].channel <= SIR_11A_CHANNEL_END)
10976 band |= 1 << NL80211_BAND_5GHZ;
10977 }
10978 i++;
10979 }
10980
10981 if (!present)
10982 return 0;
10983
10984 i = 0;
10985 attr = nla_nest_start(skb, mac_id);
10986 if (!attr)
10987 goto error;
10988
10989 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID, mac_id) ||
10990 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND, band))
10991 goto error;
10992
10993 intf_attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO);
10994 if (!intf_attr)
10995 goto error;
10996
10997 while (i < conn_count) {
10998 if (info[i].mac_id == mac_id) {
10999 if (wlan_hdd_fill_intf_info(skb, &info[i], j))
11000 return -EINVAL;
11001 j++;
11002 }
11003 i++;
11004 }
11005
11006 nla_nest_end(skb, intf_attr);
11007
11008 nla_nest_end(skb, attr);
11009
11010 return 0;
11011error:
11012 hdd_err("Fill buffer with mac info failed");
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053011013 return -EINVAL;
11014}
11015
11016
11017int wlan_hdd_send_mode_change_event(void)
11018{
11019 int err;
11020 struct hdd_context *hdd_ctx;
11021 struct sk_buff *skb;
11022 struct nlattr *attr;
11023 struct connection_info info[MAX_NUMBER_OF_CONC_CONNECTIONS];
11024 uint32_t conn_count, mac_id;
11025
Dustin Brown491d54b2018-03-14 12:39:11 -070011026 hdd_enter();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053011027 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11028 if (!hdd_ctx) {
11029 hdd_err("HDD context is NULL");
11030 return -EINVAL;
11031 }
11032
11033 err = wlan_hdd_validate_context(hdd_ctx);
11034 if (0 != err)
11035 return err;
11036
11037 conn_count = policy_mgr_get_connection_info(hdd_ctx->hdd_psoc, info);
11038 if (!conn_count)
11039 return -EINVAL;
11040
11041 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
11042 (sizeof(uint32_t) * 4) *
11043 MAX_NUMBER_OF_CONC_CONNECTIONS + NLMSG_HDRLEN,
11044 QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX,
11045 GFP_KERNEL);
11046 if (!skb) {
11047 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
11048 return -ENOMEM;
11049 }
11050
11051 attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO);
11052 if (!attr) {
11053 hdd_err("nla_nest_start failed");
11054 kfree_skb(skb);
11055 return -EINVAL;
11056 }
11057
11058 for (mac_id = 0; mac_id < MAX_MAC; mac_id++) {
Lin Baifac77972018-07-05 19:51:49 +080011059 if (wlan_hdd_fill_mac_info(skb, info, mac_id, conn_count)) {
11060 kfree_skb(skb);
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053011061 return -EINVAL;
Lin Baifac77972018-07-05 19:51:49 +080011062 }
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053011063 }
11064
11065 nla_nest_end(skb, attr);
11066
11067 cfg80211_vendor_event(skb, GFP_KERNEL);
Dustin Browne74003f2018-03-14 12:51:58 -070011068 hdd_exit();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053011069
11070 return err;
11071}
11072
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011073const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
11074 {
11075 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11076 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
11077 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +053011078 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011079 .doit = is_driver_dfs_capable
11080 },
11081
11082#ifdef WLAN_FEATURE_NAN
11083 {
11084 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11085 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
11086 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11087 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
11088 .doit = wlan_hdd_cfg80211_nan_request
11089 },
11090#endif
11091
11092#ifdef WLAN_FEATURE_STATS_EXT
11093 {
11094 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11095 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
11096 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11097 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
11098 .doit = wlan_hdd_cfg80211_stats_ext_request
11099 },
11100#endif
11101#ifdef FEATURE_WLAN_EXTSCAN
11102 {
11103 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11104 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
11105 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11106 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
11107 .doit = wlan_hdd_cfg80211_extscan_start
11108 },
11109 {
11110 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11111 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
11112 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11113 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
11114 .doit = wlan_hdd_cfg80211_extscan_stop
11115 },
11116 {
11117 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11118 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
Manjeet Singh3abd7302017-01-11 16:07:42 +053011119 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11120 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011121 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
11122 },
11123 {
11124 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11125 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
11126 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11127 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
11128 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
11129 },
11130 {
11131 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11132 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
11133 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11134 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
11135 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
11136 },
11137 {
11138 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11139 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
11140 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11141 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
11142 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
11143 },
11144 {
11145 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11146 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
11147 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11148 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
11149 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
11150 },
11151 {
11152 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11153 .info.subcmd =
11154 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
11155 .flags =
11156 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
11157 WIPHY_VENDOR_CMD_NEED_RUNNING,
11158 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
11159 },
11160 {
11161 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11162 .info.subcmd =
11163 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
11164 .flags =
11165 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
11166 WIPHY_VENDOR_CMD_NEED_RUNNING,
11167 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
11168 },
11169 {
11170 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11171 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
11172 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11173 WIPHY_VENDOR_CMD_NEED_NETDEV |
11174 WIPHY_VENDOR_CMD_NEED_RUNNING,
11175 .doit = wlan_hdd_cfg80211_set_epno_list
11176 },
11177#endif /* FEATURE_WLAN_EXTSCAN */
11178
11179#ifdef WLAN_FEATURE_LINK_LAYER_STATS
11180 {
11181 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11182 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
11183 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11184 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
11185 .doit = wlan_hdd_cfg80211_ll_stats_clear
11186 },
11187
11188 {
11189 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11190 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
11191 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11192 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
11193 .doit = wlan_hdd_cfg80211_ll_stats_set
11194 },
11195
11196 {
11197 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11198 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
11199 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11200 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
11201 .doit = wlan_hdd_cfg80211_ll_stats_get
11202 },
11203#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
11204#ifdef FEATURE_WLAN_TDLS
11205 {
11206 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11207 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
11208 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11209 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
11210 .doit = wlan_hdd_cfg80211_exttdls_enable
11211 },
11212 {
11213 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11214 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
11215 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11216 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
11217 .doit = wlan_hdd_cfg80211_exttdls_disable
11218 },
11219 {
11220 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11221 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
11222 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
11223 .doit = wlan_hdd_cfg80211_exttdls_get_status
11224 },
11225#endif
11226 {
11227 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11228 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
11229 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
11230 .doit = wlan_hdd_cfg80211_get_supported_features
11231 },
11232 {
11233 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11234 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053011235 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11236 WIPHY_VENDOR_CMD_NEED_NETDEV |
11237 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
11239 },
Qiwei Caie689a262018-07-26 15:50:22 +080011240
11241 FEATURE_CONCURRENCY_MATRIX_VENDOR_COMMANDS
11242
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011243 {
11244 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11245 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
11246 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053011247 WIPHY_VENDOR_CMD_NEED_NETDEV |
11248 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011249 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
11250 },
Manikandan Mohan80dea792016-04-28 16:36:48 -070011251 {
11252 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11253 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
11254 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053011255 WIPHY_VENDOR_CMD_NEED_NETDEV |
11256 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -070011257 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
11258 },
Qiwei Caie689a262018-07-26 15:50:22 +080011259
11260 FEATURE_STATION_INFO_VENDOR_COMMANDS
11261
Anurag Chouhan96919482016-07-13 16:36:57 +053011262 {
11263 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011264 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
11265 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11266 WIPHY_VENDOR_CMD_NEED_NETDEV |
11267 WIPHY_VENDOR_CMD_NEED_RUNNING,
11268 .doit = wlan_hdd_cfg80211_do_acs
11269 },
11270
11271 {
11272 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11273 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
11274 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11275 WIPHY_VENDOR_CMD_NEED_NETDEV,
11276 .doit = wlan_hdd_cfg80211_get_features
11277 },
11278#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11279 {
11280 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11281 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
11282 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11283 WIPHY_VENDOR_CMD_NEED_NETDEV |
11284 WIPHY_VENDOR_CMD_NEED_RUNNING,
11285 .doit = wlan_hdd_cfg80211_keymgmt_set_key
11286 },
11287#endif
11288#ifdef FEATURE_WLAN_EXTSCAN
11289 {
11290 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11291 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
11292 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11293 WIPHY_VENDOR_CMD_NEED_NETDEV |
11294 WIPHY_VENDOR_CMD_NEED_RUNNING,
11295 .doit = wlan_hdd_cfg80211_set_passpoint_list
11296 },
11297 {
11298 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11299 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
11300 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11301 WIPHY_VENDOR_CMD_NEED_NETDEV |
11302 WIPHY_VENDOR_CMD_NEED_RUNNING,
11303 .doit = wlan_hdd_cfg80211_reset_passpoint_list
11304 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011305#endif /* FEATURE_WLAN_EXTSCAN */
11306 {
11307 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11308 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
11309 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11310 WIPHY_VENDOR_CMD_NEED_NETDEV,
11311 .doit = wlan_hdd_cfg80211_get_wifi_info
11312 },
Paul Zhang3a210c52016-12-08 10:18:12 +080011313#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011314 {
11315 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11316 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
11317 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11318 WIPHY_VENDOR_CMD_NEED_NETDEV |
11319 WIPHY_VENDOR_CMD_NEED_RUNNING,
11320 .doit = wlan_hdd_cfg80211_wifi_configuration_set
11321 },
Paul Zhang3a210c52016-12-08 10:18:12 +080011322#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011323 {
11324 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -080011325 .info.subcmd =
11326 QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION,
11327 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11328 WIPHY_VENDOR_CMD_NEED_NETDEV |
11329 WIPHY_VENDOR_CMD_NEED_RUNNING,
11330 .doit = wlan_hdd_cfg80211_set_wifi_test_config
11331 },
11332
11333 {
11334 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011335 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
11336 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053011337 WIPHY_VENDOR_CMD_NEED_NETDEV |
11338 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011339 .doit = wlan_hdd_cfg80211_set_ext_roam_params
11340 },
11341 {
11342 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11343 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
11344 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053011345 WIPHY_VENDOR_CMD_NEED_NETDEV |
11346 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011347 .doit = wlan_hdd_cfg80211_wifi_logger_start
11348 },
11349 {
11350 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11351 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
11352 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053011353 WIPHY_VENDOR_CMD_NEED_NETDEV |
11354 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011355 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
11356 },
11357 {
11358 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11359 .info.subcmd =
11360 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
11361 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11362 WIPHY_VENDOR_CMD_NEED_NETDEV |
11363 WIPHY_VENDOR_CMD_NEED_RUNNING,
11364 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
11365 },
11366 {
11367 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11368 .info.subcmd =
11369 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
11370 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11371 WIPHY_VENDOR_CMD_NEED_NETDEV |
11372 WIPHY_VENDOR_CMD_NEED_RUNNING,
11373 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
11374 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070011375#ifdef WLAN_FEATURE_TSF
11376 {
11377 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11378 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
11379 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11380 WIPHY_VENDOR_CMD_NEED_NETDEV |
11381 WIPHY_VENDOR_CMD_NEED_RUNNING,
11382 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
11383 },
11384#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011385#ifdef FEATURE_WLAN_TDLS
11386 {
11387 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11388 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
11389 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11390 WIPHY_VENDOR_CMD_NEED_NETDEV |
11391 WIPHY_VENDOR_CMD_NEED_RUNNING,
11392 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
11393 },
11394#endif
11395#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
11396 {
11397 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11398 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
11399 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11400 WIPHY_VENDOR_CMD_NEED_NETDEV |
11401 WIPHY_VENDOR_CMD_NEED_RUNNING,
11402 .doit = wlan_hdd_cfg80211_offloaded_packets
11403 },
11404#endif
Qiwei Caie689a262018-07-26 15:50:22 +080011405 FEATURE_RSSI_MONITOR_VENDOR_COMMANDS
11406
Qiwei Cai1083f5b2018-07-02 19:10:11 +080011407#ifdef WLAN_NS_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011408 {
11409 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053011410 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
11411 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11412 WIPHY_VENDOR_CMD_NEED_NETDEV |
11413 WIPHY_VENDOR_CMD_NEED_RUNNING,
11414 .doit = wlan_hdd_cfg80211_set_ns_offload
11415 },
Qiwei Cai1083f5b2018-07-02 19:10:11 +080011416#endif /* WLAN_NS_OFFLOAD */
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053011417 {
11418 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011419 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
11420 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Sourav Mohapatra412ceb92018-03-07 18:41:16 +053011421 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011422 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
11423 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011424 {
11425 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11426 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
11427 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11428 WIPHY_VENDOR_CMD_NEED_NETDEV |
11429 WIPHY_VENDOR_CMD_NEED_RUNNING,
11430 .doit = wlan_hdd_cfg80211_vendor_scan
11431 },
11432
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053011433 /* Vendor abort scan */
11434 {
11435 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11436 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
11437 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11438 WIPHY_VENDOR_CMD_NEED_NETDEV |
11439 WIPHY_VENDOR_CMD_NEED_RUNNING,
11440 .doit = wlan_hdd_vendor_abort_scan
11441 },
11442
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011443 /* OCB commands */
11444 {
11445 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11446 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
11447 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11448 WIPHY_VENDOR_CMD_NEED_NETDEV |
11449 WIPHY_VENDOR_CMD_NEED_RUNNING,
11450 .doit = wlan_hdd_cfg80211_ocb_set_config
11451 },
11452 {
11453 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11454 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
11455 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11456 WIPHY_VENDOR_CMD_NEED_NETDEV |
11457 WIPHY_VENDOR_CMD_NEED_RUNNING,
11458 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
11459 },
11460 {
11461 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11462 .info.subcmd =
11463 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
11464 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11465 WIPHY_VENDOR_CMD_NEED_NETDEV |
11466 WIPHY_VENDOR_CMD_NEED_RUNNING,
11467 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
11468 },
11469 {
11470 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11471 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
11472 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11473 WIPHY_VENDOR_CMD_NEED_NETDEV |
11474 WIPHY_VENDOR_CMD_NEED_RUNNING,
11475 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
11476 },
11477 {
11478 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11479 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
11480 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11481 WIPHY_VENDOR_CMD_NEED_NETDEV |
11482 WIPHY_VENDOR_CMD_NEED_RUNNING,
11483 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
11484 },
11485 {
11486 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11487 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
11488 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11489 WIPHY_VENDOR_CMD_NEED_NETDEV |
11490 WIPHY_VENDOR_CMD_NEED_RUNNING,
11491 .doit = wlan_hdd_cfg80211_dcc_get_stats
11492 },
11493 {
11494 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11495 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
11496 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11497 WIPHY_VENDOR_CMD_NEED_NETDEV |
11498 WIPHY_VENDOR_CMD_NEED_RUNNING,
11499 .doit = wlan_hdd_cfg80211_dcc_clear_stats
11500 },
11501 {
11502 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11503 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
11504 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11505 WIPHY_VENDOR_CMD_NEED_NETDEV |
11506 WIPHY_VENDOR_CMD_NEED_RUNNING,
11507 .doit = wlan_hdd_cfg80211_dcc_update_ndl
11508 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053011509 {
11510 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11511 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
11512 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11513 WIPHY_VENDOR_CMD_NEED_NETDEV |
11514 WIPHY_VENDOR_CMD_NEED_RUNNING,
11515 .doit = wlan_hdd_cfg80211_get_link_properties
11516 },
Qiwei Caie689a262018-07-26 15:50:22 +080011517
11518 FEATURE_OTA_TEST_VENDOR_COMMANDS
11519
Ravi Joshideb5a8d2015-11-09 19:11:43 -080011520#ifdef FEATURE_LFR_SUBNET_DETECTION
11521 {
11522 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11523 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
11524 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11525 WIPHY_VENDOR_CMD_NEED_NETDEV |
11526 WIPHY_VENDOR_CMD_NEED_RUNNING,
11527 .doit = wlan_hdd_cfg80211_set_gateway_params
11528 },
11529#endif /* FEATURE_LFR_SUBNET_DETECTION */
Qiwei Caie689a262018-07-26 15:50:22 +080011530
11531 FEATURE_TX_POWER_VENDOR_COMMANDS
11532
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053011533#ifdef FEATURE_WLAN_APF
Arun Khandavalli2476ef52016-04-26 20:19:43 +053011534 {
11535 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11536 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
11537 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11538 WIPHY_VENDOR_CMD_NEED_NETDEV |
11539 WIPHY_VENDOR_CMD_NEED_RUNNING,
Nachiket Kukadee547a482018-05-22 16:43:30 +053011540 .doit = wlan_hdd_cfg80211_apf_offload
Arun Khandavalli2476ef52016-04-26 20:19:43 +053011541 },
Nachiket Kukaded0dd62e2018-05-21 18:39:22 +053011542#endif /* FEATURE_WLAN_APF */
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011543 {
11544 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053011545 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
11546 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11547 WIPHY_VENDOR_CMD_NEED_NETDEV |
11548 WIPHY_VENDOR_CMD_NEED_RUNNING,
11549 .doit = wlan_hdd_cfg80211_acs_dfs_mode
11550 },
11551 {
11552 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053011553 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
11554 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11555 WIPHY_VENDOR_CMD_NEED_NETDEV |
11556 WIPHY_VENDOR_CMD_NEED_RUNNING,
11557 .doit = wlan_hdd_cfg80211_sta_roam_policy
11558 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053011559#ifdef FEATURE_WLAN_CH_AVOID
11560 {
11561 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11562 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
11563 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11564 WIPHY_VENDOR_CMD_NEED_NETDEV |
11565 WIPHY_VENDOR_CMD_NEED_RUNNING,
11566 .doit = wlan_hdd_cfg80211_avoid_freq
11567 },
11568#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053011569 {
11570 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053011571 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
11572 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11573 WIPHY_VENDOR_CMD_NEED_NETDEV |
11574 WIPHY_VENDOR_CMD_NEED_RUNNING,
11575 .doit = wlan_hdd_cfg80211_sap_configuration_set
11576 },
Qiwei Caie689a262018-07-26 15:50:22 +080011577
11578 FEATURE_P2P_LISTEN_OFFLOAD_VENDOR_COMMANDS
11579
11580 FEATURE_SAP_COND_CHAN_SWITCH_VENDOR_COMMANDS
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070011581#ifdef WLAN_FEATURE_NAN_DATAPATH
11582 {
11583 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11584 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
11585 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11586 WIPHY_VENDOR_CMD_NEED_NETDEV |
11587 WIPHY_VENDOR_CMD_NEED_RUNNING,
11588 .doit = wlan_hdd_cfg80211_process_ndp_cmd
11589 },
11590#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011591 {
11592 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11593 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
11594 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11595 WIPHY_VENDOR_CMD_NEED_NETDEV |
11596 WIPHY_VENDOR_CMD_NEED_RUNNING,
11597 .doit = wlan_hdd_cfg80211_get_wakelock_stats
11598 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011599 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011600 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11601 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
11602 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11603 WIPHY_VENDOR_CMD_NEED_NETDEV |
11604 WIPHY_VENDOR_CMD_NEED_RUNNING,
11605 .doit = wlan_hdd_cfg80211_get_bus_size
11606 },
11607 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053011608 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11609 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
11610 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11611 WIPHY_VENDOR_CMD_NEED_NETDEV |
11612 WIPHY_VENDOR_CMD_NEED_RUNNING,
11613 .doit = wlan_hdd_cfg80211_update_vendor_channel
11614 },
11615 {
bingsd09dea32017-03-17 10:08:26 +080011616 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011617 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
11618 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11619 WIPHY_VENDOR_CMD_NEED_NETDEV |
11620 WIPHY_VENDOR_CMD_NEED_RUNNING,
11621 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053011622 },
11623 {
11624 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11625 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
11626 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11627 WIPHY_VENDOR_CMD_NEED_NETDEV |
11628 WIPHY_VENDOR_CMD_NEED_RUNNING,
11629 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053011630 },
11631#ifdef WLAN_FEATURE_DISA
11632 {
11633 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11634 .info.subcmd =
11635 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
11636 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11637 WIPHY_VENDOR_CMD_NEED_NETDEV |
11638 WIPHY_VENDOR_CMD_NEED_RUNNING,
11639 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
11640 },
11641#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070011642#ifdef FEATURE_WLAN_TDLS
11643 {
11644 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11645 .info.subcmd =
11646 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
11647 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11648 WIPHY_VENDOR_CMD_NEED_NETDEV |
11649 WIPHY_VENDOR_CMD_NEED_RUNNING,
11650 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011651 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070011652#endif
Qiwei Caie689a262018-07-26 15:50:22 +080011653 FEATURE_SAR_LIMITS_VENDOR_COMMANDS
11654
Jeff Johnson8c83f132017-12-18 16:41:37 -080011655 {
11656 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011657 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
11658 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11659 WIPHY_VENDOR_CMD_NEED_RUNNING,
11660 .doit = wlan_hdd_cfg80211_set_sar_power_limits
11661 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053011662 {
11663 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11664 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
11665 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11666 WIPHY_VENDOR_CMD_NEED_NETDEV |
11667 WIPHY_VENDOR_CMD_NEED_RUNNING,
11668 .doit = wlan_hdd_cfg80211_set_trace_level
11669 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080011670 {
11671 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11672 .info.subcmd =
11673 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
11674 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11675 WIPHY_VENDOR_CMD_NEED_NETDEV |
11676 WIPHY_VENDOR_CMD_NEED_RUNNING,
11677 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
11678 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053011679 {
11680 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11681 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET,
11682 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11683 WIPHY_VENDOR_CMD_NEED_NETDEV |
11684 WIPHY_VENDOR_CMD_NEED_RUNNING,
11685 .doit = wlan_hdd_cfg80211_set_nud_stats
11686 },
11687 {
11688 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11689 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
11690 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11691 WIPHY_VENDOR_CMD_NEED_NETDEV |
11692 WIPHY_VENDOR_CMD_NEED_RUNNING,
11693 .doit = wlan_hdd_cfg80211_get_nud_stats
11694 },
Qiwei Caie689a262018-07-26 15:50:22 +080011695
11696 FEATURE_BSS_TRANSITION_VENDOR_COMMANDS
Sandeep Puligilla063a4342018-01-10 02:50:14 -080011697 FEATURE_SPECTRAL_SCAN_VENDOR_COMMANDS
Paul Zhang3a210c52016-12-08 10:18:12 +080011698#ifdef WLAN_UMAC_CONVERGENCE
11699 COMMON_VENDOR_COMMANDS
11700#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080011701 FEATURE_11AX_VENDOR_COMMANDS
lifengd217d192017-05-09 19:44:16 +080011702
11703 {
11704 .info.vendor_id = QCA_NL80211_VENDOR_ID,
11705 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI,
11706 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
11707 WIPHY_VENDOR_CMD_NEED_NETDEV |
11708 WIPHY_VENDOR_CMD_NEED_RUNNING,
11709 .doit = wlan_hdd_cfg80211_get_chain_rssi
11710 },
Qiwei Caie689a262018-07-26 15:50:22 +080011711
11712 FEATURE_ACTIVE_TOS_VENDOR_COMMANDS
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053011713
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011714};
11715
Dustin Brown52ba1ce2017-08-16 12:10:55 -070011716#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
11717static inline void
11718hdd_wiphy_set_max_sched_scans(struct wiphy *wiphy, uint8_t max_scans)
11719{
11720 if (max_scans == 0)
11721 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
11722 else
11723 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
11724}
11725#else
11726static inline void
11727hdd_wiphy_set_max_sched_scans(struct wiphy *wiphy, uint8_t max_scans)
11728{
11729 wiphy->max_sched_scan_reqs = max_scans;
11730}
11731#endif /* KERNEL_VERSION(4, 12, 0) */
11732
Padma, Santhosh Kumar4b302b62017-07-21 17:33:27 +053011733/**
11734 * wlan_hdd_cfg80211_add_connected_pno_support() - Set connected PNO support
11735 * @wiphy: Pointer to wireless phy
11736 *
11737 * This function is used to set connected PNO support to kernel
11738 *
11739 * Return: None
11740 */
Arif Hussain67c583a2018-04-26 17:00:09 -070011741#if defined(CFG80211_REPORT_BETTER_BSS_IN_SCHED_SCAN) || \
11742 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
Padma, Santhosh Kumar4b302b62017-07-21 17:33:27 +053011743static void wlan_hdd_cfg80211_add_connected_pno_support(struct wiphy *wiphy)
11744{
11745 wiphy_ext_feature_set(wiphy,
11746 NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI);
11747}
11748#else
11749static void wlan_hdd_cfg80211_add_connected_pno_support(struct wiphy *wiphy)
11750{
11751}
11752#endif
11753
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053011754#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
11755 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
11756 defined(FEATURE_WLAN_SCAN_PNO)
11757/**
11758 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
11759 * @wiphy: pointer to wiphy
11760 * @config: pointer to config
11761 *
11762 * Return: None
11763 */
11764static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
11765 struct hdd_config *config)
11766{
11767 if (config->configPNOScanSupport) {
Dustin Brown52ba1ce2017-08-16 12:10:55 -070011768 hdd_wiphy_set_max_sched_scans(wiphy, 1);
Abhishek Singh0481d662017-04-11 18:20:11 +053011769 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
11770 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053011771 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053011772 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053011773 if (config->max_sched_scan_plan_interval)
11774 wiphy->max_sched_scan_plan_interval =
11775 config->max_sched_scan_plan_interval;
11776 if (config->max_sched_scan_plan_iterations)
11777 wiphy->max_sched_scan_plan_iterations =
11778 config->max_sched_scan_plan_iterations;
11779 }
11780}
11781#else
11782static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
11783 struct hdd_config *config)
11784{
11785}
11786#endif
11787
11788
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080011789/**
11790 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
11791 * @priv_size: Size of the hdd context.
11792 *
11793 * Allocate wiphy context and hdd context.
11794 *
11795 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011796 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011797struct hdd_context *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011798{
11799 struct wiphy *wiphy;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011800 struct hdd_context *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080011801
Dustin Brown491d54b2018-03-14 12:39:11 -070011802 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011803
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011804 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
11805
11806 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011807 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011808 return NULL;
11809 }
11810
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080011811 hdd_ctx = wiphy_priv(wiphy);
11812
11813 hdd_ctx->wiphy = wiphy;
11814
11815 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011816}
11817
11818/*
11819 * FUNCTION: wlan_hdd_cfg80211_update_band
11820 * This function is called from the supplicant through a
11821 * private ioctl to change the band value
11822 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011823int wlan_hdd_cfg80211_update_band(struct hdd_context *hdd_ctx, struct wiphy *wiphy,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080011824 enum band_info eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011825{
11826 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070011827 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011828
Dustin Brown491d54b2018-03-14 12:39:11 -070011829 hdd_enter();
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070011830
11831 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011832
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011833 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011835
11836 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
11837 struct ieee80211_supported_band *band = wiphy->bands[i];
11838
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070011839 channelEnabledState = wlan_reg_get_channel_state(
Dustin Brown07901ec2018-09-07 11:02:41 -070011840 hdd_ctx->pdev,
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070011841 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011842
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070011843 if (HDD_NL80211_BAND_2GHZ == i &&
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080011844 BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011845 /* 5G only */
11846#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
11847 /* Enable Social channels for P2P */
11848 if (WLAN_HDD_IS_SOCIAL_CHANNEL
11849 (band->channels[j].center_freq)
11850 && CHANNEL_STATE_ENABLE ==
11851 channelEnabledState)
11852 band->channels[j].flags &=
11853 ~IEEE80211_CHAN_DISABLED;
11854 else
11855#endif
11856 band->channels[j].flags |=
11857 IEEE80211_CHAN_DISABLED;
11858 continue;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070011859 } else if (HDD_NL80211_BAND_5GHZ == i &&
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080011860 BAND_2G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011861 /* 2G only */
11862 band->channels[j].flags |=
11863 IEEE80211_CHAN_DISABLED;
11864 continue;
11865 }
11866
Amar Singhal6842e8f2016-02-23 16:30:32 -080011867 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011868 band->channels[j].flags &=
11869 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011870 }
11871 }
11872 return 0;
11873}
11874
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053011875#if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \
11876 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
11877static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
11878{
Paul Zhang382248f2017-10-17 14:24:45 +080011879 struct hdd_context *hdd_ctx;
Jeff Johnsone0847ba2018-03-01 12:34:50 -080011880
Paul Zhang382248f2017-10-17 14:24:45 +080011881 hdd_ctx = wiphy_priv(wiphy);
11882
11883 if (false == hdd_ctx->config->enable_mac_spoofing) {
11884 hdd_warn("MAC address spoofing is not enabled");
11885 } else {
11886 wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
11887 wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
11888 }
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053011889}
11890#else
11891static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
11892{
11893}
11894#endif
11895
Peng Xuacfdda12017-02-06 16:15:38 -080011896#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053011897
11898#if defined(WLAN_FEATURE_FILS_SK) && \
11899 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
11900 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053011901static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
11902{
11903 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
11904}
11905#else
11906static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
11907{
11908}
11909#endif
11910
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053011911#if defined (CFG80211_SCAN_DBS_CONTROL_SUPPORT) || \
11912 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
11913static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
11914{
11915 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
11916 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
11917 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
11918}
11919#else
11920static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
11921{
11922}
11923#endif
11924
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053011925#if defined(WLAN_FEATURE_SAE) && \
11926 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053011927/**
11928 * wlan_hdd_cfg80211_set_wiphy_sae_feature() - Indicates support of SAE feature
11929 * @wiphy: Pointer to wiphy
11930 * @config: pointer to config
11931 *
11932 * This function is used to indicate the support of SAE
11933 *
11934 * Return: None
11935 */
11936static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy,
11937 struct hdd_config *config)
11938{
11939 if (config->is_sae_enabled)
11940 wiphy->features |= NL80211_FEATURE_SAE;
11941}
11942#else
11943static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy,
11944 struct hdd_config *config)
11945{
11946}
11947#endif
11948
Peng Xu8e8b0392018-04-30 11:32:34 -070011949#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
11950 defined(CFG80211_DFS_OFFLOAD_BACKPORT)
11951static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
11952{
11953 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
11954}
11955#else
11956static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
11957{
11958 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
11959}
11960#endif
11961
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070011962#ifdef WLAN_FEATURE_DSRC
11963static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
11964 int *num_ch, int *ch_len)
11965{
11966 *num_ch = QDF_ARRAY_SIZE(hdd_channels_dot11p);
11967 *ch_len = sizeof(hdd_channels_dot11p);
11968}
11969
11970static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
11971{
11972 if (!ch_arr_len)
11973 return;
11974 qdf_mem_copy(ch_ptr, &hdd_channels_dot11p[0], ch_arr_len);
11975}
11976
11977static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
11978 int *num_ch, int *ch_len)
11979{
11980 *num_ch = 0;
11981 *ch_len = 0;
11982}
11983
11984static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
11985{
11986}
11987
11988#else
11989
11990static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
11991 int *num_ch, int *ch_len)
11992{
11993 *num_ch = 0;
11994 *ch_len = 0;
11995}
11996
11997static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
11998{
11999}
12000
12001static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
12002 int *num_ch, int *ch_len)
12003{
12004 *num_ch = QDF_ARRAY_SIZE(hdd_etsi13_srd_ch);
12005 *ch_len = sizeof(hdd_etsi13_srd_ch);
12006}
12007
12008static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
12009{
12010 if (!ch_arr_len)
12011 return;
12012 qdf_mem_copy(ch_ptr, &hdd_etsi13_srd_ch[0], ch_arr_len);
12013}
12014#endif
12015
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012016/*
12017 * FUNCTION: wlan_hdd_cfg80211_init
12018 * This function is called by hdd_wlan_startup()
12019 * during initialization.
12020 * This function is used to initialize and register wiphy structure.
12021 */
12022int wlan_hdd_cfg80211_init(struct device *dev,
12023 struct wiphy *wiphy, struct hdd_config *pCfg)
12024{
12025 int i, j;
Jeff Johnsonb8944722017-09-03 09:03:19 -070012026 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070012027 int len_5g_ch = 0, num_ch, ch_arr_size;
12028 int num_dsrc_ch, len_dsrc_ch, num_srd_ch, len_srd_ch;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053012029 uint32_t *cipher_suites;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012030
Dustin Brown491d54b2018-03-14 12:39:11 -070012031 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012032
12033 /* Now bind the underlying wlan device with wiphy */
12034 set_wiphy_dev(wiphy, dev);
12035
12036 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
12037
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012038 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
12039 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
12040 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
12041#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
12042 | WIPHY_FLAG_4ADDR_STATION
12043#endif
12044 | WIPHY_FLAG_OFFCHAN_TX;
12045
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012046#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
12047 wiphy->wowlan = &wowlan_support_cfg80211_init;
12048#else
12049 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
12050 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
12051 wiphy->wowlan.pattern_min_len = 1;
12052 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
12053#endif
12054
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070012055 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012056#ifdef FEATURE_WLAN_ESE
12057 || pCfg->isEseIniFeatureEnabled
12058#endif
12059 ) {
12060 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
12061 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012062#ifdef FEATURE_WLAN_TDLS
12063 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
12064 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
12065#endif
12066
12067 wiphy->features |= NL80211_FEATURE_HT_IBSS;
12068
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012069#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
12070 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
12071#endif
Vignesh Viswanathancc7f1b92017-09-28 13:12:24 +053012072 if (pCfg->is_fils_enabled)
12073 wlan_hdd_cfg80211_set_wiphy_fils_feature(wiphy);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012074
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053012075 wlan_hdd_cfg80211_set_wiphy_scan_flags(wiphy);
12076
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053012077 wlan_hdd_cfg80211_set_wiphy_sae_feature(wiphy, pCfg);
12078
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053012079 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Padma, Santhosh Kumar4b302b62017-07-21 17:33:27 +053012080 wlan_hdd_cfg80211_add_connected_pno_support(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012081
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012082 wiphy->max_scan_ssids = MAX_SCAN_SSID;
12083
12084 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
12085
12086 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
12087
Arun Khandavallifae92942016-08-01 13:31:08 +053012088 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
12089 | BIT(NL80211_IFTYPE_ADHOC)
12090 | BIT(NL80211_IFTYPE_P2P_CLIENT)
12091 | BIT(NL80211_IFTYPE_P2P_GO)
12092 | BIT(NL80211_IFTYPE_AP)
12093 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012094
Arun Khandavallifae92942016-08-01 13:31:08 +053012095 if (pCfg->advertiseConcurrentOperation) {
12096 if (pCfg->enableMCC) {
12097 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012098
Arun Khandavallifae92942016-08-01 13:31:08 +053012099 for (i = 0;
12100 i < ARRAY_SIZE(wlan_hdd_iface_combination);
12101 i++) {
12102 if (!pCfg->allowMCCGODiffBI)
12103 wlan_hdd_iface_combination[i].
12104 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012105 }
12106 }
12107 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053012108 ARRAY_SIZE(wlan_hdd_iface_combination);
12109 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012110 }
12111
Srinivas Girigowda576b2352017-08-25 14:44:26 -070012112 if (!pCfg->nChannelBondingMode5GHz)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012113 wlan_hdd_band_5_ghz.ht_cap.cap &=
12114 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012115
Abhishek Singhf512bf32016-05-04 16:47:46 +053012116 /*
12117 * In case of static linked driver at the time of driver unload,
12118 * module exit doesn't happens. Module cleanup helps in cleaning
12119 * of static memory.
12120 * If driver load happens statically, at the time of driver unload,
12121 * wiphy flags don't get reset because of static memory.
12122 * It's better not to store channel in static memory.
12123 */
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012124 wiphy->bands[HDD_NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
12125 wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053012126 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012127 if (wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053012128 hdd_err("Not enough memory to allocate channels");
12129 return -ENOMEM;
12130 }
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012131 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053012132 &hdd_channels_2_4_ghz[0],
12133 sizeof(hdd_channels_2_4_ghz));
Jeff Johnsonb8944722017-09-03 09:03:19 -070012134 if ((hdd_is_5g_supported(hdd_ctx)) &&
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053012135 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
12136 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
12137 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
12138 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012139 wiphy->bands[HDD_NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070012140 wlan_hdd_get_num_dsrc_ch_and_len(pCfg, &num_dsrc_ch,
12141 &len_dsrc_ch);
12142 wlan_hdd_get_num_srd_ch_and_len(pCfg, &num_srd_ch, &len_srd_ch);
12143 num_ch = QDF_ARRAY_SIZE(hdd_channels_5_ghz) + num_dsrc_ch +
12144 num_srd_ch;
12145 len_5g_ch = sizeof(hdd_channels_5_ghz);
12146 ch_arr_size = len_5g_ch + len_dsrc_ch + len_srd_ch;
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053012147
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070012148 wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels =
12149 qdf_mem_malloc(ch_arr_size);
12150 if (!wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels)
12151 goto mem_fail;
12152 wiphy->bands[HDD_NL80211_BAND_5GHZ]->n_channels = num_ch;
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053012153
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070012154 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels,
12155 &hdd_channels_5_ghz[0], len_5g_ch);
12156 if (num_dsrc_ch)
12157 wlan_hdd_copy_dsrc_ch((char *)wiphy->bands[
12158 HDD_NL80211_BAND_5GHZ]->channels +
12159 len_5g_ch, len_dsrc_ch);
12160 if (num_srd_ch)
12161 wlan_hdd_copy_srd_ch((char *)wiphy->bands[
12162 HDD_NL80211_BAND_5GHZ]->channels +
12163 len_5g_ch, len_srd_ch);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012164 }
12165
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070012166 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012167
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012168 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012169 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012170
12171 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
12172 struct ieee80211_supported_band *band = wiphy->bands[i];
12173
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012174 if (HDD_NL80211_BAND_2GHZ == i &&
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080012175 BAND_5G == pCfg->nBandCapability) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012176 /* 5G only */
12177#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
12178 /* Enable social channels for P2P */
12179 if (WLAN_HDD_IS_SOCIAL_CHANNEL
12180 (band->channels[j].center_freq))
12181 band->channels[j].flags &=
12182 ~IEEE80211_CHAN_DISABLED;
12183 else
12184#endif
12185 band->channels[j].flags |=
12186 IEEE80211_CHAN_DISABLED;
12187 continue;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012188 } else if (HDD_NL80211_BAND_5GHZ == i &&
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080012189 BAND_2G == pCfg->nBandCapability) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012190 /* 2G only */
12191 band->channels[j].flags |=
12192 IEEE80211_CHAN_DISABLED;
12193 continue;
12194 }
12195 }
12196 }
12197 /*Initialise the supported cipher suite details */
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053012198 if (pCfg->gcmp_enabled) {
12199 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites) +
12200 sizeof(hdd_gcmp_cipher_suits));
12201 if (cipher_suites == NULL) {
12202 hdd_err("Not enough memory for cipher suites");
12203 return -ENOMEM;
12204 }
12205 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites) +
12206 QDF_ARRAY_SIZE(hdd_gcmp_cipher_suits);
12207 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
12208 sizeof(hdd_cipher_suites));
12209 qdf_mem_copy(cipher_suites + QDF_ARRAY_SIZE(hdd_cipher_suites),
12210 &hdd_gcmp_cipher_suits,
12211 sizeof(hdd_gcmp_cipher_suits));
12212 } else {
12213 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites));
12214 if (cipher_suites == NULL) {
12215 hdd_err("Not enough memory for cipher suites");
12216 return -ENOMEM;
12217 }
12218 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites);
12219 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
12220 sizeof(hdd_cipher_suites));
12221 }
12222 wiphy->cipher_suites = cipher_suites;
12223 cipher_suites = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012224 /*signal strength in mBm (100*dBm) */
12225 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
12226 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
12227
Anurag Chouhan6d760662016-02-20 16:05:43 +053012228 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012229 wiphy->n_vendor_commands =
12230 ARRAY_SIZE(hdd_wiphy_vendor_commands);
12231 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
12232
12233 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
12234 wiphy->n_vendor_events =
12235 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
12236 }
12237
Srinivas Girigowda576b2352017-08-25 14:44:26 -070012238 if (pCfg->enableDFSMasterCap)
Peng Xu8e8b0392018-04-30 11:32:34 -070012239 wlan_hdd_cfg80211_set_dfs_offload_feature(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012240
12241 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
12242
12243#ifdef QCA_HT_2040_COEX
12244 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
12245#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053012246 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080012247
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053012248#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) || \
wadesonga75734c2017-02-07 16:03:25 +080012249 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
12250 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
12251 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
12252 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
12253#endif
12254
Abhishek Singh1bdb1572015-10-16 16:24:19 +053012255 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080012256 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Kiran Kumar Lokered547fdd2017-09-13 17:20:55 -070012257 if (pCfg->enable_mac_spoofing)
12258 wlan_hdd_cfg80211_scan_randomization_init(wiphy);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053012259
Dustin Browne74003f2018-03-14 12:51:58 -070012260 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012261 return 0;
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053012262
12263mem_fail:
12264 hdd_err("Not enough memory to allocate channels");
12265 if (wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels != NULL) {
12266 qdf_mem_free(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels);
12267 wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels = NULL;
12268 }
12269 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012270}
12271
Abhishek Singhf512bf32016-05-04 16:47:46 +053012272/**
Yingying Tang80e15f32016-09-27 18:23:01 +080012273 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
12274 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053012275 *
12276 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053012277 * memory allocated in wlan_hdd_cfg80211_init also
12278 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053012279 *
12280 * Return: void
12281 */
12282void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
12283{
12284 int i;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053012285 const uint32_t *cipher_suites;
Abhishek Singhf512bf32016-05-04 16:47:46 +053012286
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070012287 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053012288 if (NULL != wiphy->bands[i] &&
12289 (NULL != wiphy->bands[i]->channels)) {
12290 qdf_mem_free(wiphy->bands[i]->channels);
12291 wiphy->bands[i]->channels = NULL;
12292 }
12293 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080012294
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053012295 cipher_suites = wiphy->cipher_suites;
12296 wiphy->cipher_suites = NULL;
12297 wiphy->n_cipher_suites = 0;
12298 qdf_mem_free((uint32_t *)cipher_suites);
12299 cipher_suites = NULL;
Abhishek Singh3e6172f2016-05-04 16:56:48 +053012300 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053012301}
12302
Yingying Tang80e15f32016-09-27 18:23:01 +080012303/**
12304 * wlan_hdd_update_band_cap() - update capabilities for supported bands
12305 * @hdd_ctx: HDD context
12306 *
12307 * this function will update capabilities for supported bands
12308 *
12309 * Return: void
12310 */
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053012311static void wlan_hdd_update_ht_cap(struct hdd_context *hdd_ctx)
Yingying Tang80e15f32016-09-27 18:23:01 +080012312{
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053012313 struct mlme_ht_capabilities_info ht_cap_info = {0};
Yingying Tang80e15f32016-09-27 18:23:01 +080012314 QDF_STATUS status;
12315
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053012316 status = ucfg_mlme_get_ht_cap_info(hdd_ctx->hdd_psoc, &ht_cap_info);
12317 if (QDF_STATUS_SUCCESS != status)
Yingying Tang80e15f32016-09-27 18:23:01 +080012318 hdd_err("could not get HT capability info");
Yingying Tang80e15f32016-09-27 18:23:01 +080012319
Vignesh Viswanathan78182502018-08-06 15:13:30 +053012320 if (ht_cap_info.tx_stbc) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012321 if (NULL != hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ])
12322 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ]->ht_cap.cap |=
Yingying Tang80e15f32016-09-27 18:23:01 +080012323 IEEE80211_HT_CAP_TX_STBC;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012324 if (NULL != hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ])
12325 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]->ht_cap.cap |=
Yingying Tang80e15f32016-09-27 18:23:01 +080012326 IEEE80211_HT_CAP_TX_STBC;
12327 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080012328
12329 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012330 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ]->
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080012331 vht_cap.vht_supported = 0;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012332 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ]->vht_cap.cap = 0;
12333 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]->
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080012334 vht_cap.vht_supported = 0;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070012335 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]->vht_cap.cap = 0;
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080012336 }
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053012337
Vignesh Viswanathan78182502018-08-06 15:13:30 +053012338 if (!ht_cap_info.short_gi_20_mhz) {
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053012339 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
12340 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
12341 }
12342
Vignesh Viswanathan78182502018-08-06 15:13:30 +053012343 if (!ht_cap_info.short_gi_40_mhz)
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053012344 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
Yingying Tang80e15f32016-09-27 18:23:01 +080012345}
12346
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012347/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012348 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012349 * initialization. In wlan_hdd_cfg80211_init, only the
12350 * default values will be initialized. The final initialization
12351 * of all required members can be done here.
12352 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012353void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012354{
Yingying Tang80e15f32016-09-27 18:23:01 +080012355 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
12356
Vignesh Viswanathan21c58cb2018-05-24 15:53:58 +053012357 wlan_hdd_update_ht_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012358}
12359
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080012360/**
12361 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
12362 * @cfg: hdd cfg
12363 *
12364 * this function update 11n mode in hdd cfg
12365 *
12366 * Return: void
12367 */
12368void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
12369{
12370 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012371 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080012372 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012373 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080012374 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
12375 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
12376 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +053012377 cfg->sap_11ac_override = 0;
12378 cfg->go_11ac_override = 0;
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080012379 }
12380 }
12381}
12382
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012383/* In this function we are registering wiphy. */
12384int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
12385{
Dustin Brown491d54b2018-03-14 12:39:11 -070012386 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012387 /* Register our wiphy dev with cfg80211 */
12388 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070012389 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012390 return -EIO;
12391 }
12392
Dustin Browne74003f2018-03-14 12:51:58 -070012393 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012394 return 0;
12395}
12396
12397/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012398 * HDD function to update wiphy capability based on target offload status.
12399 *
12400 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
12401 * capability even before downloading firmware to the target. In discrete
12402 * case, host will get know certain offload capability (say sched_scan
12403 * caps) only after downloading firmware to the target and target boots up.
12404 * This function is used to override setting done in wlan_hdd_cfg80211_init()
12405 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012406 */
12407void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
12408{
12409#ifdef FEATURE_WLAN_SCAN_PNO
Jeff Johnsonb8944722017-09-03 09:03:19 -070012410 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
12411 struct hdd_config *pCfg = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012412
12413 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
12414 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012415 * have PNO support.
12416 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012417 if (!pCfg->PnoOffload) {
Dustin Brown52ba1ce2017-08-16 12:10:55 -070012418 hdd_wiphy_set_max_sched_scans(wiphy, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012419 wiphy->max_sched_scan_ssids = 0;
12420 wiphy->max_match_sets = 0;
12421 wiphy->max_sched_scan_ie_len = 0;
12422 }
12423#endif
12424}
12425
12426/* This function registers for all frame which supplicant is interested in */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012427int wlan_hdd_cfg80211_register_frames(struct hdd_adapter *adapter)
Wu Gao84d120c2017-03-24 18:46:00 +080012428{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012429 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
Wu Gao84d120c2017-03-24 18:46:00 +080012430 /* Register for all P2P action, public action etc frames */
12431 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012432 QDF_STATUS status;
Wu Gao84d120c2017-03-24 18:46:00 +080012433
Dustin Brown491d54b2018-03-14 12:39:11 -070012434 hdd_enter();
Wu Gao84d120c2017-03-24 18:46:00 +080012435
12436 /* Register frame indication call back */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012437 status = sme_register_mgmt_frame_ind_callback(mac_handle,
12438 hdd_indicate_mgmt_frame);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012439 if (status != QDF_STATUS_SUCCESS) {
12440 hdd_err("Failed to register hdd_indicate_mgmt_frame");
12441 goto ret_status;
12442 }
Wu Gao84d120c2017-03-24 18:46:00 +080012443
Wu Gao84d120c2017-03-24 18:46:00 +080012444 /* Right now we are registering these frame when driver is getting
12445 * initialized. Once we will move to 2.6.37 kernel, in which we have
12446 * frame register ops, we will move this code as a part of that
12447 */
12448
12449 /* GAS Initial Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012450 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
12451 (uint8_t *) GAS_INITIAL_REQ,
12452 GAS_INITIAL_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012453 if (status != QDF_STATUS_SUCCESS) {
12454 hdd_err("Failed to register GAS_INITIAL_REQ");
12455 goto ret_status;
12456 }
Wu Gao84d120c2017-03-24 18:46:00 +080012457
12458 /* GAS Initial Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012459 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
12460 (uint8_t *) GAS_INITIAL_RSP,
12461 GAS_INITIAL_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012462 if (status != QDF_STATUS_SUCCESS) {
12463 hdd_err("Failed to register GAS_INITIAL_RSP");
12464 goto dereg_gas_initial_req;
12465 }
Wu Gao84d120c2017-03-24 18:46:00 +080012466
12467 /* GAS Comeback Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012468 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
12469 (uint8_t *) GAS_COMEBACK_REQ,
12470 GAS_COMEBACK_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012471 if (status != QDF_STATUS_SUCCESS) {
12472 hdd_err("Failed to register GAS_COMEBACK_REQ");
12473 goto dereg_gas_initial_rsp;
12474 }
Wu Gao84d120c2017-03-24 18:46:00 +080012475
12476 /* GAS Comeback Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012477 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
12478 (uint8_t *) GAS_COMEBACK_RSP,
12479 GAS_COMEBACK_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012480 if (status != QDF_STATUS_SUCCESS) {
12481 hdd_err("Failed to register GAS_COMEBACK_RSP");
12482 goto dereg_gas_comeback_req;
12483 }
Wu Gao84d120c2017-03-24 18:46:00 +080012484
12485 /* WNM BSS Transition Request frame */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012486 status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
12487 (uint8_t *) WNM_BSS_ACTION_FRAME,
12488 WNM_BSS_ACTION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012489 if (status != QDF_STATUS_SUCCESS) {
12490 hdd_err("Failed to register WNM_BSS_ACTION_FRAME");
12491 goto dereg_gas_comeback_rsp;
12492 }
Wu Gao84d120c2017-03-24 18:46:00 +080012493
12494 /* WNM-Notification */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012495 status = sme_register_mgmt_frame(mac_handle, adapter->session_id, type,
12496 (uint8_t *) WNM_NOTIFICATION_FRAME,
12497 WNM_NOTIFICATION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012498 if (status != QDF_STATUS_SUCCESS) {
12499 hdd_err("Failed to register WNM_NOTIFICATION_FRAME");
12500 goto dereg_wnm_bss_action_frm;
12501 }
12502
Dustin Brown237baee2018-05-10 13:22:18 -070012503 return 0;
12504
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012505dereg_wnm_bss_action_frm:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012506 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
12507 (uint8_t *) WNM_BSS_ACTION_FRAME,
12508 WNM_BSS_ACTION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012509dereg_gas_comeback_rsp:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012510 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
12511 (uint8_t *) GAS_COMEBACK_RSP,
12512 GAS_COMEBACK_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012513dereg_gas_comeback_req:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012514 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
12515 (uint8_t *) GAS_COMEBACK_REQ,
12516 GAS_COMEBACK_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012517dereg_gas_initial_rsp:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012518 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
12519 (uint8_t *) GAS_INITIAL_RSP,
12520 GAS_INITIAL_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012521dereg_gas_initial_req:
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012522 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
12523 (uint8_t *) GAS_INITIAL_REQ,
12524 GAS_INITIAL_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053012525ret_status:
12526 return qdf_status_to_os_return(status);
Wu Gao84d120c2017-03-24 18:46:00 +080012527}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012528
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012529void wlan_hdd_cfg80211_deregister_frames(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012530{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012531 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
12532 /* Deregister for all P2P action, public action etc frames */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012533 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
12534
Dustin Brown491d54b2018-03-14 12:39:11 -070012535 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012536
12537 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012538 * initialized. Once we will move to 2.6.37 kernel, in which we have
12539 * frame register ops, we will move this code as a part of that
12540 */
12541
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012542 /* GAS Initial Request */
12543
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012544 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012545 (uint8_t *) GAS_INITIAL_REQ,
12546 GAS_INITIAL_REQ_SIZE);
12547
12548 /* GAS Initial Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012549 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012550 (uint8_t *) GAS_INITIAL_RSP,
12551 GAS_INITIAL_RSP_SIZE);
12552
12553 /* GAS Comeback Request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012554 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012555 (uint8_t *) GAS_COMEBACK_REQ,
12556 GAS_COMEBACK_REQ_SIZE);
12557
12558 /* GAS Comeback Response */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012559 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012560 (uint8_t *) GAS_COMEBACK_RSP,
12561 GAS_COMEBACK_RSP_SIZE);
12562
12563 /* P2P Public Action */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012564 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012565 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
12566 P2P_PUBLIC_ACTION_FRAME_SIZE);
12567
12568 /* P2P Action */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012569 sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012570 (uint8_t *) P2P_ACTION_FRAME,
12571 P2P_ACTION_FRAME_SIZE);
12572
12573 /* WNM-Notification */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012574 sme_deregister_mgmt_frame(mac_handle, adapter->session_id, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012575 (uint8_t *) WNM_NOTIFICATION_FRAME,
12576 WNM_NOTIFICATION_FRAME_SIZE);
12577}
12578
12579#ifdef FEATURE_WLAN_WAPI
Sourav Mohapatrad21fc6b2018-06-01 11:31:14 +053012580static void wlan_hdd_cfg80211_set_key_wapi(struct hdd_adapter *adapter,
12581 uint8_t key_index,
12582 const uint8_t *mac_addr,
12583 const uint8_t *key,
12584 int key_Len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012585{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012586 tCsrRoamSetKey setKey;
12587 bool isConnected = true;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012588 QDF_STATUS status;
Krunal Sonibfd05492017-10-03 15:48:37 -070012589 uint32_t roamId = INVALID_ROAM_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012590 uint8_t *pKeyPtr = NULL;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012591 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012592
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012593 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012594 hdd_device_mode_to_string(adapter->device_mode),
12595 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012596
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012597 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012598 setKey.keyId = key_index; /* Store Key ID */
12599 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
12600 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
12601 setKey.paeRole = 0; /* the PAE role */
Srinivas Girigowda576b2352017-08-25 14:44:26 -070012602 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
Anurag Chouhanc5548422016-02-24 18:33:27 +053012603 qdf_set_macaddr_broadcast(&setKey.peerMac);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070012604 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012605 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070012606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012607 setKey.keyLength = key_Len;
12608 pKeyPtr = setKey.Key;
12609 memcpy(pKeyPtr, key, key_Len);
12610
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012611 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012612
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012613 if (isConnected) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012614 mac_handle = hdd_adapter_get_mac_handle(adapter);
12615 status = sme_roam_set_key(mac_handle,
12616 adapter->session_id,
12617 &setKey, &roamId);
12618 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonfee20aa2017-10-30 21:33:14 -070012619 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012620 }
12621}
12622#endif /* FEATURE_WLAN_WAPI */
12623
Krunal Soni364e0872017-05-10 21:24:34 -070012624bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
12625{
Naveen Rawat08db88f2017-09-08 15:07:48 -070012626 const uint8_t *vendor_ie;
Krunal Soni364e0872017-05-10 21:24:34 -070012627
12628 if (length < 2) {
12629 hdd_debug("bss size is less than expected");
12630 return true;
12631 }
12632 if (!ies) {
12633 hdd_debug("invalid IE pointer");
12634 return true;
12635 }
Naveen Rawat08db88f2017-09-08 15:07:48 -070012636 vendor_ie = wlan_get_vendor_ie_ptr_from_oui(VENDOR1_AP_OUI_TYPE,
Krunal Soni364e0872017-05-10 21:24:34 -070012637 VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
12638 if (vendor_ie) {
12639 hdd_debug("AP can't support immediate powersave. defer it");
12640 return false;
12641 }
12642 return true;
12643}
12644
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012645/*
12646 * FUNCTION: wlan_hdd_validate_operation_channel
12647 * called by wlan_hdd_cfg80211_start_bss() and
12648 * wlan_hdd_set_channel()
12649 * This function validates whether given channel is part of valid
12650 * channel list.
12651 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012652QDF_STATUS wlan_hdd_validate_operation_channel(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012653 int channel)
12654{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012655 uint32_t num_ch = 0;
12656 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
12657 u32 indx = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012658 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012659 uint8_t fValidChannel = false, count = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012660 struct hdd_config *hdd_pConfig_ini =
12661 (WLAN_HDD_GET_CTX(adapter))->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012662
12663 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12664
12665 if (hdd_pConfig_ini->sapAllowAllChannel) {
12666 /* Validate the channel */
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070012667 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_173; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012668 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012669 fValidChannel = true;
12670 break;
12671 }
12672 }
12673 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012674 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012675 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012676 }
12677 } else {
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012678 if (0 != sme_cfg_get_str(mac_handle, WNI_CFG_VALID_CHANNEL_LIST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012679 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070012680 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012681 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012682 }
12683 for (indx = 0; indx < num_ch; indx++) {
Srinivas Girigowda576b2352017-08-25 14:44:26 -070012684 if (channel == valid_ch[indx])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012685 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012686 }
12687
12688 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012689 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012690 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012691 }
12692 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012693 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012694
12695}
12696
12697#ifdef DHCP_SERVER_OFFLOAD
Jeff Johnson9c4f93d2017-10-04 08:56:22 -070012698static void wlan_hdd_set_dhcp_server_offload(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012699{
Jeff Johnson9c4f93d2017-10-04 08:56:22 -070012700 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012701 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
12702 uint8_t numEntries = 0;
12703 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
12704 uint8_t num;
12705 uint32_t temp;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012706 mac_handle_t mac_handle;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070012707
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012708 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012709 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070012710 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012711 return;
12712 }
Jeff Johnson1b780e42017-10-31 14:11:45 -070012713 pDhcpSrvInfo->vdev_id = adapter->session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012714 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
Jeff Johnsonb8944722017-09-03 09:03:19 -070012715 pDhcpSrvInfo->dhcpClientNum = hdd_ctx->config->dhcpMaxNumClients;
12716 hdd_string_to_u8_array(hdd_ctx->config->dhcpServerIP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012717 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
12718 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnsonb8944722017-09-03 09:03:19 -070012719 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", hdd_ctx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012720 goto end;
12721 }
12722 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnsonb8944722017-09-03 09:03:19 -070012723 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", hdd_ctx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012724 goto end;
12725 }
12726 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnsonb8944722017-09-03 09:03:19 -070012727 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", hdd_ctx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012728 goto end;
12729 }
12730 for (num = 0; num < numEntries; num++) {
12731 temp = srv_ip[num];
12732 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
12733 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012734 mac_handle = hdd_ctx->mac_handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012735 if (QDF_STATUS_SUCCESS !=
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012736 sme_set_dhcp_srv_offload(mac_handle, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070012737 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012738 goto end;
12739 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012740 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012741end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012742 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012743}
12744#endif /* DHCP_SERVER_OFFLOAD */
12745
12746static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
12747 struct net_device *dev,
12748 struct bss_parameters *params)
12749{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012750 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
12751 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012752 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012753 QDF_STATUS qdf_ret_status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012754 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012755
Dustin Brown491d54b2018-03-14 12:39:11 -070012756 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012757
Anurag Chouhan6d760662016-02-20 16:05:43 +053012758 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070012759 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012760 return -EINVAL;
12761 }
12762
Dustin Brown63500612018-08-07 11:36:09 -070012763 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012764 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012765
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012766 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012767 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
Jeff Johnson1b780e42017-10-31 14:11:45 -070012768 adapter->session_id, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012769 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012770 hdd_device_mode_to_string(adapter->device_mode),
12771 adapter->device_mode, params->ap_isolate);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012772
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012773 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070012774 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012775 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012776 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012777
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012778 if (!(adapter->device_mode == QDF_SAP_MODE ||
12779 adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012780 return -EOPNOTSUPP;
12781 }
12782
12783 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012784 * want to update this parameter
12785 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012786 if (-1 != params->ap_isolate) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070012787 adapter->session.ap.disable_intrabss_fwd =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012788 !!params->ap_isolate;
12789
Jeff Johnson34fc63a2018-06-14 10:10:02 -070012790 mac_handle = hdd_ctx->mac_handle;
12791 qdf_ret_status = sme_ap_disable_intra_bss_fwd(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -070012792 adapter->session_id,
Jeff Johnsonb9424862017-10-30 08:49:35 -070012793 adapter->session.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012794 ap.
Jeff Johnson82ceb082017-10-27 14:52:42 -070012795 disable_intrabss_fwd);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070012796 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012797 ret = -EINVAL;
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +053012798
Dustin Brown07901ec2018-09-07 11:02:41 -070012799 ucfg_ipa_set_ap_ibss_fwd(hdd_ctx->pdev,
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +053012800 adapter->session.ap.
12801 disable_intrabss_fwd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012802 }
12803
Dustin Browne74003f2018-03-14 12:51:58 -070012804 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012805 return ret;
12806}
12807
Krunal Soni8c37e322016-02-03 16:08:37 -080012808/**
12809 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
12810 * @ndev: pointer to net device provided by supplicant
12811 * @type: type of the interface, upper layer wanted to change
12812 *
12813 * Upper layer provides the new interface mode that needs to be changed
12814 * for given net device
12815 *
12816 * Return: success or failure in terms of integer value
12817 */
12818static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012819 enum nl80211_iftype type)
12820{
Jeff Johnsone5006672017-08-29 14:39:02 -070012821 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012822 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080012823 struct hdd_config *config = hdd_ctx->config;
Jeff Johnson20227a92018-03-13 09:41:05 -070012824 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012825 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053012826 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012827
Dustin Brown491d54b2018-03-14 12:39:11 -070012828 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012829
Krunal Soni8c37e322016-02-03 16:08:37 -080012830 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012831 hdd_warn("ACS is in progress, don't change iface!");
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070012832 return -EBUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012833 }
12834
12835 wdev = ndev->ieee80211_ptr;
Dustin Browndb2a8be2017-12-20 11:49:56 -080012836 hdd_stop_adapter(hdd_ctx, adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080012837 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012838 wdev->iftype = type;
12839 /*Check for sub-string p2p to confirm its a p2p interface */
12840 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080012841 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012842 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080012843 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080012844 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080012845 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012846 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080012847 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012848 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080012849 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012850 }
Jeff Johnsonb9424862017-10-30 08:49:35 -070012851 memset(&adapter->session, 0, sizeof(adapter->session));
Krunal Soni8c37e322016-02-03 16:08:37 -080012852 hdd_set_station_ops(adapter->dev);
Jeff Johnson20227a92018-03-13 09:41:05 -070012853
12854 roam_profile = hdd_roam_profile(adapter);
12855 roam_profile->pAddIEScan = adapter->scan_info.scan_add_ie.addIEdata;
12856 roam_profile->nAddIEScanLength =
Jeff Johnson37fa0402017-10-28 12:42:29 -070012857 adapter->scan_info.scan_add_ie.length;
Krunal Soni8c37e322016-02-03 16:08:37 -080012858 if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib51eec72017-11-20 21:53:01 -080012859 status = hdd_start_station_adapter(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070012860 roam_profile->BSSType = eCSR_BSS_TYPE_START_IBSS;
12861 roam_profile->phyMode =
Krunal Soni8c37e322016-02-03 16:08:37 -080012862 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
12863 }
Dustin Browne74003f2018-03-14 12:51:58 -070012864 hdd_exit();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070012865
12866 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012867}
12868
12869static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
12870 struct net_device *dev,
12871 struct bss_parameters *params)
12872{
12873 int ret;
12874
12875 cds_ssr_protect(__func__);
12876 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
12877 cds_ssr_unprotect(__func__);
12878
12879 return ret;
12880}
12881
Rajeev Kumar98edb772016-01-19 12:42:19 -080012882/**
12883 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
12884 * @wiphy: Pointer to the wiphy structure
12885 * @ndev: Pointer to the net device
12886 * @type: Interface type
12887 * @flags: Flags for change interface
12888 * @params: Pointer to change interface parameters
12889 *
12890 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012891 */
12892static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
12893 struct net_device *ndev,
12894 enum nl80211_iftype type,
12895 u32 *flags,
12896 struct vif_params *params)
12897{
12898 struct wireless_dev *wdev;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012899 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070012900 struct hdd_context *hdd_ctx;
Jeff Johnson61b5e982018-03-15 11:33:31 -070012901 struct csr_roam_profile *roam_profile = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012902 eCsrRoamBssType LastBSSType;
12903 struct hdd_config *pConfig = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012904 int status;
Arunk Khandavallia592bb62018-08-01 18:11:39 +053012905 bool iff_up = (ndev->flags & IFF_UP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012906
Dustin Brown491d54b2018-03-14 12:39:11 -070012907 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012908
Anurag Chouhan6d760662016-02-20 16:05:43 +053012909 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070012910 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012911 return -EINVAL;
12912 }
12913
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012914 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070012915 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012916 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012917 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012918
Nachiket Kukade08b9f292017-11-17 18:27:37 +053012919 if (cds_is_fw_down()) {
12920 hdd_err("Ignore if FW is already down");
12921 return -EINVAL;
12922 }
12923
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012924 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012925 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
Jeff Johnson1b780e42017-10-31 14:11:45 -070012926 adapter->session_id, type));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012927
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012928 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012929 adapter->device_mode, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012930
Dustin Browne7e71d32018-05-11 16:00:08 -070012931 status = hdd_wlan_start_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +053012932 if (status) {
12933 hdd_err("Failed to start modules");
12934 return -EINVAL;
12935 }
12936
Jeff Johnsonb8944722017-09-03 09:03:19 -070012937 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012938 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
12939 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070012940 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012941 return -EINVAL;
12942 }
12943
Jeff Johnsonb8944722017-09-03 09:03:19 -070012944 pConfig = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012945 wdev = ndev->ieee80211_ptr;
12946
12947 /* Reset the current device mode bit mask */
Jeff Johnsonb8944722017-09-03 09:03:19 -070012948 policy_mgr_clear_concurrency_mode(hdd_ctx->hdd_psoc,
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012949 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012950
Bala Venkateshb13a3c22018-08-23 11:34:35 +053012951 if (!(adapter->device_mode == QDF_P2P_DEVICE_MODE &&
12952 type == NL80211_IFTYPE_STATION)) {
12953 hdd_debug("Teardown tdls links and disable tdls in FW as new interface is coming up");
Dustin Brown89fa06e2018-09-07 10:47:27 -070012954 hdd_notify_teardown_tdls_links(adapter->vdev);
Bala Venkateshb13a3c22018-08-23 11:34:35 +053012955 }
12956
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012957 if ((adapter->device_mode == QDF_STA_MODE) ||
12958 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
12959 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
12960 (adapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012961
Jeff Johnson20227a92018-03-13 09:41:05 -070012962 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070012963 LastBSSType = roam_profile->BSSType;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012964
12965 switch (type) {
12966 case NL80211_IFTYPE_STATION:
12967 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080012968 case NL80211_IFTYPE_ADHOC:
12969 if (type == NL80211_IFTYPE_ADHOC) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012970 hdd_deregister_tx_flow_control(adapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012971 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080012972 }
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070012973 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
Krunal Soni8c37e322016-02-03 16:08:37 -080012974 type);
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070012975 if (status) {
12976 hdd_err("Failed to change iface to new mode:%d status %d",
12977 type, status);
12978 return status;
12979 }
Arunk Khandavallia592bb62018-08-01 18:11:39 +053012980 if (iff_up) {
12981 if (hdd_start_adapter(adapter)) {
12982 hdd_err("Failed to start adapter: %d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012983 adapter->device_mode);
Arunk Khandavallia592bb62018-08-01 18:11:39 +053012984 return -EINVAL;
12985 }
Arun Khandavallib2f6c262016-08-18 19:07:19 +053012986 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012987 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012988 case NL80211_IFTYPE_AP:
12989 case NL80211_IFTYPE_P2P_GO:
12990 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012991 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012992 (type ==
12993 NL80211_IFTYPE_AP) ? "SoftAP" :
12994 "P2pGo");
12995
12996 /* Cancel any remain on channel for GO mode */
12997 if (NL80211_IFTYPE_P2P_GO == type) {
12998 wlan_hdd_cancel_existing_remain_on_channel
Jeff Johnsonce2ba702017-10-02 13:30:24 -070012999 (adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013000 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013001
Dustin Browndb2a8be2017-12-20 11:49:56 -080013002 hdd_stop_adapter(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013003 /* De-init the adapter */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013004 hdd_deinit_adapter(hdd_ctx, adapter, true);
Jeff Johnsonb9424862017-10-30 08:49:35 -070013005 memset(&adapter->session, 0,
13006 sizeof(adapter->session));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013007 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013008 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080013009 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
13010 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013011
13012 /*
13013 * Fw will take care incase of concurrency
13014 */
13015
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013016 if ((QDF_SAP_MODE == adapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013017 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013018 /* To meet Android requirements create
13019 * a randomized MAC address of the
13020 * form 02:1A:11:Fx:xx:xx
13021 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013022 get_random_bytes(&ndev->dev_addr[3], 3);
13023 ndev->dev_addr[0] = 0x02;
13024 ndev->dev_addr[1] = 0x1A;
13025 ndev->dev_addr[2] = 0x11;
13026 ndev->dev_addr[3] |= 0xF0;
Jeff Johnson1e851a12017-10-28 14:36:12 -070013027 memcpy(adapter->mac_addr.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013028 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013029 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013030 pr_info("wlan: Generated HotSpot BSSID "
13031 MAC_ADDRESS_STR "\n",
13032 MAC_ADDR_ARRAY(ndev->dev_addr));
13033 }
13034
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013035 hdd_set_ap_ops(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013036
Arunk Khandavallia592bb62018-08-01 18:11:39 +053013037 if (iff_up) {
13038 if (hdd_start_adapter(adapter)) {
13039 hdd_err("Failed to start adapter: %d",
13040 adapter->device_mode);
13041 return -EINVAL;
13042 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013043 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013044 /* Interface type changed update in wiphy structure */
13045 if (wdev) {
13046 wdev->iftype = type;
13047 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070013048 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013049 return -EINVAL;
13050 }
13051 goto done;
13052 }
13053
13054 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013055 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013056 return -EOPNOTSUPP;
13057 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013058 } else if ((adapter->device_mode == QDF_SAP_MODE) ||
13059 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013060 switch (type) {
13061 case NL80211_IFTYPE_STATION:
13062 case NL80211_IFTYPE_P2P_CLIENT:
13063 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080013064 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
13065 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013066 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013067 return status;
Arunk Khandavallia592bb62018-08-01 18:11:39 +053013068
13069 if (iff_up) {
13070 if (hdd_start_adapter(adapter)) {
13071 hdd_err("Failed to start adapter: %d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013072 adapter->device_mode);
Arunk Khandavallia592bb62018-08-01 18:11:39 +053013073 return -EINVAL;
13074 }
Arun Khandavallib2f6c262016-08-18 19:07:19 +053013075 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013076 goto done;
13077
13078 case NL80211_IFTYPE_AP:
13079 case NL80211_IFTYPE_P2P_GO:
13080 wdev->iftype = type;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013081 adapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080013082 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013083 goto done;
13084
13085 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013086 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013087 return -EOPNOTSUPP;
13088 }
13089 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013090 hdd_err("Unsupported device mode: %d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013091 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013092 return -EOPNOTSUPP;
13093 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013094done:
13095 /* Set bitmask based on updated value */
Jeff Johnsonb8944722017-09-03 09:03:19 -070013096 policy_mgr_set_concurrency_mode(hdd_ctx->hdd_psoc,
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013097 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013098
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013099 hdd_lpass_notify_mode_change(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013100
Dustin Browne74003f2018-03-14 12:51:58 -070013101 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013102 return 0;
13103}
13104
Dustin Brown9ed30a52017-08-16 13:59:38 -070013105#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
Rajeev Kumar98edb772016-01-19 12:42:19 -080013106/**
13107 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
13108 * @wiphy: Pointer to the wiphy structure
13109 * @ndev: Pointer to the net device
13110 * @type: Interface type
13111 * @flags: Flags for change interface
13112 * @params: Pointer to change interface parameters
13113 *
13114 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013115 */
13116static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
13117 struct net_device *ndev,
13118 enum nl80211_iftype type,
13119 u32 *flags,
13120 struct vif_params *params)
13121{
13122 int ret;
13123
13124 cds_ssr_protect(__func__);
13125 ret =
13126 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
13127 cds_ssr_unprotect(__func__);
13128
13129 return ret;
13130}
Dustin Brown9ed30a52017-08-16 13:59:38 -070013131#else
13132static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
13133 struct net_device *ndev,
13134 enum nl80211_iftype type,
13135 struct vif_params *params)
13136{
13137 int ret;
13138
13139 cds_ssr_protect(__func__);
13140 ret = __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
13141 &params->flags, params);
13142 cds_ssr_unprotect(__func__);
13143
13144 return ret;
13145}
13146#endif /* KERNEL_VERSION(4, 12, 0) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013147
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013148/**
13149 * __wlan_hdd_change_station() - change station
13150 * @wiphy: Pointer to the wiphy structure
13151 * @dev: Pointer to the net device.
13152 * @mac: bssid
13153 * @params: Pointer to station parameters
13154 *
13155 * Return: 0 for success, error number on failure.
13156 */
13157#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13158static int __wlan_hdd_change_station(struct wiphy *wiphy,
13159 struct net_device *dev,
13160 const uint8_t *mac,
13161 struct station_parameters *params)
13162#else
13163static int __wlan_hdd_change_station(struct wiphy *wiphy,
13164 struct net_device *dev,
13165 uint8_t *mac,
13166 struct station_parameters *params)
13167#endif
13168{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013169 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013170 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070013171 struct hdd_context *hdd_ctx;
Jeff Johnsond377dce2017-10-04 10:32:42 -070013172 struct hdd_station_ctx *sta_ctx;
Vignesh Viswanathan597d9012018-07-06 15:26:08 +053013173 struct hdd_ap_ctx *ap_ctx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053013174 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013175 int ret;
13176
Dustin Brown491d54b2018-03-14 12:39:11 -070013177 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013178
Anurag Chouhan6d760662016-02-20 16:05:43 +053013179 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013180 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013181 return -EINVAL;
13182 }
13183
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013184 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013185 TRACE_CODE_HDD_CHANGE_STATION,
Jeff Johnson1b780e42017-10-31 14:11:45 -070013186 adapter->session_id, params->listen_interval));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013187
Dustin Brown63500612018-08-07 11:36:09 -070013188 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013189 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013190
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013191 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070013192 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013193 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013194 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013195
Jeff Johnsond377dce2017-10-04 10:32:42 -070013196 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013197
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013198 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013199
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013200 if ((adapter->device_mode == QDF_SAP_MODE) ||
13201 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013202 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
Vignesh Viswanathan597d9012018-07-06 15:26:08 +053013203 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
13204 /*
13205 * For Encrypted SAP session, this will be done as
13206 * part of eSAP_STA_SET_KEY_EVENT
13207 */
13208 if (ap_ctx->encryption_type !=
13209 eCSR_ENCRYPT_TYPE_NONE) {
13210 hdd_debug("Encrypt type %d, not setting peer authorized now",
13211 ap_ctx->encryption_type);
13212 return 0;
13213 }
13214
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013215 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013216 hdd_softap_change_sta_state(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013217 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080013218 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013219
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013220 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013221 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013222 return -EINVAL;
13223 }
13224 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013225 } else if ((adapter->device_mode == QDF_STA_MODE) ||
13226 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013227 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud1a28462017-09-06 22:55:48 +080013228#if defined(FEATURE_WLAN_TDLS)
Dustin Brown07901ec2018-09-07 11:02:41 -070013229 ret = wlan_cfg80211_tdls_update_peer(hdd_ctx->pdev,
Frank Liud4b2fa02017-03-29 11:46:48 +080013230 dev, mac, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013231#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080013232 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233 }
Dustin Browne74003f2018-03-14 12:51:58 -070013234 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013235 return ret;
13236}
13237
13238/**
13239 * wlan_hdd_change_station() - cfg80211 change station handler function
13240 * @wiphy: Pointer to the wiphy structure
13241 * @dev: Pointer to the net device.
13242 * @mac: bssid
13243 * @params: Pointer to station parameters
13244 *
13245 * This is the cfg80211 change station handler function which invokes
13246 * the internal function @__wlan_hdd_change_station with
13247 * SSR protection.
13248 *
13249 * Return: 0 for success, error number on failure.
13250 */
13251#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
13252static int wlan_hdd_change_station(struct wiphy *wiphy,
13253 struct net_device *dev,
13254 const u8 *mac,
13255 struct station_parameters *params)
13256#else
13257static int wlan_hdd_change_station(struct wiphy *wiphy,
13258 struct net_device *dev,
13259 u8 *mac,
13260 struct station_parameters *params)
13261#endif
13262{
13263 int ret;
13264
13265 cds_ssr_protect(__func__);
13266 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
13267 cds_ssr_unprotect(__func__);
13268
13269 return ret;
13270}
13271
13272/*
13273 * FUNCTION: __wlan_hdd_cfg80211_add_key
13274 * This function is used to initialize the key information
13275 */
13276static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
13277 struct net_device *ndev,
13278 u8 key_index, bool pairwise,
13279 const u8 *mac_addr,
13280 struct key_params *params)
13281{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013282 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013283 tCsrRoamSetKey setKey;
13284 int status;
Krunal Sonibfd05492017-10-03 15:48:37 -070013285 uint32_t roamId = INVALID_ROAM_ID;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013286 QDF_STATUS qdf_ret_status;
Jeff Johnsonb8944722017-09-03 09:03:19 -070013287 struct hdd_context *hdd_ctx;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013288 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013289
Dustin Brown491d54b2018-03-14 12:39:11 -070013290 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013291
Anurag Chouhan6d760662016-02-20 16:05:43 +053013292 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013293 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013294 return -EINVAL;
13295 }
13296
Dustin Brown63500612018-08-07 11:36:09 -070013297 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013298 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013299
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013300 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013301 TRACE_CODE_HDD_CFG80211_ADD_KEY,
Jeff Johnson1b780e42017-10-31 14:11:45 -070013302 adapter->session_id, params->key_len));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013303 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070013304 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013305
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013306 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013307 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013308
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013309 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013310 hdd_device_mode_to_string(adapter->device_mode),
13311 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013312
13313 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013314 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013315
13316 return -EINVAL;
13317 }
13318
13319 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013320 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013321
13322 return -EINVAL;
13323 }
13324
Jeff Johnsonb05f4fd2017-10-18 15:08:21 -070013325 if (CSR_MAX_RSC_LEN < params->seq_len) {
13326 hdd_err("Invalid seq length %d", params->seq_len);
13327
13328 return -EINVAL;
13329 }
13330
13331 hdd_debug("key index %d, key length %d, seq length %d",
13332 key_index, params->key_len, params->seq_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013333
13334 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013335 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013336 setKey.keyId = key_index;
13337 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013338 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Jeff Johnsonb05f4fd2017-10-18 15:08:21 -070013339 qdf_mem_copy(&setKey.keyRsc[0], params->seq, params->seq_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013340
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013341 mac_handle = hdd_ctx->mac_handle;
13342
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013343 switch (params->cipher) {
13344 case WLAN_CIPHER_SUITE_WEP40:
13345 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
13346 break;
13347
13348 case WLAN_CIPHER_SUITE_WEP104:
13349 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
13350 break;
13351
13352 case WLAN_CIPHER_SUITE_TKIP:
13353 {
13354 u8 *pKey = &setKey.Key[0];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013355
Srinivas Girigowda576b2352017-08-25 14:44:26 -070013356 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013357 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013358
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013359 /* Supplicant sends the 32bytes key in this order
13360 *
13361 * |--------------|----------|----------|
13362 * | Tk1 |TX-MIC | RX Mic |
13363 * |--------------|----------|----------|
13364 * <---16bytes---><--8bytes--><--8bytes-->
13365 *
13366 * Sme expects the 32 bytes key to be in the below order
13367 *
13368 * |--------------|----------|----------|
13369 * | Tk1 |RX-MIC | TX Mic |
13370 * |--------------|----------|----------|
13371 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013372 */
13373 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013374 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013375
13376 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013377 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013378
13379 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013380 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013381
13382 break;
13383 }
13384
13385 case WLAN_CIPHER_SUITE_CCMP:
13386 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
13387 break;
13388
13389#ifdef FEATURE_WLAN_WAPI
13390 case WLAN_CIPHER_SUITE_SMS4:
13391 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013392 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013393 wlan_hdd_cfg80211_set_key_wapi(adapter, key_index,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013394 mac_addr, params->key,
13395 params->key_len);
13396 return 0;
13397 }
13398#endif
13399
13400#ifdef FEATURE_WLAN_ESE
13401 case WLAN_CIPHER_SUITE_KRK:
13402 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
13403 break;
13404#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13405 case WLAN_CIPHER_SUITE_BTK:
13406 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
13407 break;
13408#endif
13409#endif
13410
13411#ifdef WLAN_FEATURE_11W
13412 case WLAN_CIPHER_SUITE_AES_CMAC:
13413 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
13414 break;
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +053013415#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
13416 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
13417 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GMAC_128;
13418 break;
13419 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
13420 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GMAC_256;
13421 break;
13422#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013423#endif
Mukul Sharma05504ac2017-06-08 12:35:53 +053013424 case WLAN_CIPHER_SUITE_GCMP:
13425 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GCMP;
13426 break;
13427 case WLAN_CIPHER_SUITE_GCMP_256:
13428 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GCMP_256;
13429 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013430
13431 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013432 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013433 return -EOPNOTSUPP;
13434 }
13435
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013436 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013437
13438 if (!pairwise) {
13439 /* set group key */
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070013440 hdd_debug("setting Broadcast key");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013441 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053013442 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013443 } else {
13444 /* set pairwise key */
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070013445 hdd_debug("setting pairwise key");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013446 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013447 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013448 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013449 if ((QDF_IBSS_MODE == adapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013450 /* if a key is already installed, block all subsequent ones */
Jeff Johnsonb9424862017-10-30 08:49:35 -070013451 if (adapter->session.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013452 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013453 return 0;
13454 }
13455
13456 setKey.keyDirection = eSIR_TX_RX;
13457 /*Set the group key */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013458 status = sme_roam_set_key(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -070013459 adapter->session_id, &setKey, &roamId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013460
13461 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013462 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013463 return -EINVAL;
13464 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013465 /* Save the keys here and call sme_roam_set_key for setting
13466 * the PTK after peer joins the IBSS network
13467 */
Jeff Johnsonb9424862017-10-30 08:49:35 -070013468 qdf_mem_copy(&adapter->session.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013469 &setKey, sizeof(tCsrRoamSetKey));
13470
Jeff Johnsonb9424862017-10-30 08:49:35 -070013471 adapter->session.station.ibss_enc_key_installed = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013472 return status;
13473 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013474 if ((adapter->device_mode == QDF_SAP_MODE) ||
13475 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053013476 struct hdd_hostapd_state *hostapd_state =
13477 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
13478 struct hdd_ap_ctx *ap_ctx =
13479 WLAN_HDD_GET_AP_CTX_PTR(adapter);
13480
Jeff Johnson0f9f87b2017-10-28 09:21:06 -070013481 if (hostapd_state->bss_state == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070013482 status = wlansap_set_key_sta(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013483 WLAN_HDD_GET_SAP_CTX_PTR(adapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013484 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013485 hdd_err("wlansap_set_key_sta failed status: %d",
13486 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013487 }
13488 }
13489
Jeff Johnson413c15f2017-10-27 18:56:35 -070013490 /* Save the key in ap ctx for use on START_BSS and restart */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013491 if (pairwise ||
13492 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
13493 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Jeff Johnson3d731362017-10-27 19:06:41 -070013494 qdf_mem_copy(&ap_ctx->wep_key[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013495 sizeof(tCsrRoamSetKey));
13496 else
Jeff Johnson413c15f2017-10-27 18:56:35 -070013497 qdf_mem_copy(&ap_ctx->group_key, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013498 sizeof(tCsrRoamSetKey));
13499
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013500 } else if ((adapter->device_mode == QDF_STA_MODE) ||
13501 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Jeff Johnsond377dce2017-10-04 10:32:42 -070013502 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013503 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070013504 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013505
13506 if (!pairwise) {
13507 /* set group key */
Jeff Johnsonaf2ae4b2017-11-01 11:38:50 -070013508 if (sta_ctx->roam_info.defer_key_complete) {
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070013509 hdd_debug("Perform Set key Complete");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013510 hdd_perform_roam_set_key_complete(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013511 }
13512 }
13513
Jeff Johnson20227a92018-03-13 09:41:05 -070013514 roam_profile = hdd_roam_profile(adapter);
13515 roam_profile->Keys.KeyLength[key_index] = params->key_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013516
Jeff Johnson20227a92018-03-13 09:41:05 -070013517 roam_profile->Keys.defaultIndex = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013518
Jeff Johnson20227a92018-03-13 09:41:05 -070013519 qdf_mem_copy(&roam_profile->Keys.KeyMaterial[key_index][0],
13520 params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013521
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013522 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013523 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
13524 setKey.keyDirection);
13525
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013526 /* The supplicant may attempt to set the PTK once
13527 * pre-authentication is done. Save the key in the
13528 * UMAC and include it in the ADD BSS request
13529 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013530 qdf_ret_status = sme_ft_update_key(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -070013531 adapter->session_id, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013532 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013533 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013534 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013535 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013536 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013537 return -EINVAL;
13538 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013539
13540 /* issue set key request to SME */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013541 status = sme_roam_set_key(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -070013542 adapter->session_id, &setKey, &roamId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013543
13544 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013545 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013546 return -EINVAL;
13547 }
13548
Yeshwanth Sriram Guntuka4fe30bd2018-06-13 11:41:42 +053013549 if (adapter->send_mode_change) {
13550 wlan_hdd_send_mode_change_event();
13551 adapter->send_mode_change = false;
13552 }
13553
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013554 /* in case of IBSS as there was no information
13555 * available about WEP keys during IBSS join, group
Jeff Johnson5e19a942018-05-06 15:37:39 -070013556 * key initialized with NULL key, so re-initialize
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013557 * group key with correct value
13558 */
Jeff Johnson20227a92018-03-13 09:41:05 -070013559 if ((eCSR_BSS_TYPE_START_IBSS == roam_profile->BSSType) &&
Jeff Johnson37ecea42018-03-18 17:54:40 -070013560 !((HDD_AUTH_KEY_MGMT_802_1X ==
13561 (sta_ctx->auth_key_mgmt & HDD_AUTH_KEY_MGMT_802_1X))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013562 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
Jeff Johnsond377dce2017-10-04 10:32:42 -070013563 sta_ctx->conn_info.authType)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013564 )
13565 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
13566 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
13567 )
13568 ) {
13569 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053013570 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013571
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013572 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013573 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
13574 setKey.keyDirection);
13575
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013576 status = sme_roam_set_key(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -070013577 adapter->session_id, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013578 &roamId);
13579
13580 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013581 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013582 return -EINVAL;
13583 }
13584 }
13585 }
Dustin Browne74003f2018-03-14 12:51:58 -070013586 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013587 return 0;
13588}
13589
13590static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
13591 struct net_device *ndev,
13592 u8 key_index, bool pairwise,
13593 const u8 *mac_addr,
13594 struct key_params *params)
13595{
13596 int ret;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070013597
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013598 cds_ssr_protect(__func__);
13599 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
13600 mac_addr, params);
13601 cds_ssr_unprotect(__func__);
13602
13603 return ret;
13604}
13605
13606/*
13607 * FUNCTION: __wlan_hdd_cfg80211_get_key
13608 * This function is used to get the key information
13609 */
13610static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
13611 struct net_device *ndev,
13612 u8 key_index, bool pairwise,
13613 const u8 *mac_addr, void *cookie,
13614 void (*callback)(void *cookie,
13615 struct key_params *)
13616 )
13617{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013618 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070013619 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013620 struct key_params params;
13621
Dustin Brown491d54b2018-03-14 12:39:11 -070013622 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013623
Anurag Chouhan6d760662016-02-20 16:05:43 +053013624 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013625 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013626 return -EINVAL;
13627 }
13628
Dustin Brown63500612018-08-07 11:36:09 -070013629 if (wlan_hdd_validate_session_id(adapter->session_id))
Jiachao Wud58cfc92017-12-27 14:15:23 +080013630 return -EINVAL;
Jiachao Wud58cfc92017-12-27 14:15:23 +080013631
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013632 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013633 hdd_device_mode_to_string(adapter->device_mode),
13634 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013635
13636 memset(&params, 0, sizeof(params));
13637
13638 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013639 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013640 return -EINVAL;
13641 }
13642
Nachiket Kukaded9152832017-10-16 16:18:22 +053013643 if ((adapter->device_mode == QDF_SAP_MODE) ||
13644 (adapter->device_mode == QDF_P2P_GO_MODE)) {
13645 struct hdd_ap_ctx *ap_ctx =
13646 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070013647
Nachiket Kukaded9152832017-10-16 16:18:22 +053013648 roam_profile =
13649 wlan_sap_get_roam_profile(ap_ctx->sap_context);
13650 } else {
Jeff Johnson20227a92018-03-13 09:41:05 -070013651 roam_profile = hdd_roam_profile(adapter);
Nachiket Kukaded9152832017-10-16 16:18:22 +053013652 }
13653
Jiachao Wud58cfc92017-12-27 14:15:23 +080013654 if (roam_profile == NULL) {
13655 hdd_err("Get roam profile failed!");
13656 return -EINVAL;
13657 }
13658
Jeff Johnson5b34fce2017-10-13 13:24:51 -070013659 switch (roam_profile->EncryptionType.encryptionType[0]) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660 case eCSR_ENCRYPT_TYPE_NONE:
13661 params.cipher = IW_AUTH_CIPHER_NONE;
13662 break;
13663
13664 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
13665 case eCSR_ENCRYPT_TYPE_WEP40:
13666 params.cipher = WLAN_CIPHER_SUITE_WEP40;
13667 break;
13668
13669 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
13670 case eCSR_ENCRYPT_TYPE_WEP104:
13671 params.cipher = WLAN_CIPHER_SUITE_WEP104;
13672 break;
13673
13674 case eCSR_ENCRYPT_TYPE_TKIP:
13675 params.cipher = WLAN_CIPHER_SUITE_TKIP;
13676 break;
13677
13678 case eCSR_ENCRYPT_TYPE_AES:
13679 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
13680 break;
Mukul Sharma05504ac2017-06-08 12:35:53 +053013681 case eCSR_ENCRYPT_TYPE_AES_GCMP:
13682 params.cipher = WLAN_CIPHER_SUITE_GCMP;
13683 break;
13684 case eCSR_ENCRYPT_TYPE_AES_GCMP_256:
13685 params.cipher = WLAN_CIPHER_SUITE_GCMP_256;
13686 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013687 default:
13688 params.cipher = IW_AUTH_CIPHER_NONE;
13689 break;
13690 }
13691
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013692 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013693 TRACE_CODE_HDD_CFG80211_GET_KEY,
Jeff Johnson1b780e42017-10-31 14:11:45 -070013694 adapter->session_id, params.cipher));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013695
Jeff Johnson5b34fce2017-10-13 13:24:51 -070013696 params.key_len = roam_profile->Keys.KeyLength[key_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013697 params.seq_len = 0;
13698 params.seq = NULL;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070013699 params.key = &roam_profile->Keys.KeyMaterial[key_index][0];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013700 callback(cookie, &params);
13701
Dustin Browne74003f2018-03-14 12:51:58 -070013702 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013703 return 0;
13704}
13705
13706static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
13707 struct net_device *ndev,
13708 u8 key_index, bool pairwise,
13709 const u8 *mac_addr, void *cookie,
13710 void (*callback)(void *cookie,
13711 struct key_params *)
13712 )
13713{
13714 int ret;
13715
13716 cds_ssr_protect(__func__);
13717 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
13718 mac_addr, cookie, callback);
13719 cds_ssr_unprotect(__func__);
13720
13721 return ret;
13722}
13723
13724/**
13725 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
13726 * @wiphy: wiphy interface context
13727 * @ndev: pointer to net device
13728 * @key_index: Key index used in 802.11 frames
13729 * @unicast: true if it is unicast key
13730 * @multicast: true if it is multicast key
13731 *
13732 * This function is required for cfg80211_ops API.
13733 * It is used to delete the key information
13734 * Underlying hardware implementation does not have API to delete the
13735 * encryption key. It is automatically deleted when the peer is
13736 * removed. Hence this function currently does nothing.
13737 * Future implementation may interprete delete key operation to
13738 * replacing the key with a random junk value, effectively making it
13739 * useless.
13740 *
13741 * Return: status code, always 0.
13742 */
13743
13744static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
13745 struct net_device *ndev,
13746 u8 key_index,
13747 bool pairwise, const u8 *mac_addr)
13748{
Dustin Browne74003f2018-03-14 12:51:58 -070013749 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013750 return 0;
13751}
13752
13753/**
13754 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
13755 * @wiphy: Pointer to wiphy structure.
13756 * @dev: Pointer to net_device structure.
13757 * @key_index: key index
13758 * @pairwise: pairwise
13759 * @mac_addr: mac address
13760 *
13761 * This is the cfg80211 delete key handler function which invokes
13762 * the internal function @__wlan_hdd_cfg80211_del_key with
13763 * SSR protection.
13764 *
13765 * Return: 0 for success, error number on failure.
13766 */
13767static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
13768 struct net_device *dev,
13769 u8 key_index,
13770 bool pairwise, const u8 *mac_addr)
13771{
13772 int ret;
13773
13774 cds_ssr_protect(__func__);
13775 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
13776 pairwise, mac_addr);
13777 cds_ssr_unprotect(__func__);
13778
13779 return ret;
13780}
13781
Hu Wangc3148842017-06-20 19:03:29 +080013782#ifdef FEATURE_WLAN_WAPI
13783static bool hdd_is_wapi_enc_type(eCsrEncryptionType ucEncryptionType)
13784{
13785 if (ucEncryptionType == eCSR_ENCRYPT_TYPE_WPI)
13786 return true;
13787
13788 return false;
13789}
13790#else
13791static bool hdd_is_wapi_enc_type(eCsrEncryptionType ucEncryptionType)
13792{
13793 return false;
13794}
13795#endif
13796
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013797/*
13798 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
13799 * This function is used to set the default tx key index
13800 */
13801static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
13802 struct net_device *ndev,
13803 u8 key_index,
13804 bool unicast, bool multicast)
13805{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013806 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070013807 struct hdd_context *hdd_ctx;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013808 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013809 int status;
13810
Dustin Brown491d54b2018-03-14 12:39:11 -070013811 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013812
Anurag Chouhan6d760662016-02-20 16:05:43 +053013813 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013814 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013815 return -EINVAL;
13816 }
13817
Dustin Brown63500612018-08-07 11:36:09 -070013818 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013819 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013820
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013821 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013822 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
Jeff Johnson1b780e42017-10-31 14:11:45 -070013823 adapter->session_id, key_index));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013824
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013825 hdd_debug("Device_mode %s(%d) key_index = %d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013826 hdd_device_mode_to_string(adapter->device_mode),
13827 adapter->device_mode, key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013828
13829 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013830 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013831 return -EINVAL;
13832 }
13833
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013834 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070013835 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013836
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013837 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013838 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013839
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013840 mac_handle = hdd_ctx->mac_handle;
13841
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013842 if ((adapter->device_mode == QDF_STA_MODE) ||
13843 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053013844 struct hdd_station_ctx *sta_ctx =
13845 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070013846 struct csr_roam_profile *roam_profile;
13847
13848 roam_profile = hdd_roam_profile(adapter);
Nachiket Kukaded9152832017-10-16 16:18:22 +053013849
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013850 if ((eCSR_ENCRYPT_TYPE_TKIP !=
Jeff Johnsond377dce2017-10-04 10:32:42 -070013851 sta_ctx->conn_info.ucEncryptionType) &&
Hu Wangc3148842017-06-20 19:03:29 +080013852 !hdd_is_wapi_enc_type(
Jeff Johnsond377dce2017-10-04 10:32:42 -070013853 sta_ctx->conn_info.ucEncryptionType) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013854 (eCSR_ENCRYPT_TYPE_AES !=
Jeff Johnsond377dce2017-10-04 10:32:42 -070013855 sta_ctx->conn_info.ucEncryptionType) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053013856 (eCSR_ENCRYPT_TYPE_AES_GCMP !=
Jeff Johnsond377dce2017-10-04 10:32:42 -070013857 sta_ctx->conn_info.ucEncryptionType) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053013858 (eCSR_ENCRYPT_TYPE_AES_GCMP_256 !=
Jeff Johnsond377dce2017-10-04 10:32:42 -070013859 sta_ctx->conn_info.ucEncryptionType)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013860 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013861 * then update the default key index
13862 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013863
13864 tCsrRoamSetKey setKey;
Krunal Sonibfd05492017-10-03 15:48:37 -070013865 uint32_t roamId = INVALID_ROAM_ID;
Jeff Johnson20227a92018-03-13 09:41:05 -070013866 tCsrKeys *Keys = &roam_profile->Keys;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013867
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013868 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013869
13870 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013871 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013872 setKey.keyId = key_index;
13873 setKey.keyLength = Keys->KeyLength[key_index];
13874
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013875 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013876 &Keys->KeyMaterial[key_index][0],
13877 Keys->KeyLength[key_index]);
13878
13879 setKey.keyDirection = eSIR_TX_RX;
13880
Anurag Chouhanc5548422016-02-24 18:33:27 +053013881 qdf_copy_macaddr(&setKey.peerMac,
Jeff Johnsond377dce2017-10-04 10:32:42 -070013882 &sta_ctx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013883
13884 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
Jeff Johnson20227a92018-03-13 09:41:05 -070013885 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013886 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013887 /* In the case of dynamic wep
13888 * supplicant hardcodes DWEP type to
13889 * eCSR_ENCRYPT_TYPE_WEP104 even
13890 * though ap is configured for WEP-40
13891 * encryption. In this canse the key
13892 * length is 5 but the encryption type
13893 * is 104 hence checking the key
Jeff Johnsonfe8e9492018-05-06 15:40:52 -070013894 * length(5) and encryption type(104)
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013895 * and switching encryption type to 40
13896 */
Jeff Johnson20227a92018-03-13 09:41:05 -070013897 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013898 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
Jeff Johnson20227a92018-03-13 09:41:05 -070013899 roam_profile->mcEncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013900 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
13901 }
13902
13903 setKey.encType =
Jeff Johnson20227a92018-03-13 09:41:05 -070013904 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013905 encryptionType[0];
13906
13907 /* Issue set key request */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070013908 status = sme_roam_set_key(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -070013909 adapter->session_id, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013910 &roamId);
13911
13912 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013913 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013914 status);
13915 return -EINVAL;
13916 }
13917 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013918 } else if (QDF_SAP_MODE == adapter->device_mode) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053013919 struct hdd_ap_ctx *ap_ctx =
13920 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnson61b5e982018-03-15 11:33:31 -070013921 struct csr_roam_profile *profile =
Nachiket Kukaded9152832017-10-16 16:18:22 +053013922 wlan_sap_get_roam_profile(ap_ctx->sap_context);
13923
13924 if (!profile) {
13925 hdd_err("Failed to get SAP Roam Profile");
13926 return -EINVAL;
13927 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013928 /* In SoftAp mode setting key direction for default mode */
13929 if ((eCSR_ENCRYPT_TYPE_TKIP !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053013930 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053013931 (eCSR_ENCRYPT_TYPE_AES !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053013932 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053013933 (eCSR_ENCRYPT_TYPE_AES_GCMP !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053013934 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053013935 (eCSR_ENCRYPT_TYPE_AES_GCMP_256 !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053013936 profile->EncryptionType.encryptionType[0])) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013937 /* Saving key direction for default key index to TX default */
Nachiket Kukaded9152832017-10-16 16:18:22 +053013938 ap_ctx->wep_key[key_index].keyDirection =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013939 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013940 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053013941 key_index);
Nachiket Kukaded9152832017-10-16 16:18:22 +053013942 ap_ctx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013943 }
13944 }
13945
Dustin Browne74003f2018-03-14 12:51:58 -070013946 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013947 return status;
13948}
13949
13950static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
13951 struct net_device *ndev,
13952 u8 key_index,
13953 bool unicast, bool multicast)
13954{
13955 int ret;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -070013956
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013957 cds_ssr_protect(__func__);
13958 ret =
13959 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
13960 multicast);
13961 cds_ssr_unprotect(__func__);
13962
13963 return ret;
13964}
13965
Abhishek Singhc9941602016-08-09 16:06:22 +053013966/*
Abhishek Singhc9941602016-08-09 16:06:22 +053013967 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
13968 * interface that BSS might have been lost.
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013969 * @adapter: adaptor
Abhishek Singhc9941602016-08-09 16:06:22 +053013970 * @bssid: bssid which might have been lost
13971 *
13972 * Return: bss which is unlinked from kernel cache
13973 */
13974struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013975 struct hdd_adapter *adapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013976{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070013977 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013978 struct wireless_dev *wdev = dev->ieee80211_ptr;
13979 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013980 struct cfg80211_bss *bss = NULL;
13981
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053013982 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053013983 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013984 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013985 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013986 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013987 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053013988 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013989 cfg80211_unlink_bss(wiphy, bss);
13990 }
13991 return bss;
13992}
13993
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013994#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053013995static inline int
13996wlan_hdd_get_frame_len(struct bss_description *bss_desc)
13997{
13998 return GET_IE_LEN_IN_BSS(bss_desc->length) + sizeof(qcom_ie_age);
13999}
14000
14001static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053014002 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014003{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014004 qcom_ie_age *qie_age = NULL;
Nachiket Kukade348ede72017-04-28 16:34:24 +053014005
14006 /*
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014007 * GPS Requirement: need age ie per entry. Using vendor specific.
14008 * Assuming this is the last IE, copy at the end
Nachiket Kukade348ede72017-04-28 16:34:24 +053014009 */
Abhishek Singhf1c16762018-03-07 10:48:46 +053014010 *ie_length -= sizeof(qcom_ie_age);
14011 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + *ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014012 qie_age->element_id = QCOM_VENDOR_IE_ID;
14013 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
14014 qie_age->oui_1 = QCOM_OUI1;
14015 qie_age->oui_2 = QCOM_OUI2;
14016 qie_age->oui_3 = QCOM_OUI3;
14017 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053014018 /*
14019 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
14020 * all bss related timestamp is in units of ms. Due to this when scan
14021 * results are sent to lowi the scan age is high.To address this,
14022 * send age in units of 1/10 ms.
14023 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014024 qie_age->age = (uint32_t)(qdf_mc_timer_get_system_time() -
14025 bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014026 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070014027 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
14028 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070014029 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
14030 sizeof(qie_age->seq_ctrl));
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014031}
14032#else
14033static inline int
14034wlan_hdd_get_frame_len(struct bss_description *bss_desc)
14035{
14036 return GET_IE_LEN_IN_BSS(bss_desc->length);
14037}
14038static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053014039 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014040{
14041}
14042#endif /* WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014043
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014044
14045struct cfg80211_bss *
14046wlan_hdd_inform_bss_frame(struct hdd_adapter *adapter,
14047 struct bss_description *bss_desc)
14048{
14049 struct wireless_dev *wdev = adapter->dev->ieee80211_ptr;
14050 struct wiphy *wiphy = wdev->wiphy;
Abhishek Singhf1c16762018-03-07 10:48:46 +053014051 uint32_t ie_length = wlan_hdd_get_frame_len(bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014052 const char *ie =
14053 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
14054 uint32_t freq, i;
14055 struct cfg80211_bss *bss_status = NULL;
14056 struct hdd_context *hdd_ctx;
14057 struct timespec ts;
14058 struct hdd_config *cfg_param;
14059 struct wlan_cfg80211_inform_bss bss_data = {0};
14060
14061 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14062 /*
14063 * wlan_hdd_validate_context should not be used here, In validate ctx
14064 * start_modules_in_progress or stop_modules_in_progress is validated,
14065 * If the start_modules_in_progress is set to true means the interface
14066 * is not UP yet if the stop_modules_in_progress means that interface
14067 * is already down. So in both the two scenario's driver should not be
14068 * informing bss to kernel. Hence removing the validate context.
14069 */
14070
14071 if (!hdd_ctx || !hdd_ctx->config) {
14072 hdd_debug("HDD context is Null");
14073 return NULL;
14074 }
14075
14076 if (cds_is_driver_recovering() ||
14077 cds_is_load_or_unload_in_progress()) {
14078 hdd_debug("Recovery or load/unload in progress. State: 0x%x",
14079 cds_get_driver_state());
14080 return NULL;
14081 }
14082
14083 cfg_param = hdd_ctx->config;
14084 bss_data.frame_len = ie_length + offsetof(struct ieee80211_mgmt,
14085 u.probe_resp.variable);
14086 bss_data.mgmt = qdf_mem_malloc(bss_data.frame_len);
14087 if (!bss_data.mgmt) {
14088 hdd_err("memory allocation failed");
14089 return NULL;
14090 }
14091
14092 memcpy(bss_data.mgmt->bssid, bss_desc->bssId, ETH_ALEN);
14093
14094 /* Android does not want the timestamp from the frame.
14095 * Instead it wants a monotonic increasing value
14096 */
14097 get_monotonic_boottime(&ts);
14098 bss_data.mgmt->u.probe_resp.timestamp =
14099 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
14100
14101 bss_data.mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
14102 bss_data.mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
14103
Abhishek Singhf1c16762018-03-07 10:48:46 +053014104 wlan_hdd_add_age_ie(bss_data.mgmt, &ie_length, bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014105
14106 memcpy(bss_data.mgmt->u.probe_resp.variable, ie, ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014107 if (bss_desc->fProbeRsp) {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014108 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014109 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
14110 } else {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014111 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014112 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
14113 }
14114
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014115 if (bss_desc->channelId <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070014116 (wiphy->bands[HDD_NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014117 freq =
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014118 ieee80211_channel_to_frequency(bss_desc->channelId,
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -070014119 HDD_NL80211_BAND_2GHZ);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014120 } else if ((bss_desc->channelId > ARRAY_SIZE(hdd_channels_2_4_ghz))
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070014121 && (wiphy->bands[HDD_NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014122 freq =
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014123 ieee80211_channel_to_frequency(bss_desc->channelId,
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -070014124 HDD_NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014125 } else {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014126 hdd_err("Invalid channel: %d", bss_desc->channelId);
14127 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014128 return NULL;
14129 }
14130
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014131 bss_data.chan = ieee80211_get_channel(wiphy, freq);
14132 if (!bss_data.chan) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053014133 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014134 bss_desc->channelId, freq);
14135 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014136 return NULL;
14137 }
14138
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014139 /*
14140 * Based on .ini configuration, raw rssi can be reported for bss.
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070014141 * Raw rssi is typically used for estimating power.
14142 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014143 bss_data.rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070014144 bss_desc->rssi;
14145
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014146 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014147 bss_data.rssi = QDF_MIN(bss_data.rssi, 0) * 100;
14148
14149 bss_data.boottime_ns = bss_desc->scansystimensec;
14150
14151 /* Set all per chain rssi as invalid */
14152 for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++)
14153 bss_data.per_chain_snr[i] = WLAN_INVALID_PER_CHAIN_RSSI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014154
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080014155 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014156 MAC_ADDR_ARRAY(bss_data.mgmt->bssid), bss_data.chan->center_freq,
14157 (int)(bss_data.rssi / 100),
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070014158 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014159
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014160 bss_status = wlan_cfg80211_inform_bss_frame_data(wiphy, &bss_data);
Jeff Johnsonb8944722017-09-03 09:03:19 -070014161 hdd_ctx->beacon_probe_rsp_cnt_per_scan++;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014162 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014163 return bss_status;
14164}
14165
14166/**
14167 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014168 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070014169 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014170 *
14171 * This function is used to update the BSS data base of CFG8011
14172 *
14173 * Return: struct cfg80211_bss pointer
14174 */
Jeff Johnson172237b2017-11-07 15:32:59 -080014175struct cfg80211_bss *
14176wlan_hdd_cfg80211_update_bss_db(struct hdd_adapter *adapter,
14177 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014178{
14179 tCsrRoamConnectedProfile roamProfile;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014180 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014181 struct cfg80211_bss *bss = NULL;
14182
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014183 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014184 sme_roam_get_connect_profile(mac_handle, adapter->session_id,
14185 &roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014186
14187 if (NULL != roamProfile.pBssDesc) {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014188 bss = wlan_hdd_inform_bss_frame(adapter, roamProfile.pBssDesc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014189
14190 if (NULL == bss)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053014191 hdd_debug("wlan_hdd_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014192
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080014193 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014194 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014195 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014196 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014197 return bss;
14198}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014199
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200/**
14201 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014202 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070014203 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014204 * @index: Index
14205 * @preauth: Preauth flag
14206 *
14207 * This function is used to notify the supplicant of a new PMKSA candidate.
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080014208 * PMK value is notified to supplicant whether PMK caching or OKC is enabled
14209 * in firmware or not. Supplicant needs this value becaue it uses PMK caching
14210 * by default.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014211 *
14212 * Return: 0 for success, non-zero for failure
14213 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014214int wlan_hdd_cfg80211_pmksa_candidate_notify(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080014215 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014216 int index, bool preauth)
14217{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014218 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014219
Dustin Brown491d54b2018-03-14 12:39:11 -070014220 hdd_enter();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014221 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014222
Jeff Johnsonfd060852017-10-04 10:50:51 -070014223 if (NULL == roam_info) {
14224 hdd_err("roam_info is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014225 return -EINVAL;
14226 }
14227
Dustin Brown5e89ef82018-03-14 11:50:23 -070014228 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080014229 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnsonfd060852017-10-04 10:50:51 -070014230 roam_info->bssid.bytes,
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080014231 preauth, GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014232 return 0;
14233}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014234
14235#ifdef FEATURE_WLAN_LFR_METRICS
14236/**
14237 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014238 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070014239 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014240 *
14241 * 802.11r/LFR metrics reporting function to report preauth initiation
14242 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053014243 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014244 */
14245#define MAX_LFR_METRICS_EVENT_LENGTH 100
Jeff Johnson172237b2017-11-07 15:32:59 -080014246QDF_STATUS
14247wlan_hdd_cfg80211_roam_metrics_preauth(struct hdd_adapter *adapter,
14248 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014249{
14250 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
14251 union iwreq_data wrqu;
14252
Dustin Brown491d54b2018-03-14 12:39:11 -070014253 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014254
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014255 if (NULL == adapter) {
14256 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014257 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014258 }
14259
14260 /* create the event */
14261 memset(&wrqu, 0, sizeof(wrqu));
14262 memset(metrics_notification, 0, sizeof(metrics_notification));
14263
14264 wrqu.data.pointer = metrics_notification;
14265 wrqu.data.length = scnprintf(metrics_notification,
14266 sizeof(metrics_notification),
14267 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
Jeff Johnsonfd060852017-10-04 10:50:51 -070014268 MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014269
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014270 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014271 metrics_notification);
14272
Dustin Browne74003f2018-03-14 12:51:58 -070014273 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014274
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014275 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014276}
14277
14278/**
14279 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014280 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070014281 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014282 * @preauth_status: Preauth status
14283 *
14284 * 802.11r/LFR metrics reporting function to report handover initiation
14285 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053014286 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014287 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014288QDF_STATUS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014289wlan_hdd_cfg80211_roam_metrics_preauth_status(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080014290 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014291 bool preauth_status)
14292{
14293 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
14294 union iwreq_data wrqu;
14295
Dustin Brown491d54b2018-03-14 12:39:11 -070014296 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014297
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014298 if (NULL == adapter) {
14299 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014300 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014301 }
14302
14303 /* create the event */
14304 memset(&wrqu, 0, sizeof(wrqu));
14305 memset(metrics_notification, 0, sizeof(metrics_notification));
14306
14307 scnprintf(metrics_notification, sizeof(metrics_notification),
14308 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
Jeff Johnsonfd060852017-10-04 10:50:51 -070014309 MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014310
14311 if (1 == preauth_status)
14312 strlcat(metrics_notification, " true",
14313 sizeof(metrics_notification));
14314 else
14315 strlcat(metrics_notification, " false",
14316 sizeof(metrics_notification));
14317
14318 wrqu.data.pointer = metrics_notification;
14319 wrqu.data.length = strlen(metrics_notification);
14320
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014321 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014322 metrics_notification);
14323
Dustin Browne74003f2018-03-14 12:51:58 -070014324 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014325
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014326 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014327}
14328
14329/**
14330 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014331 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070014332 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014333 *
14334 * 802.11r/LFR metrics reporting function to report handover initiation
14335 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053014336 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014337 */
Jeff Johnson172237b2017-11-07 15:32:59 -080014338QDF_STATUS
14339wlan_hdd_cfg80211_roam_metrics_handover(struct hdd_adapter *adapter,
14340 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014341{
14342 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
14343 union iwreq_data wrqu;
14344
Dustin Brown491d54b2018-03-14 12:39:11 -070014345 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014346
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014347 if (NULL == adapter) {
14348 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014349 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014350 }
14351
14352 /* create the event */
14353 memset(&wrqu, 0, sizeof(wrqu));
14354 memset(metrics_notification, 0, sizeof(metrics_notification));
14355
14356 wrqu.data.pointer = metrics_notification;
14357 wrqu.data.length = scnprintf(metrics_notification,
14358 sizeof(metrics_notification),
14359 "QCOM: LFR_PREAUTH_HANDOVER "
14360 MAC_ADDRESS_STR,
Jeff Johnsonfd060852017-10-04 10:50:51 -070014361 MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014362
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014363 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014364 metrics_notification);
14365
Dustin Browne74003f2018-03-14 12:51:58 -070014366 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014367
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014368 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014369}
14370#endif
14371
Nirav Shah73713f72018-05-17 14:50:41 +053014372#ifdef FEATURE_MONITOR_MODE_SUPPORT
14373static
14374void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
14375 uint8_t operationChannel,
14376 struct ch_params *ch_params)
14377{
14378 struct hdd_station_ctx *station_ctx =
14379 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14380 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
14381 enum hdd_dot11_mode hdd_dot11_mode;
14382 uint8_t ini_dot11_mode =
14383 (WLAN_HDD_GET_CTX(adapter))->config->dot11Mode;
14384
14385 hdd_debug("Dot11Mode is %u", ini_dot11_mode);
14386 switch (ini_dot11_mode) {
14387 case eHDD_DOT11_MODE_AUTO:
14388 case eHDD_DOT11_MODE_11ax:
14389 case eHDD_DOT11_MODE_11ax_ONLY:
14390 if (sme_is_feature_supported_by_fw(DOT11AX))
14391 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
14392 else if (sme_is_feature_supported_by_fw(DOT11AC))
14393 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
14394 else
14395 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
14396 break;
14397 case eHDD_DOT11_MODE_11ac:
14398 case eHDD_DOT11_MODE_11ac_ONLY:
14399 if (sme_is_feature_supported_by_fw(DOT11AC))
14400 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
14401 else
14402 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
14403 break;
14404 case eHDD_DOT11_MODE_11n:
14405 case eHDD_DOT11_MODE_11n_ONLY:
14406 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
14407 break;
14408 default:
14409 hdd_dot11_mode = ini_dot11_mode;
14410 break;
14411 }
14412 ch_info->channel_width = ch_params->ch_width;
14413 ch_info->phy_mode =
14414 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
14415 ch_info->channel = operationChannel;
14416 ch_info->cb_mode = ch_params->ch_width;
14417 hdd_debug("ch_info width %d, phymode %d channel %d",
14418 ch_info->channel_width, ch_info->phy_mode,
14419 ch_info->channel);
14420}
14421#else
14422static
14423void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
14424 uint8_t operationChannel,
14425 struct ch_params *ch_params)
14426{
14427}
14428#endif
14429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014430/**
14431 * hdd_select_cbmode() - select channel bonding mode
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014432 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014433 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014434 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014435 *
14436 * Return: none
14437 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014438void hdd_select_cbmode(struct hdd_adapter *adapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080014439 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014440{
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014441 uint8_t sec_ch = 0;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014442 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Chaoli Zhou75b062f2018-06-11 12:36:54 +080014443 struct hdd_station_ctx *station_ctx =
14444 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14445 eConnectionState connstate;
14446 bool cbmode_select = false;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014447
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014448 /*
14449 * CDS api expects secondary channel for calculating
14450 * the channel params
14451 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014452 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070014453 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014454 if (operationChannel >= 1 && operationChannel <= 5)
14455 sec_ch = operationChannel + 4;
14456 else if (operationChannel >= 6 && operationChannel <= 13)
14457 sec_ch = operationChannel - 4;
14458 }
14459
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014460 /* This call decides required channel bonding mode */
Dustin Brown07901ec2018-09-07 11:02:41 -070014461 wlan_reg_set_channel_params(hdd_ctx->pdev, operationChannel,
14462 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014463
Chaoli Zhou75b062f2018-06-11 12:36:54 +080014464 if (adapter->device_mode == QDF_STA_MODE &&
14465 hdd_ctx->config->enable_change_channel_bandwidth) {
14466 connstate = station_ctx->conn_info.connState;
14467 if (!(eConnectionState_Associated == connstate ||
14468 eConnectionState_Connecting == connstate)) {
14469 cbmode_select = true;
14470 }
14471 }
14472
14473 if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE || cbmode_select)
Nirav Shah73713f72018-05-17 14:50:41 +053014474 hdd_mon_select_cbmode(adapter, operationChannel, ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014475}
14476
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070014477/**
14478 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
14479 * @adapter: STA adapter
14480 * @roam_profile: STA roam profile
14481 *
14482 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
14483 *
14484 * Return: false if sta-sap conc is not allowed, else return true
14485 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070014486static
14487bool wlan_hdd_handle_sap_sta_dfs_conc(struct hdd_adapter *adapter,
14488 struct csr_roam_profile *roam_profile)
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070014489{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070014490 struct hdd_context *hdd_ctx;
Jeff Johnsone5006672017-08-29 14:39:02 -070014491 struct hdd_adapter *ap_adapter;
Jeff Johnson87251032017-08-29 13:31:11 -070014492 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070014493 struct hdd_hostapd_state *hostapd_state;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070014494 uint8_t channel = 0;
14495 QDF_STATUS status;
14496
14497 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
14498 if (!hdd_ctx) {
14499 hdd_err("HDD context is NULL");
14500 return true;
14501 }
14502
14503 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
14504 /* probably no sap running, no handling required */
14505 if (ap_adapter == NULL)
14506 return true;
14507
14508 /*
14509 * sap is not in started state, so it is fine to go ahead with sta.
14510 * if sap is currently doing CAC then don't allow sta to go further.
14511 */
14512 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
14513 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
14514 return true;
14515
14516 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
14517 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
14518 return false;
14519 }
14520
14521 /*
14522 * log and return error, if we allow STA to go through, we don't
14523 * know what is going to happen better stop sta connection
14524 */
14525 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
14526 if (NULL == hdd_ap_ctx) {
14527 hdd_err("AP context not found");
14528 return false;
14529 }
14530
14531 /* sap is on non-dfs channel, nothing to handle */
Dustin Brown07901ec2018-09-07 11:02:41 -070014532 if (!wlan_reg_is_dfs_ch(hdd_ctx->pdev,
Jeff Johnson01206862017-10-27 20:55:59 -070014533 hdd_ap_ctx->operating_channel)) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070014534 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070014535 return true;
14536 }
14537 /*
14538 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053014539 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070014540 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014541 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070014542 roam_profile, &channel);
14543
Nitesh Shah59774522016-09-16 15:14:21 +053014544 /*
14545 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
14546 * channels for roaming case.
14547 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070014548 if (WLAN_REG_IS_24GHZ_CH(channel)) {
14549 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053014550 return true;
14551 }
14552
14553 /*
Jeff Johnsondcf84ce2017-10-05 09:26:24 -070014554 * If channel is 0 or DFS or LTE unsafe then better to call pcl and
Tushnim Bhattacharyya9a929992017-06-18 00:59:09 -070014555 * find out the best channel. If channel is non-dfs 5 GHz then
14556 * better move SAP to STA's channel to make scc, so we have room
14557 * for 3port MCC scenario.
Nitesh Shah59774522016-09-16 15:14:21 +053014558 */
Dustin Brown07901ec2018-09-07 11:02:41 -070014559 if (!channel || wlan_reg_is_dfs_ch(hdd_ctx->pdev, channel) ||
14560 !policy_mgr_is_safe_channel(hdd_ctx->hdd_psoc, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014561 channel = policy_mgr_get_nondfs_preferred_channel(
14562 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070014563
14564 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
14565 qdf_event_reset(&hostapd_state->qdf_event);
14566 status = wlansap_set_channel_change_with_csa(
14567 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
Jeff Johnson91df29d2017-10-27 19:29:50 -070014568 hdd_ap_ctx->sap_config.ch_width_orig, false);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070014569
14570 if (QDF_STATUS_SUCCESS != status) {
14571 hdd_err("Set channel with CSA IE failed, can't allow STA");
14572 return false;
14573 }
14574
14575 /*
14576 * wait here for SAP to finish the channel switch. When channel
14577 * switch happens, SAP sends few beacons with CSA_IE. After
14578 * successfully Transmission of those beacons, it will move its
14579 * state from started to disconnected and move to new channel.
14580 * once it moves to new channel, sap again moves its state
14581 * machine from disconnected to started and set this event.
14582 * wait for 10 secs to finish this.
14583 */
Nachiket Kukade0396b732017-11-14 16:35:16 +053014584 status = qdf_wait_for_event_completion(&hostapd_state->qdf_event, 10000);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070014585 if (!QDF_IS_STATUS_SUCCESS(status)) {
14586 hdd_err("wait for qdf_event failed, STA not allowed!!");
14587 return false;
14588 }
14589
14590 return true;
14591}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014592
Abhishek Singhcfb44482017-03-10 12:42:37 +053014593#ifdef WLAN_FEATURE_11W
14594/**
14595 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
14596 * @roam_profile: pointer to roam profile
14597 *
14598 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
14599 * or pmf=2 is an explicit configuration in the supplicant
14600 * configuration, drop the connection request.
14601 *
14602 * Return: 0 if check result is valid, otherwise return error code
14603 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070014604static
14605int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053014606{
14607 if (roam_profile->MFPEnabled &&
Jeff Johnson20227a92018-03-13 09:41:05 -070014608 !(roam_profile->MFPRequired || roam_profile->MFPCapable)) {
Abhishek Singhcfb44482017-03-10 12:42:37 +053014609 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
14610 roam_profile->MFPEnabled,
14611 roam_profile->MFPRequired,
14612 roam_profile->MFPCapable);
14613 return -EINVAL;
14614 }
14615 return 0;
14616}
14617#else
14618static inline
Jeff Johnson61b5e982018-03-15 11:33:31 -070014619int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053014620{
14621 return 0;
14622}
14623#endif
14624
Krunal Soni31949422016-07-29 17:17:53 -070014625/**
14626 * wlan_hdd_cfg80211_connect_start() - to start the association process
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014627 * @adapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070014628 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014629 * @ssid_len: Length of ssid
14630 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070014631 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014632 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014633 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014634 *
14635 * This function is used to start the association process
14636 *
14637 * Return: 0 for success, non-zero for failure
14638 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014639static int wlan_hdd_cfg80211_connect_start(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014640 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070014641 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014642 u8 operatingChannel,
14643 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014644{
14645 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080014646 QDF_STATUS qdf_status;
Jeff Johnsonb8944722017-09-03 09:03:19 -070014647 struct hdd_context *hdd_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070014648 struct hdd_station_ctx *hdd_sta_ctx;
Krunal Sonibfd05492017-10-03 15:48:37 -070014649 uint32_t roamId = INVALID_ROAM_ID;
Jeff Johnson61b5e982018-03-15 11:33:31 -070014650 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014651 eCsrAuthType RSNAuthType;
14652 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053014653 uint8_t channel = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014654 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014655
Dustin Brown491d54b2018-03-14 12:39:11 -070014656 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014657
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014658 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14659 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014660
Jeff Johnsonb8944722017-09-03 09:03:19 -070014661 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014662 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014663 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014664
14665 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014666 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014667 status = -EINVAL;
14668 goto ret_status;
14669 }
14670
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014671 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014672 hdd_err("Connection refused: conn in progress");
14673 status = -EINVAL;
14674 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014675 }
14676
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053014677 /* Disable roaming on all other adapters before connect start */
14678 wlan_hdd_disable_roaming(adapter);
14679
Dustin Brown89fa06e2018-09-07 10:47:27 -070014680 hdd_notify_teardown_tdls_links(adapter->vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053014681
Anurag Chouhand939d3d2016-07-20 17:45:48 +053014682 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
14683 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014684
Jeff Johnson20227a92018-03-13 09:41:05 -070014685 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014686 if (roam_profile) {
Jeff Johnsond377dce2017-10-04 10:32:42 -070014687 struct hdd_station_ctx *sta_ctx;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070014688
Jeff Johnsond377dce2017-10-04 10:32:42 -070014689 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014690
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014691 /* Restart the opportunistic timer
14692 *
14693 * If hw_mode_change_in_progress is true, then wait
14694 * till firmware sends the callback for hw_mode change.
14695 *
14696 * Else set connect_in_progress as true and proceed.
14697 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014698 policy_mgr_restart_opportunistic_timer(
Jeff Johnsonb8944722017-09-03 09:03:19 -070014699 hdd_ctx->hdd_psoc, false);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014700 if (policy_mgr_is_hw_mode_change_in_progress(
Jeff Johnsonb8944722017-09-03 09:03:19 -070014701 hdd_ctx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053014702 qdf_status = policy_mgr_wait_for_connection_update(
Jeff Johnsonb8944722017-09-03 09:03:19 -070014703 hdd_ctx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053014704 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014705 hdd_err("qdf wait for event failed!!");
14706 status = -EINVAL;
14707 goto ret_status;
14708 }
14709 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014710 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014711
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014712 if (HDD_WMM_USER_MODE_NO_QOS ==
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014713 (WLAN_HDD_GET_CTX(adapter))->config->WmmMode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014714 /*QoS not enabled in cfg file */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014715 roam_profile->uapsd_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014716 } else {
14717 /*QoS enabled, update uapsd mask from cfg file */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014718 roam_profile->uapsd_mask =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014719 (WLAN_HDD_GET_CTX(adapter))->config->UapsdMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014720 }
14721
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014722 roam_profile->SSIDs.numOfSSIDs = 1;
14723 roam_profile->SSIDs.SSIDList->SSID.length = ssid_len;
14724 qdf_mem_zero(roam_profile->SSIDs.SSIDList->SSID.ssId,
14725 sizeof(roam_profile->SSIDs.SSIDList->SSID.ssId));
14726 qdf_mem_copy((void *)(roam_profile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014727 ssid, ssid_len);
14728
Abhishek Singh1f217ec2017-12-22 11:48:27 +053014729 roam_profile->supplicant_disabled_roaming = false;
Varun Reddy Yeturue5a35d12017-10-20 11:26:57 -070014730
Abhishek Singh3c9910e2017-01-06 17:56:47 +053014731 /* cleanup bssid hint */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014732 qdf_mem_zero(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053014733 QDF_MAC_ADDR_SIZE);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014734 qdf_mem_zero((void *)(roam_profile->BSSIDs.bssid),
Abhishek Singh3c9910e2017-01-06 17:56:47 +053014735 QDF_MAC_ADDR_SIZE);
14736
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014737 if (bssid) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014738 roam_profile->BSSIDs.numOfBSSIDs = 1;
Varun Reddy Yeturue5a35d12017-10-20 11:26:57 -070014739 roam_profile->supplicant_disabled_roaming = true;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014740 qdf_mem_copy((void *)(roam_profile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053014741 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070014742 /*
Jeff Johnsonfa7d9602018-05-06 11:25:31 -070014743 * Save BSSID in separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014744 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070014745 * association process. In case of join failure
14746 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014747 */
Jeff Johnson731bc322017-10-14 19:53:44 -070014748 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
14749 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014750 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014751 } else if (bssid_hint) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014752 qdf_mem_copy(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053014753 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070014754 /*
14755 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014756 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070014757 * association process. In case of join failure
14758 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014759 */
Jeff Johnson731bc322017-10-14 19:53:44 -070014760 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053014761 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014762 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070014763 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014764 }
14765
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014766 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014767 roam_profile->SSIDs.SSIDList->SSID.length,
14768 roam_profile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014769 operatingChannel);
14770
Jeff Johnsonce4a8342017-10-14 13:12:22 -070014771 if (hdd_sta_ctx->wpa_versions) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014772 hdd_set_genie_to_csr(adapter, &RSNAuthType);
14773 hdd_set_csr_auth_type(adapter, RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014774 }
14775#ifdef FEATURE_WLAN_WAPI
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070014776 if (adapter->wapi_info.wapi_mode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014777 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070014778 switch (adapter->wapi_info.wapi_auth_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014779 case WAPI_AUTH_MODE_PSK:
14780 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014781 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070014782 adapter->wapi_info.wapi_auth_mode);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014783 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014784 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
14785 break;
14786 }
14787 case WAPI_AUTH_MODE_CERT:
14788 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014789 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070014790 adapter->wapi_info.wapi_auth_mode);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014791 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014792 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
14793 break;
14794 }
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070014795 default:
14796 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014797 } /* End of switch */
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070014798 if (adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014799 WAPI_AUTH_MODE_PSK
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070014800 || adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014801 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014802 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014803 roam_profile->AuthType.numEntries = 1;
14804 roam_profile->EncryptionType.numEntries = 1;
14805 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014806 eCSR_ENCRYPT_TYPE_WPI;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014807 roam_profile->mcEncryptionType.numEntries = 1;
14808 roam_profile->mcEncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014809 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
14810 }
14811 }
Krunal Soni31949422016-07-29 17:17:53 -070014812#endif
Dustin Brown89fa06e2018-09-07 10:47:27 -070014813 pmo_ucfg_flush_gtk_offload_req(adapter->vdev);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014814 roam_profile->csrPersona = adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014815
14816 if (operatingChannel) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014817 roam_profile->ChannelInfo.ChannelList =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014818 &operatingChannel;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014819 roam_profile->ChannelInfo.numOfChannels = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014820 } else {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014821 roam_profile->ChannelInfo.ChannelList = NULL;
14822 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014823 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014824 if ((QDF_IBSS_MODE == adapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014825 && operatingChannel) {
14826 /*
14827 * Need to post the IBSS power save parameters
14828 * to WMA. WMA will configure this parameters
14829 * to firmware if power save is enabled by the
14830 * firmware.
14831 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014832 qdf_status = hdd_set_ibss_power_save_params(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014833
Abhishek Singh471652b2017-04-14 12:28:32 +053014834 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014835 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014836 status = -EINVAL;
14837 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014838 }
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014839 roam_profile->ch_params.ch_width =
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014840 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053014841 /*
14842 * In IBSS mode while operating in 2.4 GHz,
14843 * the device supports only 20 MHz.
14844 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070014845 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014846 roam_profile->ch_params.ch_width =
Nitesh Shah87335a52016-09-05 15:47:32 +053014847 CH_WIDTH_20MHZ;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014848 hdd_select_cbmode(adapter, operatingChannel,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014849 &roam_profile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014850 }
14851
Jeff Johnson20227a92018-03-13 09:41:05 -070014852 if (wlan_hdd_cfg80211_check_pmf_valid(roam_profile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014853 status = -EINVAL;
14854 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014855 }
14856
Krunal Soni31949422016-07-29 17:17:53 -070014857 /*
14858 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014859 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070014860 * enhancements, the supplicant is not issuing the scan command
14861 * now. So the unicast frames which are sent from the host are
14862 * not having the additional IEs. If it is P2P CLIENT and there
14863 * is no additional IE present in roamProfile, then use the
14864 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014865 */
14866
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014867 if ((adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014868 (!roam_profile->pAddIEScan)) {
14869 roam_profile->pAddIEScan =
Jeff Johnson37fa0402017-10-28 12:42:29 -070014870 &adapter->scan_info.scan_add_ie.addIEdata[0];
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014871 roam_profile->nAddIEScanLength =
Jeff Johnson37fa0402017-10-28 12:42:29 -070014872 adapter->scan_info.scan_add_ie.length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014873 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014874
Jeff Johnsonb8944722017-09-03 09:03:19 -070014875 if ((policy_mgr_is_hw_dbs_capable(hdd_ctx->hdd_psoc) == true)
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014876 && (false == wlan_hdd_handle_sap_sta_dfs_conc(adapter,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014877 roam_profile))) {
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070014878 hdd_err("sap-sta conc will fail, can't allow sta");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014879 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070014880 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014881 status = -ENOMEM;
14882 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070014883 }
14884
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014885 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014886 if (!sme_config) {
14887 hdd_err("unable to allocate sme_config");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014888 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070014889 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014890 status = -ENOMEM;
14891 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014892 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014893
14894 mac_handle = hdd_ctx->mac_handle;
14895 sme_get_config_param(mac_handle, sme_config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014896 /* These values are not sessionized. So, any change in these SME
14897 * configs on an older or parallel interface will affect the
14898 * cb mode. So, restoring the default INI params before starting
14899 * interfaces such as sta, cli etc.,
14900 */
14901 sme_config->csrConfig.channelBondingMode5GHz =
Jeff Johnsonb8944722017-09-03 09:03:19 -070014902 hdd_ctx->config->nChannelBondingMode5GHz;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014903 sme_config->csrConfig.channelBondingMode24GHz =
Jeff Johnsonb8944722017-09-03 09:03:19 -070014904 hdd_ctx->config->nChannelBondingMode24GHz;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014905 sme_update_config(mac_handle, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014906 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053014907 /*
14908 * Change conn_state to connecting before sme_roam_connect(),
14909 * because sme_roam_connect() has a direct path to call
14910 * hdd_sme_roam_callback(), which will change the conn_state
14911 * If direct path, conn_state will be accordingly changed to
14912 * NotConnected or Associated by either
14913 * hdd_association_completion_handler() or
14914 * hdd_dis_connect_handler() in sme_RoamCallback()if
14915 * sme_RomConnect is to be queued,
14916 * Connecting state will remain until it is completed.
14917 *
14918 * If connection state is not changed, connection state will
14919 * remain in eConnectionState_NotConnected state.
14920 * In hdd_association_completion_handler, "hddDisconInProgress"
14921 * is set to true if conn state is
14922 * eConnectionState_NotConnected.
14923 * If "hddDisconInProgress" is set to true then cfg80211 layer
14924 * is not informed of connect result indication which
14925 * is an issue.
14926 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014927 if (QDF_STA_MODE == adapter->device_mode ||
14928 QDF_P2P_CLIENT_MODE == adapter->device_mode)
14929 hdd_conn_set_connection_state(adapter,
Agrawal Ashish6b015762016-05-05 11:22:18 +053014930 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014931
Alok Kumarb64650c2018-03-23 17:05:11 +053014932 hdd_set_disconnect_status(adapter, false);
14933
Jingxiang Geb49aa302018-01-17 20:54:15 +080014934 qdf_runtime_pm_prevent_suspend(
14935 &hdd_ctx->runtime_context.connect);
Padma, Santhosh Kumarc88de482018-04-09 16:17:04 +053014936 hdd_prevent_suspend_timeout(HDD_WAKELOCK_CONNECT_COMPLETE,
Dustin Brownceed67e2017-05-26 11:57:31 -070014937 WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070014938 qdf_status = sme_roam_connect(mac_handle,
14939 adapter->session_id, roam_profile,
14940 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053014941 if (QDF_IS_STATUS_ERROR(qdf_status))
14942 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014943
Rajeev Kumard31e1542017-01-13 14:37:42 -080014944 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014945 (QDF_STA_MODE == adapter->device_mode ||
14946 QDF_P2P_CLIENT_MODE == adapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014947 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080014948 "qdf_status %d. -> NotConnected",
Jeff Johnson1b780e42017-10-31 14:11:45 -070014949 adapter->session_id, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014950 /* change back to NotAssociated */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014951 hdd_conn_set_connection_state(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014952 eConnectionState_NotConnected);
Jingxiang Geb49aa302018-01-17 20:54:15 +080014953 qdf_runtime_pm_allow_suspend(
14954 &hdd_ctx->runtime_context.connect);
Dustin Brownceed67e2017-05-26 11:57:31 -070014955 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014956 }
14957
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014958 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014959 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014960
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014961 roam_profile->ChannelInfo.ChannelList = NULL;
14962 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014963
Jeff Johnsonce2ba702017-10-02 13:30:24 -070014964 if ((QDF_STA_MODE == adapter->device_mode)
Jeff Johnsonb8944722017-09-03 09:03:19 -070014965 && policy_mgr_is_current_hwmode_dbs(hdd_ctx->hdd_psoc)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014966 && !policy_mgr_is_hw_dbs_2x2_capable(
Jeff Johnsonb8944722017-09-03 09:03:19 -070014967 hdd_ctx->hdd_psoc)) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014968 policy_mgr_get_channel_from_scan_result(
Jeff Johnsonb8944722017-09-03 09:03:19 -070014969 hdd_ctx->hdd_psoc,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070014970 roam_profile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080014971 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053014972 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014973 policy_mgr_checkn_update_hw_mode_single_mac_mode(
Jeff Johnsonb8944722017-09-03 09:03:19 -070014974 hdd_ctx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053014975 }
14976
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014977 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014978 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014979 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014980 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014981 goto ret_status;
14982
14983conn_failure:
14984 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014985 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053014986
14987ret_status:
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053014988 /*
14989 * Enable roaming on other STA adapter for failure case.
14990 * For success case, it is enabled in assoc completion handler
14991 */
14992 if (status)
14993 wlan_hdd_enable_roaming(adapter);
14994
Dustin Browne74003f2018-03-14 12:51:58 -070014995 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014996 return status;
14997}
14998
14999/**
15000 * wlan_hdd_cfg80211_set_auth_type() - set auth type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015001 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015002 * @auth_type: Auth type
15003 *
15004 * This function is used to set the authentication type (OPEN/SHARED).
15005 *
15006 * Return: 0 for success, non-zero for failure
15007 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015008static int wlan_hdd_cfg80211_set_auth_type(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015009 enum nl80211_auth_type auth_type)
15010{
Jeff Johnsond377dce2017-10-04 10:32:42 -070015011 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015012 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070015013 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015014
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015015 /*set authentication type */
15016 switch (auth_type) {
15017 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015018 hdd_debug("set authentication type to AUTOSWITCH");
Jeff Johnsond377dce2017-10-04 10:32:42 -070015019 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015020 break;
15021
15022 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015023 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015024 hdd_debug("set authentication type to OPEN");
Jeff Johnsond377dce2017-10-04 10:32:42 -070015025 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015026 break;
15027
15028 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015029 hdd_debug("set authentication type to SHARED");
Jeff Johnsond377dce2017-10-04 10:32:42 -070015030 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015031 break;
15032#ifdef FEATURE_WLAN_ESE
15033 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015034 hdd_debug("set authentication type to CCKM WPA");
Jeff Johnsond377dce2017-10-04 10:32:42 -070015035 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015036 break;
15037#endif
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053015038#if defined(WLAN_FEATURE_FILS_SK) && \
15039 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
15040 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015041 case NL80211_AUTHTYPE_FILS_SK:
Dustin Brown5e89ef82018-03-14 11:50:23 -070015042 hdd_debug("set authentication type to FILS SHARED");
Jeff Johnsond377dce2017-10-04 10:32:42 -070015043 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015044 break;
15045#endif
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053015046 case NL80211_AUTHTYPE_SAE:
15047 hdd_debug("set authentication type to SAE");
15048 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_SAE;
15049 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015050 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015051 hdd_err("Unsupported authentication type: %d", auth_type);
Jeff Johnsond377dce2017-10-04 10:32:42 -070015052 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015053 return -EINVAL;
15054 }
15055
Jeff Johnson20227a92018-03-13 09:41:05 -070015056 roam_profile = hdd_roam_profile(adapter);
15057 roam_profile->AuthType.authType[0] = sta_ctx->conn_info.authType;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015058 return 0;
15059}
15060
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053015061#if defined(WLAN_FEATURE_FILS_SK) && \
15062 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
15063 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Jeff Johnson20227a92018-03-13 09:41:05 -070015064static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015065{
15066 struct cds_fils_connection_info *fils_con_info;
15067
Jeff Johnson20227a92018-03-13 09:41:05 -070015068 fils_con_info = roam_profile->fils_con_info;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015069 if (!fils_con_info) {
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070015070 hdd_err("No valid Roam profile");
15071 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015072 }
15073
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070015074 return true;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015075}
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070015076
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070015077static enum eAniAuthType wlan_hdd_get_fils_auth_type(
15078 enum nl80211_auth_type auth)
15079{
15080 switch (auth) {
15081 case NL80211_AUTHTYPE_FILS_SK:
15082 return SIR_FILS_SK_WITHOUT_PFS;
15083 case NL80211_AUTHTYPE_FILS_SK_PFS:
15084 return SIR_FILS_SK_WITH_PFS;
15085 case NL80211_AUTHTYPE_FILS_PK:
15086 return SIR_FILS_PK_AUTH;
15087 default:
15088 return eSIR_DONOT_USE_AUTH_TYPE;
15089 }
15090}
15091
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080015092static bool wlan_hdd_fils_data_in_limits(struct cfg80211_connect_params *req)
15093{
15094 hdd_debug("seq=%d auth=%d lengths: user=%zu rrk=%zu realm=%zu",
15095 req->fils_erp_next_seq_num, req->auth_type,
15096 req->fils_erp_username_len, req->fils_erp_rrk_len,
15097 req->fils_erp_realm_len);
15098 if (!req->fils_erp_rrk_len || !req->fils_erp_realm_len ||
15099 !req->fils_erp_username_len ||
15100 req->fils_erp_rrk_len > FILS_MAX_RRK_LENGTH ||
15101 req->fils_erp_realm_len > FILS_MAX_REALM_LEN ||
15102 req->fils_erp_username_len > FILS_MAX_KEYNAME_NAI_LENGTH) {
15103 hdd_err("length incorrect, user=%zu rrk=%zu realm=%zu",
15104 req->fils_erp_username_len, req->fils_erp_rrk_len,
15105 req->fils_erp_realm_len);
15106 return false;
15107 }
15108
bings77a35ac2018-06-01 15:10:44 +080015109 if (!req->fils_erp_rrk || !req->fils_erp_realm ||
15110 !req->fils_erp_username) {
15111 hdd_err("buffer incorrect, user=%pK rrk=%pK realm=%pK",
15112 req->fils_erp_username, req->fils_erp_rrk,
15113 req->fils_erp_realm);
15114 return false;
15115 }
15116
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080015117 return true;
15118}
15119
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070015120/**
15121 * wlan_hdd_cfg80211_set_fils_config() - set fils config params during connect
15122 * @adapter: Pointer to adapter
15123 * @req: Pointer to fils parameters
15124 *
15125 * Return: 0 for success, non-zero for failure
15126 */
15127static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
15128 struct cfg80211_connect_params *req)
15129{
Jeff Johnson61b5e982018-03-15 11:33:31 -070015130 struct csr_roam_profile *roam_profile;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070015131 enum eAniAuthType auth_type;
15132 uint8_t *buf;
15133 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
15134
Jeff Johnson20227a92018-03-13 09:41:05 -070015135 roam_profile = hdd_roam_profile(adapter);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070015136
15137 if (!hdd_ctx->config->is_fils_enabled) {
15138 hdd_err("FILS disabled");
15139 return -EINVAL;
15140 }
15141 hdd_clear_fils_connection_info(adapter);
15142 roam_profile->fils_con_info =
15143 qdf_mem_malloc(sizeof(*roam_profile->fils_con_info));
15144
15145 if (!roam_profile->fils_con_info) {
15146 hdd_err("failed to allocate memory");
15147 return -EINVAL;
15148 }
15149 /*
15150 * The initial connection for FILS may happen with an OPEN
15151 * auth type. Hence we need to allow the connection to go
15152 * through in that case as well. Below is_fils_connection
15153 * flag is propagated down to CSR and PE sessions through
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080015154 * the JOIN request. As the flag is used, do not free the
15155 * memory allocated to fils_con_info and return success.
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070015156 */
15157 if (req->auth_type != NL80211_AUTHTYPE_FILS_SK) {
15158 roam_profile->fils_con_info->is_fils_connection = false;
15159 return 0;
15160 }
15161
15162 /*
15163 * Once above check is done, then we can check for valid FILS
15164 * auth types. Currently only NL80211_AUTHTYPE_FILS_SK is
15165 * supported. Once all auth types are supported, then we can
15166 * merge these 2 conditions into one.
15167 */
15168 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
15169 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
15170 hdd_err("invalid auth type for fils %d", req->auth_type);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070015171 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070015172 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080015173 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080015174 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070015175
15176 roam_profile->fils_con_info->is_fils_connection = true;
15177 roam_profile->fils_con_info->sequence_number =
15178 req->fils_erp_next_seq_num;
15179 roam_profile->fils_con_info->auth_type = auth_type;
15180
15181 roam_profile->fils_con_info->r_rk_length =
15182 req->fils_erp_rrk_len;
15183 if (req->fils_erp_rrk_len)
15184 qdf_mem_copy(roam_profile->fils_con_info->r_rk,
15185 req->fils_erp_rrk,
15186 roam_profile->fils_con_info->r_rk_length);
15187
15188 roam_profile->fils_con_info->realm_len = req->fils_erp_realm_len;
15189 if (req->fils_erp_realm_len)
15190 qdf_mem_copy(roam_profile->fils_con_info->realm,
15191 req->fils_erp_realm,
15192 roam_profile->fils_con_info->realm_len);
15193
15194 roam_profile->fils_con_info->key_nai_length =
15195 req->fils_erp_username_len + sizeof(char) +
15196 req->fils_erp_realm_len;
15197 hdd_debug("key_nai_length = %d",
15198 roam_profile->fils_con_info->key_nai_length);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070015199 if (roam_profile->fils_con_info->key_nai_length >
15200 FILS_MAX_KEYNAME_NAI_LENGTH) {
15201 hdd_err("Do not allow FILS conn due to excess NAI Length %d",
15202 roam_profile->fils_con_info->key_nai_length);
15203 goto fils_conn_fail;
15204 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080015205 buf = roam_profile->fils_con_info->keyname_nai;
15206 qdf_mem_copy(buf, req->fils_erp_username, req->fils_erp_username_len);
15207 buf += req->fils_erp_username_len;
15208 *buf++ = '@';
15209 qdf_mem_copy(buf, req->fils_erp_realm, req->fils_erp_realm_len);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070015210
15211 return 0;
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070015212
15213fils_conn_fail:
15214 if (roam_profile->fils_con_info) {
15215 qdf_mem_free(roam_profile->fils_con_info);
15216 roam_profile->fils_con_info = NULL;
15217 }
15218 return -EINVAL;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070015219}
15220
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070015221static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
15222{
15223 switch (key_mgmt) {
15224 case WLAN_AKM_SUITE_FILS_SHA256:
15225 case WLAN_AKM_SUITE_FILS_SHA384:
15226 case WLAN_AKM_SUITE_FT_FILS_SHA256:
15227 case WLAN_AKM_SUITE_FT_FILS_SHA384:
15228 return true;
15229 default:
15230 return false;
15231 }
15232}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070015233
15234static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
15235{
15236 enum nl80211_auth_type auth_type = req->auth_type;
15237 /*
15238 * Below n_akm_suites is defined as int in the kernel, even though it
15239 * is supposed to be unsigned.
15240 */
15241 int num_akm_suites = req->crypto.n_akm_suites;
15242 uint32_t key_mgmt = req->crypto.akm_suites[0];
15243 enum eAniAuthType fils_auth_type =
15244 wlan_hdd_get_fils_auth_type(req->auth_type);
15245
15246 hdd_debug("Num of AKM suites = %d", num_akm_suites);
15247 if (num_akm_suites <= 0)
15248 return false;
15249
15250 /*
15251 * Auth type will be either be OPEN or FILS type for a FILS connection
15252 */
15253 if ((auth_type != NL80211_AUTHTYPE_OPEN_SYSTEM) &&
15254 (fils_auth_type == eSIR_DONOT_USE_AUTH_TYPE)) {
15255 hdd_debug("Not a FILS auth type, auth = %d, fils auth = %d",
15256 auth_type, fils_auth_type);
15257 return false;
15258 }
15259
15260 if (!wlan_hdd_is_akm_suite_fils(key_mgmt)) {
15261 hdd_debug("Not a FILS AKM SUITE %d", key_mgmt);
15262 return false;
15263 }
15264
15265 return true;
15266}
15267
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070015268#else
Jeff Johnson20227a92018-03-13 09:41:05 -070015269static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070015270{
15271 return true;
15272}
15273
15274static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
15275 struct cfg80211_connect_params *req)
15276{
15277 return 0;
15278}
15279
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070015280static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
15281{
15282 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015283}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070015284
15285static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
15286{
15287 return false;
15288}
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015289#endif
15290
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015291/**
15292 * wlan_hdd_set_akm_suite() - set key management type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015293 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015294 * @key_mgmt: Key management type
15295 *
15296 * This function is used to set the key mgmt type(PSK/8021x).
15297 *
15298 * Return: 0 for success, non-zero for failure
15299 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015300static int wlan_hdd_set_akm_suite(struct hdd_adapter *adapter, u32 key_mgmt)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015301{
Jeff Johnson37ecea42018-03-18 17:54:40 -070015302 struct hdd_station_ctx *sta_ctx;
Jeff Johnson61b5e982018-03-15 11:33:31 -070015303 struct csr_roam_profile *roam_profile;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015304
Jeff Johnson20227a92018-03-13 09:41:05 -070015305 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015306
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070015307 if (wlan_hdd_is_akm_suite_fils(key_mgmt) &&
Jeff Johnson20227a92018-03-13 09:41:05 -070015308 !hdd_validate_fils_info_ptr(roam_profile))
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070015309 return -EINVAL;
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053015310#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015311#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053015312#endif
15313#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015314#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053015315#endif
Jeff Johnson37ecea42018-03-18 17:54:40 -070015316
15317 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15318
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015319 /*set key mgmt type */
15320 switch (key_mgmt) {
15321 case WLAN_AKM_SUITE_PSK:
15322 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015323 case WLAN_AKM_SUITE_FT_PSK:
Abhishek Singh02cb9e02017-08-30 17:39:50 +053015324 case WLAN_AKM_SUITE_DPP_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015325 hdd_debug("setting key mgmt type to PSK");
Jeff Johnson37ecea42018-03-18 17:54:40 -070015326 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_PSK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015327 break;
15328
15329 case WLAN_AKM_SUITE_8021X_SHA256:
15330 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015331 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015332 hdd_debug("setting key mgmt type to 8021x");
Jeff Johnson37ecea42018-03-18 17:54:40 -070015333 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015334 break;
15335#ifdef FEATURE_WLAN_ESE
15336#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015337 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015338 hdd_debug("setting key mgmt type to CCKM");
Jeff Johnson37ecea42018-03-18 17:54:40 -070015339 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_CCKM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015340 break;
15341#endif
15342#ifndef WLAN_AKM_SUITE_OSEN
15343#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
15344#endif
15345 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015346 hdd_debug("setting key mgmt type to OSEN");
Jeff Johnson37ecea42018-03-18 17:54:40 -070015347 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015348 break;
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053015349#if defined(WLAN_FEATURE_FILS_SK) && \
15350 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
15351 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053015352 case WLAN_AKM_SUITE_FILS_SHA256:
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015353 hdd_debug("setting key mgmt type to FILS SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070015354 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015355 roam_profile->fils_con_info->akm_type =
15356 eCSR_AUTH_TYPE_FILS_SHA256;
15357 break;
15358
15359 case WLAN_AKM_SUITE_FILS_SHA384:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070015360 hdd_debug("setting key mgmt type to FILS SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070015361 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015362 roam_profile->fils_con_info->akm_type =
15363 eCSR_AUTH_TYPE_FILS_SHA384;
15364 break;
15365
15366 case WLAN_AKM_SUITE_FT_FILS_SHA256:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070015367 hdd_debug("setting key mgmt type to FILS FT SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070015368 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015369 roam_profile->fils_con_info->akm_type =
15370 eCSR_AUTH_TYPE_FT_FILS_SHA256;
15371 break;
15372
15373 case WLAN_AKM_SUITE_FT_FILS_SHA384:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070015374 hdd_debug("setting key mgmt type to FILS FT SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070015375 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015376 roam_profile->fils_con_info->akm_type =
15377 eCSR_AUTH_TYPE_FT_FILS_SHA384;
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053015378 break;
15379#endif
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053015380
15381 case WLAN_AKM_SUITE_OWE:
15382 hdd_debug("setting key mgmt type to OWE");
Jeff Johnson37ecea42018-03-18 17:54:40 -070015383 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053015384 break;
15385
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053015386 case WLAN_AKM_SUITE_EAP_SHA256:
15387 hdd_debug("setting key mgmt type to EAP_SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070015388 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053015389 break;
15390 case WLAN_AKM_SUITE_EAP_SHA384:
15391 hdd_debug("setting key mgmt type to EAP_SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070015392 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053015393 break;
15394
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053015395 case WLAN_AKM_SUITE_SAE:
15396 hdd_debug("setting key mgmt type to SAE");
Jeff Johnson37ecea42018-03-18 17:54:40 -070015397 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053015398 break;
15399
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015400 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015401 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015402 return -EINVAL;
15403
15404 }
15405 return 0;
15406}
15407
15408/**
15409 * wlan_hdd_cfg80211_set_cipher() - set encryption type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015410 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015411 * @cipher: Cipher type
15412 * @ucast: Unicast flag
15413 *
15414 * This function is used to set the encryption type
15415 * (NONE/WEP40/WEP104/TKIP/CCMP).
15416 *
15417 * Return: 0 for success, non-zero for failure
15418 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015419static int wlan_hdd_cfg80211_set_cipher(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015420 u32 cipher, bool ucast)
15421{
15422 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Jeff Johnsond377dce2017-10-04 10:32:42 -070015423 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015424 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070015425 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015426
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015427 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015428 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015429 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
15430 } else {
15431
15432 /*set encryption method */
15433 switch (cipher) {
15434 case IW_AUTH_CIPHER_NONE:
15435 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
15436 break;
15437
15438 case WLAN_CIPHER_SUITE_WEP40:
15439 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
15440 break;
15441
15442 case WLAN_CIPHER_SUITE_WEP104:
15443 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
15444 break;
15445
15446 case WLAN_CIPHER_SUITE_TKIP:
15447 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
15448 break;
15449
15450 case WLAN_CIPHER_SUITE_CCMP:
15451 encryptionType = eCSR_ENCRYPT_TYPE_AES;
15452 break;
15453#ifdef FEATURE_WLAN_WAPI
15454 case WLAN_CIPHER_SUITE_SMS4:
15455 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
15456 break;
15457#endif
15458
15459#ifdef FEATURE_WLAN_ESE
15460 case WLAN_CIPHER_SUITE_KRK:
15461 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
15462 break;
15463#ifdef WLAN_FEATURE_ROAM_OFFLOAD
15464 case WLAN_CIPHER_SUITE_BTK:
15465 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
15466 break;
15467#endif
15468#endif
Mukul Sharma05504ac2017-06-08 12:35:53 +053015469 case WLAN_CIPHER_SUITE_GCMP:
15470 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP;
15471 break;
15472 case WLAN_CIPHER_SUITE_GCMP_256:
15473 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP_256;
15474 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015475 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015476 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015477 return -EOPNOTSUPP;
15478 }
15479 }
15480
Jeff Johnson20227a92018-03-13 09:41:05 -070015481 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015482 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015483 hdd_debug("setting unicast cipher type to %d", encryptionType);
Jeff Johnsond377dce2017-10-04 10:32:42 -070015484 sta_ctx->conn_info.ucEncryptionType = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070015485 roam_profile->EncryptionType.numEntries = 1;
15486 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015487 encryptionType;
15488 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015489 hdd_debug("setting mcast cipher type to %d", encryptionType);
Jeff Johnsond377dce2017-10-04 10:32:42 -070015490 sta_ctx->conn_info.mcEncryptionType = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070015491 roam_profile->mcEncryptionType.numEntries = 1;
15492 roam_profile->mcEncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015493 encryptionType;
15494 }
15495
15496 return 0;
15497}
15498
15499/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053015500 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
Jeff Johnson20227a92018-03-13 09:41:05 -070015501 * @adapter: Pointer to adapter
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053015502 * @gen_ie: Pointer to IE data
15503 * @len: length of IE data
15504 *
15505 * Return: 0 for success, non-zero for failure
15506 */
Jeff Johnson20227a92018-03-13 09:41:05 -070015507static int wlan_hdd_add_assoc_ie(struct hdd_adapter *adapter,
15508 const uint8_t *gen_ie, uint16_t len)
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053015509{
Jeff Johnson20227a92018-03-13 09:41:05 -070015510 struct csr_roam_profile *roam_profile;
15511 tSirAddie *assoc_add_ie;
15512 uint16_t cur_add_ie_len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053015513
Jeff Johnson20227a92018-03-13 09:41:05 -070015514 assoc_add_ie = hdd_assoc_additional_ie(adapter);
15515 cur_add_ie_len = assoc_add_ie->length;
15516 if (SIR_MAC_MAX_ADD_IE_LENGTH < (cur_add_ie_len + len)) {
15517 hdd_err("current len %u, new ie of len %u will overflow",
15518 cur_add_ie_len, len);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053015519 return -ENOMEM;
15520 }
Jeff Johnson20227a92018-03-13 09:41:05 -070015521 memcpy(assoc_add_ie->addIEdata + cur_add_ie_len, gen_ie, len);
15522 assoc_add_ie->length += len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053015523
Jeff Johnson20227a92018-03-13 09:41:05 -070015524 roam_profile = hdd_roam_profile(adapter);
15525 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
15526 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
15527
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053015528 return 0;
15529}
15530
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053015531#ifdef WLAN_FEATURE_FILS_SK
15532/**
15533 * wlan_hdd_save_hlp_ie - API to save HLP IE
15534 * @roam_profile: Pointer to roam profile
15535 * @gen_ie: IE buffer to store
15536 * @len: length of the IE buffer @gen_ie
15537 * @flush: Flush the older saved HLP if any
15538 *
15539 * Return: None
15540 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070015541static void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070015542 const uint8_t *gen_ie, uint16_t len,
15543 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053015544{
15545 uint8_t *hlp_ie = roam_profile->hlp_ie;
15546
15547 if (flush) {
15548 roam_profile->hlp_ie_len = 0;
15549 if (hlp_ie) {
15550 qdf_mem_free(hlp_ie);
15551 roam_profile->hlp_ie = NULL;
15552 }
15553 }
15554
15555 if ((roam_profile->hlp_ie_len +
15556 len) > FILS_MAX_HLP_DATA_LEN) {
15557 hdd_err("HLP len exceeds: hlp_ie_len %d len %d",
15558 roam_profile->hlp_ie_len, len);
15559 return;
15560 }
15561
15562 if (!roam_profile->hlp_ie) {
15563 roam_profile->hlp_ie =
15564 qdf_mem_malloc(FILS_MAX_HLP_DATA_LEN);
15565 hlp_ie = roam_profile->hlp_ie;
15566 if (!hlp_ie) {
15567 hdd_err("HLP IE mem alloc fails");
15568 return;
15569 }
15570 }
15571
15572 qdf_mem_copy(hlp_ie + roam_profile->hlp_ie_len, gen_ie, len);
15573 roam_profile->hlp_ie_len += len;
15574}
15575#else
Jeff Johnson61b5e982018-03-15 11:33:31 -070015576static inline void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070015577 const uint8_t *gen_ie, uint16_t len,
15578 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053015579{}
15580#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053015581/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015582 * wlan_hdd_cfg80211_set_ie() - set IEs
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015583 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015584 * @ie: Pointer ot ie
15585 * @ie: IE length
15586 *
15587 * Return: 0 for success, non-zero for failure
15588 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015589static int wlan_hdd_cfg80211_set_ie(struct hdd_adapter *adapter,
Jeff Johnson2a722002017-09-30 20:02:35 -070015590 const uint8_t *ie,
15591 size_t ie_len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015592{
Jeff Johnson20227a92018-03-13 09:41:05 -070015593 struct csr_roam_profile *roam_profile;
15594 tSirAddie *assoc_add_ie;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015595 const uint8_t *genie = ie;
15596 uint16_t remLen = ie_len;
15597#ifdef FEATURE_WLAN_WAPI
15598 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
tinlin8a44b642018-04-25 13:56:06 +080015599 uint8_t *tmp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015600 uint16_t akmsuiteCount;
tinlin8a44b642018-04-25 13:56:06 +080015601 uint32_t *akmlist;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015602#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053015603 int status;
Jeff Johnson20227a92018-03-13 09:41:05 -070015604 uint8_t *security_ie;
15605
15606 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015607
15608 /* clear previous assocAddIE */
Jeff Johnson20227a92018-03-13 09:41:05 -070015609 assoc_add_ie = hdd_assoc_additional_ie(adapter);
15610 assoc_add_ie->length = 0;
15611 roam_profile->bWPSAssociation = false;
15612 roam_profile->bOSENAssociation = false;
15613 security_ie = hdd_security_ie(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015614
15615 while (remLen >= 2) {
15616 uint16_t eLen = 0;
15617 uint8_t elementId;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015618
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015619 elementId = *genie++;
15620 eLen = *genie++;
15621 remLen -= 2;
15622
Nachiket Kukade4bea8b42017-06-13 11:53:19 +053015623 /* Sanity check on eLen */
15624 if (eLen > remLen) {
15625 hdd_err("%s: Invalid IE length[%d] for IE[0x%X]",
15626 __func__, eLen, elementId);
15627 QDF_ASSERT(0);
15628 return -EINVAL;
15629 }
15630
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015631 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015632
15633 switch (elementId) {
15634 case DOT11F_EID_WPA:
15635 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 -070015636 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015637 return -EINVAL;
15638 } else if (0 ==
15639 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
Jeff Johnson20227a92018-03-13 09:41:05 -070015640 uint16_t curAddIELen = assoc_add_ie->length;
15641
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015642 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015643
15644 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070015645 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070015646 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015647 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015648 return -ENOMEM;
15649 }
15650 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070015651 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015652 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070015653 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015654
Jeff Johnson20227a92018-03-13 09:41:05 -070015655 roam_profile->bWPSAssociation = true;
15656 roam_profile->pAddIEAssoc =
15657 assoc_add_ie->addIEdata;
15658 roam_profile->nAddIEAssocLength =
15659 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015660 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Nachiket Kukade2f6509f2017-06-13 17:45:46 +053015661 if (eLen > (MAX_WPA_RSN_IE_LEN - 2)) {
15662 hdd_err("%s: Invalid WPA IE length[%d]",
15663 __func__, eLen);
15664 QDF_ASSERT(0);
15665 return -EINVAL;
15666 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015667 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070015668 memset(security_ie, 0, MAX_WPA_RSN_IE_LEN);
15669 memcpy(security_ie, genie - 2, (eLen + 2));
15670 roam_profile->pWPAReqIE = security_ie;
15671 roam_profile->nWPAReqIELength = eLen + 2; /* ie_len; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015672 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
15673 P2P_OUI_TYPE_SIZE))) {
15674 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070015675 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015676 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015677
15678 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070015679 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070015680 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015681 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015682 return -ENOMEM;
15683 }
15684 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070015685 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015686 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070015687 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015688
Jeff Johnson20227a92018-03-13 09:41:05 -070015689 roam_profile->pAddIEAssoc =
15690 assoc_add_ie->addIEdata;
15691 roam_profile->nAddIEAssocLength =
15692 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015693 }
15694#ifdef WLAN_FEATURE_WFD
15695 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
15696 WFD_OUI_TYPE_SIZE)) &&
15697 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080015698 (QDF_P2P_CLIENT_MODE ==
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015699 adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015700 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070015701 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015702 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015703
15704 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070015705 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070015706 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015707 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015708 return -ENOMEM;
15709 }
15710 /* WFD IE is saved to Additional IE ; it should
15711 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015712 * WFD IE
15713 */
Jeff Johnson20227a92018-03-13 09:41:05 -070015714 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015715 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070015716 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015717
Jeff Johnson20227a92018-03-13 09:41:05 -070015718 roam_profile->pAddIEAssoc =
15719 assoc_add_ie->addIEdata;
15720 roam_profile->nAddIEAssocLength =
15721 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015722 }
15723#endif
15724 /* Appending HS 2.0 Indication Element in Assiciation Request */
15725 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
15726 HS20_OUI_TYPE_SIZE))) {
15727 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070015728 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015729 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015730
15731 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070015732 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070015733 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015734 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015735 return -ENOMEM;
15736 }
Jeff Johnson20227a92018-03-13 09:41:05 -070015737 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015738 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070015739 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015740
Jeff Johnson20227a92018-03-13 09:41:05 -070015741 roam_profile->pAddIEAssoc =
15742 assoc_add_ie->addIEdata;
15743 roam_profile->nAddIEAssocLength =
15744 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015745 }
15746 /* Appending OSEN Information Element in Assiciation Request */
15747 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
15748 OSEN_OUI_TYPE_SIZE))) {
15749 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070015750 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015751 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015752
15753 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070015754 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070015755 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015756 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015757 return -ENOMEM;
15758 }
Jeff Johnson20227a92018-03-13 09:41:05 -070015759 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015760 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070015761 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015762
Jeff Johnson20227a92018-03-13 09:41:05 -070015763 roam_profile->bOSENAssociation = true;
15764 roam_profile->pAddIEAssoc =
15765 assoc_add_ie->addIEdata;
15766 roam_profile->nAddIEAssocLength =
15767 assoc_add_ie->length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053015768 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
15769 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015770 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070015771 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053015772 genie - 2, eLen + 2);
15773 if (status)
15774 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015775 } else {
15776 uint16_t add_ie_len =
Jeff Johnson20227a92018-03-13 09:41:05 -070015777 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015778
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015779 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015780
15781 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070015782 (assoc_add_ie->length + eLen)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015783 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015784 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015785 return -ENOMEM;
15786 }
15787
Jeff Johnson20227a92018-03-13 09:41:05 -070015788 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015789 add_ie_len, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070015790 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015791
Jeff Johnson20227a92018-03-13 09:41:05 -070015792 roam_profile->pAddIEAssoc =
15793 assoc_add_ie->addIEdata;
15794 roam_profile->nAddIEAssocLength =
15795 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015796 }
15797 break;
15798 case DOT11F_EID_RSN:
tinlin8a44b642018-04-25 13:56:06 +080015799 if (eLen > DOT11F_IE_RSN_MAX_LEN) {
Vignesh Viswanathan96e0e702017-12-05 19:42:46 +053015800 hdd_err("%s: Invalid WPA RSN IE length[%d]",
tinlin8a44b642018-04-25 13:56:06 +080015801 __func__, eLen);
Vignesh Viswanathan96e0e702017-12-05 19:42:46 +053015802 return -EINVAL;
15803 }
Jeff Johnson20227a92018-03-13 09:41:05 -070015804 memset(security_ie, 0, MAX_WPA_RSN_IE_LEN);
15805 memcpy(security_ie, genie - 2, (eLen + 2));
15806 roam_profile->pRSNReqIE = security_ie;
15807 roam_profile->nRSNReqIELength = eLen + 2; /* ie_len; */
tinlin8a44b642018-04-25 13:56:06 +080015808 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015809 break;
15810 /*
15811 * Appending Extended Capabilities with Interworking bit set
15812 * in Assoc Req.
15813 *
15814 * In assoc req this EXT Cap will only be taken into account if
15815 * interworkingService bit is set to 1. Currently
15816 * driver is only interested in interworkingService capability
15817 * from supplicant. If in future any other EXT Cap info is
15818 * required from supplicat, it needs to be handled while
15819 * sending Assoc Req in LIM.
15820 */
15821 case DOT11F_EID_EXTCAP:
15822 {
15823 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070015824 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015825 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015826
15827 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070015828 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070015829 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015830 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015831 return -ENOMEM;
15832 }
Jeff Johnson20227a92018-03-13 09:41:05 -070015833 memcpy(assoc_add_ie->addIEdata + curAddIELen, genie - 2, eLen + 2);
15834 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015835
Jeff Johnson20227a92018-03-13 09:41:05 -070015836 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
15837 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015838 break;
15839 }
15840#ifdef FEATURE_WLAN_WAPI
15841 case WLAN_EID_WAPI:
15842 /* Setting WAPI Mode to ON=1 */
tinlin8a44b642018-04-25 13:56:06 +080015843 adapter->wapi_info.wapi_mode = 1;
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070015844 hdd_debug("WAPI MODE IS %u", adapter->wapi_info.wapi_mode);
Abhinav Kumarf56c81f2018-06-06 16:07:01 +053015845 /* genie is pointing to data field of WAPI IE's buffer */
15846 tmp = (uint8_t *)genie;
15847 /* Validate length for Version(2 bytes) and Number
15848 * of AKM suite (2 bytes) in WAPI IE buffer, coming from
15849 * supplicant*/
15850 if (eLen < 4) {
15851 hdd_err("Invalid IE Len: %u", eLen);
15852 return -EINVAL;
15853 }
15854 tmp = tmp + 2; /* Skip Version */
tinlin8a44b642018-04-25 13:56:06 +080015855 /* Get the number of AKM suite */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015856 akmsuiteCount = WPA_GET_LE16(tmp);
tinlin8a44b642018-04-25 13:56:06 +080015857 /* Skip the number of AKM suite */
15858 tmp = tmp + 2;
Abhinav Kumarf56c81f2018-06-06 16:07:01 +053015859 /* Validate total length for WAPI IE's buffer */
15860 if (eLen < (4 + (akmsuiteCount * sizeof(uint32_t)))) {
15861 hdd_err("Invalid IE Len: %u", eLen);
15862 return -EINVAL;
15863 }
tinlin8a44b642018-04-25 13:56:06 +080015864 /* AKM suite list, each OUI contains 4 bytes */
15865 akmlist = (uint32_t *)(tmp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015866 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
Vignesh Viswanathan845bd472018-06-11 18:45:45 +053015867 qdf_mem_copy(akmsuite, akmlist,
15868 sizeof(uint32_t) * akmsuiteCount);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015869 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015870 hdd_err("Invalid akmSuite count: %u",
15871 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015872 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015873 return -EINVAL;
15874 }
15875
15876 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015877 hdd_debug("WAPI AUTH MODE SET TO PSK");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070015878 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015879 WAPI_AUTH_MODE_PSK;
15880 }
15881 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015882 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070015883 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015884 WAPI_AUTH_MODE_CERT;
15885 }
15886 break;
15887#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053015888 case DOT11F_EID_SUPPOPERATINGCLASSES:
15889 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015890 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070015891 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053015892 genie - 2, eLen + 2);
15893 if (status)
15894 return status;
15895 break;
15896 }
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053015897 case SIR_MAC_REQUEST_EID_MAX:
15898 {
15899 if (genie[0] == SIR_FILS_HLP_EXT_EID) {
15900 hdd_debug("Set HLP EXT IE(len %d)",
15901 eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070015902 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053015903 genie - 2, eLen + 2,
15904 true);
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053015905 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070015906 adapter, genie - 2,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053015907 eLen + 2);
15908 if (status)
15909 return status;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053015910 } else if (genie[0] ==
15911 SIR_DH_PARAMETER_ELEMENT_EXT_EID) {
15912 hdd_debug("Set DH EXT IE(len %d)",
15913 eLen + 2);
15914 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070015915 adapter, genie - 2,
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053015916 eLen + 2);
15917 if (status)
15918 return status;
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053015919 } else {
15920 hdd_err("UNKNOWN EID: %X", genie[0]);
15921 }
15922 break;
15923 }
15924 case DOT11F_EID_FRAGMENT_IE:
15925 {
15926 hdd_debug("Set Fragment IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070015927 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053015928 genie - 2, eLen + 2,
15929 false);
Jeff Johnson20227a92018-03-13 09:41:05 -070015930 status = wlan_hdd_add_assoc_ie(adapter,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053015931 genie - 2, eLen + 2);
15932 if (status)
15933 return status;
15934 break;
15935 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015936 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015937 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015938 /* when Unknown IE is received we break
15939 * and continue to the next IE in the buffer
15940 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015941 break;
15942 }
15943 genie += eLen;
15944 remLen -= eLen;
15945 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015946 return 0;
15947}
15948
15949/**
15950 * hdd_is_wpaie_present() - check for WPA ie
15951 * @ie: Pointer to ie
15952 * @ie_len: Ie length
15953 *
15954 * Parse the received IE to find the WPA IE
15955 *
15956 * Return: true if wpa ie is found else false
15957 */
15958static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
15959{
15960 uint8_t eLen = 0;
15961 uint16_t remLen = ie_len;
15962 uint8_t elementId = 0;
15963
15964 while (remLen >= 2) {
15965 elementId = *ie++;
15966 eLen = *ie++;
15967 remLen -= 2;
15968 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015969 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015970 return false;
15971 }
15972 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
15973 /* OUI - 0x00 0X50 0XF2
15974 * WPA Information Element - 0x01
15975 * WPA version - 0x01
15976 */
15977 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
15978 return true;
15979 }
15980 ie += eLen;
15981 remLen -= eLen;
15982 }
15983 return false;
15984}
15985
15986/**
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070015987 * hdd_populate_crypto_auth_type() - populate auth type for crypto
15988 * @vdev: pointed to vdev obmgr
15989 * @auth_type: legacy auth_type
15990 *
15991 * set the crypto auth type for corresponding auth type received
15992 * from NL
15993 *
15994 * Return: None
15995 */
15996static void hdd_populate_crypto_auth_type(struct wlan_objmgr_vdev *vdev,
15997 enum nl80211_auth_type auth_type)
15998{
15999 wlan_crypto_auth_mode crypto_auth_type =
16000 osif_nl_to_crypto_auth_type(auth_type);
16001
16002 wlan_crypto_set_vdev_param(vdev,
16003 WLAN_CRYPTO_PARAM_AUTH_MODE,
16004 crypto_auth_type);
16005}
16006
16007/**
16008 * hdd_populate_crypto_akm_type() - populate akm type for crypto
16009 * @vdev: pointed to vdev obmgr
16010 * @akm_type: legacy akm_type
16011 *
16012 * set the crypto akm type for corresponding akm type received
16013 * from NL
16014 *
16015 * Return: None
16016 */
16017static void hdd_populate_crypto_akm_type(struct wlan_objmgr_vdev *vdev,
16018 u32 key_mgmt)
16019{
16020 wlan_crypto_key_mgmt crypto_akm_type =
16021 osif_nl_to_crypto_akm_type(key_mgmt);
16022
16023 wlan_crypto_set_vdev_param(vdev,
16024 WLAN_CRYPTO_PARAM_KEY_MGMT,
16025 crypto_akm_type);
16026}
16027
16028/**
16029 * hdd_populate_crypto_cipher_type() - populate cipher type for crypto
16030 * @cipher: legacy cipher type
16031 * @vdev: pointed to vdev obmgr
16032 * @cipher_param_type: param type, UCST/MCAST
16033 *
16034 * set the crypto cipher type for corresponding cipher type received
16035 * from NL
16036 *
16037 * Return: None
16038 */
16039static void hdd_populate_crypto_cipher_type(u32 cipher,
16040 struct wlan_objmgr_vdev *vdev,
16041 wlan_crypto_param_type
16042 cipher_param_type)
16043{
16044 wlan_crypto_cipher_type crypto_cipher_type =
16045 osif_nl_to_crypto_cipher_type(cipher);
16046
16047 wlan_crypto_set_vdev_param(vdev,
16048 cipher_param_type,
16049 crypto_cipher_type);
16050}
16051
16052/**
16053 * hdd_populate_crypto_params() - set crypto params
16054 * @vdev: Pointer to vdev obh mgr
16055 * @req: Pointer to security parameters
16056 *
16057 * Set Auth, Akm and Cipher type for crypto
16058 *
16059 * Return: None
16060 */
16061static void hdd_populate_crypto_params(struct wlan_objmgr_vdev *vdev,
16062 struct cfg80211_connect_params *req)
16063{
16064 hdd_populate_crypto_auth_type(vdev, req->auth_type);
16065
16066 if (req->crypto.n_akm_suites)
16067 hdd_populate_crypto_akm_type(vdev, req->crypto.akm_suites[0]);
16068
16069 if (req->crypto.n_ciphers_pairwise) {
16070 hdd_populate_crypto_cipher_type(req->crypto.ciphers_pairwise[0],
16071 vdev,
16072 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
16073 } else {
16074 /* Reset previous cipher suite to none */
16075 hdd_populate_crypto_cipher_type(0, vdev,
16076 WLAN_CRYPTO_PARAM_UCAST_CIPHER);
16077 }
16078
16079 hdd_populate_crypto_cipher_type(req->crypto.cipher_group,
16080 vdev,
16081 WLAN_CRYPTO_PARAM_MCAST_CIPHER);
16082}
16083
16084/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016085 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016086 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016087 * @req: Pointer to security parameters
16088 *
16089 * Return: 0 for success, non-zero for failure
16090 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016091static int wlan_hdd_cfg80211_set_privacy(struct hdd_adapter *adapter,
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016092 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016093{
16094 int status = 0;
Jeff Johnsonce4a8342017-10-14 13:12:22 -070016095 struct hdd_station_ctx *sta_ctx;
Jeff Johnson20227a92018-03-13 09:41:05 -070016096 struct csr_roam_profile *roam_profile;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070016097
Dustin Brown491d54b2018-03-14 12:39:11 -070016098 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016099
Jeff Johnsonce4a8342017-10-14 13:12:22 -070016100 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16101 sta_ctx->wpa_versions = req->crypto.wpa_versions;
16102 hdd_debug("set wpa version to %d", sta_ctx->wpa_versions);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016103
Jeff Johnson20227a92018-03-13 09:41:05 -070016104 roam_profile = hdd_roam_profile(adapter);
16105
Harprit Chhabada6c641ba2018-06-28 14:45:10 -070016106 /* populate auth,akm and cipher params for crypto */
16107 hdd_populate_crypto_params(adapter->vdev, req);
16108
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016109 /*set authentication type */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016110 status = wlan_hdd_cfg80211_set_auth_type(adapter, req->auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016111
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016112 if (wlan_hdd_is_conn_type_fils(req)) {
16113 status = wlan_hdd_cfg80211_set_fils_config(adapter, req);
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053016114
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070016115 if (0 > status) {
16116 hdd_err("Failed to set fils config");
16117 return status;
16118 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016119 }
16120
16121 /*set key mgmt type */
16122 if (req->crypto.n_akm_suites) {
16123 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016124 wlan_hdd_set_akm_suite(adapter, req->crypto.akm_suites[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016125 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016126 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016127 return status;
16128 }
16129 }
16130
16131 /*set pairwise cipher type */
16132 if (req->crypto.n_ciphers_pairwise) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016133 status = wlan_hdd_cfg80211_set_cipher(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016134 req->crypto.
16135 ciphers_pairwise[0],
16136 true);
16137 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016138 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016139 return status;
16140 }
16141 } else {
16142 /*Reset previous cipher suite to none */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016143 status = wlan_hdd_cfg80211_set_cipher(adapter, 0, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016144 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016145 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016146 return status;
16147 }
16148 }
16149
16150 /*set group cipher type */
16151 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016152 wlan_hdd_cfg80211_set_cipher(adapter, req->crypto.cipher_group,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016153 false);
16154
16155 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016156 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016157 return status;
16158 }
16159#ifdef WLAN_FEATURE_11W
Jeff Johnson20227a92018-03-13 09:41:05 -070016160 roam_profile->MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016161#endif
16162
16163 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
16164 if (req->ie_len) {
16165 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016166 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016167 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016168 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016169 return status;
16170 }
16171 }
16172
16173 /*incase of WEP set default key information */
16174 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080016175 u8 key_len = req->key_len;
16176 u8 key_idx = req->key_idx;
Jeff Johnson37ecea42018-03-18 17:54:40 -070016177 u32 cipher = req->crypto.ciphers_pairwise[0];
Jeff Johnson68755312017-02-10 11:46:55 -080016178
Jeff Johnson37ecea42018-03-18 17:54:40 -070016179 if ((WLAN_CIPHER_SUITE_WEP40 == cipher) ||
16180 (WLAN_CIPHER_SUITE_WEP104 == cipher)) {
16181 enum hdd_auth_key_mgmt key_mgmt =
16182 sta_ctx->auth_key_mgmt;
16183
16184 if (key_mgmt & HDD_AUTH_KEY_MGMT_802_1X) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016185 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016186 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080016187 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016188
Jeff Johnson68755312017-02-10 11:46:55 -080016189 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
16190 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016191 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080016192 key_idx, key_len);
Jeff Johnson20227a92018-03-13 09:41:05 -070016193 qdf_mem_copy(&roam_profile->Keys.
Jeff Johnson68755312017-02-10 11:46:55 -080016194 KeyMaterial[key_idx][0],
16195 req->key, key_len);
Jeff Johnson20227a92018-03-13 09:41:05 -070016196 roam_profile->Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016197 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson20227a92018-03-13 09:41:05 -070016198 roam_profile->Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016199 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016200 }
16201 }
16202 }
16203
16204 return status;
16205}
16206
wadesongcaad7c72018-08-06 13:26:27 +080016207/**
16208 * wlan_hdd_clear_wapi_privacy() - reset WAPI settings in HDD layer
16209 * @adapter: pointer to HDD adapter object
16210 *
16211 * This function resets all WAPI related parameters imposed before STA
16212 * connection starts. It's invoked when privacy checking against concurrency
16213 * fails, to make sure no improper WAPI settings are still populated before
16214 * returning an error to the upper layer requester.
16215 *
16216 * Return: none
16217 */
16218#ifdef FEATURE_WLAN_WAPI
16219static inline void wlan_hdd_clear_wapi_privacy(struct hdd_adapter *adapter)
16220{
16221 adapter->wapi_info.wapi_mode = 0;
16222 adapter->wapi_info.wapi_auth_mode = WAPI_AUTH_MODE_OPEN;
16223}
16224#else
16225static inline void wlan_hdd_clear_wapi_privacy(struct hdd_adapter *adapter)
16226{
16227}
16228#endif
16229
16230/**
16231 * wlan_hdd_cfg80211_clear_privacy() - reset STA security parameters
16232 * @adapter: pointer to HDD adapter object
16233 *
16234 * This function resets all privacy related parameters imposed
16235 * before STA connection starts. It's invoked when privacy checking
16236 * against concurrency fails, to make sure no improper settings are
16237 * still populated before returning an error to the upper layer requester.
16238 *
16239 * Return: none
16240 */
16241static void wlan_hdd_cfg80211_clear_privacy(struct hdd_adapter *adapter)
16242{
16243 struct hdd_station_ctx *hdd_sta_ctx =
16244 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16245
16246 hdd_debug("resetting all privacy configurations");
16247
16248 hdd_sta_ctx->wpa_versions = 0;
16249
16250 hdd_sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_NONE;
16251 hdd_sta_ctx->roam_profile.AuthType.authType[0] = eCSR_AUTH_TYPE_NONE;
16252
16253 hdd_sta_ctx->conn_info.ucEncryptionType = eCSR_ENCRYPT_TYPE_NONE;
16254 hdd_sta_ctx->roam_profile.EncryptionType.numEntries = 0;
16255 hdd_sta_ctx->conn_info.mcEncryptionType = eCSR_ENCRYPT_TYPE_NONE;
16256 hdd_sta_ctx->roam_profile.mcEncryptionType.numEntries = 0;
16257
16258 wlan_hdd_clear_wapi_privacy(adapter);
16259}
16260
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016261int wlan_hdd_try_disconnect(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016262{
16263 unsigned long rc;
Jeff Johnsond377dce2017-10-04 10:32:42 -070016264 struct hdd_station_ctx *sta_ctx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053016265 int status, result = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016266 mac_handle_t mac_handle;
Abhishek Singh0edeba02018-06-05 10:04:08 +053016267 uint32_t wait_time = WLAN_WAIT_TIME_DISCONNECT;
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053016268 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016269
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053016270 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsond377dce2017-10-04 10:32:42 -070016271 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016272 mac_handle = hdd_adapter_get_mac_handle(adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016273 if (adapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016274 hdd_debug("Stop firmware roaming");
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016275 sme_stop_roaming(mac_handle, adapter->session_id,
16276 eCsrForcedDisassoc);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016277
Abhishek Singh533c9da2017-05-04 10:23:34 +053016278 /*
16279 * If firmware has already started roaming process, driver
16280 * needs to wait for processing of this disconnect request.
16281 *
16282 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016283 INIT_COMPLETION(adapter->roaming_comp_var);
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053016284 if (hdd_is_roaming_in_progress(hdd_ctx)) {
Abhishek Singh533c9da2017-05-04 10:23:34 +053016285 rc = wait_for_completion_timeout(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016286 &adapter->roaming_comp_var,
Abhishek Singh533c9da2017-05-04 10:23:34 +053016287 msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));
16288 if (!rc) {
16289 hdd_err("roaming comp var timed out session Id: %d",
Jeff Johnson1b780e42017-10-31 14:11:45 -070016290 adapter->session_id);
Abhishek Singh533c9da2017-05-04 10:23:34 +053016291 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016292 if (adapter->roam_ho_fail) {
16293 INIT_COMPLETION(adapter->disconnect_comp_var);
16294 hdd_conn_set_connection_state(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053016295 eConnectionState_Disconnecting);
16296 }
16297 }
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016298 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016299
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016300 if ((QDF_IBSS_MODE == adapter->device_mode) ||
Jeff Johnsond377dce2017-10-04 10:32:42 -070016301 (eConnectionState_Associated == sta_ctx->conn_info.connState) ||
16302 (eConnectionState_Connecting == sta_ctx->conn_info.connState) ||
16303 (eConnectionState_IbssConnected == sta_ctx->conn_info.connState)) {
Abhishek Singh0edeba02018-06-05 10:04:08 +053016304 eConnectionState prev_conn_state;
16305
16306 prev_conn_state = sta_ctx->conn_info.connState;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016307 hdd_conn_set_connection_state(adapter,
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016308 eConnectionState_Disconnecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016309 /* Issue disconnect to CSR */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016310 INIT_COMPLETION(adapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053016311
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016312 status = sme_roam_disconnect(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016313 adapter->session_id,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053016314 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Abhishek Singh0edeba02018-06-05 10:04:08 +053016315
16316 if ((status == QDF_STATUS_CMD_NOT_QUEUED) &&
16317 prev_conn_state != eConnectionState_Connecting) {
16318 hdd_debug("Already disconnect in progress");
16319 result = 0;
16320 /*
16321 * Wait here instead of returning directly. This will
16322 * block the connect command and allow processing
16323 * of the disconnect in SME. As disconnect is already
16324 * in progress, wait here for 1 sec instead of 5 sec.
16325 */
16326 wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS;
16327 } else if (status == QDF_STATUS_CMD_NOT_QUEUED) {
16328 /*
16329 * Wait here instead of returning directly, this will
16330 * block the connect command and allow processing
16331 * of the scan for ssid and the previous connect command
16332 * in CSR.
16333 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016334 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053016335 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016336 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053016337 (int)status);
Jeff Johnson8380f232017-10-25 12:39:44 -070016338 sta_ctx->sta_debug_state = status;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053016339 result = -EINVAL;
16340 goto disconnected;
16341 }
16342
Abhishek Singh0edeba02018-06-05 10:04:08 +053016343 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
16344 msecs_to_jiffies(wait_time));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016345 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson8380f232017-10-25 12:39:44 -070016346 hdd_err("Sme disconnect event timed out session Id: %d sta_debug_state: %d",
Jeff Johnson1b780e42017-10-31 14:11:45 -070016347 adapter->session_id, sta_ctx->sta_debug_state);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053016348 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016349 }
16350 } else if (eConnectionState_Disconnecting ==
Jeff Johnsond377dce2017-10-04 10:32:42 -070016351 sta_ctx->conn_info.connState) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016352 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Abhishek Singh0edeba02018-06-05 10:04:08 +053016353 msecs_to_jiffies(wait_time));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016354 if (!rc) {
Jeff Johnson8380f232017-10-25 12:39:44 -070016355 hdd_err("Disconnect event timed out session Id: %d sta_debug_state: %d",
Jeff Johnson1b780e42017-10-31 14:11:45 -070016356 adapter->session_id, sta_ctx->sta_debug_state);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053016357 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016358 }
16359 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053016360disconnected:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016361 hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053016362 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016363}
16364
16365/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016366 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
16367 * @adapter: Pointer to the HDD adapter
16368 * @req: Pointer to the structure cfg_connect_params receieved from user space
16369 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053016370 * This function will start reassociation if prev_bssid is set and bssid/
16371 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016372 *
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053016373 * Return: 0 if connect was for ReAssociation, non-zero error code otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016374 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053016375#if defined(CFG80211_CONNECT_PREV_BSSID) || \
16376 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053016377static int wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
16378 struct cfg80211_connect_params *req)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016379{
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053016380 int status = -EINVAL;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053016381 const uint8_t *bssid = NULL;
16382 uint16_t channel = 0;
Jeff Johnson731bc322017-10-14 19:53:44 -070016383 struct hdd_station_ctx *sta_ctx;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053016384
16385 if (req->bssid)
16386 bssid = req->bssid;
16387 else if (req->bssid_hint)
16388 bssid = req->bssid_hint;
16389
16390 if (req->channel)
16391 channel = req->channel->hw_value;
16392 else if (req->channel_hint)
16393 channel = req->channel_hint->hw_value;
16394
16395 if (bssid && channel && req->prev_bssid) {
Dustin Brownbacc48f2018-03-14 14:48:44 -070016396 hdd_debug("REASSOC Attempt on channel %d to " MAC_ADDRESS_STR,
16397 channel, MAC_ADDR_ARRAY(bssid));
Arif Hussain43354e62017-05-24 11:24:25 -070016398 /*
16399 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016400 * roam_profile's BSSID is getting zeroed out in the
Arif Hussain43354e62017-05-24 11:24:25 -070016401 * association process. In case of join failure
16402 * we should send valid BSSID to supplicant
16403 */
Jeff Johnson731bc322017-10-14 19:53:44 -070016404 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16405 qdf_mem_copy(sta_ctx->requested_bssid.bytes, bssid,
Arif Hussain43354e62017-05-24 11:24:25 -070016406 QDF_MAC_ADDR_SIZE);
16407
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053016408 status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016409 CONNECT_CMD_USERSPACE);
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053016410 hdd_debug("hdd_reassoc: status: %d", status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016411 }
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053016412 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016413}
16414#else
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053016415static int wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
16416 struct cfg80211_connect_params *req)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016417{
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053016418 return -ENOTSUPP;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016419}
16420#endif
16421
Abhishek Singhb59f8d42017-07-31 14:42:47 +053016422
16423/**
16424 * wlan_hdd_check_ht20_ht40_ind() - check if Supplicant has indicated to
16425 * connect in HT20 mode
16426 * @hdd_ctx: hdd context
16427 * @adapter: Pointer to the HDD adapter
16428 * @req: Pointer to the structure cfg_connect_params receieved from user space
16429 *
16430 * This function will check if supplicant has indicated to to connect in HT20
16431 * mode. this is currently applicable only for 2.4Ghz mode only.
16432 * if feature is enabled and supplicant indicate HT20 set
16433 * force_24ghz_in_ht20 to true to force 2.4Ghz in HT20 else set it to false.
16434 *
16435 * Return: void
16436 */
16437#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
Jeff Johnson20227a92018-03-13 09:41:05 -070016438static void
16439wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
16440 struct hdd_adapter *adapter,
16441 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053016442{
Jeff Johnson61b5e982018-03-15 11:33:31 -070016443 struct csr_roam_profile *roam_profile;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053016444
Jeff Johnson20227a92018-03-13 09:41:05 -070016445 roam_profile = hdd_roam_profile(adapter);
16446
Abhishek Singhb59f8d42017-07-31 14:42:47 +053016447 roam_profile->force_24ghz_in_ht20 = false;
16448
16449 if (hdd_ctx->config->override_ht20_40_24g &&
Jeff Johnson20227a92018-03-13 09:41:05 -070016450 !(req->ht_capa.cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
Abhishek Singhb59f8d42017-07-31 14:42:47 +053016451 roam_profile->force_24ghz_in_ht20 = true;
16452
16453 hdd_debug("req->ht_capa.cap_info %x override_ht20_40_24g %d",
16454 req->ht_capa.cap_info,
16455 hdd_ctx->config->override_ht20_40_24g);
16456}
16457#else
Jeff Johnson20227a92018-03-13 09:41:05 -070016458static inline void
16459wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
16460 struct hdd_adapter *adapter,
16461 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053016462{
Jeff Johnson61b5e982018-03-15 11:33:31 -070016463 struct csr_roam_profile *roam_profile;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053016464
Jeff Johnson20227a92018-03-13 09:41:05 -070016465 roam_profile = hdd_roam_profile(adapter);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053016466
16467 roam_profile->force_24ghz_in_ht20 = false;
16468}
16469#endif
16470
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016471/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016472 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
16473 * @wiphy: Pointer to wiphy
16474 * @dev: Pointer to network device
16475 * @req: Pointer to cfg80211 connect request
16476 *
16477 * This function is used to start the association process
16478 *
16479 * Return: 0 for success, non-zero for failure
16480 */
16481static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
16482 struct net_device *ndev,
16483 struct cfg80211_connect_params *req)
16484{
16485 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053016486 u16 channel;
Arif Hussainee677012017-01-26 17:50:13 -080016487 const u8 *bssid = NULL;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053016488#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
16489 const u8 *bssid_hint = req->bssid_hint;
16490#else
16491 const u8 *bssid_hint = NULL;
16492#endif
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016493 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016494 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016495
Dustin Brown491d54b2018-03-14 12:39:11 -070016496 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016497
Anurag Chouhan6d760662016-02-20 16:05:43 +053016498 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016499 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016500 return -EINVAL;
16501 }
16502
Dustin Brown63500612018-08-07 11:36:09 -070016503 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016504 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016505
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016506 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016507 TRACE_CODE_HDD_CFG80211_CONNECT,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016508 adapter->session_id, adapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016509 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016510 hdd_device_mode_to_string(adapter->device_mode),
16511 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016512
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016513 if (adapter->device_mode != QDF_STA_MODE &&
16514 adapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016515 hdd_err("Device_mode %s(%d) is not supported",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016516 hdd_device_mode_to_string(adapter->device_mode),
16517 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016518 return -EINVAL;
16519 }
16520
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016521 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016522 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016523 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016524 return -EINVAL;
16525 }
16526
Jeff Johnsonb8944722017-09-03 09:03:19 -070016527 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016528 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016529 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016530
Arif Hussainee677012017-01-26 17:50:13 -080016531 if (req->bssid)
16532 bssid = req->bssid;
16533 else if (bssid_hint)
16534 bssid = bssid_hint;
16535
Jeff Johnsonb8944722017-09-03 09:03:19 -070016536 if (bssid && hdd_get_adapter_by_macaddr(hdd_ctx, (uint8_t *)bssid)) {
Arif Hussain7631afa2017-02-08 14:35:00 -080016537 hdd_err("adapter exist with same mac address " MAC_ADDRESS_STR,
16538 MAC_ADDR_ARRAY(bssid));
16539 return -EINVAL;
Arif Hussainee677012017-01-26 17:50:13 -080016540 }
16541
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053016542 /*
16543 * Check if this is reassoc to same bssid, if reassoc is success, return
16544 */
16545 status = wlan_hdd_reassoc_bssid_hint(adapter, req);
Padma, Santhosh Kumar41552782018-06-29 15:31:25 +053016546 if (!status) {
16547 hdd_set_roaming_in_progress(true);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016548 return status;
Padma, Santhosh Kumar41552782018-06-29 15:31:25 +053016549 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016550
Agrawal Ashishf156e942016-08-04 14:54:47 +053016551 /* Try disconnecting if already in connected state */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016552 status = wlan_hdd_try_disconnect(adapter);
Agrawal Ashishf156e942016-08-04 14:54:47 +053016553 if (0 > status) {
16554 hdd_err("Failed to disconnect the existing connection");
16555 return -EALREADY;
16556 }
16557
Liangwei Dong3fa5cba2018-07-16 06:41:55 -040016558 /*initialise security parameters */
16559 status = wlan_hdd_cfg80211_set_privacy(adapter, req);
16560
16561 if (status < 0) {
16562 hdd_err("Failed to set security params");
16563 return status;
16564 }
16565
16566 /*
16567 * Check for max concurrent connections after doing disconnect if any,
16568 * must be called after the invocation of wlan_hdd_cfg80211_set_privacy
16569 * so privacy is already set for the current adapter before it's
16570 * checked against concurrency.
16571 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016572 if (req->channel) {
Min Liuab6ed4f2018-01-09 13:13:57 +080016573 bool ok = false;
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053016574
16575 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
Jeff Johnsonb8944722017-09-03 09:03:19 -070016576 hdd_ctx->hdd_psoc,
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053016577 req->channel->hw_value,
16578 &ok)) {
16579 hdd_warn("Unable to get channel:%d eligibility for DNBS",
16580 req->channel->hw_value);
16581 return -EINVAL;
16582 }
16583 /**
16584 * Send connection timedout, so that Android framework does not
16585 * blacklist us.
16586 */
16587 if (!ok) {
16588 struct ieee80211_channel *chan =
Dustin Brown2eb1e452017-08-15 12:40:34 -070016589 ieee80211_get_channel(wiphy,
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053016590 wlan_chan_to_freq(req->channel->hw_value));
16591 struct cfg80211_bss *bss;
16592
16593 hdd_warn("Channel:%d not OK for DNBS",
16594 req->channel->hw_value);
16595 if (chan) {
16596 bss = hdd_cfg80211_get_bss(wiphy,
16597 chan,
16598 req->bssid, req->ssid,
16599 req->ssid_len);
16600 if (bss) {
16601 cfg80211_assoc_timeout(ndev, bss);
16602 return -ETIMEDOUT;
16603 }
16604 }
16605 return -EINVAL;
16606 }
16607
Jeff Johnsonb8944722017-09-03 09:03:19 -070016608 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016609 policy_mgr_convert_device_mode_to_qdf_type(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016610 adapter->device_mode),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016611 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016612 hdd_warn("This concurrency combination is not allowed");
wadesongcaad7c72018-08-06 13:26:27 +080016613 status = -ECONNREFUSED;
16614 goto con_chk_failed;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016615 }
16616 } else {
Jeff Johnsonb8944722017-09-03 09:03:19 -070016617 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016618 policy_mgr_convert_device_mode_to_qdf_type(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016619 adapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016620 hdd_warn("This concurrency combination is not allowed");
wadesongcaad7c72018-08-06 13:26:27 +080016621 status = -ECONNREFUSED;
16622 goto con_chk_failed;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016623 }
16624 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070016625
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053016626 if (req->channel)
16627 channel = req->channel->hw_value;
16628 else
16629 channel = 0;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053016630
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016631 wlan_hdd_check_ht20_ht40_ind(hdd_ctx, adapter, req);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053016632
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016633 status = wlan_hdd_cfg80211_connect_start(adapter, req->ssid,
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053016634 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016635 bssid_hint, channel, 0);
Srinivas Girigowdad2412882018-09-07 15:42:04 -070016636 if (0 > status)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016637 hdd_err("connect failed");
Srinivas Girigowdad2412882018-09-07 15:42:04 -070016638
wadesongcaad7c72018-08-06 13:26:27 +080016639 return status;
16640
16641con_chk_failed:
16642 wlan_hdd_cfg80211_clear_privacy(adapter);
Dustin Browne74003f2018-03-14 12:51:58 -070016643 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016644 return status;
16645}
16646
16647/**
16648 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
16649 * @wiphy: Pointer to wiphy
16650 * @dev: Pointer to network device
16651 * @req: Pointer to cfg80211 connect request
16652 *
16653 * Return: 0 for success, non-zero for failure
16654 */
16655static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
16656 struct net_device *ndev,
16657 struct cfg80211_connect_params *req)
16658{
16659 int ret;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070016660
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016661 cds_ssr_protect(__func__);
16662 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
16663 cds_ssr_unprotect(__func__);
16664
16665 return ret;
16666}
16667
Himanshu Agarwal6c3607a2018-01-12 12:04:19 +053016668int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016669{
Dundi Ravitejacc95c562018-07-27 12:30:24 +053016670 QDF_STATUS status;
16671 int result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016672 unsigned long rc;
Jeff Johnsond377dce2017-10-04 10:32:42 -070016673 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016674 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053016675 eConnectionState prev_conn_state;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016676 mac_handle_t mac_handle;
Abhishek Singhe9706cc2017-10-12 17:25:06 +053016677 uint32_t wait_time = WLAN_WAIT_TIME_DISCONNECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016678
Dustin Brown491d54b2018-03-14 12:39:11 -070016679 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016680
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016681 mac_handle = hdd_ctx->mac_handle;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016682 if (adapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016683 hdd_debug("Stop firmware roaming");
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016684 status = sme_stop_roaming(mac_handle, adapter->session_id,
16685 eCsrForcedDisassoc);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016686 /*
Abhishek Singh533c9da2017-05-04 10:23:34 +053016687 * If firmware has already started roaming process, driver
16688 * needs to wait for processing of this disconnect request.
16689 *
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016690 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016691 INIT_COMPLETION(adapter->roaming_comp_var);
Padma, Santhosh Kumar86747ec2018-05-29 18:28:29 +053016692 if (hdd_is_roaming_in_progress(hdd_ctx)) {
Abhishek Singh533c9da2017-05-04 10:23:34 +053016693 rc = wait_for_completion_timeout(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016694 &adapter->roaming_comp_var,
Abhishek Singh533c9da2017-05-04 10:23:34 +053016695 msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));
16696 if (!rc) {
16697 hdd_err("roaming comp var timed out session Id: %d",
Jeff Johnson1b780e42017-10-31 14:11:45 -070016698 adapter->session_id);
Abhishek Singh533c9da2017-05-04 10:23:34 +053016699 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016700 if (adapter->roam_ho_fail) {
16701 INIT_COMPLETION(adapter->disconnect_comp_var);
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -070016702 hdd_debug("Disabling queues");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016703 wlan_hdd_netif_queue_control(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053016704 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
16705 WLAN_CONTROL_PATH);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016706 hdd_conn_set_connection_state(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053016707 eConnectionState_Disconnecting);
16708 goto wait_for_disconnect;
16709 }
16710 }
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016711 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016712
Jeff Johnsond377dce2017-10-04 10:32:42 -070016713 prev_conn_state = sta_ctx->conn_info.connState;
Srinivas Girigowda6598eea2017-07-06 19:26:19 -070016714 /*stop tx queues */
16715 hdd_info("Disabling queues");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016716 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053016717 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016718 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016719 hdd_conn_set_connection_state(adapter, eConnectionState_Disconnecting);
Varun Reddy Yeturu9e0032c2017-07-12 18:39:59 -070016720
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016721 INIT_COMPLETION(adapter->disconnect_comp_var);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016722
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016723 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016724
Jeff Johnson34fc63a2018-06-14 10:10:02 -070016725 status = sme_roam_disconnect(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016726 adapter->session_id, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053016727 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
16728 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016729 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053016730 result = 0;
Abhishek Singhe9706cc2017-10-12 17:25:06 +053016731 /*
16732 * Wait here instead of returning directly. This will block the
16733 * next connect command and allow processing of the disconnect
16734 * in SME else we might hit some race conditions leading to SME
16735 * and HDD out of sync. As disconnect is already in progress,
16736 * wait here for 1 sec instead of 5 sec.
16737 */
16738 wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS;
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053016739 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
16740 /*
16741 * Wait here instead of returning directly, this will block the
16742 * next connect command and allow processing of the scan for
16743 * ssid and the previous connect command in CSR. Else we might
16744 * hit some race conditions leading to SME and HDD out of sync.
16745 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016746 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016747 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016748 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Jeff Johnson8380f232017-10-25 12:39:44 -070016749 sta_ctx->sta_debug_state = status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016750 result = -EINVAL;
16751 goto disconnected;
16752 }
Abhishek Singh533c9da2017-05-04 10:23:34 +053016753wait_for_disconnect:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016754 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Abhishek Singhe9706cc2017-10-12 17:25:06 +053016755 msecs_to_jiffies(wait_time));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016756
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016757 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016758 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016759 result = -ETIMEDOUT;
16760 }
16761disconnected:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016762 hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016763#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
16764 /* Sending disconnect event to userspace for kernel version < 3.11
16765 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
16766 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016767 hdd_debug("Send disconnected event to userspace");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016768 wlan_hdd_cfg80211_indicate_disconnect(adapter->dev, true,
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053016769 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016770#endif
16771
16772 return result;
16773}
16774
16775/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080016776 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
16777 * @reason: ieee80211 reason code.
16778 *
16779 * This utility function helps log string conversion of reason code.
16780 *
16781 * Return: string conversion of reason code, if match found;
16782 * "Unknown" otherwise.
16783 */
16784static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
16785{
16786 switch (reason) {
16787 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
16788 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
16789 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
16790 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
16791 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
16792 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
16793 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
16794 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
16795 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
16796 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
16797 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
16798 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
16799 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
16800 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
16801 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
16802 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
16803 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
16804 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
16805 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
16806 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
16807 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
16808 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
16809 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
16810 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
16811 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
16812 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
16813 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
16814 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
16815 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
16816 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
16817 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
16818 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
16819 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
16820 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
16821 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
16822 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
16823 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
16824 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
16825 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
16826 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
16827 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
16828 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
16829 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
16830 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
16831 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
16832 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
16833 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
16834 default:
16835 return "Unknown";
16836 }
16837}
16838
16839/**
Srinivas Girigowda44cff5c2018-04-16 15:49:30 -070016840 * hdd_print_netdev_txq_status() - print netdev tx queue status
16841 * @dev: Pointer to network device
16842 *
16843 * This function is used to print netdev tx queue status
16844 *
16845 * Return: none
16846 */
16847static void hdd_print_netdev_txq_status(struct net_device *dev)
16848{
16849 unsigned int i;
16850
16851 if (!dev)
16852 return;
16853
16854 for (i = 0; i < dev->num_tx_queues; i++) {
16855 struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
16856
Dustin Brown1e3ec6b2018-08-07 11:18:47 -070016857 hdd_debug("netdev tx queue[%u] state: 0x%lx", i, txq->state);
Srinivas Girigowda44cff5c2018-04-16 15:49:30 -070016858 }
16859}
16860
16861/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016862 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
16863 * @wiphy: Pointer to wiphy
16864 * @dev: Pointer to network device
16865 * @reason: Disconnect reason code
16866 *
16867 * This function is used to issue a disconnect request to SME
16868 *
16869 * Return: 0 for success, non-zero for failure
16870 */
16871static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
16872 struct net_device *dev, u16 reason)
16873{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016874 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016875 int status;
Jeff Johnsond377dce2017-10-04 10:32:42 -070016876 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016877 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16878 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016879
Dustin Brown491d54b2018-03-14 12:39:11 -070016880 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016881
Anurag Chouhan6d760662016-02-20 16:05:43 +053016882 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016883 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016884 return -EINVAL;
16885 }
16886
Dustin Brown63500612018-08-07 11:36:09 -070016887 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016888 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016889
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016890 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016891 TRACE_CODE_HDD_CFG80211_DISCONNECT,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016892 adapter->session_id, reason));
Srinivas Girigowda44cff5c2018-04-16 15:49:30 -070016893 hdd_print_netdev_txq_status(dev);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016894 hdd_debug("Device_mode %s(%d) reason code(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016895 hdd_device_mode_to_string(adapter->device_mode),
16896 adapter->device_mode, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016897
Jeff Johnsonb8944722017-09-03 09:03:19 -070016898 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016899
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016900 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016901 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016902
Alok Kumarb64650c2018-03-23 17:05:11 +053016903 qdf_mutex_acquire(&adapter->disconnection_status_lock);
16904 if (adapter->disconnection_in_progress) {
16905 qdf_mutex_release(&adapter->disconnection_status_lock);
16906 hdd_debug("Disconnect is already in progress");
16907 return 0;
16908 }
16909 adapter->disconnection_in_progress = true;
16910 qdf_mutex_release(&adapter->disconnection_status_lock);
16911
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016912 /* Issue disconnect request to SME, if station is in connected state */
Jeff Johnsond377dce2017-10-04 10:32:42 -070016913 if ((sta_ctx->conn_info.connState == eConnectionState_Associated) ||
16914 (sta_ctx->conn_info.connState == eConnectionState_Connecting)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016915 eCsrRoamDisconnectReason reasonCode =
16916 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016917
16918 switch (reason) {
16919 case WLAN_REASON_MIC_FAILURE:
16920 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
16921 break;
16922
16923 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
16924 case WLAN_REASON_DISASSOC_AP_BUSY:
16925 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
16926 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
16927 break;
16928
16929 case WLAN_REASON_PREV_AUTH_NOT_VALID:
16930 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
16931 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
16932 break;
16933
16934 case WLAN_REASON_DEAUTH_LEAVING:
16935 reasonCode =
Jeff Johnsonb8944722017-09-03 09:03:19 -070016936 hdd_ctx->config->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016937 gEnableDeauthToDisassocMap ?
16938 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
16939 eCSR_DISCONNECT_REASON_DEAUTH;
Mohit Khannaceb97782017-04-05 16:27:08 -070016940 qdf_dp_trace_dump_all(
16941 WLAN_DEAUTH_DPTRACE_DUMP_COUNT,
16942 QDF_TRACE_DEFAULT_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016943 break;
16944 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
16945 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
16946 break;
16947 default:
16948 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
16949 break;
16950 }
Dustin Brown89fa06e2018-09-07 10:47:27 -070016951 if (ucfg_scan_get_vdev_status(adapter->vdev) !=
Sandeep Puligilla5f86d992017-10-29 14:58:53 -070016952 SCAN_NOT_IN_PROGRESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016953 hdd_debug("Disconnect is in progress, Aborting Scan");
Dustin Brown07901ec2018-09-07 11:02:41 -070016954 wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID,
16955 adapter->session_id, INVALID_SCAN_ID,
16956 false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016957 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016958 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016959 /* First clean up the tdls peers if any */
Jeff Johnson1b780e42017-10-31 14:11:45 -070016960 hdd_notify_sta_disconnect(adapter->session_id,
Dustin Brown89fa06e2018-09-07 10:47:27 -070016961 false, true, adapter->vdev);
Kabilan Kannanb6153b12017-07-13 17:54:02 -070016962
Dustin Browna7bb6ae2018-08-16 16:51:50 -070016963 hdd_info("Disconnect from userspace; reason:%d (%s)",
16964 reason, hdd_ieee80211_reason_code_to_str(reason));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016965 status = wlan_hdd_disconnect(adapter, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016966 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016967 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Alok Kumarb64650c2018-03-23 17:05:11 +053016968 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016969 return -EINVAL;
16970 }
16971 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016972 hdd_err("Unexpected cfg disconnect called while in state: %d",
Jeff Johnsond377dce2017-10-04 10:32:42 -070016973 sta_ctx->conn_info.connState);
Alok Kumarb64650c2018-03-23 17:05:11 +053016974 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016975 }
16976
16977 return status;
16978}
16979
16980/**
16981 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
16982 * @wiphy: Pointer to wiphy
16983 * @dev: Pointer to network device
16984 * @reason: Disconnect reason code
16985 *
16986 * Return: 0 for success, non-zero for failure
16987 */
16988static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
16989 struct net_device *dev, u16 reason)
16990{
16991 int ret;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070016992
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016993 cds_ssr_protect(__func__);
16994 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
16995 cds_ssr_unprotect(__func__);
16996
16997 return ret;
16998}
16999
17000/**
17001 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017002 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017003 * @param: Pointer to IBSS parameters
17004 *
17005 * This function is used to initialize the security settings in IBSS mode
17006 *
17007 * Return: 0 for success, non-zero for failure
17008 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017009static int wlan_hdd_cfg80211_set_privacy_ibss(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017010 struct cfg80211_ibss_params
17011 *params)
17012{
Naveen Rawat72475db2017-12-13 18:07:35 -080017013 uint32_t ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017014 int status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017015 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Jeff Johnsond377dce2017-10-04 10:32:42 -070017016 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017017 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070017018 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017019
Dustin Brown491d54b2018-03-14 12:39:11 -070017020 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017021
Jeff Johnsonce4a8342017-10-14 13:12:22 -070017022 sta_ctx->wpa_versions = 0;
Jeff Johnsond377dce2017-10-04 10:32:42 -070017023 qdf_mem_zero(&sta_ctx->ibss_enc_key, sizeof(tCsrRoamSetKey));
17024 sta_ctx->ibss_enc_key_installed = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017025
17026 if (params->ie_len && (NULL != params->ie)) {
Naveen Rawat08db88f2017-09-08 15:07:48 -070017027 if (wlan_get_ie_ptr_from_eid(WLAN_EID_RSN, params->ie,
17028 params->ie_len)) {
Jeff Johnsonce4a8342017-10-14 13:12:22 -070017029 sta_ctx->wpa_versions = NL80211_WPA_VERSION_2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017030 encryptionType = eCSR_ENCRYPT_TYPE_AES;
17031 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
17032 tDot11fIEWPA dot11WPAIE;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017033 mac_handle_t mac_handle =
17034 hdd_adapter_get_mac_handle(adapter);
Naveen Rawat08db88f2017-09-08 15:07:48 -070017035 const u8 *ie;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017036
17037 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
Naveen Rawat08db88f2017-09-08 15:07:48 -070017038 ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_WPA,
17039 params->ie, params->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017040 if (NULL != ie) {
Jeff Johnsonce4a8342017-10-14 13:12:22 -070017041 sta_ctx->wpa_versions = NL80211_WPA_VERSION_1;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080017042 /* Unpack the WPA IE
17043 * Skip past the EID byte and length byte
17044 * and four byte WiFi OUI
17045 */
Hanumanth Reddy Pothulaf6e3db32018-01-24 17:54:15 +053017046 if (ie[1] < DOT11F_IE_WPA_MIN_LEN ||
17047 ie[1] > DOT11F_IE_WPA_MAX_LEN) {
17048 hdd_err("invalid ie len:%d", ie[1]);
17049 return -EINVAL;
17050 }
Naveen Rawat72475db2017-12-13 18:07:35 -080017051 ret = dot11f_unpack_ie_wpa(
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017052 (tpAniSirGlobal) mac_handle,
Naveen Rawat72475db2017-12-13 18:07:35 -080017053 (uint8_t *)&ie[2 + 4],
17054 ie[1] - 4, &dot11WPAIE, false);
17055 if (DOT11F_FAILED(ret)) {
17056 hdd_err("unpack failed ret: 0x%x", ret);
17057 return -EINVAL;
17058 }
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053017059 /*
17060 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080017061 * encType for unicast cipher for
17062 * wpa-none is none
17063 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017064 encryptionType =
17065 hdd_translate_wpa_to_csr_encryption_type
17066 (dot11WPAIE.multicast_cipher);
17067 }
17068 }
17069
17070 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017071 wlan_hdd_cfg80211_set_ie(adapter, params->ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017072 params->ie_len);
17073
17074 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017075 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017076 return status;
17077 }
17078 }
17079
Jeff Johnson20227a92018-03-13 09:41:05 -070017080 roam_profile = hdd_roam_profile(adapter);
17081 roam_profile->AuthType.authType[0] =
Jeff Johnsond377dce2017-10-04 10:32:42 -070017082 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017083
17084 if (params->privacy) {
17085 /* Security enabled IBSS, At this time there is no information
Jeff Johnson60ed45a2018-05-06 15:28:49 -070017086 * available about the security parameters, so initialise the
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017087 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
17088 * The correct security parameters will be updated later in
17089 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
17090 * set inorder enable privacy bit in beacons
17091 */
17092
17093 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
17094 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017095 hdd_debug("encryptionType=%d", encryptionType);
Jeff Johnsond377dce2017-10-04 10:32:42 -070017096 sta_ctx->conn_info.ucEncryptionType = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070017097 roam_profile->EncryptionType.numEntries = 1;
17098 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017099 encryptionType;
17100 return status;
17101}
17102
17103/**
17104 * __wlan_hdd_cfg80211_join_ibss() - join ibss
17105 * @wiphy: Pointer to wiphy
17106 * @dev: Pointer to network device
17107 * @param: Pointer to IBSS join parameters
17108 *
17109 * This function is used to create/join an IBSS network
17110 *
17111 * Return: 0 for success, non-zero for failure
17112 */
17113static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
17114 struct net_device *dev,
17115 struct cfg80211_ibss_params *params)
17116{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017117 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070017118 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017119 int status;
Jeff Johnsond377dce2017-10-04 10:32:42 -070017120 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017121 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17122 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053017123 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017124 u8 channelNum = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017125 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017126
Dustin Brown491d54b2018-03-14 12:39:11 -070017127 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017128
Anurag Chouhan6d760662016-02-20 16:05:43 +053017129 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017130 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017131 return -EINVAL;
17132 }
17133
Dustin Brown63500612018-08-07 11:36:09 -070017134 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017135 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017136
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017137 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017138 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
Jeff Johnson1b780e42017-10-31 14:11:45 -070017139 adapter->session_id, adapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017140 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017141 hdd_device_mode_to_string(adapter->device_mode),
17142 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017143
Jeff Johnsonb8944722017-09-03 09:03:19 -070017144 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017145
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053017146 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017147 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017148
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017149 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017150 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053017151 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017152 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
17153 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017154 int indx;
17155
17156 /* Get channel number */
17157 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017158 params->
17159 chandef.
17160 chan->
17161 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017162
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017163 if (0 != sme_cfg_get_str(mac_handle, WNI_CFG_VALID_CHANNEL_LIST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017164 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017165 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017166 return -EOPNOTSUPP;
17167 }
17168
17169 for (indx = 0; indx < numChans; indx++) {
Srinivas Girigowda576b2352017-08-25 14:44:26 -070017170 if (channelNum == validChan[indx])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017171 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017172 }
17173 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017174 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017175 return -EINVAL;
17176 }
17177 }
17178
Jeff Johnsonb8944722017-09-03 09:03:19 -070017179 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017180 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017181 hdd_err("This concurrency combination is not allowed");
17182 return -ECONNREFUSED;
17183 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017184
Jeff Johnsonb8944722017-09-03 09:03:19 -070017185 status = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070017186 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017187 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070017188
Jeff Johnsonb8944722017-09-03 09:03:19 -070017189 status = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
Jeff Johnson1b780e42017-10-31 14:11:45 -070017190 adapter->session_id, channelNum,
Tushnim Bhattacharyya3b99f4b2018-03-26 14:19:24 -070017191 POLICY_MGR_UPDATE_REASON_JOIN_IBSS);
Krunal Soni3091bcc2016-06-23 12:28:21 -070017192 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017193 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070017194 return -EINVAL;
17195 }
17196
17197 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017198 status = policy_mgr_wait_for_connection_update(
Jeff Johnsonb8944722017-09-03 09:03:19 -070017199 hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070017200 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017201 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017202 return -EINVAL;
17203 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017204 }
17205
17206 /*Try disconnecting if already in connected state */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017207 status = wlan_hdd_try_disconnect(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017208 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017209 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017210 return -EALREADY;
17211 }
17212
Jeff Johnson20227a92018-03-13 09:41:05 -070017213 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017214
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017215 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017216 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017217 return -EINVAL;
17218 }
17219
17220 /* enable selected protection checks in IBSS mode */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017221 roam_profile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017222
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017223 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(mac_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017224 WNI_CFG_IBSS_ATIM_WIN_SIZE,
Jeff Johnsonb8944722017-09-03 09:03:19 -070017225 hdd_ctx->config->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017226 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017227 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017228 }
17229
17230 /* BSSID is provided by upper layers hence no need to AUTO generate */
17231 if (NULL != params->bssid) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017232 if (sme_cfg_set_int(mac_handle, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017233 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017234 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017235 return -EIO;
17236 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053017237 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Jeff Johnsonb8944722017-09-03 09:03:19 -070017238 } else if (hdd_ctx->config->isCoalesingInIBSSAllowed == 0) {
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017239 if (sme_cfg_set_int(mac_handle, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017240 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017241 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017242 return -EIO;
17243 }
Jeff Johnsonb8944722017-09-03 09:03:19 -070017244 qdf_copy_macaddr(&bssid, &hdd_ctx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017245 }
17246 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
17247 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017248 roam_profile->beaconInterval = params->beacon_interval;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017249 else {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017250 roam_profile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017251 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017252 params->beacon_interval, roam_profile->beaconInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017253 }
17254
17255 /* Set Channel */
17256 if (channelNum) {
17257 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017258 hdd_debug("set channel %d", channelNum);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017259 roam_profile->ChannelInfo.numOfChannels = 1;
Jeff Johnsond377dce2017-10-04 10:32:42 -070017260 sta_ctx->conn_info.operationChannel = channelNum;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017261 roam_profile->ChannelInfo.ChannelList =
Jeff Johnsond377dce2017-10-04 10:32:42 -070017262 &sta_ctx->conn_info.operationChannel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017263 }
17264
17265 /* Initialize security parameters */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017266 status = wlan_hdd_cfg80211_set_privacy_ibss(adapter, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017267 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017268 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017269 return status;
17270 }
17271
17272 /* Issue connect start */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017273 status = wlan_hdd_cfg80211_connect_start(adapter, params->ssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017274 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017275 bssid.bytes, NULL,
Jeff Johnsond377dce2017-10-04 10:32:42 -070017276 sta_ctx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017277 operationChannel,
17278 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017279
17280 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017281 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017282 return status;
17283 }
Dustin Browne74003f2018-03-14 12:51:58 -070017284 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017285 return 0;
17286}
17287
17288/**
17289 * wlan_hdd_cfg80211_join_ibss() - join ibss
17290 * @wiphy: Pointer to wiphy
17291 * @dev: Pointer to network device
17292 * @param: Pointer to IBSS join parameters
17293 *
17294 * This function is used to create/join an IBSS network
17295 *
17296 * Return: 0 for success, non-zero for failure
17297 */
17298static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
17299 struct net_device *dev,
17300 struct cfg80211_ibss_params *params)
17301{
17302 int ret = 0;
17303
17304 cds_ssr_protect(__func__);
17305 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
17306 cds_ssr_unprotect(__func__);
17307
17308 return ret;
17309}
17310
17311/**
17312 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
17313 * @wiphy: Pointer to wiphy
17314 * @dev: Pointer to network device
17315 *
17316 * This function is used to leave an IBSS network
17317 *
17318 * Return: 0 for success, non-zero for failure
17319 */
17320static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
17321 struct net_device *dev)
17322{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017323 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070017324 struct csr_roam_profile *roam_profile;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017325 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017326 int status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017327 mac_handle_t mac_handle;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053017328 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080017329 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017330
Dustin Brown491d54b2018-03-14 12:39:11 -070017331 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017332
Anurag Chouhan6d760662016-02-20 16:05:43 +053017333 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017334 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017335 return -EINVAL;
17336 }
17337
Dustin Brown63500612018-08-07 11:36:09 -070017338 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017339 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017340
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017341 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017342 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
Jeff Johnson1b780e42017-10-31 14:11:45 -070017343 adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017344 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
Jeff Johnsonb8944722017-09-03 09:03:19 -070017345 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053017346 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017347 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017348
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017349 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017350 hdd_device_mode_to_string(adapter->device_mode),
17351 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017352
Jeff Johnson20227a92018-03-13 09:41:05 -070017353 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017354
17355 /* Issue disconnect only if interface type is set to IBSS */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017356 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017357 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017358 return -EINVAL;
17359 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080017360 /* Clearing add IE of beacon */
Jeff Johnson1e851a12017-10-28 14:36:12 -070017361 qdf_mem_copy(updateIE.bssid.bytes, adapter->mac_addr.bytes,
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080017362 sizeof(tSirMacAddr));
Jeff Johnson1b780e42017-10-31 14:11:45 -070017363 updateIE.smeSessionId = adapter->session_id;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080017364 updateIE.ieBufferlength = 0;
17365 updateIE.pAdditionIEBuffer = NULL;
17366 updateIE.append = true;
17367 updateIE.notify = true;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017368 mac_handle = hdd_ctx->mac_handle;
17369 if (sme_update_add_ie(mac_handle,
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080017370 &updateIE,
17371 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017372 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080017373 }
17374
17375 /* Reset WNI_CFG_PROBE_RSP Flags */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017376 wlan_hdd_reset_prob_rspies(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017377
17378 /* Issue Disconnect request */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017379 INIT_COMPLETION(adapter->disconnect_comp_var);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017380 status = sme_roam_disconnect(mac_handle,
17381 adapter->session_id,
17382 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
17383 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017384 hdd_err("sme_roam_disconnect failed status: %d",
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017385 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017386 return -EAGAIN;
17387 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053017388
17389 /* wait for mc thread to cleanup and then return to upper stack
17390 * so by the time upper layer calls the change interface, we are
17391 * all set to proceed further
17392 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017393 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053017394 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
17395 if (!rc) {
17396 hdd_err("Failed to disconnect, timed out");
17397 return -ETIMEDOUT;
17398 }
17399
Dustin Browne74003f2018-03-14 12:51:58 -070017400 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017401 return 0;
17402}
17403
17404/**
17405 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
17406 * @wiphy: Pointer to wiphy
17407 * @dev: Pointer to network device
17408 *
17409 * This function is used to leave an IBSS network
17410 *
17411 * Return: 0 for success, non-zero for failure
17412 */
17413static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
17414 struct net_device *dev)
17415{
17416 int ret = 0;
17417
17418 cds_ssr_protect(__func__);
17419 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
17420 cds_ssr_unprotect(__func__);
17421
17422 return ret;
17423}
17424
17425/**
17426 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
17427 * @wiphy: Pointer to wiphy
17428 * @changed: Parameters changed
17429 *
17430 * This function is used to set the phy parameters. RTS Threshold/FRAG
17431 * Threshold/Retry Count etc.
17432 *
17433 * Return: 0 for success, non-zero for failure
17434 */
17435static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
17436 u32 changed)
17437{
Jeff Johnsonb8944722017-09-03 09:03:19 -070017438 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017439 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017440 int status;
17441
Dustin Brown491d54b2018-03-14 12:39:11 -070017442 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017443
Anurag Chouhan6d760662016-02-20 16:05:43 +053017444 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017445 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017446 return -EINVAL;
17447 }
17448
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017449 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017450 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
17451 NO_SESSION, wiphy->rts_threshold));
Jeff Johnsonb8944722017-09-03 09:03:19 -070017452 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017453
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053017454 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017455 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017456
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017457 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017458 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
17459 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
17460 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
17461
17462 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
17463 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017464 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017465 rts_threshold);
17466 return -EINVAL;
17467 }
17468
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017469 if (0 != sme_cfg_set_int(mac_handle, WNI_CFG_RTS_THRESHOLD,
17470 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017471 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017472 rts_threshold);
17473 return -EIO;
17474 }
17475
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017476 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017477 }
17478
17479 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
17480 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
17481 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
17482 wiphy->frag_threshold;
17483
17484 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
17485 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017486 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017487 frag_threshold);
17488 return -EINVAL;
17489 }
17490
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017491 if (0 != sme_cfg_set_int(mac_handle,
17492 WNI_CFG_FRAGMENTATION_THRESHOLD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017493 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017494 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017495 frag_threshold);
17496 return -EIO;
17497 }
17498
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017499 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017500 }
17501
Dustin Browne74003f2018-03-14 12:51:58 -070017502 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017503 return 0;
17504}
17505
17506/**
17507 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
17508 * @wiphy: Pointer to wiphy
17509 * @changed: Parameters changed
17510 *
17511 * Return: 0 for success, non-zero for failure
17512 */
17513static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
17514{
17515 int ret;
17516
17517 cds_ssr_protect(__func__);
17518 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
17519 cds_ssr_unprotect(__func__);
17520
17521 return ret;
17522}
17523
17524/**
17525 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
17526 * key
17527 * @wiphy: Pointer to wiphy
17528 * @dev: Pointer to network device
17529 * @key_index: Key index
17530 *
17531 * Return: 0
17532 */
17533static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
17534 struct net_device *netdev,
17535 u8 key_index)
17536{
Dustin Brown491d54b2018-03-14 12:39:11 -070017537 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017538 return 0;
17539}
17540
17541/**
17542 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
17543 * wlan_hdd_set_default_mgmt_key
17544 * @wiphy: pointer to wiphy
17545 * @netdev: pointer to net_device structure
17546 * @key_index: key index
17547 *
17548 * Return: 0 on success, error number on failure
17549 */
17550static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
17551 struct net_device *netdev,
17552 u8 key_index)
17553{
17554 int ret;
17555
17556 cds_ssr_protect(__func__);
17557 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
17558 cds_ssr_unprotect(__func__);
17559
17560 return ret;
17561}
17562
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017563/**
17564 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
17565 * @wiphy: Pointer to wiphy
17566 * @dev: Pointer to network device
17567 * @params: Pointer to tx queue parameters
17568 *
17569 * Return: 0
17570 */
17571static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
17572 struct net_device *dev,
17573 struct ieee80211_txq_params *params)
17574{
Dustin Brown491d54b2018-03-14 12:39:11 -070017575 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017576 return 0;
17577}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017578
17579/**
17580 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
17581 * @wiphy: pointer to wiphy
17582 * @netdev: pointer to net_device structure
17583 * @params: pointer to ieee80211_txq_params
17584 *
17585 * Return: 0 on success, error number on failure
17586 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017587static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
17588 struct net_device *dev,
17589 struct ieee80211_txq_params *params)
17590{
17591 int ret;
17592
17593 cds_ssr_protect(__func__);
17594 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
17595 cds_ssr_unprotect(__func__);
17596
17597 return ret;
17598}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017599
17600/**
17601 * __wlan_hdd_cfg80211_del_station() - delete station v2
17602 * @wiphy: Pointer to wiphy
17603 * @param: Pointer to delete station parameter
17604 *
17605 * Return: 0 for success, non-zero for failure
17606 */
17607static
17608int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
17609 struct net_device *dev,
Jeff Johnsone6bf7192017-11-07 15:16:09 -080017610 struct csr_del_sta_params *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017611{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017612 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070017613 struct hdd_context *hdd_ctx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053017614 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070017615 struct hdd_hostapd_state *hapd_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017616 int status;
17617 uint8_t staId;
17618 uint8_t *mac;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017619 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017620
Dustin Brown491d54b2018-03-14 12:39:11 -070017621 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017622
Anurag Chouhan6d760662016-02-20 16:05:43 +053017623 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017624 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017625 return -EINVAL;
17626 }
17627
Dustin Brown63500612018-08-07 11:36:09 -070017628 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017629 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017630
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017631 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017632 TRACE_CODE_HDD_CFG80211_DEL_STA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070017633 adapter->session_id, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017634
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017635 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070017636 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017637
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053017638 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017639 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017640
17641 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017642 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017643
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017644 if ((QDF_SAP_MODE == adapter->device_mode) ||
17645 (QDF_P2P_GO_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017646
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017647 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017648 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017649 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017650 return 0;
17651 }
17652
Anurag Chouhanc5548422016-02-24 18:33:27 +053017653 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017654 uint16_t i;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070017655
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017656 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070017657 if ((adapter->sta_info[i].in_use) &&
17658 (!adapter->sta_info[i].
Jeff Johnsone4f5d932017-10-21 13:21:15 -070017659 is_deauth_in_progress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053017660 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017661 mac,
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070017662 adapter->sta_info[i].
Jeff Johnsonf2356512017-10-21 16:04:12 -070017663 sta_mac.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053017664 QDF_MAC_ADDR_SIZE);
Yun Parka4bb37c2017-12-08 16:14:22 -080017665
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017666 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017667 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017668 MAC_ADDR_ARRAY(mac));
17669
Jeff Johnsonb8944722017-09-03 09:03:19 -070017670 if (hdd_ctx->dev_dfs_cac_status ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017671 DFS_CAC_IN_PROGRESS)
17672 goto fn_end;
17673
Wei Song2f76f642016-11-18 16:32:53 +080017674 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017675 hdd_softap_sta_disassoc(adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053017676 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017677 qdf_status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017678 hdd_softap_sta_deauth(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017679 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017680 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070017681 adapter->sta_info[i].
Jeff Johnsone4f5d932017-10-21 13:21:15 -070017682 is_deauth_in_progress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053017683 qdf_status =
Nachiket Kukade0396b732017-11-14 16:35:16 +053017684 qdf_wait_for_event_completion(
Naveen Rawatb56880c2016-12-13 17:56:03 -080017685 &hapd_state->
17686 qdf_sta_disassoc_event,
17687 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053017688 if (!QDF_IS_STATUS_SUCCESS(
17689 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017690 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017691 }
17692 }
17693 }
17694 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017695 qdf_status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017696 hdd_softap_get_sta_id(adapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053017697 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017698 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017699 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017700 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017701 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017702 MAC_ADDR_ARRAY(mac));
17703 return -ENOENT;
17704 }
17705
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070017706 if (adapter->sta_info[staId].is_deauth_in_progress ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017707 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017708 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017709 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017710 MAC_ADDR_ARRAY(mac));
17711 return -ENOENT;
17712 }
17713
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070017714 adapter->sta_info[staId].is_deauth_in_progress = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017715
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017716 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017717 MAC_ADDR_ARRAY(mac));
17718
17719 /* Case: SAP in ACS selected DFS ch and client connected
17720 * Now Radar detected. Then if random channel is another
17721 * DFS ch then new CAC is initiated and no TX allowed.
17722 * So do not send any mgmt frames as it will timeout
17723 * during CAC.
17724 */
17725
Jeff Johnsonb8944722017-09-03 09:03:19 -070017726 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017727 goto fn_end;
17728
Wei Song2f76f642016-11-18 16:32:53 +080017729 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070017730 sme_send_disassoc_req_frame(mac_handle,
17731 adapter->session_id,
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053017732 (uint8_t *)&pDelStaParams->peerMacAddr,
17733 pDelStaParams->reason_code, 0);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017734 qdf_status = hdd_softap_sta_deauth(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017735 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017736 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070017737 adapter->sta_info[staId].is_deauth_in_progress =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017738 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017739 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017740 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017741 MAC_ADDR_ARRAY(mac));
17742 return -ENOENT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017743 }
Nachiket Kukade0396b732017-11-14 16:35:16 +053017744 qdf_status = qdf_wait_for_event_completion(
Srinivas Girigowda576b2352017-08-25 14:44:26 -070017745 &hapd_state->
17746 qdf_sta_disassoc_event,
17747 SME_CMD_TIMEOUT_VALUE);
17748 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
17749 hdd_warn("Deauth wait time expired");
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +053017750
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017751 }
17752 }
17753
17754fn_end:
Dustin Browne74003f2018-03-14 12:51:58 -070017755 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017756 return 0;
17757}
17758
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080017759#if defined(USE_CFG80211_DEL_STA_V2)
17760/**
17761 * wlan_hdd_del_station() - delete station wrapper
17762 * @adapter: pointer to the hdd adapter
17763 *
17764 * Return: None
17765 */
Jeff Johnsone5006672017-08-29 14:39:02 -070017766void wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080017767{
17768 struct station_del_parameters del_sta;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070017769
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080017770 del_sta.mac = NULL;
17771 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
17772 del_sta.reason_code = eCsrForcedDeauthSta;
17773
17774 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
17775 &del_sta);
17776}
17777#else
Jeff Johnsone5006672017-08-29 14:39:02 -070017778void wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080017779{
17780 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
17781}
17782#endif
17783
17784#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017785/**
17786 * wlan_hdd_cfg80211_del_station() - delete station v2
17787 * @wiphy: Pointer to wiphy
17788 * @param: Pointer to delete station parameter
17789 *
17790 * Return: 0 for success, non-zero for failure
17791 */
17792int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
17793 struct net_device *dev,
17794 struct station_del_parameters *param)
17795#else
17796/**
17797 * wlan_hdd_cfg80211_del_station() - delete station
17798 * @wiphy: Pointer to wiphy
17799 * @mac: Pointer to station mac address
17800 *
17801 * Return: 0 for success, non-zero for failure
17802 */
17803#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
17804int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
17805 struct net_device *dev,
17806 const uint8_t *mac)
17807#else
17808int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
17809 struct net_device *dev,
17810 uint8_t *mac)
17811#endif
17812#endif
17813{
17814 int ret;
Jeff Johnsone6bf7192017-11-07 15:16:09 -080017815 struct csr_del_sta_params delStaParams;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017816
17817 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080017818#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017819 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080017820 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017821 return -EINVAL;
17822 }
17823 wlansap_populate_del_sta_params(param->mac, param->reason_code,
17824 param->subtype, &delStaParams);
17825#else
17826 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
17827 (SIR_MAC_MGMT_DEAUTH >> 4),
17828 &delStaParams);
17829#endif
17830 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
17831 cds_ssr_unprotect(__func__);
17832
17833 return ret;
17834}
17835
17836/**
17837 * __wlan_hdd_cfg80211_add_station() - add station
17838 * @wiphy: Pointer to wiphy
17839 * @mac: Pointer to station mac address
17840 * @pmksa: Pointer to add station parameter
17841 *
17842 * Return: 0 for success, non-zero for failure
17843 */
17844static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
17845 struct net_device *dev,
17846 const uint8_t *mac,
17847 struct station_parameters *params)
17848{
17849 int status = -EPERM;
17850#ifdef FEATURE_WLAN_TDLS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017851 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070017852 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017853 u32 mask, set;
17854
Dustin Brown491d54b2018-03-14 12:39:11 -070017855 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017856
Anurag Chouhan6d760662016-02-20 16:05:43 +053017857 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017858 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017859 return -EINVAL;
17860 }
17861
Dustin Brown63500612018-08-07 11:36:09 -070017862 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017863 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017864
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017865 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017866 TRACE_CODE_HDD_CFG80211_ADD_STA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070017867 adapter->session_id, params->listen_interval));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017868
Jeff Johnsonb8944722017-09-03 09:03:19 -070017869 if (0 != wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017870 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017871
17872 mask = params->sta_flags_mask;
17873
17874 set = params->sta_flags_set;
17875
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017876 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017877 MAC_ADDR_ARRAY(mac));
17878
17879 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud1a28462017-09-06 22:55:48 +080017880 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
Dustin Brown07901ec2018-09-07 11:02:41 -070017881 status = wlan_cfg80211_tdls_add_peer(hdd_ctx->pdev,
Frank Liud4b2fa02017-03-29 11:46:48 +080017882 dev, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017883 }
17884#endif
Dustin Browne74003f2018-03-14 12:51:58 -070017885 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017886 return status;
17887}
17888
17889/**
17890 * wlan_hdd_cfg80211_add_station() - add station
17891 * @wiphy: Pointer to wiphy
17892 * @mac: Pointer to station mac address
17893 * @pmksa: Pointer to add station parameter
17894 *
17895 * Return: 0 for success, non-zero for failure
17896 */
17897#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
17898static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
17899 struct net_device *dev,
17900 const uint8_t *mac,
17901 struct station_parameters *params)
17902#else
17903static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
17904 struct net_device *dev, uint8_t *mac,
17905 struct station_parameters *params)
17906#endif
17907{
17908 int ret;
17909
17910 cds_ssr_protect(__func__);
17911 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
17912 cds_ssr_unprotect(__func__);
17913
17914 return ret;
17915}
17916
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053017917#if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
17918 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053017919/*
17920 * wlan_hdd_is_pmksa_valid: API to validate pmksa
17921 * @pmksa: pointer to cfg80211_pmksa structure
17922 *
17923 * Return: True if valid else false
17924 */
17925static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
17926{
17927 if (!pmksa->bssid) {
Vignesh Viswanathanfa90d622017-12-22 13:13:26 +053017928 hdd_warn("bssid (%pK) is NULL",
17929 pmksa->bssid);
17930 if (!pmksa->ssid || !pmksa->cache_id) {
17931 hdd_err("either ssid (%pK) or cache_id (%pK) are NULL",
17932 pmksa->ssid, pmksa->cache_id);
17933 return false;
17934 }
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053017935 }
17936 return true;
17937}
17938
17939/*
17940 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
gaurank kathpalia99d06c12018-05-16 16:28:35 +053017941 * @adapter: Pointer to hdd adapter
17942 * @pmk_cache: pmk that needs to be udated
17943 * @pmksa: pmk from supplicant
17944 * @is_delete: Bool to decide set or delete PMK
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053017945 * Return: None
17946 */
gaurank kathpalia99d06c12018-05-16 16:28:35 +053017947static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
17948 tPmkidCacheInfo *pmk_cache,
17949 struct cfg80211_pmksa *pmksa, bool is_delete)
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053017950{
17951 if (pmksa->bssid) {
17952 hdd_debug("%s PMKSA for " MAC_ADDRESS_STR,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053017953 is_delete ? "Delete" : "Set",
17954 MAC_ADDR_ARRAY(pmksa->bssid));
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053017955 qdf_mem_copy(pmk_cache->BSSID.bytes,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053017956 pmksa->bssid, QDF_MAC_ADDR_SIZE);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053017957 } else {
Jeff Johnson9c749db2018-05-07 12:50:46 -070017958 qdf_mem_copy(pmk_cache->ssid, pmksa->ssid, pmksa->ssid_len);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053017959 qdf_mem_copy(pmk_cache->cache_id, pmksa->cache_id,
17960 CACHE_ID_LEN);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053017961 pmk_cache->ssid_len = pmksa->ssid_len;
17962 hdd_debug("%s PMKSA for ssid %*.*s cache_id %x %x",
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053017963 is_delete ? "Delete" : "Set",
17964 pmk_cache->ssid_len, pmk_cache->ssid_len,
17965 pmk_cache->ssid, pmk_cache->cache_id[0],
17966 pmk_cache->cache_id[1]);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053017967 }
17968
17969 if (is_delete)
17970 return;
17971
17972 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
17973 if (pmksa->pmk_len && (pmksa->pmk_len <= CSR_RSN_MAX_PMK_LEN)) {
17974 qdf_mem_copy(pmk_cache->pmk, pmksa->pmk, pmksa->pmk_len);
17975 pmk_cache->pmk_len = pmksa->pmk_len;
17976 } else
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053017977 hdd_debug("pmk len is %zu", pmksa->pmk_len);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053017978}
17979#else
17980/*
17981 * wlan_hdd_is_pmksa_valid: API to validate pmksa
17982 * @pmksa: pointer to cfg80211_pmksa structure
17983 *
17984 * Return: True if valid else false
17985 */
17986static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
17987{
17988 if (!pmksa->bssid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070017989 hdd_err("both bssid is NULL %pK", pmksa->bssid);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053017990 return false;
17991 }
17992 return true;
17993}
17994
17995/*
17996 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
gaurank kathpalia99d06c12018-05-16 16:28:35 +053017997 * @adapter: Pointer to hdd adapter
17998 * @pmk_cache: pmk which needs to be updated
17999 * @pmksa: pmk from supplicant
18000 * @is_delete: Bool to decide whether to set or delete PMK
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018001 *
18002 * Return: None
18003 */
gaurank kathpalia99d06c12018-05-16 16:28:35 +053018004static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
18005 tPmkidCacheInfo *pmk_cache,
18006 struct cfg80211_pmksa *pmksa, bool is_delete)
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018007{
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018008 mac_handle_t mac_handle;
Srinivas Girigowda50335342018-09-07 15:21:01 -070018009
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018010 hdd_debug("%s PMKSA for " MAC_ADDRESS_STR, is_delete ? "Delete" : "Set",
18011 MAC_ADDR_ARRAY(pmksa->bssid));
18012 qdf_mem_copy(pmk_cache->BSSID.bytes,
18013 pmksa->bssid, QDF_MAC_ADDR_SIZE);
18014
18015 if (is_delete)
18016 return;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018017 mac_handle = hdd_adapter_get_mac_handle(adapter);
18018 sme_get_pmk_info(mac_handle, adapter->session_id, pmk_cache);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018019 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
18020}
18021#endif
18022
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018023/**
18024 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
18025 * @wiphy: Pointer to wiphy
18026 * @dev: Pointer to network device
18027 * @pmksa: Pointer to set pmksa parameter
18028 *
18029 * Return: 0 for success, non-zero for failure
18030 */
18031static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
18032 struct net_device *dev,
18033 struct cfg80211_pmksa *pmksa)
18034{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018035 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
18036 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018037 mac_handle_t mac_handle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053018038 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018039 int status;
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018040 tPmkidCacheInfo pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018041
Dustin Brown491d54b2018-03-14 12:39:11 -070018042 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018043
Anurag Chouhan6d760662016-02-20 16:05:43 +053018044 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018045 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018046 return -EINVAL;
18047 }
18048
Dustin Brown63500612018-08-07 11:36:09 -070018049 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018050 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018051
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018052 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018053 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018054 return -EINVAL;
18055 }
18056
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018057 if (!pmksa->pmkid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070018058 hdd_err("pmksa->pmkid(%pK) is NULL",
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018059 pmksa->pmkid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018060 return -EINVAL;
18061 }
18062
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018063 if (!wlan_hdd_is_pmksa_valid(pmksa))
18064 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018065
Jeff Johnsonb8944722017-09-03 09:03:19 -070018066 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018067
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018068 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018069 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018070
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018071 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018072
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018073 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018074
gaurank kathpalia99d06c12018-05-16 16:28:35 +053018075 hdd_fill_pmksa_info(adapter, &pmk_cache, pmksa, false);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018076
18077 /*
18078 * Add to the PMKSA Cache in CSR
18079 * PMKSA cache will be having following
18080 * 1. pmkid id
18081 * 2. pmk
18082 * 3. bssid or cache identifier
18083 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018084 result = sme_roam_set_pmkid_cache(mac_handle, adapter->session_id,
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018085 &pmk_cache, 1, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018086
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018087 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018088 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070018089 adapter->session_id, result));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018090
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018091 sme_set_del_pmkid_cache(mac_handle, adapter->session_id,
18092 &pmk_cache, true);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018093
Dustin Browne74003f2018-03-14 12:51:58 -070018094 hdd_exit();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053018095 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018096}
18097
18098/**
18099 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
18100 * @wiphy: Pointer to wiphy
18101 * @dev: Pointer to network device
18102 * @pmksa: Pointer to set pmksa parameter
18103 *
18104 * Return: 0 for success, non-zero for failure
18105 */
18106static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
18107 struct net_device *dev,
18108 struct cfg80211_pmksa *pmksa)
18109{
18110 int ret;
18111
18112 cds_ssr_protect(__func__);
18113 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
18114 cds_ssr_unprotect(__func__);
18115
18116 return ret;
18117}
18118
18119/**
18120 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
18121 * @wiphy: Pointer to wiphy
18122 * @dev: Pointer to network device
18123 * @pmksa: Pointer to pmksa parameter
18124 *
18125 * Return: 0 for success, non-zero for failure
18126 */
18127static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
18128 struct net_device *dev,
18129 struct cfg80211_pmksa *pmksa)
18130{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018131 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
18132 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018133 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018134 int status = 0;
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018135 tPmkidCacheInfo pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018136
Dustin Brown491d54b2018-03-14 12:39:11 -070018137 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018138
Anurag Chouhan6d760662016-02-20 16:05:43 +053018139 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018140 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018141 return -EINVAL;
18142 }
18143
Dustin Brown63500612018-08-07 11:36:09 -070018144 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018145 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018146
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018147 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018148 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018149 return -EINVAL;
18150 }
18151
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018152 if (!wlan_hdd_is_pmksa_valid(pmksa))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018153 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018154
Jeff Johnsonb8944722017-09-03 09:03:19 -070018155 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018156
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018157 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018158 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018159
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018160 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018161
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018162 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053018163 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070018164 adapter->session_id, 0));
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018165
18166 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
18167
gaurank kathpalia99d06c12018-05-16 16:28:35 +053018168 hdd_fill_pmksa_info(adapter, &pmk_cache, pmksa, true);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053018169
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018170 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053018171 if (QDF_STATUS_SUCCESS !=
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018172 sme_roam_del_pmkid_from_cache(mac_handle,
Jeff Johnson1b780e42017-10-31 14:11:45 -070018173 adapter->session_id, &pmk_cache,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018174 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018175 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018176 MAC_ADDR_ARRAY(pmksa->bssid));
18177 status = -EINVAL;
18178 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018179
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018180 sme_set_del_pmkid_cache(mac_handle, adapter->session_id, &pmk_cache,
18181 false);
Dustin Browne74003f2018-03-14 12:51:58 -070018182 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018183 return status;
18184}
18185
18186/**
18187 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
18188 * @wiphy: Pointer to wiphy
18189 * @dev: Pointer to network device
18190 * @pmksa: Pointer to pmksa parameter
18191 *
18192 * Return: 0 for success, non-zero for failure
18193 */
18194static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
18195 struct net_device *dev,
18196 struct cfg80211_pmksa *pmksa)
18197{
18198 int ret;
18199
18200 cds_ssr_protect(__func__);
18201 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
18202 cds_ssr_unprotect(__func__);
18203
18204 return ret;
18205
18206}
18207
18208/**
18209 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
18210 * @wiphy: Pointer to wiphy
18211 * @dev: Pointer to network device
18212 *
18213 * Return: 0 for success, non-zero for failure
18214 */
18215static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
18216 struct net_device *dev)
18217{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018218 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
18219 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018220 mac_handle_t mac_handle;
18221 int errno;
18222 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018223
Dustin Brown491d54b2018-03-14 12:39:11 -070018224 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018225
Anurag Chouhan6d760662016-02-20 16:05:43 +053018226 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018227 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018228 return -EINVAL;
18229 }
18230
Dustin Brown63500612018-08-07 11:36:09 -070018231 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018232 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018233
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018234 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018235
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018236 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018237 errno = wlan_hdd_validate_context(hdd_ctx);
18238 if (errno)
18239 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018240
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018241 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018242
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018243 status = sme_roam_del_pmkid_from_cache(mac_handle,
18244 adapter->session_id,
18245 NULL, true);
18246 if (QDF_IS_STATUS_ERROR(status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018247 hdd_err("Cannot flush PMKIDCache");
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018248 errno = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018249 }
Vignesh Viswanathane8a26b22017-10-11 20:38:47 +053018250
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018251 sme_set_del_pmkid_cache(mac_handle, adapter->session_id, NULL, false);
Dustin Browne74003f2018-03-14 12:51:58 -070018252 hdd_exit();
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018253 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018254}
18255
18256/**
18257 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
18258 * @wiphy: Pointer to wiphy
18259 * @dev: Pointer to network device
18260 *
18261 * Return: 0 for success, non-zero for failure
18262 */
18263static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
18264 struct net_device *dev)
18265{
18266 int ret;
18267
18268 cds_ssr_protect(__func__);
18269 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
18270 cds_ssr_unprotect(__func__);
18271
18272 return ret;
18273}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018274
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080018275#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018276/**
18277 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
18278 * @wiphy: Pointer to wiphy
18279 * @dev: Pointer to network device
18280 * @ftie: Pointer to fast transition ie parameter
18281 *
18282 * Return: 0 for success, non-zero for failure
18283 */
18284static int
18285__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
18286 struct net_device *dev,
18287 struct cfg80211_update_ft_ies_params *ftie)
18288{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070018289 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018290 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsond377dce2017-10-04 10:32:42 -070018291 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018292 int status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018293 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018294
Dustin Brown491d54b2018-03-14 12:39:11 -070018295 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018296
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018297 status = wlan_hdd_validate_context(hdd_ctx);
18298 if (status)
18299 return status;
18300
Anurag Chouhan6d760662016-02-20 16:05:43 +053018301 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018302 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018303 return -EINVAL;
18304 }
18305
Dustin Brown63500612018-08-07 11:36:09 -070018306 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018307 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018308
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018309 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018310 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
Jeff Johnson1b780e42017-10-31 14:11:45 -070018311 adapter->session_id, sta_ctx->conn_info.connState));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018312 /* Added for debug on reception of Re-assoc Req. */
Jeff Johnsond377dce2017-10-04 10:32:42 -070018313 if (eConnectionState_Associated != sta_ctx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018314 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018315 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018316 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018317 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018318 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018319 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018320
18321 /* Pass the received FT IEs to SME */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070018322 mac_handle = hdd_ctx->mac_handle;
18323 sme_set_ft_ies(mac_handle, adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018324 (const u8 *)ftie->ie, ftie->ie_len);
Dustin Browne74003f2018-03-14 12:51:58 -070018325 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018326 return 0;
18327}
18328
18329/**
18330 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
18331 * @wiphy: Pointer to wiphy
18332 * @dev: Pointer to network device
18333 * @ftie: Pointer to fast transition ie parameter
18334 *
18335 * Return: 0 for success, non-zero for failure
18336 */
18337static int
18338wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
18339 struct net_device *dev,
18340 struct cfg80211_update_ft_ies_params *ftie)
18341{
18342 int ret;
18343
18344 cds_ssr_protect(__func__);
18345 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
18346 cds_ssr_unprotect(__func__);
18347
18348 return ret;
18349}
18350#endif
18351
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +053018352void wlan_hdd_cfg80211_update_replay_counter_cb(
Mukul Sharma3d36c392017-01-18 18:39:12 +053018353 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
18354
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018355{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018356 struct hdd_adapter *adapter = (struct hdd_adapter *)cb_ctx;
Mukul Sharma3d36c392017-01-18 18:39:12 +053018357 uint8_t temp_replay_counter[8];
18358 int i;
18359 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018360
Dustin Brown491d54b2018-03-14 12:39:11 -070018361 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018362
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018363 if (!adapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018364 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053018365 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018366 }
18367
Mukul Sharma3d36c392017-01-18 18:39:12 +053018368 if (!gtk_rsp_param) {
18369 hdd_err("gtk_rsp_param is Null");
18370 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018371 }
18372
Mukul Sharma3d36c392017-01-18 18:39:12 +053018373 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018374 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053018375 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018376 }
18377
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018378 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053018379 gtk_rsp_param->replay_counter);
18380 /* convert little to big endian since supplicant works on big endian */
18381 p = (uint8_t *)&gtk_rsp_param->replay_counter;
18382 for (i = 0; i < 8; i++)
18383 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018384
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018385 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018386 /* Update replay counter to NL */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018387 cfg80211_gtk_rekey_notify(adapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053018388 gtk_rsp_param->bssid.bytes,
18389 temp_replay_counter, GFP_KERNEL);
18390out:
Dustin Browne74003f2018-03-14 12:51:58 -070018391 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053018392
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018393}
18394
Wu Gaoa9d336b2018-05-30 14:48:04 +080018395#ifdef WLAN_FEATURE_GTK_OFFLOAD
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018396/**
18397 * wlan_hdd_copy_gtk_kek - Copy the KEK from GTK rekey data to GTK request
18398 * @gtk_req: Pointer to GTK request
18399 * @data: Pointer to rekey data
18400 *
18401 * Return: none
18402 */
18403#ifdef CFG80211_REKEY_DATA_KEK_LEN
18404static
18405void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
18406 struct cfg80211_gtk_rekey_data *data)
18407{
18408 qdf_mem_copy(gtk_req->kek, data->kek, data->kek_len);
18409 gtk_req->kek_len = data->kek_len;
18410}
18411#else
18412static
18413void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
18414 struct cfg80211_gtk_rekey_data *data)
18415{
18416 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
18417 gtk_req->kek_len = NL80211_KEK_LEN;
18418}
18419#endif
18420
18421/**
18422 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
18423 * @wiphy: Pointer to wiphy
18424 * @dev: Pointer to network device
18425 * @data: Pointer to rekey data
18426 *
18427 * This function is used to offload GTK rekeying job to the firmware.
18428 *
18429 * Return: 0 for success, non-zero for failure
18430 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070018431static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018432int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053018433 struct net_device *dev,
18434 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018435{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018436 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053018437 int result, i;
18438 struct pmo_gtk_req *gtk_req = NULL;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018439 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharma3d36c392017-01-18 18:39:12 +053018440 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053018441 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018442
Dustin Brown491d54b2018-03-14 12:39:11 -070018443 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018444
Anurag Chouhan6d760662016-02-20 16:05:43 +053018445 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018446 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053018447 result = -EINVAL;
18448 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018449 }
18450
Jeff Johnson1b780e42017-10-31 14:11:45 -070018451 if (wlan_hdd_validate_session_id(adapter->session_id)) {
Mukul Sharma3d36c392017-01-18 18:39:12 +053018452 result = -EINVAL;
18453 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018454 }
18455
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018456 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018457 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070018458 adapter->session_id, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018459
Mukul Sharma3d36c392017-01-18 18:39:12 +053018460 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018461 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053018462 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018463
Mukul Sharma3d36c392017-01-18 18:39:12 +053018464 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
18465 if (!gtk_req) {
18466 hdd_err("cannot allocate gtk_req");
18467 result = -ENOMEM;
18468 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018469 }
18470
Mukul Sharma3d36c392017-01-18 18:39:12 +053018471 /* convert big to little endian since driver work on little endian */
18472 buf = (uint8_t *)&gtk_req->replay_counter;
18473 for (i = 0; i < 8; i++)
18474 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018475
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018476 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053018477 gtk_req->replay_counter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018478
18479 wlan_hdd_copy_gtk_kek(gtk_req, data);
Mukul Sharma3d36c392017-01-18 18:39:12 +053018480 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
gaurank kathpalia82a1b2b2018-07-10 16:49:10 +053018481 gtk_req->is_fils_connection = hdd_is_fils_connection(adapter);
Dustin Brown89fa06e2018-09-07 10:47:27 -070018482 status = pmo_ucfg_cache_gtk_offload_req(adapter->vdev, gtk_req);
Mukul Sharma3d36c392017-01-18 18:39:12 +053018483 if (status != QDF_STATUS_SUCCESS) {
18484 hdd_err("Failed to cache GTK Offload");
18485 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018486 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053018487out:
18488 if (gtk_req)
18489 qdf_mem_free(gtk_req);
Dustin Browne74003f2018-03-14 12:51:58 -070018490 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053018491
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018492 return result;
18493}
18494
18495/**
18496 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
18497 * @wiphy: Pointer to wiphy
18498 * @dev: Pointer to network device
18499 * @data: Pointer to rekey data
18500 *
18501 * This function is used to offload GTK rekeying job to the firmware.
18502 *
18503 * Return: 0 for success, non-zero for failure
18504 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070018505static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018506int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
18507 struct net_device *dev,
18508 struct cfg80211_gtk_rekey_data *data)
18509{
18510 int ret;
18511
18512 cds_ssr_protect(__func__);
18513 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
18514 cds_ssr_unprotect(__func__);
18515
18516 return ret;
18517}
Wu Gaoa9d336b2018-05-30 14:48:04 +080018518#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018519
18520/**
18521 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
18522 * @wiphy: Pointer to wiphy
18523 * @dev: Pointer to network device
18524 * @param: Pointer to access control parameter
18525 *
18526 * Return: 0 for success, non-zero for failure
18527 */
18528static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
18529 struct net_device *dev,
18530 const struct cfg80211_acl_data *params)
18531{
18532 int i;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018533 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson5c19ade2017-10-04 09:52:12 -070018534 struct hdd_hostapd_state *hostapd_state;
Jeff Johnsone4c11db2018-05-05 23:22:32 -070018535 tsap_config_t *pConfig;
Jeff Johnsonb8944722017-09-03 09:03:19 -070018536 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018537 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053018538 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018539
Dustin Brown491d54b2018-03-14 12:39:11 -070018540 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018541
Anurag Chouhan6d760662016-02-20 16:05:43 +053018542 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018543 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018544 return -EINVAL;
18545 }
18546
18547 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018548 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018549 return -EINVAL;
18550 }
18551
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018552 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070018553 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018554
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018555 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018556 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018557
Jeff Johnson5c19ade2017-10-04 09:52:12 -070018558 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018559
Jeff Johnson5c19ade2017-10-04 09:52:12 -070018560 if (NULL == hostapd_state) {
18561 hdd_err("hostapd_state is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018562 return -EINVAL;
18563 }
18564
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018565 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018566 params->n_acl_entries);
18567
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018568 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053018569 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
Jeff Johnson1b780e42017-10-31 14:11:45 -070018570 adapter->session_id, adapter->device_mode));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018571 if (QDF_SAP_MODE == adapter->device_mode) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070018572 pConfig = &adapter->session.ap.sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018573
18574 /* default value */
18575 pConfig->num_accept_mac = 0;
18576 pConfig->num_deny_mac = 0;
18577
18578 /**
18579 * access control policy
18580 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
18581 * listed in hostapd.deny file.
18582 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
18583 * listed in hostapd.accept file.
18584 */
18585 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
18586 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
18587 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
18588 params->acl_policy) {
18589 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
18590 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018591 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018592 params->acl_policy);
18593 return -ENOTSUPP;
18594 }
18595
18596 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
18597 pConfig->num_accept_mac = params->n_acl_entries;
18598 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018599 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018600 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018601 MAC_ADDR_ARRAY(
18602 params->mac_addrs[i].addr));
18603
Anurag Chouhan600c3a02016-03-01 10:33:54 +053018604 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018605 params->mac_addrs[i].addr,
18606 sizeof(qcmacaddr));
18607 }
18608 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
18609 pConfig->num_deny_mac = params->n_acl_entries;
18610 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018611 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018612 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018613 MAC_ADDR_ARRAY(
18614 params->mac_addrs[i].addr));
18615
Anurag Chouhan600c3a02016-03-01 10:33:54 +053018616 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018617 params->mac_addrs[i].addr,
18618 sizeof(qcmacaddr));
18619 }
18620 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070018621 qdf_status = wlansap_set_mac_acl(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018622 WLAN_HDD_GET_SAP_CTX_PTR(adapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053018623 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018624 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018625 return -EINVAL;
18626 }
18627 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018628 hdd_debug("Invalid device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018629 hdd_device_mode_to_string(adapter->device_mode),
18630 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018631 return -EINVAL;
18632 }
Dustin Browne74003f2018-03-14 12:51:58 -070018633 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018634 return 0;
18635}
18636
18637/**
18638 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
18639 * __wlan_hdd_cfg80211_set_mac_acl
18640 * @wiphy: pointer to wiphy structure
18641 * @dev: pointer to net_device
18642 * @params: pointer to cfg80211_acl_data
18643 *
18644 * Return; 0 on success, error number otherwise
18645 */
18646static int
18647wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
18648 struct net_device *dev,
18649 const struct cfg80211_acl_data *params)
18650{
18651 int ret;
18652
18653 cds_ssr_protect(__func__);
18654 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
18655 cds_ssr_unprotect(__func__);
18656
18657 return ret;
18658}
18659
18660#ifdef WLAN_NL80211_TESTMODE
18661#ifdef FEATURE_WLAN_LPHB
18662/**
18663 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
Jeff Johnsonb8944722017-09-03 09:03:19 -070018664 * @hdd_ctx: Pointer to hdd context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018665 * @lphbInd: Pointer to low power heart beat indication parameter
18666 *
18667 * Return: none
18668 */
Jeff Johnsonb8944722017-09-03 09:03:19 -070018669static void wlan_hdd_cfg80211_lphb_ind_handler(void *hdd_ctx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053018670 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018671{
18672 struct sk_buff *skb;
18673
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018674 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018675
Jeff Johnsonb8944722017-09-03 09:03:19 -070018676 if (0 != wlan_hdd_validate_context((struct hdd_context *) hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018677 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018678
Mukul Sharmafcd57f52017-03-20 18:18:59 +053018679 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018680 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018681 return;
18682 }
18683
Jeff Johnsonb8944722017-09-03 09:03:19 -070018684 skb = cfg80211_testmode_alloc_event_skb(((struct hdd_context *) hdd_ctx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053018685 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018686 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018687 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018688 return;
18689 }
18690
18691 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018692 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018693 goto nla_put_failure;
18694 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053018695 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018696 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018697 goto nla_put_failure;
18698 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053018699 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
18700 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018701 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018702 goto nla_put_failure;
18703 }
18704 cfg80211_testmode_event(skb, GFP_ATOMIC);
18705 return;
18706
18707nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018708 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018709 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018710}
18711#endif /* FEATURE_WLAN_LPHB */
18712
18713/**
18714 * __wlan_hdd_cfg80211_testmode() - test mode
18715 * @wiphy: Pointer to wiphy
18716 * @data: Data pointer
18717 * @len: Data length
18718 *
18719 * Return: 0 for success, non-zero for failure
18720 */
18721static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
18722 void *data, int len)
18723{
18724 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
18725 int err;
Jeff Johnsonb8944722017-09-03 09:03:19 -070018726 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018727
Dustin Brown491d54b2018-03-14 12:39:11 -070018728 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053018729
Jeff Johnsonb8944722017-09-03 09:03:19 -070018730 err = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018731 if (err)
18732 return err;
18733
Ryan Hsu4df41382018-06-15 15:45:22 -070018734 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
18735 hdd_err("Driver Modules are closed");
18736 return -EINVAL;
18737 }
18738
Dustin Brown4ea21db2018-01-05 14:13:17 -080018739 err = wlan_cfg80211_nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
18740 len, wlan_hdd_tm_policy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018741 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018742 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018743 return err;
18744 }
18745
18746 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018747 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018748 return -EINVAL;
18749 }
18750
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018751 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053018752 TRACE_CODE_HDD_CFG80211_TESTMODE,
18753 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018754 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
18755#ifdef FEATURE_WLAN_LPHB
18756 /* Low Power Heartbeat configuration request */
18757 case WLAN_HDD_TM_CMD_WLAN_HB:
18758 {
18759 int buf_len;
18760 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053018761 struct pmo_lphb_req *hb_params = NULL;
18762 struct pmo_lphb_req *hb_params_temp = NULL;
18763 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018764
18765 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018766 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018767 return -EINVAL;
18768 }
18769
18770 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
18771 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
18772
Mukul Sharmafcd57f52017-03-20 18:18:59 +053018773 hb_params_temp = (struct pmo_lphb_req *) buf;
18774 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
18775 && (hb_params_temp->params.lphb_tcp_params.
18776 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018777 return -EINVAL;
18778
Manjeet Singh00b2a562017-01-03 12:08:10 +053018779 if (buf_len > sizeof(*hb_params)) {
18780 hdd_err("buf_len=%d exceeded hb_params size limit",
18781 buf_len);
18782 return -ERANGE;
18783 }
18784
Mukul Sharmafcd57f52017-03-20 18:18:59 +053018785 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
18786 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018787 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018788 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018789 return -ENOMEM;
18790 }
18791
Ashish Kumar Dhanotiya0fa8ee02017-07-13 14:04:31 +053018792 qdf_mem_zero(hb_params, sizeof(*hb_params));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053018793 qdf_mem_copy(hb_params, buf, buf_len);
Jeff Johnsonb8944722017-09-03 09:03:19 -070018794 status = pmo_ucfg_lphb_config_req(hdd_ctx->hdd_psoc,
18795 hb_params, (void *)hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018796 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053018797 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018798 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053018799
18800 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018801 return 0;
18802 }
18803#endif /* FEATURE_WLAN_LPHB */
18804
18805#if defined(QCA_WIFI_FTM)
18806 case WLAN_HDD_TM_CMD_WLAN_FTM:
18807 {
Ryan Hsu4df41382018-06-15 15:45:22 -070018808 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam()) {
18809 hdd_err("Command not allowed in FTM mode, mode %d",
18810 hdd_get_conparam());
18811 return -EINVAL;
18812 }
18813
Dustin Brown07901ec2018-09-07 11:02:41 -070018814 err = wlan_cfg80211_ftm_testmode_cmd(hdd_ctx->pdev,
Ryan Hsuc8b27a42018-01-02 13:57:56 -080018815 data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018816 break;
18817 }
18818#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018819 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018820 hdd_err("command: %d not supported",
Ryan Hsuc8b27a42018-01-02 13:57:56 -080018821 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018822 return -EOPNOTSUPP;
18823 }
Ryan Hsuc8b27a42018-01-02 13:57:56 -080018824
Dustin Browne74003f2018-03-14 12:51:58 -070018825 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018826 return err;
18827}
18828
18829/**
18830 * wlan_hdd_cfg80211_testmode() - test mode
18831 * @wiphy: Pointer to wiphy
18832 * @dev: Pointer to network device
18833 * @data: Data pointer
18834 * @len: Data length
18835 *
18836 * Return: 0 for success, non-zero for failure
18837 */
18838static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
18839#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
18840 struct wireless_dev *wdev,
18841#endif
18842 void *data, int len)
18843{
18844 int ret;
18845
18846 cds_ssr_protect(__func__);
18847 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
18848 cds_ssr_unprotect(__func__);
18849
18850 return ret;
18851}
18852
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018853#endif /* CONFIG_NL80211_TESTMODE */
18854
18855#ifdef QCA_HT_2040_COEX
18856/**
18857 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
18858 * @wiphy: Pointer to wiphy
18859 * @dev: Pointer to network device
18860 * @chandef: Pointer to channel definition parameter
18861 *
18862 * Return: 0 for success, non-zero for failure
18863 */
18864static int
18865__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
18866 struct net_device *dev,
18867 struct cfg80211_chan_def *chandef)
18868{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018869 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070018870 struct hdd_context *hdd_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053018871 QDF_STATUS status;
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053018872 int retval = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018873
Anurag Chouhan6d760662016-02-20 16:05:43 +053018874 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070018875 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018876 return -EINVAL;
18877 }
18878
Dustin Brown63500612018-08-07 11:36:09 -070018879 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018880 return -EINVAL;
Dustin Brown63500612018-08-07 11:36:09 -070018881
Abhishek Singh9d5f4582017-10-11 17:59:48 +053018882 if (!(adapter->device_mode == QDF_SAP_MODE ||
18883 adapter->device_mode == QDF_P2P_GO_MODE))
18884 return -EOPNOTSUPP;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018885
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018886 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070018887 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053018888 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018889 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018890
Abhishek Singh9d5f4582017-10-11 17:59:48 +053018891 hdd_debug("Channel width changed to %d ",
18892 cfg80211_get_chandef_type(chandef));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018893
18894 /* Change SAP ht2040 mode */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018895 status = hdd_set_sap_ht2040_mode(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018896 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053018897 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018898 hdd_err("Cannot set SAP HT20/40 mode!");
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053018899 retval = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018900 }
18901
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053018902 return retval;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018903}
18904
18905/**
18906 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
18907 * @wiphy: Pointer to wiphy
18908 * @dev: Pointer to network device
18909 * @chandef: Pointer to channel definition parameter
18910 *
18911 * Return: 0 for success, non-zero for failure
18912 */
18913static int
18914wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
18915 struct net_device *dev,
18916 struct cfg80211_chan_def *chandef)
18917{
18918 int ret;
18919
18920 cds_ssr_protect(__func__);
18921 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
18922 cds_ssr_unprotect(__func__);
18923
18924 return ret;
18925}
18926#endif
18927
Abhishek Singh1bdb1572015-10-16 16:24:19 +053018928#ifdef CHANNEL_SWITCH_SUPPORTED
18929/**
18930 * __wlan_hdd_cfg80211_channel_switch()- function to switch
18931 * channel in SAP/GO
18932 * @wiphy: wiphy pointer
18933 * @dev: dev pointer.
18934 * @csa_params: Change channel params
18935 *
18936 * This function is called to switch channel in SAP/GO
18937 *
18938 * Return: 0 if success else return non zero
18939 */
18940static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
18941 struct net_device *dev,
18942 struct cfg80211_csa_settings *csa_params)
18943{
Jeff Johnsone5006672017-08-29 14:39:02 -070018944 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070018945 struct hdd_context *hdd_ctx;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053018946 uint8_t channel;
18947 uint16_t freq;
18948 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080018949 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053018950
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018951 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053018952 csa_params->chandef.chan->center_freq);
18953
Dustin Brown63500612018-08-07 11:36:09 -070018954 if (wlan_hdd_validate_session_id(adapter->session_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018955 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053018956
Abhishek Singh1bdb1572015-10-16 16:24:19 +053018957 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
18958 ret = wlan_hdd_validate_context(hdd_ctx);
18959
18960 if (0 != ret)
18961 return ret;
18962
Krunal Sonib4326f22016-03-10 13:05:51 -080018963 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
18964 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053018965 return -ENOTSUPP;
18966
18967 freq = csa_params->chandef.chan->center_freq;
18968 channel = cds_freq_to_chan(freq);
18969
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053018970 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
18971
Min Liu2fef5792018-01-19 17:59:42 +080018972 ret = hdd_softap_set_channel_change(dev, channel, ch_width, false);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053018973 return ret;
18974}
18975
18976/**
18977 * wlan_hdd_cfg80211_channel_switch()- function to switch
18978 * channel in SAP/GO
18979 * @wiphy: wiphy pointer
18980 * @dev: dev pointer.
18981 * @csa_params: Change channel params
18982 *
18983 * This function is called to switch channel in SAP/GO
18984 *
18985 * Return: 0 if success else return non zero
18986 */
18987static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
18988 struct net_device *dev,
18989 struct cfg80211_csa_settings *csa_params)
18990{
18991 int ret;
18992
18993 cds_ssr_protect(__func__);
18994 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
18995 cds_ssr_unprotect(__func__);
18996 return ret;
18997}
18998#endif
18999
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019000/**
19001 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
19002 * translation from NL to policy manager type
19003 * @type: Generic connection mode type defined in NL
19004 *
19005 *
19006 * This function provides the type translation
19007 *
19008 * Return: cds_con_mode enum
19009 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080019010enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019011 enum nl80211_iftype type)
19012{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080019013 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019014
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019015 switch (type) {
19016 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080019017 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019018 break;
19019 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080019020 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019021 break;
19022 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080019023 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019024 break;
19025 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080019026 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019027 break;
19028 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080019029 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019030 break;
19031 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019032 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019033 }
19034 return mode;
19035}
19036
Krunal Sonied3bc8e2018-01-26 12:13:34 -080019037int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter,
19038 uint8_t channel,
19039 enum policy_mgr_conn_update_reason reason)
19040{
19041 QDF_STATUS status;
19042 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
19043
Dustin Brown491d54b2018-03-14 12:39:11 -070019044 hdd_enter();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080019045 if (0 != wlan_hdd_validate_context(hdd_ctx))
19046 return -EINVAL;
19047
19048 status = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
19049 if (!QDF_IS_STATUS_SUCCESS(status))
19050 hdd_err("clearing event failed");
19051
19052 status = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
19053 adapter->session_id, channel, reason);
19054 switch (status) {
19055 case QDF_STATUS_E_FAILURE:
19056 /*
Jeff Johnson11d7c9d2018-05-06 15:44:09 -070019057 * QDF_STATUS_E_FAILURE indicates that some error has occurred
Krunal Sonied3bc8e2018-01-26 12:13:34 -080019058 * while changing the hw mode
19059 */
19060 hdd_err("ERROR: connections update failed!!");
19061 return -EINVAL;
19062
19063 case QDF_STATUS_SUCCESS:
19064 /*
19065 * QDF_STATUS_SUCCESS indicates that HW mode change has been
19066 * triggered and wait for it to finish.
19067 */
19068 status = policy_mgr_wait_for_connection_update(
19069 hdd_ctx->hdd_psoc);
19070 if (!QDF_IS_STATUS_SUCCESS(status)) {
19071 hdd_err("ERROR: qdf wait for event failed!!");
19072 return -EINVAL;
19073 }
19074 if (QDF_MONITOR_MODE == adapter->device_mode)
19075 hdd_info("Monitor mode:channel:%d (SMM->DBS)", channel);
19076 break;
19077
19078 default:
19079 /*
19080 * QDF_STATUS_E_NOSUPPORT indicates that no HW mode change is
19081 * required, so caller can proceed further.
19082 */
19083 break;
19084
19085 }
Dustin Browne74003f2018-03-14 12:51:58 -070019086 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080019087
19088 return 0;
19089}
19090
Nirav Shah73713f72018-05-17 14:50:41 +053019091#ifdef FEATURE_MONITOR_MODE_SUPPORT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019092/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019093 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
19094 * @wiphy: Handle to struct wiphy to get handle to module context.
19095 * @chandef: Contains information about the capture channel to be set.
19096 *
19097 * This interface is called if and only if monitor mode interface alone is
19098 * active.
19099 *
19100 * Return: 0 success or error code on failure.
19101 */
19102static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
19103 struct cfg80211_chan_def *chandef)
19104{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070019105 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsone5006672017-08-29 14:39:02 -070019106 struct hdd_adapter *adapter;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070019107 struct hdd_station_ctx *sta_ctx;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019108 struct hdd_mon_set_ch_info *ch_info;
19109 QDF_STATUS status;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019110 mac_handle_t mac_handle;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019111 struct qdf_mac_addr bssid;
Jeff Johnson61b5e982018-03-15 11:33:31 -070019112 struct csr_roam_profile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080019113 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070019114 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019115 int ret;
19116 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
19117
Dustin Brown491d54b2018-03-14 12:39:11 -070019118 hdd_enter();
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019119
19120 ret = wlan_hdd_validate_context(hdd_ctx);
19121 if (ret)
19122 return ret;
19123
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019124 mac_handle = hdd_ctx->mac_handle;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019125
19126 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
19127 if (!adapter)
19128 return -EIO;
19129
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019130 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019131 adapter->dev->name, chan_num, chandef->chan->center_freq);
19132
19133 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19134 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019135 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
19136 roam_profile.ChannelInfo.numOfChannels = 1;
19137 roam_profile.phyMode = ch_info->phy_mode;
Naveen Rawat3184dd82017-07-05 14:58:18 -070019138 roam_profile.ch_params.ch_width = hdd_map_nl_chan_width(chandef->width);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070019139 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019140
Jeff Johnson1e851a12017-10-28 14:36:12 -070019141 qdf_mem_copy(bssid.bytes, adapter->mac_addr.bytes,
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019142 QDF_MAC_ADDR_SIZE);
19143
Naveen Rawat3184dd82017-07-05 14:58:18 -070019144 ch_params.ch_width = hdd_map_nl_chan_width(chandef->width);
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070019145 /*
19146 * CDS api expects secondary channel for calculating
19147 * the channel params
19148 */
19149 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070019150 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070019151 if (chan_num >= 1 && chan_num <= 5)
19152 sec_ch = chan_num + 4;
19153 else if (chan_num >= 6 && chan_num <= 13)
19154 sec_ch = chan_num - 4;
19155 }
Dustin Brown07901ec2018-09-07 11:02:41 -070019156 wlan_reg_set_channel_params(hdd_ctx->pdev, chan_num,
19157 sec_ch, &ch_params);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080019158 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, chan_num,
19159 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
19160 hdd_err("Failed to change hw mode");
19161 return -EINVAL;
19162 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019163 status = sme_roam_channel_change_req(mac_handle, bssid, &ch_params,
19164 &roam_profile);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019165 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019166 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019167 status);
19168 ret = qdf_status_to_os_return(status);
19169 return ret;
19170 }
Dustin Browne74003f2018-03-14 12:51:58 -070019171 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080019172
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019173 return 0;
19174}
19175
19176/**
19177 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
19178 * @wiphy: Handle to struct wiphy to get handle to module context.
19179 * @chandef: Contains information about the capture channel to be set.
19180 *
19181 * This interface is called if and only if monitor mode interface alone is
19182 * active.
19183 *
19184 * Return: 0 success or error code on failure.
19185 */
19186static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
19187 struct cfg80211_chan_def *chandef)
19188{
19189 int ret;
19190
19191 cds_ssr_protect(__func__);
19192 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
19193 cds_ssr_unprotect(__func__);
19194 return ret;
19195}
Nirav Shah73713f72018-05-17 14:50:41 +053019196#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019197
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053019198#define CNT_DIFF(cur, prev) \
19199 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
19200#define MAX_COUNT 0xffffffff
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070019201static void hdd_update_chan_info(struct hdd_context *hdd_ctx,
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053019202 struct scan_chan_info *chan,
19203 struct scan_chan_info *info, uint32_t cmd_flag)
19204{
19205 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
19206 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
19207 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
19208
19209 mutex_lock(&hdd_ctx->chan_info_lock);
19210
19211 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
19212 qdf_mem_zero(chan, sizeof(*chan));
19213
19214 chan->freq = info->freq;
19215 chan->noise_floor = info->noise_floor;
19216 chan->clock_freq = info->clock_freq;
19217 chan->cmd_flag = info->cmd_flag;
19218 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
19219
19220 chan->rx_clear_count =
19221 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
19222
19223 chan->tx_frame_count =
19224 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
19225
19226 mutex_unlock(&hdd_ctx->chan_info_lock);
19227
19228}
19229#undef CNT_DIFF
19230#undef MAX_COUNT
19231
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019232#if defined(WLAN_FEATURE_FILS_SK) &&\
Sridhar Selvaraje5260442017-08-19 10:12:03 +053019233 defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) &&\
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019234 (defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
19235 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
19236
19237#ifndef UPDATE_FILS_ERP_INFO
19238#define UPDATE_FILS_ERP_INFO BIT(1)
19239#endif
19240
19241#ifndef UPDATE_FILS_AUTH_TYPE
19242#define UPDATE_FILS_AUTH_TYPE BIT(2)
19243#endif
19244
19245/**
19246 * __wlan_hdd_cfg80211_update_connect_params - update connect params
19247 * @wiphy: Handle to struct wiphy to get handle to module context.
19248 * @dev: Pointer to network device
19249 * @req: Pointer to connect params
19250 * @changed: Bitmap used to indicate the changed params
19251 *
19252 * Update the connect parameters while connected to a BSS. The updated
19253 * parameters can be used by driver/firmware for subsequent BSS selection
19254 * (roaming) decisions and to form the Authentication/(Re)Association
19255 * Request frames. This call does not request an immediate disassociation
19256 * or reassociation with the current BSS, i.e., this impacts only
19257 * subsequent (re)associations. The bits in changed are defined in enum
19258 * cfg80211_connect_params_changed
19259 *
19260 * Return: zero for success, non-zero for failure
19261 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019262static int
19263__wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
19264 struct net_device *dev,
19265 struct cfg80211_connect_params *req,
19266 uint32_t changed)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019267{
Jeff Johnson61b5e982018-03-15 11:33:31 -070019268 struct csr_roam_profile *roam_profile;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019269 uint8_t *buf;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070019270 int ret;
19271 enum eAniAuthType auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019272 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19273 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
19274 QDF_STATUS status;
19275 struct cds_fils_connection_info *fils_info;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019276 mac_handle_t mac_handle;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019277
Dustin Brownfdf17c12018-03-14 12:55:34 -070019278 hdd_enter_dev(dev);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019279
Dustin Brown63500612018-08-07 11:36:09 -070019280 if (wlan_hdd_validate_session_id(adapter->session_id))
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019281 return -EINVAL;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019282
19283 ret = wlan_hdd_validate_context(hdd_ctx);
19284 if (ret)
19285 return -EINVAL;
19286
Jeff Johnson20227a92018-03-13 09:41:05 -070019287 roam_profile = hdd_roam_profile(adapter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019288 fils_info = roam_profile->fils_con_info;
19289
19290 if (!fils_info) {
19291 hdd_err("No valid FILS conn info");
19292 return -EINVAL;
19293 }
19294
19295 if (req->ie_len)
19296 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
19297
19298 if (changed)
19299 fils_info->is_fils_connection = true;
19300
19301 if (changed & UPDATE_FILS_ERP_INFO) {
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080019302 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080019303 return -EINVAL;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019304 fils_info->key_nai_length = req->fils_erp_username_len +
19305 sizeof(char) +
19306 req->fils_erp_realm_len;
Dundi Raviteja170d2872018-03-23 15:49:54 +053019307 if (fils_info->key_nai_length >
19308 FILS_MAX_KEYNAME_NAI_LENGTH) {
19309 hdd_err("Key NAI Length %d",
19310 fils_info->key_nai_length);
19311 return -EINVAL;
19312 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019313 if (req->fils_erp_username_len && req->fils_erp_username) {
19314 buf = fils_info->keyname_nai;
19315 qdf_mem_copy(buf, req->fils_erp_username,
19316 req->fils_erp_username_len);
19317 buf += req->fils_erp_username_len;
19318 *buf++ = '@';
19319 qdf_mem_copy(buf, req->fils_erp_realm,
19320 req->fils_erp_realm_len);
19321 }
19322
19323 fils_info->sequence_number = req->fils_erp_next_seq_num;
19324 fils_info->r_rk_length = req->fils_erp_rrk_len;
19325
19326 if (req->fils_erp_rrk_len && req->fils_erp_rrk)
19327 qdf_mem_copy(fils_info->r_rk, req->fils_erp_rrk,
19328 fils_info->r_rk_length);
19329
19330 fils_info->realm_len = req->fils_erp_realm_len;
19331 if (req->fils_erp_realm_len && req->fils_erp_realm)
19332 qdf_mem_copy(fils_info->realm, req->fils_erp_realm,
19333 fils_info->realm_len);
19334 }
19335
19336 if (changed & UPDATE_FILS_AUTH_TYPE) {
19337 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070019338 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019339 hdd_err("invalid auth type for fils %d",
19340 req->auth_type);
19341 return -EINVAL;
19342 }
19343
19344 roam_profile->fils_con_info->auth_type = auth_type;
19345 }
19346
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080019347 hdd_debug("fils conn update: changed %x is_fils %d keyname nai len %d",
19348 changed, roam_profile->fils_con_info->is_fils_connection,
19349 roam_profile->fils_con_info->key_nai_length);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019350
Abhishek Singh1f217ec2017-12-22 11:48:27 +053019351 if (!hdd_ctx->is_fils_roaming_supported) {
19352 hdd_debug("FILS roaming support %d",
Vignesh Viswanathan731186f2017-09-18 13:47:37 +053019353 hdd_ctx->is_fils_roaming_supported);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019354 return 0;
19355 }
19356
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019357 mac_handle = hdd_ctx->mac_handle;
19358 status = sme_update_fils_config(mac_handle, adapter->session_id,
19359 roam_profile);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019360 if (QDF_IS_STATUS_ERROR(status))
19361 hdd_err("Update FILS connect params to Fw failed %d", status);
19362
19363 return 0;
19364}
19365
19366/**
19367 * wlan_hdd_cfg80211_update_connect_params - SSR wrapper for
19368 * __wlan_hdd_cfg80211_update_connect_params
19369 * @wiphy: Pointer to wiphy structure
19370 * @dev: Pointer to net_device
19371 * @req: Pointer to connect params
19372 * @changed: flags used to indicate the changed params
19373 *
19374 * Return: zero for success, non-zero for failure
19375 */
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019376static int
19377wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
19378 struct net_device *dev,
19379 struct cfg80211_connect_params *req,
19380 uint32_t changed)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019381{
19382 int ret;
19383
19384 cds_ssr_protect(__func__);
19385 ret = __wlan_hdd_cfg80211_update_connect_params(wiphy, dev,
19386 req, changed);
19387 cds_ssr_unprotect(__func__);
19388
19389 return ret;
19390}
19391#endif
19392
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053019393#if defined(WLAN_FEATURE_SAE) && \
19394 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
19395/**
19396 * __wlan_hdd_cfg80211_external_auth() - Handle external auth
19397 * @wiphy: Pointer to wireless phy
19398 * @dev: net device
19399 * @params: Pointer to external auth params
19400 *
19401 * Return: 0 on success, negative errno on failure
19402 */
19403static int
19404__wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
19405 struct net_device *dev,
19406 struct cfg80211_external_auth_params *params)
19407{
19408 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
19409 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19410 int ret;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019411 mac_handle_t mac_handle;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053019412
19413 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
19414 hdd_err("Command not allowed in FTM mode");
19415 return -EPERM;
19416 }
19417
Dustin Brown63500612018-08-07 11:36:09 -070019418 if (wlan_hdd_validate_session_id(adapter->session_id))
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053019419 return -EINVAL;
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053019420
19421 ret = wlan_hdd_validate_context(hdd_ctx);
19422 if (ret)
19423 return ret;
19424
19425
19426 hdd_debug("external_auth status: %d", params->status);
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019427 mac_handle = hdd_ctx->mac_handle;
19428 sme_handle_sae_msg(mac_handle, adapter->session_id, params->status);
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053019429
19430 return ret;
19431}
19432
19433/**
19434 * wlan_hdd_cfg80211_external_auth() - Handle external auth
19435 * @wiphy: Pointer to wireless phy
19436 * @dev: net device
19437 * @params: Pointer to external auth params
19438 *
19439 * Return: 0 on success, negative errno on failure
19440 */
19441static int
19442wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
19443 struct net_device *dev,
19444 struct cfg80211_external_auth_params *params)
19445{
19446 int ret;
19447
19448 cds_ssr_protect(__func__);
19449 ret = __wlan_hdd_cfg80211_external_auth(wiphy, dev, params);
19450 cds_ssr_unprotect(__func__);
19451
19452 return ret;
19453}
19454#endif
19455
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053019456/**
19457 * wlan_hdd_chan_info_cb() - channel info callback
19458 * @chan_info: struct scan_chan_info
19459 *
19460 * Store channel info into HDD context
19461 *
19462 * Return: None.
19463 */
19464static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
19465{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070019466 struct hdd_context *hdd_ctx;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053019467 struct scan_chan_info *chan;
19468 uint8_t idx;
19469
Dustin Brown491d54b2018-03-14 12:39:11 -070019470 hdd_enter();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053019471
19472 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
19473 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
19474 hdd_err("hdd_ctx is invalid");
19475 return;
19476 }
19477
19478 if (!hdd_ctx->chan_info) {
19479 hdd_err("chan_info is NULL");
19480 return;
19481 }
19482
19483 chan = hdd_ctx->chan_info;
19484 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
19485 if (chan[idx].freq == info->freq) {
19486 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
19487 info->cmd_flag);
19488 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
19489 chan[idx].cmd_flag, chan[idx].freq,
19490 chan[idx].noise_floor,
19491 chan[idx].cycle_count, chan[idx].rx_clear_count,
19492 chan[idx].clock_freq, chan[idx].cmd_flag,
19493 chan[idx].tx_frame_count, idx);
19494 if (chan[idx].freq == 0)
19495 break;
19496
19497 }
19498 }
19499
Dustin Browne74003f2018-03-14 12:51:58 -070019500 hdd_exit();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053019501}
19502
19503/**
19504 * wlan_hdd_init_chan_info() - init chan info in hdd context
19505 * @hdd_ctx: HDD context pointer
19506 *
19507 * Return: none
19508 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070019509void wlan_hdd_init_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053019510{
19511 uint8_t num_2g, num_5g, index = 0;
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019512 mac_handle_t mac_handle;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053019513
Kapil Gupta63e75282017-05-18 20:55:10 +053019514 hdd_ctx->chan_info = NULL;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053019515 if (!hdd_ctx->config->fEnableSNRMonitoring) {
Dustin Brown31116772018-08-15 14:59:21 -070019516 hdd_debug("SNR monitoring is disabled");
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053019517 return;
19518 }
19519
19520 hdd_ctx->chan_info =
19521 qdf_mem_malloc(sizeof(struct scan_chan_info)
19522 * QDF_MAX_NUM_CHAN);
19523 if (hdd_ctx->chan_info == NULL) {
19524 hdd_err("Failed to malloc for chan info");
19525 return;
19526 }
19527 mutex_init(&hdd_ctx->chan_info_lock);
19528
19529 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
19530 for (; index < num_2g; index++) {
19531 hdd_ctx->chan_info[index].freq =
19532 hdd_channels_2_4_ghz[index].center_freq;
19533 }
19534
19535 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
19536 for (; (index - num_2g) < num_5g; index++) {
Dustin Brown07901ec2018-09-07 11:02:41 -070019537 if (wlan_reg_is_dsrc_chan(hdd_ctx->pdev,
Kiran Kumar Lokere1a43bcf2018-05-15 15:51:58 -070019538 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053019539 continue;
19540 hdd_ctx->chan_info[index].freq =
19541 hdd_channels_5_ghz[index - num_2g].center_freq;
19542 }
Jeff Johnson34fc63a2018-06-14 10:10:02 -070019543 mac_handle = hdd_ctx->mac_handle;
19544 sme_set_chan_info_callback(mac_handle,
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053019545 &wlan_hdd_chan_info_cb);
19546}
19547
19548/**
19549 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
19550 * @hdd_ctx: hdd context pointer
19551 *
19552 * Return: none
19553 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070019554void wlan_hdd_deinit_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053019555{
19556 struct scan_chan_info *chan;
19557
19558 chan = hdd_ctx->chan_info;
19559 hdd_ctx->chan_info = NULL;
19560 if (chan)
19561 qdf_mem_free(chan);
19562}
19563
Dustin Brown32cb4792017-06-15 15:33:42 -070019564#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
19565static enum rate_info_bw hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
19566{
19567 switch (hdd_bw) {
19568 case HDD_RATE_BW_5:
19569 return RATE_INFO_BW_5;
19570 case HDD_RATE_BW_10:
19571 return RATE_INFO_BW_10;
19572 case HDD_RATE_BW_20:
19573 return RATE_INFO_BW_20;
19574 case HDD_RATE_BW_40:
19575 return RATE_INFO_BW_40;
19576 case HDD_RATE_BW_80:
19577 return RATE_INFO_BW_80;
19578 case HDD_RATE_BW_160:
19579 return RATE_INFO_BW_160;
19580 }
19581
19582 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
19583
19584 return RATE_INFO_BW_20;
19585}
19586
19587void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
19588{
19589 info->bw = hdd_map_hdd_bw_to_os(hdd_bw);
19590}
19591#else
19592static enum rate_info_flags hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
19593{
19594 switch (hdd_bw) {
19595 case HDD_RATE_BW_5:
19596 case HDD_RATE_BW_10:
19597 case HDD_RATE_BW_20:
19598 return (enum rate_info_flags)0;
19599 case HDD_RATE_BW_40:
19600 return RATE_INFO_FLAGS_40_MHZ_WIDTH;
19601 case HDD_RATE_BW_80:
19602 return RATE_INFO_FLAGS_80_MHZ_WIDTH;
19603 case HDD_RATE_BW_160:
19604 return RATE_INFO_FLAGS_160_MHZ_WIDTH;
19605 }
19606
19607 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
19608
19609 return (enum rate_info_flags)0;
19610}
19611
19612void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
19613{
19614 const enum rate_info_flags all_bws =
19615 RATE_INFO_FLAGS_40_MHZ_WIDTH |
19616 RATE_INFO_FLAGS_80_MHZ_WIDTH |
19617 RATE_INFO_FLAGS_80P80_MHZ_WIDTH |
19618 RATE_INFO_FLAGS_160_MHZ_WIDTH;
19619
19620 info->flags &= ~all_bws;
19621 info->flags |= hdd_map_hdd_bw_to_os(hdd_bw);
19622}
19623#endif
19624
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053019625/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019626 * struct cfg80211_ops - cfg80211_ops
19627 *
19628 * @add_virtual_intf: Add virtual interface
19629 * @del_virtual_intf: Delete virtual interface
19630 * @change_virtual_intf: Change virtual interface
19631 * @change_station: Change station
19632 * @add_beacon: Add beacon in sap mode
19633 * @del_beacon: Delete beacon in sap mode
19634 * @set_beacon: Set beacon in sap mode
19635 * @start_ap: Start ap
19636 * @change_beacon: Change beacon
19637 * @stop_ap: Stop ap
19638 * @change_bss: Change bss
19639 * @add_key: Add key
19640 * @get_key: Get key
19641 * @del_key: Delete key
19642 * @set_default_key: Set default key
19643 * @set_channel: Set channel
19644 * @scan: Scan
19645 * @connect: Connect
19646 * @disconnect: Disconnect
19647 * @join_ibss = Join ibss
19648 * @leave_ibss = Leave ibss
19649 * @set_wiphy_params = Set wiphy params
19650 * @set_tx_power = Set tx power
19651 * @get_tx_power = get tx power
19652 * @remain_on_channel = Remain on channel
19653 * @cancel_remain_on_channel = Cancel remain on channel
19654 * @mgmt_tx = Tx management frame
19655 * @mgmt_tx_cancel_wait = Cancel management tx wait
19656 * @set_default_mgmt_key = Set default management key
19657 * @set_txq_params = Set tx queue parameters
19658 * @get_station = Get station
19659 * @set_power_mgmt = Set power management
19660 * @del_station = Delete station
19661 * @add_station = Add station
19662 * @set_pmksa = Set pmksa
19663 * @del_pmksa = Delete pmksa
19664 * @flush_pmksa = Flush pmksa
19665 * @update_ft_ies = Update FT IEs
19666 * @tdls_mgmt = Tdls management
19667 * @tdls_oper = Tdls operation
19668 * @set_rekey_data = Set rekey data
19669 * @sched_scan_start = Scheduled scan start
19670 * @sched_scan_stop = Scheduled scan stop
19671 * @resume = Resume wlan
19672 * @suspend = Suspend wlan
19673 * @set_mac_acl = Set mac acl
19674 * @testmode_cmd = Test mode command
19675 * @set_ap_chanwidth = Set AP channel bandwidth
19676 * @dump_survey = Dump survey
19677 * @key_mgmt_set_pmk = Set pmk key management
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019678 * @update_connect_params = Update connect params
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019679 */
19680static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
19681 .add_virtual_intf = wlan_hdd_add_virtual_intf,
19682 .del_virtual_intf = wlan_hdd_del_virtual_intf,
19683 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
19684 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019685 .start_ap = wlan_hdd_cfg80211_start_ap,
19686 .change_beacon = wlan_hdd_cfg80211_change_beacon,
19687 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019688 .change_bss = wlan_hdd_cfg80211_change_bss,
19689 .add_key = wlan_hdd_cfg80211_add_key,
19690 .get_key = wlan_hdd_cfg80211_get_key,
19691 .del_key = wlan_hdd_cfg80211_del_key,
19692 .set_default_key = wlan_hdd_cfg80211_set_default_key,
19693 .scan = wlan_hdd_cfg80211_scan,
19694 .connect = wlan_hdd_cfg80211_connect,
19695 .disconnect = wlan_hdd_cfg80211_disconnect,
19696 .join_ibss = wlan_hdd_cfg80211_join_ibss,
19697 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
19698 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
19699 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
19700 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
19701 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
19702 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
19703 .mgmt_tx = wlan_hdd_mgmt_tx,
19704 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
19705 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
19706 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053019707 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019708 .get_station = wlan_hdd_cfg80211_get_station,
19709 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
19710 .del_station = wlan_hdd_cfg80211_del_station,
19711 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019712 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
19713 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
19714 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080019715#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019716 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
19717#endif
19718#ifdef FEATURE_WLAN_TDLS
19719 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
19720 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
19721#endif
19722#ifdef WLAN_FEATURE_GTK_OFFLOAD
19723 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
19724#endif /* WLAN_FEATURE_GTK_OFFLOAD */
19725#ifdef FEATURE_WLAN_SCAN_PNO
19726 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
19727 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
19728#endif /*FEATURE_WLAN_SCAN_PNO */
19729 .resume = wlan_hdd_cfg80211_resume_wlan,
19730 .suspend = wlan_hdd_cfg80211_suspend_wlan,
19731 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
19732#ifdef WLAN_NL80211_TESTMODE
19733 .testmode_cmd = wlan_hdd_cfg80211_testmode,
19734#endif
19735#ifdef QCA_HT_2040_COEX
19736 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
19737#endif
19738 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053019739#ifdef CHANNEL_SWITCH_SUPPORTED
19740 .channel_switch = wlan_hdd_cfg80211_channel_switch,
19741#endif
Nirav Shah73713f72018-05-17 14:50:41 +053019742#ifdef FEATURE_MONITOR_MODE_SUPPORT
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070019743 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Nirav Shah73713f72018-05-17 14:50:41 +053019744#endif
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053019745#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019746 defined(CFG80211_ABORT_SCAN)
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053019747 .abort_scan = wlan_hdd_cfg80211_abort_scan,
19748#endif
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019749#if defined(WLAN_FEATURE_FILS_SK) &&\
Sridhar Selvaraje5260442017-08-19 10:12:03 +053019750 defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) &&\
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019751 (defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
19752 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
19753 .update_connect_params = wlan_hdd_cfg80211_update_connect_params,
19754#endif
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053019755#if defined(WLAN_FEATURE_SAE) && \
19756 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
19757 .external_auth = wlan_hdd_cfg80211_external_auth,
19758#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019759};